Commit 813cf9d1 authored by Jonathan Cooper's avatar Jonathan Cooper Committed by David S. Miller

sfc: Split STATE_READY in to STATE_NET_DOWN and STATE_NET_UP.

This patch splits the READY state in to NET_UP and NET_DOWN. This
is to prepare for future work to delay resource allocation until
interface up so that we can use resources more efficiently in
SRIOV environments, and also to lay the ground work for an extra
PROBED state where we don't create a network interface,
for VDPA operation.
Signed-off-by: default avatarJonathan Cooper <jonathan.s.cooper@amd.com>
Acked-by: default avatarMartin Habets <habetsm.xilinx@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent da8ff2a2
...@@ -96,6 +96,8 @@ static int ef100_net_stop(struct net_device *net_dev) ...@@ -96,6 +96,8 @@ static int ef100_net_stop(struct net_device *net_dev)
efx_mcdi_free_vis(efx); efx_mcdi_free_vis(efx);
efx_remove_interrupts(efx); efx_remove_interrupts(efx);
efx->state = STATE_NET_DOWN;
return 0; return 0;
} }
...@@ -172,6 +174,8 @@ static int ef100_net_open(struct net_device *net_dev) ...@@ -172,6 +174,8 @@ static int ef100_net_open(struct net_device *net_dev)
efx_link_status_changed(efx); efx_link_status_changed(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
efx->state = STATE_NET_UP;
return 0; return 0;
fail: fail:
...@@ -271,7 +275,7 @@ int ef100_register_netdev(struct efx_nic *efx) ...@@ -271,7 +275,7 @@ int ef100_register_netdev(struct efx_nic *efx)
/* Always start with carrier off; PHY events will detect the link */ /* Always start with carrier off; PHY events will detect the link */
netif_carrier_off(net_dev); netif_carrier_off(net_dev);
efx->state = STATE_READY; efx->state = STATE_NET_DOWN;
rtnl_unlock(); rtnl_unlock();
efx_init_mcdi_logging(efx); efx_init_mcdi_logging(efx);
......
...@@ -106,14 +106,6 @@ static int efx_xdp(struct net_device *dev, struct netdev_bpf *xdp); ...@@ -106,14 +106,6 @@ static int efx_xdp(struct net_device *dev, struct netdev_bpf *xdp);
static int efx_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **xdpfs, static int efx_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **xdpfs,
u32 flags); u32 flags);
#define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \
if ((efx->state == STATE_READY) || \
(efx->state == STATE_RECOVERY) || \
(efx->state == STATE_DISABLED)) \
ASSERT_RTNL(); \
} while (0)
/************************************************************************** /**************************************************************************
* *
* Port handling * Port handling
...@@ -378,6 +370,8 @@ static int efx_probe_all(struct efx_nic *efx) ...@@ -378,6 +370,8 @@ static int efx_probe_all(struct efx_nic *efx)
if (rc) if (rc)
goto fail5; goto fail5;
efx->state = STATE_NET_DOWN;
return 0; return 0;
fail5: fail5:
...@@ -544,6 +538,9 @@ int efx_net_open(struct net_device *net_dev) ...@@ -544,6 +538,9 @@ int efx_net_open(struct net_device *net_dev)
efx_start_all(efx); efx_start_all(efx);
if (efx->state == STATE_DISABLED || efx->reset_pending) if (efx->state == STATE_DISABLED || efx->reset_pending)
netif_device_detach(efx->net_dev); netif_device_detach(efx->net_dev);
else
efx->state = STATE_NET_UP;
efx_selftest_async_start(efx); efx_selftest_async_start(efx);
return 0; return 0;
} }
...@@ -720,8 +717,6 @@ static int efx_register_netdev(struct efx_nic *efx) ...@@ -720,8 +717,6 @@ static int efx_register_netdev(struct efx_nic *efx)
* already requested. If so, the NIC is probably hosed so we * already requested. If so, the NIC is probably hosed so we
* abort. * abort.
*/ */
efx->state = STATE_READY;
smp_mb(); /* ensure we change state before checking reset_pending */
if (efx->reset_pending) { if (efx->reset_pending) {
pci_err(efx->pci_dev, "aborting probe due to scheduled reset\n"); pci_err(efx->pci_dev, "aborting probe due to scheduled reset\n");
rc = -EIO; rc = -EIO;
...@@ -748,6 +743,8 @@ static int efx_register_netdev(struct efx_nic *efx) ...@@ -748,6 +743,8 @@ static int efx_register_netdev(struct efx_nic *efx)
efx_associate(efx); efx_associate(efx);
efx->state = STATE_NET_DOWN;
rtnl_unlock(); rtnl_unlock();
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
...@@ -845,7 +842,7 @@ static void efx_pci_remove_main(struct efx_nic *efx) ...@@ -845,7 +842,7 @@ static void efx_pci_remove_main(struct efx_nic *efx)
/* Flush reset_work. It can no longer be scheduled since we /* Flush reset_work. It can no longer be scheduled since we
* are not READY. * are not READY.
*/ */
BUG_ON(efx->state == STATE_READY); WARN_ON(efx_net_active(efx->state));
efx_flush_reset_workqueue(efx); efx_flush_reset_workqueue(efx);
efx_disable_interrupts(efx); efx_disable_interrupts(efx);
...@@ -1150,13 +1147,13 @@ static int efx_pm_freeze(struct device *dev) ...@@ -1150,13 +1147,13 @@ static int efx_pm_freeze(struct device *dev)
rtnl_lock(); rtnl_lock();
if (efx->state != STATE_DISABLED) { if (efx_net_active(efx->state)) {
efx->state = STATE_UNINIT;
efx_device_detach_sync(efx); efx_device_detach_sync(efx);
efx_stop_all(efx); efx_stop_all(efx);
efx_disable_interrupts(efx); efx_disable_interrupts(efx);
efx->state = efx_freeze(efx->state);
} }
rtnl_unlock(); rtnl_unlock();
...@@ -1171,7 +1168,7 @@ static int efx_pm_thaw(struct device *dev) ...@@ -1171,7 +1168,7 @@ static int efx_pm_thaw(struct device *dev)
rtnl_lock(); rtnl_lock();
if (efx->state != STATE_DISABLED) { if (efx_frozen(efx->state)) {
rc = efx_enable_interrupts(efx); rc = efx_enable_interrupts(efx);
if (rc) if (rc)
goto fail; goto fail;
...@@ -1184,7 +1181,7 @@ static int efx_pm_thaw(struct device *dev) ...@@ -1184,7 +1181,7 @@ static int efx_pm_thaw(struct device *dev)
efx_device_attach_if_not_resetting(efx); efx_device_attach_if_not_resetting(efx);
efx->state = STATE_READY; efx->state = efx_thaw(efx->state);
efx->type->resume_wol(efx); efx->type->resume_wol(efx);
} }
......
...@@ -898,7 +898,7 @@ static void efx_reset_work(struct work_struct *data) ...@@ -898,7 +898,7 @@ static void efx_reset_work(struct work_struct *data)
* have changed by now. Now that we have the RTNL lock, * have changed by now. Now that we have the RTNL lock,
* it cannot change again. * it cannot change again.
*/ */
if (efx->state == STATE_READY) if (efx_net_active(efx->state))
(void)efx_reset(efx, method); (void)efx_reset(efx, method);
rtnl_unlock(); rtnl_unlock();
...@@ -908,7 +908,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) ...@@ -908,7 +908,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
{ {
enum reset_type method; enum reset_type method;
if (efx->state == STATE_RECOVERY) { if (efx_recovering(efx->state)) {
netif_dbg(efx, drv, efx->net_dev, netif_dbg(efx, drv, efx->net_dev,
"recovering: skip scheduling %s reset\n", "recovering: skip scheduling %s reset\n",
RESET_TYPE(type)); RESET_TYPE(type));
...@@ -943,7 +943,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) ...@@ -943,7 +943,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
/* If we're not READY then just leave the flags set as the cue /* If we're not READY then just leave the flags set as the cue
* to abort probing or reschedule the reset later. * to abort probing or reschedule the reset later.
*/ */
if (READ_ONCE(efx->state) != STATE_READY) if (!efx_net_active(READ_ONCE(efx->state)))
return; return;
/* efx_process_channel() will no longer read events once a /* efx_process_channel() will no longer read events once a
...@@ -1217,7 +1217,7 @@ static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev, ...@@ -1217,7 +1217,7 @@ static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev,
rtnl_lock(); rtnl_lock();
if (efx->state != STATE_DISABLED) { if (efx->state != STATE_DISABLED) {
efx->state = STATE_RECOVERY; efx->state = efx_recover(efx->state);
efx->reset_pending = 0; efx->reset_pending = 0;
efx_device_detach_sync(efx); efx_device_detach_sync(efx);
...@@ -1271,7 +1271,7 @@ static void efx_io_resume(struct pci_dev *pdev) ...@@ -1271,7 +1271,7 @@ static void efx_io_resume(struct pci_dev *pdev)
netif_err(efx, hw, efx->net_dev, netif_err(efx, hw, efx->net_dev,
"efx_reset failed after PCI error (%d)\n", rc); "efx_reset failed after PCI error (%d)\n", rc);
} else { } else {
efx->state = STATE_READY; efx->state = efx_recovered(efx->state);
netif_dbg(efx, hw, efx->net_dev, netif_dbg(efx, hw, efx->net_dev,
"Done resetting and resuming IO after PCI error.\n"); "Done resetting and resuming IO after PCI error.\n");
} }
......
...@@ -45,9 +45,7 @@ int efx_reconfigure_port(struct efx_nic *efx); ...@@ -45,9 +45,7 @@ int efx_reconfigure_port(struct efx_nic *efx);
#define EFX_ASSERT_RESET_SERIALISED(efx) \ #define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \ do { \
if ((efx->state == STATE_READY) || \ if (efx->state != STATE_UNINIT) \
(efx->state == STATE_RECOVERY) || \
(efx->state == STATE_DISABLED)) \
ASSERT_RTNL(); \ ASSERT_RTNL(); \
} while (0) } while (0)
...@@ -64,7 +62,7 @@ void efx_port_dummy_op_void(struct efx_nic *efx); ...@@ -64,7 +62,7 @@ void efx_port_dummy_op_void(struct efx_nic *efx);
static inline int efx_check_disabled(struct efx_nic *efx) static inline int efx_check_disabled(struct efx_nic *efx)
{ {
if (efx->state == STATE_DISABLED || efx->state == STATE_RECOVERY) { if (efx->state == STATE_DISABLED || efx_recovering(efx->state)) {
netif_err(efx, drv, efx->net_dev, netif_err(efx, drv, efx->net_dev,
"device is disabled due to earlier errors\n"); "device is disabled due to earlier errors\n");
return -EIO; return -EIO;
......
...@@ -137,7 +137,7 @@ void efx_ethtool_self_test(struct net_device *net_dev, ...@@ -137,7 +137,7 @@ void efx_ethtool_self_test(struct net_device *net_dev,
if (!efx_tests) if (!efx_tests)
goto fail; goto fail;
if (efx->state != STATE_READY) { if (!efx_net_active(efx->state)) {
rc = -EBUSY; rc = -EBUSY;
goto out; goto out;
} }
......
...@@ -622,12 +622,54 @@ enum efx_int_mode { ...@@ -622,12 +622,54 @@ enum efx_int_mode {
#define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI) #define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
enum nic_state { enum nic_state {
STATE_UNINIT = 0, /* device being probed/removed or is frozen */ STATE_UNINIT = 0, /* device being probed/removed */
STATE_READY = 1, /* hardware ready and netdev registered */ STATE_NET_DOWN, /* hardware probed and netdev registered */
STATE_DISABLED = 2, /* device disabled due to hardware errors */ STATE_NET_UP, /* ready for traffic */
STATE_RECOVERY = 3, /* device recovering from PCI error */ STATE_DISABLED, /* device disabled due to hardware errors */
STATE_RECOVERY = 0x100,/* recovering from PCI error */
STATE_FROZEN = 0x200, /* frozen by power management */
}; };
static inline bool efx_net_active(enum nic_state state)
{
return state == STATE_NET_DOWN || state == STATE_NET_UP;
}
static inline bool efx_frozen(enum nic_state state)
{
return state & STATE_FROZEN;
}
static inline bool efx_recovering(enum nic_state state)
{
return state & STATE_RECOVERY;
}
static inline enum nic_state efx_freeze(enum nic_state state)
{
WARN_ON(!efx_net_active(state));
return state | STATE_FROZEN;
}
static inline enum nic_state efx_thaw(enum nic_state state)
{
WARN_ON(!efx_frozen(state));
return state & ~STATE_FROZEN;
}
static inline enum nic_state efx_recover(enum nic_state state)
{
WARN_ON(!efx_net_active(state));
return state | STATE_RECOVERY;
}
static inline enum nic_state efx_recovered(enum nic_state state)
{
WARN_ON(!efx_recovering(state));
return state & ~STATE_RECOVERY;
}
/* Forward declaration */ /* Forward declaration */
struct efx_nic; struct efx_nic;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment