Loading drivers/net/sfc/efx.c +48 −50 Original line number Diff line number Diff line Loading @@ -1754,58 +1754,49 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) rc = efx->type->init(efx); if (rc) { EFX_ERR(efx, "failed to initialise NIC\n"); ok = false; goto fail; } if (!ok) goto fail; if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { if (ok) { rc = efx->phy_op->init(efx); if (rc) ok = false; goto fail; if (efx->phy_op->reconfigure(efx)) EFX_ERR(efx, "could not restore PHY settings\n"); } if (!ok) efx->port_initialized = false; } if (ok) { efx->mac_op->reconfigure(efx); efx_init_channels(efx); } mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); if (ok) efx_start_all(efx); return 0; fail: efx->port_initialized = false; mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); return rc; } /* Reset the NIC as transparently as possible. Do not reset the PHY * Note that the reset may fail, in which case the card will be left * in a most-probably-unusable state. /* Reset the NIC using the specified method. Note that the reset may * fail, in which case the card will be left in an unusable state. * * This function will sleep. You cannot reset from within an atomic * state; use efx_schedule_reset() instead. * * Grabs the rtnl_lock. * Caller must hold the rtnl_lock. */ static int efx_reset(struct efx_nic *efx) int efx_reset(struct efx_nic *efx, enum reset_type method) { enum reset_type method = efx->reset_pending; int rc = 0; /* Serialise with kernel interfaces */ rtnl_lock(); /* If we're not RUNNING then don't reset. Leave the reset_pending * flag set so that efx_pci_probe_main will be retried */ if (efx->state != STATE_RUNNING) { EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n"); goto out_unlock; } int rc, rc2; bool disabled; EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method)); Loading @@ -1814,7 +1805,7 @@ static int efx_reset(struct efx_nic *efx) rc = efx->type->reset(efx, method); if (rc) { EFX_ERR(efx, "failed to reset hardware\n"); goto out_disable; goto out; } /* Allow resets to be rescheduled. */ Loading @@ -1826,25 +1817,22 @@ static int efx_reset(struct efx_nic *efx) * can respond to requests. */ pci_set_master(efx->pci_dev); out: /* Leave device stopped if necessary */ if (method == RESET_TYPE_DISABLE) { efx_reset_up(efx, method, false); rc = -EIO; } else { rc = efx_reset_up(efx, method, true); disabled = rc || method == RESET_TYPE_DISABLE; rc2 = efx_reset_up(efx, method, !disabled); if (rc2) { disabled = true; if (!rc) rc = rc2; } out_disable: if (rc) { if (disabled) { EFX_ERR(efx, "has been disabled\n"); efx->state = STATE_DISABLED; dev_close(efx->net_dev); } else { EFX_LOG(efx, "reset complete\n"); } out_unlock: rtnl_unlock(); return rc; } Loading @@ -1853,9 +1841,19 @@ static int efx_reset(struct efx_nic *efx) */ static void efx_reset_work(struct work_struct *data) { struct efx_nic *nic = container_of(data, struct efx_nic, reset_work); struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); efx_reset(nic); /* If we're not RUNNING then don't reset. Leave the reset_pending * flag set so that efx_pci_probe_main will be retried */ if (efx->state != STATE_RUNNING) { EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n"); return; } rtnl_lock(); if (efx_reset(efx, efx->reset_pending)) dev_close(efx->net_dev); rtnl_unlock(); } void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) Loading drivers/net/sfc/efx.h +1 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ extern int efx_ethtool_set_settings(struct net_device *net_dev, extern const struct ethtool_ops efx_ethtool_ops; /* Reset handling */ extern int efx_reset(struct efx_nic *efx, enum reset_type method); 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); Loading drivers/net/sfc/ethtool.c +30 −0 Original line number Diff line number Diff line Loading @@ -754,6 +754,35 @@ static int efx_ethtool_set_wol(struct net_device *net_dev, return efx->type->set_wol(efx, wol->wolopts); } extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) { struct efx_nic *efx = netdev_priv(net_dev); enum reset_type method; enum { ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | ETH_RESET_OFFLOAD | ETH_RESET_MAC) }; /* Check for minimal reset flags */ if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE) return -EINVAL; *flags ^= ETH_RESET_EFX_INVISIBLE; method = RESET_TYPE_INVISIBLE; if (*flags & ETH_RESET_PHY) { *flags ^= ETH_RESET_PHY; method = RESET_TYPE_ALL; } if ((*flags & efx->type->reset_world_flags) == efx->type->reset_world_flags) { *flags ^= efx->type->reset_world_flags; method = RESET_TYPE_WORLD; } return efx_reset(efx, method); } const struct ethtool_ops efx_ethtool_ops = { .get_settings = efx_ethtool_get_settings, .set_settings = efx_ethtool_set_settings, Loading Loading @@ -784,4 +813,5 @@ const struct ethtool_ops efx_ethtool_ops = { .get_ethtool_stats = efx_ethtool_get_stats, .get_wol = efx_ethtool_get_wol, .set_wol = efx_ethtool_set_wol, .reset = efx_ethtool_reset, }; drivers/net/sfc/falcon.c +2 −0 Original line number Diff line number Diff line Loading @@ -3305,6 +3305,7 @@ struct efx_nic_type falcon_a1_nic_type = { .phys_addr_channels = 4, .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .reset_world_flags = ETH_RESET_IRQ, }; struct efx_nic_type falcon_b0_nic_type = { Loading Loading @@ -3348,5 +3349,6 @@ struct efx_nic_type falcon_b0_nic_type = { * channels */ .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .reset_world_flags = ETH_RESET_IRQ, }; drivers/net/sfc/net_driver.h +3 −0 Original line number Diff line number Diff line Loading @@ -880,6 +880,8 @@ static inline const char *efx_dev_name(struct efx_nic *efx) * descriptors * @tx_dc_base: Base address in SRAM of TX queue descriptor caches * @rx_dc_base: Base address in SRAM of RX queue descriptor caches * @reset_world_flags: Flags for additional components covered by * reset method RESET_TYPE_WORLD */ struct efx_nic_type { int (*probe)(struct efx_nic *efx); Loading Loading @@ -915,6 +917,7 @@ struct efx_nic_type { unsigned int phys_addr_channels; unsigned int tx_dc_base; unsigned int rx_dc_base; u32 reset_world_flags; }; /************************************************************************** Loading Loading
drivers/net/sfc/efx.c +48 −50 Original line number Diff line number Diff line Loading @@ -1754,58 +1754,49 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) rc = efx->type->init(efx); if (rc) { EFX_ERR(efx, "failed to initialise NIC\n"); ok = false; goto fail; } if (!ok) goto fail; if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { if (ok) { rc = efx->phy_op->init(efx); if (rc) ok = false; goto fail; if (efx->phy_op->reconfigure(efx)) EFX_ERR(efx, "could not restore PHY settings\n"); } if (!ok) efx->port_initialized = false; } if (ok) { efx->mac_op->reconfigure(efx); efx_init_channels(efx); } mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); if (ok) efx_start_all(efx); return 0; fail: efx->port_initialized = false; mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->mac_lock); return rc; } /* Reset the NIC as transparently as possible. Do not reset the PHY * Note that the reset may fail, in which case the card will be left * in a most-probably-unusable state. /* Reset the NIC using the specified method. Note that the reset may * fail, in which case the card will be left in an unusable state. * * This function will sleep. You cannot reset from within an atomic * state; use efx_schedule_reset() instead. * * Grabs the rtnl_lock. * Caller must hold the rtnl_lock. */ static int efx_reset(struct efx_nic *efx) int efx_reset(struct efx_nic *efx, enum reset_type method) { enum reset_type method = efx->reset_pending; int rc = 0; /* Serialise with kernel interfaces */ rtnl_lock(); /* If we're not RUNNING then don't reset. Leave the reset_pending * flag set so that efx_pci_probe_main will be retried */ if (efx->state != STATE_RUNNING) { EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n"); goto out_unlock; } int rc, rc2; bool disabled; EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method)); Loading @@ -1814,7 +1805,7 @@ static int efx_reset(struct efx_nic *efx) rc = efx->type->reset(efx, method); if (rc) { EFX_ERR(efx, "failed to reset hardware\n"); goto out_disable; goto out; } /* Allow resets to be rescheduled. */ Loading @@ -1826,25 +1817,22 @@ static int efx_reset(struct efx_nic *efx) * can respond to requests. */ pci_set_master(efx->pci_dev); out: /* Leave device stopped if necessary */ if (method == RESET_TYPE_DISABLE) { efx_reset_up(efx, method, false); rc = -EIO; } else { rc = efx_reset_up(efx, method, true); disabled = rc || method == RESET_TYPE_DISABLE; rc2 = efx_reset_up(efx, method, !disabled); if (rc2) { disabled = true; if (!rc) rc = rc2; } out_disable: if (rc) { if (disabled) { EFX_ERR(efx, "has been disabled\n"); efx->state = STATE_DISABLED; dev_close(efx->net_dev); } else { EFX_LOG(efx, "reset complete\n"); } out_unlock: rtnl_unlock(); return rc; } Loading @@ -1853,9 +1841,19 @@ static int efx_reset(struct efx_nic *efx) */ static void efx_reset_work(struct work_struct *data) { struct efx_nic *nic = container_of(data, struct efx_nic, reset_work); struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); efx_reset(nic); /* If we're not RUNNING then don't reset. Leave the reset_pending * flag set so that efx_pci_probe_main will be retried */ if (efx->state != STATE_RUNNING) { EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n"); return; } rtnl_lock(); if (efx_reset(efx, efx->reset_pending)) dev_close(efx->net_dev); rtnl_unlock(); } void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) Loading
drivers/net/sfc/efx.h +1 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ extern int efx_ethtool_set_settings(struct net_device *net_dev, extern const struct ethtool_ops efx_ethtool_ops; /* Reset handling */ extern int efx_reset(struct efx_nic *efx, enum reset_type method); 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); Loading
drivers/net/sfc/ethtool.c +30 −0 Original line number Diff line number Diff line Loading @@ -754,6 +754,35 @@ static int efx_ethtool_set_wol(struct net_device *net_dev, return efx->type->set_wol(efx, wol->wolopts); } extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) { struct efx_nic *efx = netdev_priv(net_dev); enum reset_type method; enum { ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | ETH_RESET_OFFLOAD | ETH_RESET_MAC) }; /* Check for minimal reset flags */ if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE) return -EINVAL; *flags ^= ETH_RESET_EFX_INVISIBLE; method = RESET_TYPE_INVISIBLE; if (*flags & ETH_RESET_PHY) { *flags ^= ETH_RESET_PHY; method = RESET_TYPE_ALL; } if ((*flags & efx->type->reset_world_flags) == efx->type->reset_world_flags) { *flags ^= efx->type->reset_world_flags; method = RESET_TYPE_WORLD; } return efx_reset(efx, method); } const struct ethtool_ops efx_ethtool_ops = { .get_settings = efx_ethtool_get_settings, .set_settings = efx_ethtool_set_settings, Loading Loading @@ -784,4 +813,5 @@ const struct ethtool_ops efx_ethtool_ops = { .get_ethtool_stats = efx_ethtool_get_stats, .get_wol = efx_ethtool_get_wol, .set_wol = efx_ethtool_set_wol, .reset = efx_ethtool_reset, };
drivers/net/sfc/falcon.c +2 −0 Original line number Diff line number Diff line Loading @@ -3305,6 +3305,7 @@ struct efx_nic_type falcon_a1_nic_type = { .phys_addr_channels = 4, .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .reset_world_flags = ETH_RESET_IRQ, }; struct efx_nic_type falcon_b0_nic_type = { Loading Loading @@ -3348,5 +3349,6 @@ struct efx_nic_type falcon_b0_nic_type = { * channels */ .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .reset_world_flags = ETH_RESET_IRQ, };
drivers/net/sfc/net_driver.h +3 −0 Original line number Diff line number Diff line Loading @@ -880,6 +880,8 @@ static inline const char *efx_dev_name(struct efx_nic *efx) * descriptors * @tx_dc_base: Base address in SRAM of TX queue descriptor caches * @rx_dc_base: Base address in SRAM of RX queue descriptor caches * @reset_world_flags: Flags for additional components covered by * reset method RESET_TYPE_WORLD */ struct efx_nic_type { int (*probe)(struct efx_nic *efx); Loading Loading @@ -915,6 +917,7 @@ struct efx_nic_type { unsigned int phys_addr_channels; unsigned int tx_dc_base; unsigned int rx_dc_base; u32 reset_world_flags; }; /************************************************************************** Loading