aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel
diff options
context:
space:
mode:
authorMitch Williams <mitch.a.williams@intel.com>2014-08-01 16:27:14 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-02 22:41:15 -0400
commit6ba36a246ef58100ff3f31b0738e317cfab1f240 (patch)
tree4562184f83685780216c78940ec372ff53fd1520 /drivers/net/ethernet/intel
parentd31944d6f0872ba9536501c4850dfb20dea5bf64 (diff)
i40evf: fix memory leak on unused interfaces
If the driver is loaded and then unloaded before the interface is brought up, then it will allocate a MAC filter entry and never free it. To fix this, on unload, run through the mac filter list and free all the entries. We also do this during reset recovery when the driver cannot contact the PF and needs to shut down completely. Change-ID: I15fabd67eb4a1bfc57605a7db60d0b5d819839db Signed-off-by: Mitch Williams <mitch.a.williams@intel.com> Tested-by: Sibai Li <sibai.li@intel.com> Signed-off-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 0c4f7baffad6..e5679d82e0c0 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1527,6 +1527,9 @@ static void i40evf_reset_task(struct work_struct *work)
1527 msleep(I40EVF_RESET_WAIT_MS); 1527 msleep(I40EVF_RESET_WAIT_MS);
1528 } 1528 }
1529 if (i == I40EVF_RESET_WAIT_COUNT) { 1529 if (i == I40EVF_RESET_WAIT_COUNT) {
1530 struct i40evf_mac_filter *f, *ftmp;
1531 struct i40evf_vlan_filter *fv, *fvtmp;
1532
1530 /* reset never finished */ 1533 /* reset never finished */
1531 dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", 1534 dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
1532 rstat_val); 1535 rstat_val);
@@ -1539,6 +1542,19 @@ static void i40evf_reset_task(struct work_struct *work)
1539 i40evf_free_all_tx_resources(adapter); 1542 i40evf_free_all_tx_resources(adapter);
1540 i40evf_free_all_rx_resources(adapter); 1543 i40evf_free_all_rx_resources(adapter);
1541 } 1544 }
1545
1546 /* Delete all of the filters, both MAC and VLAN. */
1547 list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list,
1548 list) {
1549 list_del(&f->list);
1550 kfree(f);
1551 }
1552 list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list,
1553 list) {
1554 list_del(&fv->list);
1555 kfree(fv);
1556 }
1557
1542 i40evf_free_misc_irq(adapter); 1558 i40evf_free_misc_irq(adapter);
1543 i40evf_reset_interrupt_capability(adapter); 1559 i40evf_reset_interrupt_capability(adapter);
1544 i40evf_free_queues(adapter); 1560 i40evf_free_queues(adapter);
@@ -2415,6 +2431,7 @@ static void i40evf_remove(struct pci_dev *pdev)
2415{ 2431{
2416 struct net_device *netdev = pci_get_drvdata(pdev); 2432 struct net_device *netdev = pci_get_drvdata(pdev);
2417 struct i40evf_adapter *adapter = netdev_priv(netdev); 2433 struct i40evf_adapter *adapter = netdev_priv(netdev);
2434 struct i40evf_mac_filter *f, *ftmp;
2418 struct i40e_hw *hw = &adapter->hw; 2435 struct i40e_hw *hw = &adapter->hw;
2419 2436
2420 cancel_delayed_work_sync(&adapter->init_task); 2437 cancel_delayed_work_sync(&adapter->init_task);
@@ -2446,6 +2463,13 @@ static void i40evf_remove(struct pci_dev *pdev)
2446 2463
2447 i40evf_free_queues(adapter); 2464 i40evf_free_queues(adapter);
2448 kfree(adapter->vf_res); 2465 kfree(adapter->vf_res);
2466 /* If we got removed before an up/down sequence, we've got a filter
2467 * hanging out there that we need to get rid of.
2468 */
2469 list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
2470 list_del(&f->list);
2471 kfree(f);
2472 }
2449 2473
2450 free_netdev(netdev); 2474 free_netdev(netdev);
2451 2475