Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 172007
b: refs/heads/master
c: d3245b2
h: refs/heads/master
i:
  172005: d89d635
  172003: 45862b1
  171999: f52599b
v: v3
  • Loading branch information
Ben Hutchings authored and David S. Miller committed Nov 30, 2009
1 parent 6c92f6c commit 77f8fe0
Show file tree
Hide file tree
Showing 16 changed files with 274 additions and 183 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ef2b90ee4dba7a3d9001f1f0003b860b39a4aaae
refs/heads/master: d3245b28ef2a45ec4e115062a38100bd06229289
132 changes: 80 additions & 52 deletions trunk/drivers/net/sfc/efx.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,59 +620,84 @@ void efx_link_status_changed(struct efx_nic *efx)

}

void efx_link_set_advertising(struct efx_nic *efx, u32 advertising)
{
efx->link_advertising = advertising;
if (advertising) {
if (advertising & ADVERTISED_Pause)
efx->wanted_fc |= (EFX_FC_TX | EFX_FC_RX);
else
efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX);
if (advertising & ADVERTISED_Asym_Pause)
efx->wanted_fc ^= EFX_FC_TX;
}
}

void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type wanted_fc)
{
efx->wanted_fc = wanted_fc;
if (efx->link_advertising) {
if (wanted_fc & EFX_FC_RX)
efx->link_advertising |= (ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
else
efx->link_advertising &= ~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
if (wanted_fc & EFX_FC_TX)
efx->link_advertising ^= ADVERTISED_Asym_Pause;
}
}

static void efx_fini_port(struct efx_nic *efx);

/* This call reinitialises the MAC to pick up new PHY settings. The
* caller must hold the mac_lock */
void __efx_reconfigure_port(struct efx_nic *efx)
/* Push loopback/power/transmit disable settings to the PHY, and reconfigure
* the MAC appropriately. All other PHY configuration changes are pushed
* through phy_op->set_settings(), and pushed asynchronously to the MAC
* through efx_monitor().
*
* Callers must hold the mac_lock
*/
int __efx_reconfigure_port(struct efx_nic *efx)
{
WARN_ON(!mutex_is_locked(&efx->mac_lock));
enum efx_phy_mode phy_mode;
int rc;

EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n",
raw_smp_processor_id());
WARN_ON(!mutex_is_locked(&efx->mac_lock));

/* Serialise the promiscuous flag with efx_set_multicast_list. */
if (efx_dev_registered(efx)) {
netif_addr_lock_bh(efx->net_dev);
netif_addr_unlock_bh(efx->net_dev);
}

efx->type->stop_stats(efx);
falcon_deconfigure_mac_wrapper(efx);

/* Reconfigure the PHY, disabling transmit in mac level loopback. */
/* Disable PHY transmit in mac level loopbacks */
phy_mode = efx->phy_mode;
if (LOOPBACK_INTERNAL(efx))
efx->phy_mode |= PHY_MODE_TX_DISABLED;
else
efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
efx->phy_op->reconfigure(efx);

if (falcon_switch_mac(efx))
goto fail;

efx->mac_op->reconfigure(efx);
rc = efx->type->reconfigure_port(efx);

efx->type->start_stats(efx);

/* Inform kernel of loss/gain of carrier */
efx_link_status_changed(efx);
return;
if (rc)
efx->phy_mode = phy_mode;

fail:
EFX_ERR(efx, "failed to reconfigure MAC\n");
efx->port_enabled = false;
efx_fini_port(efx);
return rc;
}

/* Reinitialise the MAC to pick up new PHY settings, even if the port is
* disabled. */
void efx_reconfigure_port(struct efx_nic *efx)
int efx_reconfigure_port(struct efx_nic *efx)
{
int rc;

EFX_ASSERT_RESET_SERIALISED(efx);

mutex_lock(&efx->mac_lock);
__efx_reconfigure_port(efx);
rc = __efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock);

return rc;
}

/* Asynchronous work item for changing MAC promiscuity and multicast
Expand Down Expand Up @@ -737,14 +762,18 @@ static int efx_init_port(struct efx_nic *efx)
rc = efx->phy_op->init(efx);
if (rc)
goto fail1;
efx->phy_op->reconfigure(efx);
rc = falcon_switch_mac(efx);
if (rc)
goto fail2;
efx->mac_op->reconfigure(efx);

efx->port_initialized = true;

/* Reconfigure the MAC before creating dma queues (required for
* Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
efx->mac_op->reconfigure(efx);

/* Ensure the PHY advertises the correct flow control settings */
rc = efx->phy_op->reconfigure(efx);
if (rc)
goto fail2;

mutex_unlock(&efx->mac_lock);
return 0;

Expand Down Expand Up @@ -1209,12 +1238,6 @@ static void efx_stop_all(struct efx_nic *efx)
/* Flush efx_mac_work(), refill_workqueue, monitor_work */
efx_flush_all(efx);

/* Isolate the MAC from the TX and RX engines, so that queue
* flushes will complete in a timely fashion. */
falcon_deconfigure_mac_wrapper(efx);
msleep(10); /* Let the Rx FIFO drain */
falcon_drain_tx_fifo(efx);

/* Stop the kernel transmit interface late, so the watchdog
* timer isn't ticking over the flush */
if (efx_dev_registered(efx)) {
Expand Down Expand Up @@ -1491,7 +1514,14 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
EFX_LOG(efx, "changing MTU to %d\n", new_mtu);

efx_fini_channels(efx);

mutex_lock(&efx->mac_lock);
/* Reconfigure the MAC before enabling the dma queues so that
* the RX buffers don't overflow */
net_dev->mtu = new_mtu;
efx->mac_op->reconfigure(efx);
mutex_unlock(&efx->mac_lock);

efx_init_channels(efx);

efx_start_all(efx);
Expand All @@ -1515,7 +1545,9 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);

/* Reconfigure the MAC */
efx_reconfigure_port(efx);
mutex_lock(&efx->mac_lock);
efx->mac_op->reconfigure(efx);
mutex_unlock(&efx->mac_lock);

return 0;
}
Expand Down Expand Up @@ -1682,17 +1714,14 @@ static void efx_unregister_netdev(struct efx_nic *efx)

/* Tears down the entire software state and most of the hardware state
* before reset. */
void efx_reset_down(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd)
void efx_reset_down(struct efx_nic *efx, enum reset_type method)
{
EFX_ASSERT_RESET_SERIALISED(efx);

efx_stop_all(efx);
mutex_lock(&efx->mac_lock);
mutex_lock(&efx->spi_lock);

efx->phy_op->get_settings(efx, ecmd);

efx_fini_channels(efx);
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
efx->phy_op->fini(efx);
Expand All @@ -1704,8 +1733,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
* that we were unable to reinitialise the hardware, and the
* driver should be disabled. If ok is false, then the rx and tx
* engines are not restarted, pending a RESET_DISABLE. */
int efx_reset_up(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd, bool ok)
int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
{
int rc;

Expand All @@ -1722,16 +1750,17 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
rc = efx->phy_op->init(efx);
if (rc)
ok = false;
if (efx->phy_op->reconfigure(efx))
EFX_ERR(efx, "could not restore PHY settings\n");
}
if (!ok)
efx->port_initialized = false;
}

if (ok) {
efx_init_channels(efx);
efx->mac_op->reconfigure(efx);

if (efx->phy_op->set_settings(efx, ecmd))
EFX_ERR(efx, "could not restore PHY settings\n");
efx_init_channels(efx);
}

mutex_unlock(&efx->spi_lock);
Expand All @@ -1753,7 +1782,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
*/
static int efx_reset(struct efx_nic *efx)
{
struct ethtool_cmd ecmd;
enum reset_type method = efx->reset_pending;
int rc = 0;

Expand All @@ -1769,7 +1797,7 @@ static int efx_reset(struct efx_nic *efx)

EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));

efx_reset_down(efx, method, &ecmd);
efx_reset_down(efx, method);

rc = efx->type->reset(efx, method);
if (rc) {
Expand All @@ -1788,10 +1816,10 @@ static int efx_reset(struct efx_nic *efx)

/* Leave device stopped if necessary */
if (method == RESET_TYPE_DISABLE) {
efx_reset_up(efx, method, &ecmd, false);
efx_reset_up(efx, method, false);
rc = -EIO;
} else {
rc = efx_reset_up(efx, method, &ecmd, true);
rc = efx_reset_up(efx, method, true);
}

out_disable:
Expand Down Expand Up @@ -1895,7 +1923,7 @@ bool efx_port_dummy_op_poll(struct efx_nic *efx)

static struct efx_phy_operations efx_dummy_phy_operations = {
.init = efx_port_dummy_op_int,
.reconfigure = efx_port_dummy_op_void,
.reconfigure = efx_port_dummy_op_int,
.poll = efx_port_dummy_op_poll,
.fini = efx_port_dummy_op_void,
};
Expand Down
12 changes: 6 additions & 6 deletions trunk/drivers/net/sfc/efx.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ extern void efx_process_channel_now(struct efx_channel *channel);
#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)

/* Ports */
extern void efx_reconfigure_port(struct efx_nic *efx);
extern void __efx_reconfigure_port(struct efx_nic *efx);
extern int efx_reconfigure_port(struct efx_nic *efx);
extern int __efx_reconfigure_port(struct efx_nic *efx);

/* Ethtool support */
extern int efx_ethtool_get_settings(struct net_device *net_dev,
Expand All @@ -71,10 +71,8 @@ extern int efx_ethtool_set_settings(struct net_device *net_dev,
extern const struct ethtool_ops efx_ethtool_ops;

/* Reset handling */
extern void efx_reset_down(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd);
extern int efx_reset_up(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd, bool ok);
extern void efx_reset_down(struct efx_nic *efx, enum reset_type method);
extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);

/* Global */
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
Expand Down Expand Up @@ -115,5 +113,7 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
}

extern void efx_link_status_changed(struct efx_nic *efx);
extern void efx_link_set_advertising(struct efx_nic *efx, u32);
extern void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type);

#endif /* EFX_EFX_H */
Loading

0 comments on commit 77f8fe0

Please sign in to comment.