diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40evf/i40evf_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf_main.c | 112 |
1 files changed, 58 insertions, 54 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index cabaf599f562..8d8c201c63c1 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"; | |||
36 | static const char i40evf_driver_string[] = | 36 | static const char i40evf_driver_string[] = |
37 | "Intel(R) XL710/X710 Virtual Function Network Driver"; | 37 | "Intel(R) XL710/X710 Virtual Function Network Driver"; |
38 | 38 | ||
39 | #define DRV_VERSION "1.0.6" | 39 | #define DRV_VERSION "1.2.0" |
40 | const char i40evf_driver_version[] = DRV_VERSION; | 40 | const char i40evf_driver_version[] = DRV_VERSION; |
41 | static const char i40evf_copyright[] = | 41 | static const char i40evf_copyright[] = |
42 | "Copyright (c) 2013 - 2014 Intel Corporation."; | 42 | "Copyright (c) 2013 - 2014 Intel Corporation."; |
@@ -313,10 +313,6 @@ static irqreturn_t i40evf_msix_aq(int irq, void *data) | |||
313 | val = val | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK; | 313 | val = val | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK; |
314 | wr32(hw, I40E_VFINT_DYN_CTL01, val); | 314 | wr32(hw, I40E_VFINT_DYN_CTL01, val); |
315 | 315 | ||
316 | /* re-enable interrupt causes */ | ||
317 | wr32(hw, I40E_VFINT_ICR0_ENA1, ena_mask); | ||
318 | wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK); | ||
319 | |||
320 | /* schedule work on the private workqueue */ | 316 | /* schedule work on the private workqueue */ |
321 | schedule_work(&adapter->adminq_task); | 317 | schedule_work(&adapter->adminq_task); |
322 | 318 | ||
@@ -947,30 +943,6 @@ static int i40evf_up_complete(struct i40evf_adapter *adapter) | |||
947 | } | 943 | } |
948 | 944 | ||
949 | /** | 945 | /** |
950 | * i40evf_clean_all_rx_rings - Free Rx Buffers for all queues | ||
951 | * @adapter: board private structure | ||
952 | **/ | ||
953 | static void i40evf_clean_all_rx_rings(struct i40evf_adapter *adapter) | ||
954 | { | ||
955 | int i; | ||
956 | |||
957 | for (i = 0; i < adapter->num_active_queues; i++) | ||
958 | i40evf_clean_rx_ring(adapter->rx_rings[i]); | ||
959 | } | ||
960 | |||
961 | /** | ||
962 | * i40evf_clean_all_tx_rings - Free Tx Buffers for all queues | ||
963 | * @adapter: board private structure | ||
964 | **/ | ||
965 | static void i40evf_clean_all_tx_rings(struct i40evf_adapter *adapter) | ||
966 | { | ||
967 | int i; | ||
968 | |||
969 | for (i = 0; i < adapter->num_active_queues; i++) | ||
970 | i40evf_clean_tx_ring(adapter->tx_rings[i]); | ||
971 | } | ||
972 | |||
973 | /** | ||
974 | * i40e_down - Shutdown the connection processing | 946 | * i40e_down - Shutdown the connection processing |
975 | * @adapter: board private structure | 947 | * @adapter: board private structure |
976 | **/ | 948 | **/ |
@@ -982,6 +954,12 @@ void i40evf_down(struct i40evf_adapter *adapter) | |||
982 | if (adapter->state == __I40EVF_DOWN) | 954 | if (adapter->state == __I40EVF_DOWN) |
983 | return; | 955 | return; |
984 | 956 | ||
957 | while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, | ||
958 | &adapter->crit_section)) | ||
959 | usleep_range(500, 1000); | ||
960 | |||
961 | i40evf_irq_disable(adapter); | ||
962 | |||
985 | /* remove all MAC filters */ | 963 | /* remove all MAC filters */ |
986 | list_for_each_entry(f, &adapter->mac_filter_list, list) { | 964 | list_for_each_entry(f, &adapter->mac_filter_list, list) { |
987 | f->remove = true; | 965 | f->remove = true; |
@@ -992,25 +970,27 @@ void i40evf_down(struct i40evf_adapter *adapter) | |||
992 | } | 970 | } |
993 | if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) && | 971 | if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) && |
994 | adapter->state != __I40EVF_RESETTING) { | 972 | adapter->state != __I40EVF_RESETTING) { |
995 | adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER; | 973 | /* cancel any current operation */ |
974 | adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN; | ||
975 | adapter->aq_pending = 0; | ||
976 | /* Schedule operations to close down the HW. Don't wait | ||
977 | * here for this to complete. The watchdog is still running | ||
978 | * and it will take care of this. | ||
979 | */ | ||
980 | adapter->aq_required = I40EVF_FLAG_AQ_DEL_MAC_FILTER; | ||
996 | adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; | 981 | adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; |
997 | /* disable receives */ | ||
998 | adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES; | 982 | adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES; |
999 | mod_timer_pending(&adapter->watchdog_timer, jiffies + 1); | ||
1000 | msleep(20); | ||
1001 | } | 983 | } |
1002 | netif_tx_disable(netdev); | 984 | netif_tx_disable(netdev); |
1003 | 985 | ||
1004 | netif_tx_stop_all_queues(netdev); | 986 | netif_tx_stop_all_queues(netdev); |
1005 | 987 | ||
1006 | i40evf_irq_disable(adapter); | ||
1007 | |||
1008 | i40evf_napi_disable_all(adapter); | 988 | i40evf_napi_disable_all(adapter); |
1009 | 989 | ||
1010 | netif_carrier_off(netdev); | 990 | msleep(20); |
1011 | 991 | ||
1012 | i40evf_clean_all_tx_rings(adapter); | 992 | netif_carrier_off(netdev); |
1013 | i40evf_clean_all_rx_rings(adapter); | 993 | clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); |
1014 | } | 994 | } |
1015 | 995 | ||
1016 | /** | 996 | /** |
@@ -1356,8 +1336,13 @@ static void i40evf_watchdog_task(struct work_struct *work) | |||
1356 | /* Process admin queue tasks. After init, everything gets done | 1336 | /* Process admin queue tasks. After init, everything gets done |
1357 | * here so we don't race on the admin queue. | 1337 | * here so we don't race on the admin queue. |
1358 | */ | 1338 | */ |
1359 | if (adapter->aq_pending) | 1339 | if (adapter->aq_pending) { |
1340 | if (!i40evf_asq_done(hw)) { | ||
1341 | dev_dbg(&adapter->pdev->dev, "Admin queue timeout\n"); | ||
1342 | i40evf_send_api_ver(adapter); | ||
1343 | } | ||
1360 | goto watchdog_done; | 1344 | goto watchdog_done; |
1345 | } | ||
1361 | 1346 | ||
1362 | if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) { | 1347 | if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) { |
1363 | i40evf_map_queues(adapter); | 1348 | i40evf_map_queues(adapter); |
@@ -1401,11 +1386,14 @@ static void i40evf_watchdog_task(struct work_struct *work) | |||
1401 | 1386 | ||
1402 | if (adapter->state == __I40EVF_RUNNING) | 1387 | if (adapter->state == __I40EVF_RUNNING) |
1403 | i40evf_request_stats(adapter); | 1388 | i40evf_request_stats(adapter); |
1404 | |||
1405 | i40evf_irq_enable(adapter, true); | ||
1406 | i40evf_fire_sw_int(adapter, 0xFF); | ||
1407 | |||
1408 | watchdog_done: | 1389 | watchdog_done: |
1390 | if (adapter->state == __I40EVF_RUNNING) { | ||
1391 | i40evf_irq_enable_queues(adapter, ~0); | ||
1392 | i40evf_fire_sw_int(adapter, 0xFF); | ||
1393 | } else { | ||
1394 | i40evf_fire_sw_int(adapter, 0x1); | ||
1395 | } | ||
1396 | |||
1409 | clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); | 1397 | clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); |
1410 | restart_watchdog: | 1398 | restart_watchdog: |
1411 | if (adapter->state == __I40EVF_REMOVE) | 1399 | if (adapter->state == __I40EVF_REMOVE) |
@@ -1633,17 +1621,17 @@ static void i40evf_adminq_task(struct work_struct *work) | |||
1633 | u16 pending; | 1621 | u16 pending; |
1634 | 1622 | ||
1635 | if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) | 1623 | if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) |
1636 | return; | 1624 | goto out; |
1637 | 1625 | ||
1638 | event.buf_len = I40EVF_MAX_AQ_BUF_SIZE; | 1626 | event.buf_len = I40EVF_MAX_AQ_BUF_SIZE; |
1639 | event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); | 1627 | event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); |
1640 | if (!event.msg_buf) | 1628 | if (!event.msg_buf) |
1641 | return; | 1629 | goto out; |
1642 | 1630 | ||
1643 | v_msg = (struct i40e_virtchnl_msg *)&event.desc; | 1631 | v_msg = (struct i40e_virtchnl_msg *)&event.desc; |
1644 | do { | 1632 | do { |
1645 | ret = i40evf_clean_arq_element(hw, &event, &pending); | 1633 | ret = i40evf_clean_arq_element(hw, &event, &pending); |
1646 | if (ret) | 1634 | if (ret || !v_msg->v_opcode) |
1647 | break; /* No event to process or error cleaning ARQ */ | 1635 | break; /* No event to process or error cleaning ARQ */ |
1648 | 1636 | ||
1649 | i40evf_virtchnl_completion(adapter, v_msg->v_opcode, | 1637 | i40evf_virtchnl_completion(adapter, v_msg->v_opcode, |
@@ -1688,10 +1676,10 @@ static void i40evf_adminq_task(struct work_struct *work) | |||
1688 | if (oldval != val) | 1676 | if (oldval != val) |
1689 | wr32(hw, hw->aq.asq.len, val); | 1677 | wr32(hw, hw->aq.asq.len, val); |
1690 | 1678 | ||
1679 | kfree(event.msg_buf); | ||
1680 | out: | ||
1691 | /* re-enable Admin queue interrupt cause */ | 1681 | /* re-enable Admin queue interrupt cause */ |
1692 | i40evf_misc_irq_enable(adapter); | 1682 | i40evf_misc_irq_enable(adapter); |
1693 | |||
1694 | kfree(event.msg_buf); | ||
1695 | } | 1683 | } |
1696 | 1684 | ||
1697 | /** | 1685 | /** |
@@ -2053,12 +2041,8 @@ static void i40evf_init_task(struct work_struct *work) | |||
2053 | /* aq msg sent, awaiting reply */ | 2041 | /* aq msg sent, awaiting reply */ |
2054 | err = i40evf_verify_api_ver(adapter); | 2042 | err = i40evf_verify_api_ver(adapter); |
2055 | if (err) { | 2043 | if (err) { |
2056 | dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n", | 2044 | if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) |
2057 | err); | ||
2058 | if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { | ||
2059 | dev_info(&pdev->dev, "Resending request\n"); | ||
2060 | err = i40evf_send_api_ver(adapter); | 2045 | err = i40evf_send_api_ver(adapter); |
2061 | } | ||
2062 | goto err; | 2046 | goto err; |
2063 | } | 2047 | } |
2064 | err = i40evf_send_vf_config_msg(adapter); | 2048 | err = i40evf_send_vf_config_msg(adapter); |
@@ -2081,7 +2065,6 @@ static void i40evf_init_task(struct work_struct *work) | |||
2081 | } | 2065 | } |
2082 | err = i40evf_get_vf_config(adapter); | 2066 | err = i40evf_get_vf_config(adapter); |
2083 | if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { | 2067 | if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { |
2084 | dev_info(&pdev->dev, "Resending VF config request\n"); | ||
2085 | err = i40evf_send_vf_config_msg(adapter); | 2068 | err = i40evf_send_vf_config_msg(adapter); |
2086 | goto err; | 2069 | goto err; |
2087 | } | 2070 | } |
@@ -2230,12 +2213,18 @@ err: | |||
2230 | static void i40evf_shutdown(struct pci_dev *pdev) | 2213 | static void i40evf_shutdown(struct pci_dev *pdev) |
2231 | { | 2214 | { |
2232 | struct net_device *netdev = pci_get_drvdata(pdev); | 2215 | struct net_device *netdev = pci_get_drvdata(pdev); |
2216 | struct i40evf_adapter *adapter = netdev_priv(netdev); | ||
2233 | 2217 | ||
2234 | netif_device_detach(netdev); | 2218 | netif_device_detach(netdev); |
2235 | 2219 | ||
2236 | if (netif_running(netdev)) | 2220 | if (netif_running(netdev)) |
2237 | i40evf_close(netdev); | 2221 | i40evf_close(netdev); |
2238 | 2222 | ||
2223 | /* Prevent the watchdog from running. */ | ||
2224 | adapter->state = __I40EVF_REMOVE; | ||
2225 | adapter->aq_required = 0; | ||
2226 | adapter->aq_pending = 0; | ||
2227 | |||
2239 | #ifdef CONFIG_PM | 2228 | #ifdef CONFIG_PM |
2240 | pci_save_state(pdev); | 2229 | pci_save_state(pdev); |
2241 | 2230 | ||
@@ -2448,7 +2437,18 @@ static void i40evf_remove(struct pci_dev *pdev) | |||
2448 | unregister_netdev(netdev); | 2437 | unregister_netdev(netdev); |
2449 | adapter->netdev_registered = false; | 2438 | adapter->netdev_registered = false; |
2450 | } | 2439 | } |
2440 | |||
2441 | /* Shut down all the garbage mashers on the detention level */ | ||
2451 | adapter->state = __I40EVF_REMOVE; | 2442 | adapter->state = __I40EVF_REMOVE; |
2443 | adapter->aq_required = 0; | ||
2444 | adapter->aq_pending = 0; | ||
2445 | i40evf_request_reset(adapter); | ||
2446 | msleep(20); | ||
2447 | /* If the FW isn't responding, kick it once, but only once. */ | ||
2448 | if (!i40evf_asq_done(hw)) { | ||
2449 | i40evf_request_reset(adapter); | ||
2450 | msleep(20); | ||
2451 | } | ||
2452 | 2452 | ||
2453 | if (adapter->msix_entries) { | 2453 | if (adapter->msix_entries) { |
2454 | i40evf_misc_irq_disable(adapter); | 2454 | i40evf_misc_irq_disable(adapter); |
@@ -2477,6 +2477,10 @@ static void i40evf_remove(struct pci_dev *pdev) | |||
2477 | list_del(&f->list); | 2477 | list_del(&f->list); |
2478 | kfree(f); | 2478 | kfree(f); |
2479 | } | 2479 | } |
2480 | list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { | ||
2481 | list_del(&f->list); | ||
2482 | kfree(f); | ||
2483 | } | ||
2480 | 2484 | ||
2481 | free_netdev(netdev); | 2485 | free_netdev(netdev); |
2482 | 2486 | ||