Commit 2dad7b27 authored by Emil Tantilov's avatar Emil Tantilov Committed by Jeff Kirsher

ixgbevf: handle race between close and suspend on shutdown

When an interface is part of a namespace it is possible that
ixgbevf_close() may be called while ixgbevf_suspend() is running
which ends up in a double free WARN and/or a BUG in free_msi_irqs()

To handle this situation we extend the rtnl_lock() to protect the
call to netif_device_detach() and check for !netif_device_present()
to avoid entering close while in suspend.

Also added rtnl locks to ixgbevf_queue_reset_subtask().

CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarEmil Tantilov <emil.s.tantilov@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent f7f37e7f
...@@ -3242,6 +3242,9 @@ int ixgbevf_close(struct net_device *netdev) ...@@ -3242,6 +3242,9 @@ int ixgbevf_close(struct net_device *netdev)
{ {
struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbevf_adapter *adapter = netdev_priv(netdev);
if (!netif_device_present(netdev))
return 0;
ixgbevf_down(adapter); ixgbevf_down(adapter);
ixgbevf_free_irq(adapter); ixgbevf_free_irq(adapter);
...@@ -3268,6 +3271,8 @@ static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter) ...@@ -3268,6 +3271,8 @@ static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter)
* match packet buffer alignment. Unfortunately, the * match packet buffer alignment. Unfortunately, the
* hardware is not flexible enough to do this dynamically. * hardware is not flexible enough to do this dynamically.
*/ */
rtnl_lock();
if (netif_running(dev)) if (netif_running(dev))
ixgbevf_close(dev); ixgbevf_close(dev);
...@@ -3276,6 +3281,8 @@ static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter) ...@@ -3276,6 +3281,8 @@ static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter)
if (netif_running(dev)) if (netif_running(dev))
ixgbevf_open(dev); ixgbevf_open(dev);
rtnl_unlock();
} }
static void ixgbevf_tx_ctxtdesc(struct ixgbevf_ring *tx_ring, static void ixgbevf_tx_ctxtdesc(struct ixgbevf_ring *tx_ring,
...@@ -3796,17 +3803,17 @@ static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -3796,17 +3803,17 @@ static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state)
int retval = 0; int retval = 0;
#endif #endif
rtnl_lock();
netif_device_detach(netdev); netif_device_detach(netdev);
if (netif_running(netdev)) { if (netif_running(netdev)) {
rtnl_lock();
ixgbevf_down(adapter); ixgbevf_down(adapter);
ixgbevf_free_irq(adapter); ixgbevf_free_irq(adapter);
ixgbevf_free_all_tx_resources(adapter); ixgbevf_free_all_tx_resources(adapter);
ixgbevf_free_all_rx_resources(adapter); ixgbevf_free_all_rx_resources(adapter);
ixgbevf_clear_interrupt_scheme(adapter); ixgbevf_clear_interrupt_scheme(adapter);
rtnl_unlock();
} }
rtnl_unlock();
#ifdef CONFIG_PM #ifdef CONFIG_PM
retval = pci_save_state(pdev); retval = pci_save_state(pdev);
......
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