sfc: Use netif_device_{detach,attach}() around reset and self-test
We need to keep the TX queues stopped throughout a reset, without triggering the TX watchdog and regardless of the link state. The proper way to do this is to use netif_device_{detach,attach}() just as we do around suspend/resume, rather than the current bodge of faking link-down. Since we also need to do this during an offline self-test and we perform a reset during that, add these function calls outside of efx_reset_down() and efx_reset_up(). Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
This commit is contained in:
Родитель
602a5322a7
Коммит
e4abce8538
|
@ -798,11 +798,6 @@ void efx_link_status_changed(struct efx_nic *efx)
|
||||||
if (!netif_running(efx->net_dev))
|
if (!netif_running(efx->net_dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (efx->port_inhibited) {
|
|
||||||
netif_carrier_off(efx->net_dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (link_state->up != netif_carrier_ok(efx->net_dev)) {
|
if (link_state->up != netif_carrier_ok(efx->net_dev)) {
|
||||||
efx->n_link_state_changes++;
|
efx->n_link_state_changes++;
|
||||||
|
|
||||||
|
@ -1450,7 +1445,7 @@ static void efx_start_all(struct efx_nic *efx)
|
||||||
* restart the transmit interface early so the watchdog timer stops */
|
* restart the transmit interface early so the watchdog timer stops */
|
||||||
efx_start_port(efx);
|
efx_start_port(efx);
|
||||||
|
|
||||||
if (efx_dev_registered(efx) && !efx->port_inhibited)
|
if (efx_dev_registered(efx) && netif_device_present(efx->net_dev))
|
||||||
netif_tx_wake_all_queues(efx->net_dev);
|
netif_tx_wake_all_queues(efx->net_dev);
|
||||||
|
|
||||||
efx_for_each_channel(channel, efx)
|
efx_for_each_channel(channel, efx)
|
||||||
|
@ -2114,6 +2109,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
|
||||||
netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
|
netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
|
||||||
RESET_TYPE(method));
|
RESET_TYPE(method));
|
||||||
|
|
||||||
|
netif_device_detach(efx->net_dev);
|
||||||
efx_reset_down(efx, method);
|
efx_reset_down(efx, method);
|
||||||
|
|
||||||
rc = efx->type->reset(efx, method);
|
rc = efx->type->reset(efx, method);
|
||||||
|
@ -2147,6 +2143,7 @@ out:
|
||||||
efx->state = STATE_DISABLED;
|
efx->state = STATE_DISABLED;
|
||||||
} else {
|
} else {
|
||||||
netif_dbg(efx, drv, efx->net_dev, "reset complete\n");
|
netif_dbg(efx, drv, efx->net_dev, "reset complete\n");
|
||||||
|
netif_device_attach(efx->net_dev);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -670,13 +670,12 @@ struct efx_filter_state;
|
||||||
* @mtd_list: List of MTDs attached to the NIC
|
* @mtd_list: List of MTDs attached to the NIC
|
||||||
* @nic_data: Hardware dependent state
|
* @nic_data: Hardware dependent state
|
||||||
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
|
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
|
||||||
* @port_inhibited, efx_monitor() and efx_reconfigure_port()
|
* efx_monitor() and efx_reconfigure_port()
|
||||||
* @port_enabled: Port enabled indicator.
|
* @port_enabled: Port enabled indicator.
|
||||||
* Serialises efx_stop_all(), efx_start_all(), efx_monitor() and
|
* Serialises efx_stop_all(), efx_start_all(), efx_monitor() and
|
||||||
* efx_mac_work() with kernel interfaces. Safe to read under any
|
* efx_mac_work() with kernel interfaces. Safe to read under any
|
||||||
* one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
|
* one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
|
||||||
* be held to modify it.
|
* be held to modify it.
|
||||||
* @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
|
|
||||||
* @port_initialized: Port initialized?
|
* @port_initialized: Port initialized?
|
||||||
* @net_dev: Operating system network device. Consider holding the rtnl lock
|
* @net_dev: Operating system network device. Consider holding the rtnl lock
|
||||||
* @stats_buffer: DMA buffer for statistics
|
* @stats_buffer: DMA buffer for statistics
|
||||||
|
@ -764,7 +763,6 @@ struct efx_nic {
|
||||||
struct mutex mac_lock;
|
struct mutex mac_lock;
|
||||||
struct work_struct mac_work;
|
struct work_struct mac_work;
|
||||||
bool port_enabled;
|
bool port_enabled;
|
||||||
bool port_inhibited;
|
|
||||||
|
|
||||||
bool port_initialized;
|
bool port_initialized;
|
||||||
struct net_device *net_dev;
|
struct net_device *net_dev;
|
||||||
|
|
|
@ -695,12 +695,12 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
|
||||||
/* Offline (i.e. disruptive) testing
|
/* Offline (i.e. disruptive) testing
|
||||||
* This checks MAC and PHY loopback on the specified port. */
|
* This checks MAC and PHY loopback on the specified port. */
|
||||||
|
|
||||||
/* force the carrier state off so the kernel doesn't transmit during
|
/* Detach the device so the kernel doesn't transmit during the
|
||||||
* the loopback test, and the watchdog timeout doesn't fire. Also put
|
* loopback test and the watchdog timeout doesn't fire.
|
||||||
* falcon into loopback for the register test.
|
|
||||||
*/
|
*/
|
||||||
|
netif_device_detach(efx->net_dev);
|
||||||
|
|
||||||
mutex_lock(&efx->mac_lock);
|
mutex_lock(&efx->mac_lock);
|
||||||
efx->port_inhibited = true;
|
|
||||||
if (efx->loopback_modes) {
|
if (efx->loopback_modes) {
|
||||||
/* We need the 312 clock from the PHY to test the XMAC
|
/* We need the 312 clock from the PHY to test the XMAC
|
||||||
* registers, so move into XGMII loopback if available */
|
* registers, so move into XGMII loopback if available */
|
||||||
|
@ -750,12 +750,11 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
|
||||||
/* restore the PHY to the previous state */
|
/* restore the PHY to the previous state */
|
||||||
mutex_lock(&efx->mac_lock);
|
mutex_lock(&efx->mac_lock);
|
||||||
efx->phy_mode = phy_mode;
|
efx->phy_mode = phy_mode;
|
||||||
efx->port_inhibited = false;
|
|
||||||
efx->loopback_mode = loopback_mode;
|
efx->loopback_mode = loopback_mode;
|
||||||
__efx_reconfigure_port(efx);
|
__efx_reconfigure_port(efx);
|
||||||
mutex_unlock(&efx->mac_lock);
|
mutex_unlock(&efx->mac_lock);
|
||||||
|
|
||||||
netif_tx_wake_all_queues(efx->net_dev);
|
netif_device_attach(efx->net_dev);
|
||||||
|
|
||||||
return rc_test;
|
return rc_test;
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
|
||||||
goto unwind;
|
goto unwind;
|
||||||
}
|
}
|
||||||
smp_mb();
|
smp_mb();
|
||||||
netif_tx_start_queue(tx_queue->core_txq);
|
if (likely(!efx->loopback_selftest))
|
||||||
|
netif_tx_start_queue(
|
||||||
|
tx_queue->core_txq);
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
|
insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
|
||||||
|
@ -338,8 +340,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
|
||||||
struct efx_tx_queue *tx_queue;
|
struct efx_tx_queue *tx_queue;
|
||||||
unsigned index, type;
|
unsigned index, type;
|
||||||
|
|
||||||
if (unlikely(efx->port_inhibited))
|
EFX_WARN_ON_PARANOID(!netif_device_present(net_dev));
|
||||||
return NETDEV_TX_BUSY;
|
|
||||||
|
|
||||||
index = skb_get_queue_mapping(skb);
|
index = skb_get_queue_mapping(skb);
|
||||||
type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0;
|
type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0;
|
||||||
|
@ -436,7 +437,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
|
||||||
smp_mb();
|
smp_mb();
|
||||||
if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
|
if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
|
||||||
likely(efx->port_enabled) &&
|
likely(efx->port_enabled) &&
|
||||||
likely(!efx->port_inhibited)) {
|
likely(netif_device_present(efx->net_dev))) {
|
||||||
fill_level = tx_queue->insert_count - tx_queue->read_count;
|
fill_level = tx_queue->insert_count - tx_queue->read_count;
|
||||||
if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
|
if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
|
||||||
EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
|
EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче