From ff30cb6b59f429c0d9e398d2af045af0d6960676 Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:02 +0000 Subject: i40evf: remove redundant code These functions are redundant and duplicate functionality found in i40evf_free_all_[tx|rx]_resources. Change-ID: Ia199908926d7a1a4b8247f75f89b5da24c9b149c Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 27 ------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index cabaf599f562..ee0db5900d52 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -946,30 +946,6 @@ static int i40evf_up_complete(struct i40evf_adapter *adapter) return 0; } -/** - * i40evf_clean_all_rx_rings - Free Rx Buffers for all queues - * @adapter: board private structure - **/ -static void i40evf_clean_all_rx_rings(struct i40evf_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_active_queues; i++) - i40evf_clean_rx_ring(adapter->rx_rings[i]); -} - -/** - * i40evf_clean_all_tx_rings - Free Tx Buffers for all queues - * @adapter: board private structure - **/ -static void i40evf_clean_all_tx_rings(struct i40evf_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_active_queues; i++) - i40evf_clean_tx_ring(adapter->tx_rings[i]); -} - /** * i40e_down - Shutdown the connection processing * @adapter: board private structure @@ -1008,9 +984,6 @@ void i40evf_down(struct i40evf_adapter *adapter) i40evf_napi_disable_all(adapter); netif_carrier_off(netdev); - - i40evf_clean_all_tx_rings(adapter); - i40evf_clean_all_rx_rings(adapter); } /** -- cgit v1.2.3 From d4f82fd36836f6c90771cd0ceb4dfe191569e2c6 Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:03 +0000 Subject: i40evf: Remove some scary log messages These messages may be triggered during normal init of the driver if the PF or FW take a long time to respond. There's nothing really wrong, so don't freak people out logging messages. If the communication channel really is dead, then we'll retry a few times and give up. This will log a different more scary message that should cause consternation. This allows the user to more easily detect a genuine failure. Change-ID: I6e2b758d4234a3a09c1015c82c8f2442a697cbdb Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 7 +------ drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c | 3 --- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index ee0db5900d52..6c73acf7d2d9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2026,12 +2026,8 @@ static void i40evf_init_task(struct work_struct *work) /* aq msg sent, awaiting reply */ err = i40evf_verify_api_ver(adapter); if (err) { - dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n", - err); - if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { - dev_info(&pdev->dev, "Resending request\n"); + if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) err = i40evf_send_api_ver(adapter); - } goto err; } err = i40evf_send_vf_config_msg(adapter); @@ -2054,7 +2050,6 @@ static void i40evf_init_task(struct work_struct *work) } err = i40evf_get_vf_config(adapter); if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { - dev_info(&pdev->dev, "Resending VF config request\n"); err = i40evf_send_vf_config_msg(adapter); goto err; } diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 5fde5a7f4591..3aeb633e6bc2 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -715,9 +715,6 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, } return; } - if (v_opcode != adapter->current_op) - dev_info(&adapter->pdev->dev, "Pending op is %d, received %d\n", - adapter->current_op, v_opcode); if (v_retval) { dev_err(&adapter->pdev->dev, "%s: PF returned error %d to our request %d\n", __func__, v_retval, v_opcode); -- cgit v1.2.3 From 53d0b3ae2590bbd15620ce905c05320ed9cfed1a Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:04 +0000 Subject: i40evf: refactor shutdown code If the VF driver is running in the host, the shutdown code is completely broken. We cannot wait in our down routine for the PF to respond to our requests, as its admin queue task will never run while we hold the lock. Instead, we schedule operations, then let the watchdog take care of shutting things down. If the driver is being removed, then wait in the remove routine until the watchdog is done before continuing. Change-ID: I93a58d17389e8d6b58f21e430b56ed7b4590b2c5 Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 29 ++++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 6c73acf7d2d9..d3392569485c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -958,6 +958,12 @@ void i40evf_down(struct i40evf_adapter *adapter) if (adapter->state == __I40EVF_DOWN) return; + while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, + &adapter->crit_section)) + usleep_range(500, 1000); + + i40evf_irq_disable(adapter); + /* remove all MAC filters */ list_for_each_entry(f, &adapter->mac_filter_list, list) { f->remove = true; @@ -968,22 +974,27 @@ void i40evf_down(struct i40evf_adapter *adapter) } if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) && adapter->state != __I40EVF_RESETTING) { - adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER; + /* cancel any current operation */ + adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN; + adapter->aq_pending = 0; + /* Schedule operations to close down the HW. Don't wait + * here for this to complete. The watchdog is still running + * and it will take care of this. + */ + adapter->aq_required = I40EVF_FLAG_AQ_DEL_MAC_FILTER; adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; - /* disable receives */ adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES; - mod_timer_pending(&adapter->watchdog_timer, jiffies + 1); - msleep(20); } netif_tx_disable(netdev); netif_tx_stop_all_queues(netdev); - i40evf_irq_disable(adapter); - i40evf_napi_disable_all(adapter); + msleep(20); + netif_carrier_off(netdev); + clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); } /** @@ -2408,6 +2419,7 @@ static void i40evf_remove(struct pci_dev *pdev) struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_mac_filter *f, *ftmp; struct i40e_hw *hw = &adapter->hw; + int count = 50; cancel_delayed_work_sync(&adapter->init_task); cancel_work_sync(&adapter->reset_task); @@ -2416,6 +2428,11 @@ static void i40evf_remove(struct pci_dev *pdev) unregister_netdev(netdev); adapter->netdev_registered = false; } + while (count-- && adapter->aq_required) + msleep(50); + + if (count < 0) + dev_err(&pdev->dev, "Timed out waiting for PF driver.\n"); adapter->state = __I40EVF_REMOVE; if (adapter->msix_entries) { -- cgit v1.2.3 From 37dfdf373ce98a7b9fe99478bc40ffaef2ea5eee Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:05 +0000 Subject: i40evf: remove leftover VLAN filters If we're using VLANs and communications with the PF fail during shutdown, we will leak memory because not all of the VLAN filters will be removed. To eliminate this possibility, go through the list again right before the module is removed and delete any leftover entries. Change-ID: Id3b5315c47ca0a61ae123a96ff345d010bc41aed Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index d3392569485c..994ae4e782d4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2462,6 +2462,10 @@ static void i40evf_remove(struct pci_dev *pdev) list_del(&f->list); kfree(f); } + list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { + list_del(&f->list); + kfree(f); + } free_netdev(netdev); -- cgit v1.2.3 From 4870e176aada5c214d2224a8596465a0f7fbab3d Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:06 +0000 Subject: i40evf: don't fire traffic IRQs when the interface is down There is always a possibility that MSI-X interrupts can get lost. To keep this problem from stalling the driver, we fire all of our MSI-X vectors during the watchdog routine. However, we should not fire the traffic vectors when the interface is closed. In this case, just fire vector 0, which is used for admin queue events. As a result, we do not enable the interrupt cause for vector 0. This can cause the admin queue handler to be called reentrantly, which causes a scary "critical section violation" message to be logged, even though no real damage is done. Change-ID: Ic43a5184708ab2cb9a23fca7dedd808a46717795 Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 994ae4e782d4..c960ef5007cf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1385,11 +1385,14 @@ static void i40evf_watchdog_task(struct work_struct *work) if (adapter->state == __I40EVF_RUNNING) i40evf_request_stats(adapter); - - i40evf_irq_enable(adapter, true); - i40evf_fire_sw_int(adapter, 0xFF); - watchdog_done: + if (adapter->state == __I40EVF_RUNNING) { + i40evf_irq_enable_queues(adapter, ~0); + i40evf_fire_sw_int(adapter, 0xFF); + } else { + i40evf_fire_sw_int(adapter, 0x1); + } + clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); restart_watchdog: if (adapter->state == __I40EVF_REMOVE) -- cgit v1.2.3 From 7235448c9d90ca221587178e9b468839b2724440 Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:07 +0000 Subject: i40evf: enable interrupt 0 appropriately Don't enable vector 0 in the ISR, just schedule the adminq task and let it enable the vector. This prevents the task from being called reentrantly. Make sure that the vector is enabled on all exit paths of the adminq task, including error exits. Change-ID: I53f3d14f91ed7a9e90291ea41c681122a5eca5b5 Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index c960ef5007cf..e2311affdfe2 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -313,10 +313,6 @@ static irqreturn_t i40evf_msix_aq(int irq, void *data) val = val | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK; wr32(hw, I40E_VFINT_DYN_CTL01, val); - /* re-enable interrupt causes */ - wr32(hw, I40E_VFINT_ICR0_ENA1, ena_mask); - wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK); - /* schedule work on the private workqueue */ schedule_work(&adapter->adminq_task); @@ -1620,12 +1616,12 @@ static void i40evf_adminq_task(struct work_struct *work) u16 pending; if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) - return; + goto out; event.buf_len = I40EVF_MAX_AQ_BUF_SIZE; event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); if (!event.msg_buf) - return; + goto out; v_msg = (struct i40e_virtchnl_msg *)&event.desc; do { @@ -1675,10 +1671,10 @@ static void i40evf_adminq_task(struct work_struct *work) if (oldval != val) wr32(hw, hw->aq.asq.len, val); + kfree(event.msg_buf); +out: /* re-enable Admin queue interrupt cause */ i40evf_misc_irq_enable(adapter); - - kfree(event.msg_buf); } /** -- cgit v1.2.3 From 0758e7cb5f61a61dffe814bc91ebb4ea8e5cc534 Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Tue, 9 Dec 2014 08:53:08 +0000 Subject: i40evf: kick a stalled admin queue On some versions of the firmware, the VF admin send queue may become stalled. In this case, the easiest solution is to just place another descriptor on the queue; the firmware will then process both requests. The early init code already accounts for this, but the runtime code does not. In the watchdog task, check for the stall condition, and if it's found, send our API version to the PF. When the PF replies, just ignore the reply. Change-ID: I380d78185a4f284d649c44d263e648afc9b4d50c Signed-off-by: Mitch Williams Acked-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 7 ++++++- drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index e2311affdfe2..21ccbe8b6d13 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1336,8 +1336,13 @@ static void i40evf_watchdog_task(struct work_struct *work) /* Process admin queue tasks. After init, everything gets done * here so we don't race on the admin queue. */ - if (adapter->aq_pending) + if (adapter->aq_pending) { + if (!i40evf_asq_done(hw)) { + dev_dbg(&adapter->pdev->dev, "Admin queue timeout\n"); + i40evf_send_api_ver(adapter); + } goto watchdog_done; + } if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) { i40evf_map_queues(adapter); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 3aeb633e6bc2..3f0c85ecbca6 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -720,6 +720,9 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, __func__, v_retval, v_opcode); } switch (v_opcode) { + case I40E_VIRTCHNL_OP_VERSION: + /* no action, but also not an error */ + break; case I40E_VIRTCHNL_OP_GET_STATS: { struct i40e_eth_stats *stats = (struct i40e_eth_stats *)msg; -- cgit v1.2.3 From 65b206d24e52d539e2e0f96e2f5cf3404bf9ce26 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 11 Dec 2014 07:06:41 +0000 Subject: i40e/i40evf: Bump i40e/i40evf versions Bump i40e to 1.2.5 and i40evf to 1.0.7. Change-ID: I622556829056e3ed42d3b9d285fc5ffb693b21cc Signed-off-by: Catherine Sullivan Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4d1fe5689537..c3a353dd524e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 2 -#define DRV_VERSION_BUILD 2 +#define DRV_VERSION_BUILD 5 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 21ccbe8b6d13..a4920328438d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -36,7 +36,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.0.6" +#define DRV_VERSION "1.0.7" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2014 Intel Corporation."; -- cgit v1.2.3 From 300c34c13edf9c4d6d643e2b92860a6d9d0d0498 Mon Sep 17 00:00:00 2001 From: Sravanthi Tangeda Date: Sun, 14 Dec 2014 01:55:17 +0000 Subject: i40e/i40evf: Bump i40e and i40evf versions Bump i40e to 1.2.6 and i40evf to 1.2.0 version. Change-ID: Ice127eee3a5a5d1b8765d83cff8c30f9f3b1bc32 Signed-off-by: Sravanthi Tangeda Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f1256f96944d..e774a23901f9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 2 -#define DRV_VERSION_BUILD 5 +#define DRV_VERSION_BUILD 6 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index a4920328438d..f946aac1df71 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -36,7 +36,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.0.7" +#define DRV_VERSION "1.2.0" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2014 Intel Corporation."; -- cgit v1.2.3 From f4a718810cf73fa55c85d253634d4a1f9464f6e7 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 9 Jan 2015 11:18:16 +0000 Subject: i40evf: reset on module unload When the module is being unloaded, don't wait for the PF to politely handle all of our admin queue requests, as that might take forever with a lot of VFs enabled. Instead, just stop everything and request a VF reset. When the original shutdown code was written, VF resets were unreliable, so we avoided them. But with production hardware and firmware, and the 1.x PF driver, this is no longer the case. This fixes a potential multi-minute delay on driver unload, VF disable, or system shutdown. Change-ID: Ib43d6d860ef6b9b8f26e8dce0615a0302608c7d9 Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index f946aac1df71..cd71c47732b2 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2423,7 +2423,6 @@ static void i40evf_remove(struct pci_dev *pdev) struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40evf_mac_filter *f, *ftmp; struct i40e_hw *hw = &adapter->hw; - int count = 50; cancel_delayed_work_sync(&adapter->init_task); cancel_work_sync(&adapter->reset_task); @@ -2432,12 +2431,18 @@ static void i40evf_remove(struct pci_dev *pdev) unregister_netdev(netdev); adapter->netdev_registered = false; } - while (count-- && adapter->aq_required) - msleep(50); - if (count < 0) - dev_err(&pdev->dev, "Timed out waiting for PF driver.\n"); + /* Shut down all the garbage mashers on the detention level */ adapter->state = __I40EVF_REMOVE; + adapter->aq_required = 0; + adapter->aq_pending = 0; + i40evf_request_reset(adapter); + msleep(20); + /* If the FW isn't responding, kick it once, but only once. */ + if (!i40evf_asq_done(hw)) { + i40evf_request_reset(adapter); + msleep(20); + } if (adapter->msix_entries) { i40evf_misc_irq_disable(adapter); -- cgit v1.2.3 From 8b011ebb5c371f8767e6e813a1aca3b7fc795f94 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 9 Jan 2015 11:18:17 +0000 Subject: i40evf: ignore bogus messages from FW Occasionally on shutdown, the FW will hand us a bunch of messages filled with zeros, which can cause us to spin trying to handle them. Just ignore these and get on with shutting down. Change-ID: I347e9648f7153ad5a7b7e0847b87f7aad5f3e0da Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index cd71c47732b2..38126f5d6fd9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1631,7 +1631,7 @@ static void i40evf_adminq_task(struct work_struct *work) v_msg = (struct i40e_virtchnl_msg *)&event.desc; do { ret = i40evf_clean_arq_element(hw, &event, &pending); - if (ret) + if (ret || !v_msg->v_opcode) break; /* No event to process or error cleaning ARQ */ i40evf_virtchnl_completion(adapter, v_msg->v_opcode, -- cgit v1.2.3 From 00293fdc4229e493556f8cca403305f3c2124743 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 9 Jan 2015 11:18:18 +0000 Subject: i40evf: stop the watchdog for shutdown Stop the watchdog during shutdown. Failing to do this causes a log full of admin queue errors and the occasional hang when the system is shut down. Change-ID: Ib2fd11213cca2fa589eb68577e86b1000c23c250 Signed-off-by: Mitch Williams Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 38126f5d6fd9..8d8c201c63c1 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2213,12 +2213,18 @@ err: static void i40evf_shutdown(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); + struct i40evf_adapter *adapter = netdev_priv(netdev); netif_device_detach(netdev); if (netif_running(netdev)) i40evf_close(netdev); + /* Prevent the watchdog from running. */ + adapter->state = __I40EVF_REMOVE; + adapter->aq_required = 0; + adapter->aq_pending = 0; + #ifdef CONFIG_PM pci_save_state(pdev); -- cgit v1.2.3