Refactor several ixgbe driver operations to check whether the
netdev they operate on is enabled. This will allow the system
to get synchronized, for example, during the PCI resets.

Fixes: f7f37e7ff2b9 ("ixgbe: handle close/suspend race with 
netif_device_detach/present")
Signed-off-by: Sergey Temerkhanov <[email protected]>
Reviewed-by: Aleksandr Loktionov <[email protected]>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe.h      |  5 +++
 .../net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c   | 13 +++++--
 .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c  | 34 ++++++++++++-------
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c  |  4 +--
 5 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h 
b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index a5304390f975..bac3b85a1d63 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -955,6 +955,11 @@ extern char ixgbe_driver_name[];
 extern char ixgbe_default_device_descr[];
 #endif /* IXGBE_FCOE */
 
+static inline bool ixgbe_netif_running(struct net_device *netdev)
+{
+       return netif_running(netdev) && netif_device_present(netdev);
+}
+
 int ixgbe_open(struct net_device *netdev);
 int ixgbe_close(struct net_device *netdev);
 void ixgbe_up(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index 382d097e4b11..4420d3c32996 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -277,17 +277,23 @@ static void ixgbe_dcbnl_get_pfc_cfg(struct net_device 
*netdev, int priority,
 static void ixgbe_dcbnl_devreset(struct net_device *dev)
 {
        struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
+       bool running;
+
+       if (!netif_device_present(dev))
+               return;
+
+       running = netif_running(dev);
 
        while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
                usleep_range(1000, 2000);
 
-       if (netif_running(dev))
+       if (running)
                dev->netdev_ops->ndo_stop(dev);
 
        ixgbe_clear_interrupt_scheme(adapter);
        ixgbe_init_interrupt_scheme(adapter);
 
-       if (netif_running(dev))
+       if (running)
                dev->netdev_ops->ndo_open(dev);
 
        clear_bit(__IXGBE_RESETTING, &adapter->state);
@@ -515,6 +521,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
        if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
                return -EINVAL;
 
+       if (!netif_device_present(dev))
+               return -ENETDOWN;
+
        if (!adapter->ixgbe_ieee_ets) {
                adapter->ixgbe_ieee_ets = kmalloc_obj(struct ieee_ets);
                if (!adapter->ixgbe_ieee_ets)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 1e1db8435506..f6258d1276e3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -468,6 +468,9 @@ static int ixgbe_set_link_ksettings(struct net_device 
*netdev,
        u32 advertised, old;
        int err = 0;
 
+       if (!netif_device_present(netdev))
+               return -ENETDOWN;
+
        if ((hw->phy.media_type == ixgbe_media_type_copper) ||
            (hw->phy.multispeed_fiber)) {
                /*
@@ -578,9 +581,9 @@ static void ixgbe_set_pauseparam_finalize(struct net_device 
*netdev,
        /* If the thing changed then we'll update and use new autoneg. */
        if (memcmp(fc, &hw->fc, sizeof(*fc))) {
                hw->fc = *fc;
-               if (netif_running(netdev))
+               if (ixgbe_netif_running(netdev))
                        ixgbe_reinit_locked(adapter);
-               else
+               else if (netif_device_present(netdev))
                        ixgbe_reset(adapter);
        }
 }
@@ -1268,7 +1271,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
        while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
                usleep_range(1000, 2000);
 
-       if (!netif_running(adapter->netdev)) {
+       if (!ixgbe_netif_running(adapter->netdev)) {
                for (i = 0; i < adapter->num_tx_queues; i++)
                        adapter->tx_ring[i]->count = new_tx_count;
                for (i = 0; i < adapter->num_xdp_queues; i++)
@@ -2251,10 +2254,11 @@ static void ixgbe_diag_test(struct net_device *netdev,
                            struct ethtool_test *eth_test, u64 *data)
 {
        struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
-       bool if_running = netif_running(netdev);
+       bool if_running = ixgbe_netif_running(netdev);
 
-       if (ixgbe_removed(adapter->hw.hw_addr)) {
-               e_err(hw, "Adapter removed - test blocked\n");
+       if (ixgbe_removed(adapter->hw.hw_addr) ||
+           !netif_device_present(netdev)) {
+               e_err(hw, "Adapter removed or detached - test blocked\n");
                data[0] = 1;
                data[1] = 1;
                data[2] = 1;
@@ -2468,7 +2472,7 @@ static int ixgbe_nway_reset(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev);
 
-       if (netif_running(netdev))
+       if (ixgbe_netif_running(netdev))
                ixgbe_reinit_locked(adapter);
 
        return 0;
@@ -2652,7 +2656,8 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                else
                        /* rx only or mixed */
                        q_vector->itr = rx_itr_param;
-               ixgbe_write_eitr(q_vector);
+               if (netif_device_present(netdev))
+                       ixgbe_write_eitr(q_vector);
        }
 
        /*
@@ -3696,6 +3701,9 @@ static int ixgbe_set_eee_e610(struct net_device *netdev,
            kedata->eee_enabled)
                return -EOPNOTSUPP;
 
+       if (!netif_device_present(netdev))
+               return -ENETDOWN;
+
        hw->phy.eee_speeds_advertised = kedata->eee_enabled ?
                                        hw->phy.eee_speeds_supported : 0;
 
@@ -3711,9 +3719,9 @@ static int ixgbe_set_eee_e610(struct net_device *netdev,
        else
                adapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED;
 
-       if (netif_running(netdev))
+       if (ixgbe_netif_running(netdev))
                ixgbe_reinit_locked(adapter);
-       else
+       else if (netif_device_present(netdev))
                ixgbe_reset(adapter);
 
        return 0;
@@ -3795,9 +3803,9 @@ static int ixgbe_set_eee(struct net_device *netdev, 
struct ethtool_keee *edata)
        }
 
        /* reset link */
-       if (netif_running(netdev))
+       if (ixgbe_netif_running(netdev))
                ixgbe_reinit_locked(adapter);
-       else
+       else if (netif_device_present(netdev))
                ixgbe_reset(adapter);
 
        return 0;
@@ -3879,7 +3887,7 @@ static int ixgbe_set_priv_flags(struct net_device 
*netdev, u32 priv_flags)
                adapter->flags2 = flags2;
 
                /* reset interface to repopulate queues */
-               if (netif_running(netdev))
+               if (ixgbe_netif_running(netdev))
                        ixgbe_reinit_locked(adapter);
        }
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index a219590b3118..42d3594827f7 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7395,7 +7395,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, 
int new_mtu)
        /* must set new MTU before calling down or up */
        WRITE_ONCE(netdev->mtu, new_mtu);
 
-       if (netif_running(netdev))
+       if (ixgbe_netif_running(netdev))
                ixgbe_reinit_locked(adapter);
 
        return 0;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
index 89f96c463f02..02820982b202 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
@@ -39,7 +39,7 @@ static int ixgbe_xsk_pool_enable(struct ixgbe_adapter 
*adapter,
        if (err)
                return err;
 
-       if_running = netif_running(adapter->netdev) &&
+       if_running = ixgbe_netif_running(adapter->netdev) &&
                     ixgbe_enabled_xdp_adapter(adapter);
 
        if (if_running)
@@ -71,7 +71,7 @@ static int ixgbe_xsk_pool_disable(struct ixgbe_adapter 
*adapter, u16 qid)
        if (!pool)
                return -EINVAL;
 
-       if_running = netif_running(adapter->netdev) &&
+       if_running = ixgbe_netif_running(adapter->netdev) &&
                     ixgbe_enabled_xdp_adapter(adapter);
 
        if (if_running)
-- 
2.53.0

Reply via email to