i40evf: delay releasing rings
When the VF interface is closed, we cannot immediately free our rings and RX buffers, because the hardware hasn't yet stopped accessing this memory. This shows up as a panic or memory corruption when the device is brought down while under heavy stress. To fix this, delay releasing resources until we receive acknowledgment from the PF driver that the rings have indeed been stopped. Because of this delay, we also need to check to make sure that all of our admin queue requests have been handled before allowing the device to be opened. Change-ID: I44edd35529ce2fa2a9512437a3a8e6f14ed8ed63 Signed-off-by: Mitch Williams <mitch.a.williams@intel.com> Tested-by: Jim Young <james.m.young@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
ae24b4095c
commit
e284fc88df
|
@ -272,6 +272,8 @@ void i40evf_update_stats(struct i40evf_adapter *adapter);
|
|||
void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter);
|
||||
int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter);
|
||||
void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask);
|
||||
void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter);
|
||||
void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter);
|
||||
|
||||
void i40e_napi_add_all(struct i40evf_adapter *adapter);
|
||||
void i40e_napi_del_all(struct i40evf_adapter *adapter);
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include "i40e_prototype.h"
|
||||
static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter);
|
||||
static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter);
|
||||
static void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter);
|
||||
static void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter);
|
||||
static int i40evf_close(struct net_device *netdev);
|
||||
|
||||
char i40evf_driver_name[] = "i40evf";
|
||||
|
@ -1358,6 +1356,11 @@ static void i40evf_watchdog_task(struct work_struct *work)
|
|||
goto watchdog_done;
|
||||
}
|
||||
|
||||
if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_QUEUES) {
|
||||
i40evf_disable_queues(adapter);
|
||||
goto watchdog_done;
|
||||
}
|
||||
|
||||
if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) {
|
||||
i40evf_map_queues(adapter);
|
||||
goto watchdog_done;
|
||||
|
@ -1383,11 +1386,6 @@ static void i40evf_watchdog_task(struct work_struct *work)
|
|||
goto watchdog_done;
|
||||
}
|
||||
|
||||
if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_QUEUES) {
|
||||
i40evf_disable_queues(adapter);
|
||||
goto watchdog_done;
|
||||
}
|
||||
|
||||
if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_QUEUES) {
|
||||
i40evf_configure_queues(adapter);
|
||||
goto watchdog_done;
|
||||
|
@ -1724,7 +1722,7 @@ out:
|
|||
*
|
||||
* Free all transmit software resources
|
||||
**/
|
||||
static void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter)
|
||||
void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1794,7 +1792,7 @@ static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter)
|
|||
*
|
||||
* Free all receive software resources
|
||||
**/
|
||||
static void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter)
|
||||
void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1824,7 +1822,7 @@ static int i40evf_open(struct net_device *netdev)
|
|||
dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (adapter->state != __I40EVF_DOWN)
|
||||
if (adapter->state != __I40EVF_DOWN || adapter->aq_required)
|
||||
return -EBUSY;
|
||||
|
||||
/* allocate transmit descriptors */
|
||||
|
@ -1888,9 +1886,6 @@ static int i40evf_close(struct net_device *netdev)
|
|||
adapter->state = __I40EVF_DOWN;
|
||||
i40evf_free_traffic_irqs(adapter);
|
||||
|
||||
i40evf_free_all_tx_resources(adapter);
|
||||
i40evf_free_all_rx_resources(adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2504,6 +2499,8 @@ static void i40evf_remove(struct pci_dev *pdev)
|
|||
iounmap(hw->hw_addr);
|
||||
pci_release_regions(pdev);
|
||||
|
||||
i40evf_free_all_tx_resources(adapter);
|
||||
i40evf_free_all_rx_resources(adapter);
|
||||
i40evf_free_queues(adapter);
|
||||
kfree(adapter->vf_res);
|
||||
/* If we got removed before an up/down sequence, we've got a filter
|
||||
|
|
|
@ -761,6 +761,8 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
|
|||
break;
|
||||
case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
|
||||
adapter->aq_pending &= ~(I40EVF_FLAG_AQ_DISABLE_QUEUES);
|
||||
i40evf_free_all_tx_resources(adapter);
|
||||
i40evf_free_all_rx_resources(adapter);
|
||||
break;
|
||||
case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
|
||||
adapter->aq_pending &= ~(I40EVF_FLAG_AQ_CONFIGURE_QUEUES);
|
||||
|
|
Loading…
Reference in New Issue