diff options
author | Sathya Perla <sathya.perla@emulex.com> | 2012-05-08 15:41:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-10 23:33:00 -0400 |
commit | 39f1d94d300a58eb3e9b851d077cada4e2fa9d46 (patch) | |
tree | 59e712ce3241535273ebef657b4bb74f1dfec34f /drivers/net/ethernet | |
parent | d301e3256866bfd3ae3093aeb43d3ca9570d758e (diff) |
be2net: avoid disabling sriov while VFs are assigned
Calling pci_disable_sriov() while VFs are assigned to VMs causes
kernel panic. This patch uses PCI_DEV_FLAGS_ASSIGNED bit state of the
VF's pci_dev to avoid this. Also, the unconditional function reset cmd
issued on a PF probe can delete the VF configuration for the
previously enabled VFs. A scratchpad register is now used to issue a
function reset only when needed (i.e., in a crash dump scenario.)
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_hw.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 199 |
3 files changed, 134 insertions, 89 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index c3ee9103ff4f..ecf1a81f26e2 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -313,6 +313,11 @@ struct be_vf_cfg { | |||
313 | u32 tx_rate; | 313 | u32 tx_rate; |
314 | }; | 314 | }; |
315 | 315 | ||
316 | enum vf_state { | ||
317 | ENABLED = 0, | ||
318 | ASSIGNED = 1 | ||
319 | }; | ||
320 | |||
316 | #define BE_FLAGS_LINK_STATUS_INIT 1 | 321 | #define BE_FLAGS_LINK_STATUS_INIT 1 |
317 | #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) | 322 | #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) |
318 | #define BE_UC_PMAC_COUNT 30 | 323 | #define BE_UC_PMAC_COUNT 30 |
@@ -403,8 +408,9 @@ struct be_adapter { | |||
403 | u32 flash_status; | 408 | u32 flash_status; |
404 | struct completion flash_compl; | 409 | struct completion flash_compl; |
405 | 410 | ||
406 | u32 num_vfs; | 411 | u32 num_vfs; /* Number of VFs provisioned by PF driver */ |
407 | u8 is_virtfn; | 412 | u32 dev_num_vfs; /* Number of VFs supported by HW */ |
413 | u8 virtfn; | ||
408 | struct be_vf_cfg *vf_cfg; | 414 | struct be_vf_cfg *vf_cfg; |
409 | bool be3_native; | 415 | bool be3_native; |
410 | u32 sli_family; | 416 | u32 sli_family; |
@@ -417,8 +423,10 @@ struct be_adapter { | |||
417 | u32 uc_macs; /* Count of secondary UC MAC programmed */ | 423 | u32 uc_macs; /* Count of secondary UC MAC programmed */ |
418 | }; | 424 | }; |
419 | 425 | ||
420 | #define be_physfn(adapter) (!adapter->is_virtfn) | 426 | #define be_physfn(adapter) (!adapter->virtfn) |
421 | #define sriov_enabled(adapter) (adapter->num_vfs > 0) | 427 | #define sriov_enabled(adapter) (adapter->num_vfs > 0) |
428 | #define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \ | ||
429 | be_physfn(adapter)) | ||
422 | #define for_all_vfs(adapter, vf_cfg, i) \ | 430 | #define for_all_vfs(adapter, vf_cfg, i) \ |
423 | for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ | 431 | for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ |
424 | i++, vf_cfg++) | 432 | i++, vf_cfg++) |
@@ -547,14 +555,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) | |||
547 | return val; | 555 | return val; |
548 | } | 556 | } |
549 | 557 | ||
550 | static inline void be_check_sriov_fn_type(struct be_adapter *adapter) | ||
551 | { | ||
552 | u32 sli_intf; | ||
553 | |||
554 | pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); | ||
555 | adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; | ||
556 | } | ||
557 | |||
558 | static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) | 558 | static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) |
559 | { | 559 | { |
560 | u32 addr; | 560 | u32 addr; |
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 0949aa609164..f38b58c8dbba 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h | |||
@@ -58,6 +58,8 @@ | |||
58 | 58 | ||
59 | #define SLI_PORT_CONTROL_IP_MASK 0x08000000 | 59 | #define SLI_PORT_CONTROL_IP_MASK 0x08000000 |
60 | 60 | ||
61 | #define PCICFG_CUST_SCRATCHPAD_CSR 0x1EC | ||
62 | |||
61 | /********* Memory BAR register ************/ | 63 | /********* Memory BAR register ************/ |
62 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc | 64 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc |
63 | /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt | 65 | /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 6d5d30be0481..a01f73467532 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -1049,6 +1049,29 @@ static int be_set_vf_tx_rate(struct net_device *netdev, | |||
1049 | return status; | 1049 | return status; |
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | static int be_find_vfs(struct be_adapter *adapter, int vf_state) | ||
1053 | { | ||
1054 | struct pci_dev *dev, *pdev = adapter->pdev; | ||
1055 | int vfs = 0, assigned_vfs = 0, pos, vf_fn; | ||
1056 | u16 offset, stride; | ||
1057 | |||
1058 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); | ||
1059 | pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset); | ||
1060 | pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride); | ||
1061 | |||
1062 | dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL); | ||
1063 | while (dev) { | ||
1064 | vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF; | ||
1065 | if (dev->is_virtfn && dev->devfn == vf_fn) { | ||
1066 | vfs++; | ||
1067 | if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) | ||
1068 | assigned_vfs++; | ||
1069 | } | ||
1070 | dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev); | ||
1071 | } | ||
1072 | return (vf_state == ASSIGNED) ? assigned_vfs : vfs; | ||
1073 | } | ||
1074 | |||
1052 | static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) | 1075 | static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) |
1053 | { | 1076 | { |
1054 | struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); | 1077 | struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); |
@@ -1789,9 +1812,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) | |||
1789 | 1812 | ||
1790 | static int be_num_txqs_want(struct be_adapter *adapter) | 1813 | static int be_num_txqs_want(struct be_adapter *adapter) |
1791 | { | 1814 | { |
1792 | if (sriov_enabled(adapter) || be_is_mc(adapter) || | 1815 | if (sriov_want(adapter) || be_is_mc(adapter) || |
1793 | lancer_chip(adapter) || !be_physfn(adapter) || | 1816 | lancer_chip(adapter) || !be_physfn(adapter) || |
1794 | adapter->generation == BE_GEN2) | 1817 | adapter->generation == BE_GEN2) |
1795 | return 1; | 1818 | return 1; |
1796 | else | 1819 | else |
1797 | return MAX_TX_QS; | 1820 | return MAX_TX_QS; |
@@ -2118,7 +2141,7 @@ static void be_msix_disable(struct be_adapter *adapter) | |||
2118 | static uint be_num_rss_want(struct be_adapter *adapter) | 2141 | static uint be_num_rss_want(struct be_adapter *adapter) |
2119 | { | 2142 | { |
2120 | if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && | 2143 | if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && |
2121 | adapter->num_vfs == 0 && be_physfn(adapter) && | 2144 | !sriov_want(adapter) && be_physfn(adapter) && |
2122 | !be_is_mc(adapter)) | 2145 | !be_is_mc(adapter)) |
2123 | return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; | 2146 | return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; |
2124 | else | 2147 | else |
@@ -2152,53 +2175,6 @@ done: | |||
2152 | return; | 2175 | return; |
2153 | } | 2176 | } |
2154 | 2177 | ||
2155 | static int be_sriov_enable(struct be_adapter *adapter) | ||
2156 | { | ||
2157 | be_check_sriov_fn_type(adapter); | ||
2158 | |||
2159 | #ifdef CONFIG_PCI_IOV | ||
2160 | if (be_physfn(adapter) && num_vfs) { | ||
2161 | int status, pos; | ||
2162 | u16 dev_vfs; | ||
2163 | |||
2164 | pos = pci_find_ext_capability(adapter->pdev, | ||
2165 | PCI_EXT_CAP_ID_SRIOV); | ||
2166 | pci_read_config_word(adapter->pdev, | ||
2167 | pos + PCI_SRIOV_TOTAL_VF, &dev_vfs); | ||
2168 | |||
2169 | adapter->num_vfs = min_t(u16, num_vfs, dev_vfs); | ||
2170 | if (adapter->num_vfs != num_vfs) | ||
2171 | dev_info(&adapter->pdev->dev, | ||
2172 | "Device supports %d VFs and not %d\n", | ||
2173 | adapter->num_vfs, num_vfs); | ||
2174 | |||
2175 | status = pci_enable_sriov(adapter->pdev, adapter->num_vfs); | ||
2176 | if (status) | ||
2177 | adapter->num_vfs = 0; | ||
2178 | |||
2179 | if (adapter->num_vfs) { | ||
2180 | adapter->vf_cfg = kcalloc(num_vfs, | ||
2181 | sizeof(struct be_vf_cfg), | ||
2182 | GFP_KERNEL); | ||
2183 | if (!adapter->vf_cfg) | ||
2184 | return -ENOMEM; | ||
2185 | } | ||
2186 | } | ||
2187 | #endif | ||
2188 | return 0; | ||
2189 | } | ||
2190 | |||
2191 | static void be_sriov_disable(struct be_adapter *adapter) | ||
2192 | { | ||
2193 | #ifdef CONFIG_PCI_IOV | ||
2194 | if (sriov_enabled(adapter)) { | ||
2195 | pci_disable_sriov(adapter->pdev); | ||
2196 | kfree(adapter->vf_cfg); | ||
2197 | adapter->num_vfs = 0; | ||
2198 | } | ||
2199 | #endif | ||
2200 | } | ||
2201 | |||
2202 | static inline int be_msix_vec_get(struct be_adapter *adapter, | 2178 | static inline int be_msix_vec_get(struct be_adapter *adapter, |
2203 | struct be_eq_obj *eqo) | 2179 | struct be_eq_obj *eqo) |
2204 | { | 2180 | { |
@@ -2500,6 +2476,11 @@ static void be_vf_clear(struct be_adapter *adapter) | |||
2500 | struct be_vf_cfg *vf_cfg; | 2476 | struct be_vf_cfg *vf_cfg; |
2501 | u32 vf; | 2477 | u32 vf; |
2502 | 2478 | ||
2479 | if (be_find_vfs(adapter, ASSIGNED)) { | ||
2480 | dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n"); | ||
2481 | goto done; | ||
2482 | } | ||
2483 | |||
2503 | for_all_vfs(adapter, vf_cfg, vf) { | 2484 | for_all_vfs(adapter, vf_cfg, vf) { |
2504 | if (lancer_chip(adapter)) | 2485 | if (lancer_chip(adapter)) |
2505 | be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); | 2486 | be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); |
@@ -2509,6 +2490,10 @@ static void be_vf_clear(struct be_adapter *adapter) | |||
2509 | 2490 | ||
2510 | be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); | 2491 | be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); |
2511 | } | 2492 | } |
2493 | pci_disable_sriov(adapter->pdev); | ||
2494 | done: | ||
2495 | kfree(adapter->vf_cfg); | ||
2496 | adapter->num_vfs = 0; | ||
2512 | } | 2497 | } |
2513 | 2498 | ||
2514 | static int be_clear(struct be_adapter *adapter) | 2499 | static int be_clear(struct be_adapter *adapter) |
@@ -2538,29 +2523,60 @@ static int be_clear(struct be_adapter *adapter) | |||
2538 | be_cmd_fw_clean(adapter); | 2523 | be_cmd_fw_clean(adapter); |
2539 | 2524 | ||
2540 | be_msix_disable(adapter); | 2525 | be_msix_disable(adapter); |
2541 | kfree(adapter->pmac_id); | 2526 | pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0); |
2542 | return 0; | 2527 | return 0; |
2543 | } | 2528 | } |
2544 | 2529 | ||
2545 | static void be_vf_setup_init(struct be_adapter *adapter) | 2530 | static int be_vf_setup_init(struct be_adapter *adapter) |
2546 | { | 2531 | { |
2547 | struct be_vf_cfg *vf_cfg; | 2532 | struct be_vf_cfg *vf_cfg; |
2548 | int vf; | 2533 | int vf; |
2549 | 2534 | ||
2535 | adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg), | ||
2536 | GFP_KERNEL); | ||
2537 | if (!adapter->vf_cfg) | ||
2538 | return -ENOMEM; | ||
2539 | |||
2550 | for_all_vfs(adapter, vf_cfg, vf) { | 2540 | for_all_vfs(adapter, vf_cfg, vf) { |
2551 | vf_cfg->if_handle = -1; | 2541 | vf_cfg->if_handle = -1; |
2552 | vf_cfg->pmac_id = -1; | 2542 | vf_cfg->pmac_id = -1; |
2553 | } | 2543 | } |
2544 | return 0; | ||
2554 | } | 2545 | } |
2555 | 2546 | ||
2556 | static int be_vf_setup(struct be_adapter *adapter) | 2547 | static int be_vf_setup(struct be_adapter *adapter) |
2557 | { | 2548 | { |
2558 | struct be_vf_cfg *vf_cfg; | 2549 | struct be_vf_cfg *vf_cfg; |
2550 | struct device *dev = &adapter->pdev->dev; | ||
2559 | u32 cap_flags, en_flags, vf; | 2551 | u32 cap_flags, en_flags, vf; |
2560 | u16 def_vlan, lnk_speed; | 2552 | u16 def_vlan, lnk_speed; |
2561 | int status; | 2553 | int status, enabled_vfs; |
2554 | |||
2555 | enabled_vfs = be_find_vfs(adapter, ENABLED); | ||
2556 | if (enabled_vfs) { | ||
2557 | dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs); | ||
2558 | dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); | ||
2559 | return 0; | ||
2560 | } | ||
2562 | 2561 | ||
2563 | be_vf_setup_init(adapter); | 2562 | if (num_vfs > adapter->dev_num_vfs) { |
2563 | dev_warn(dev, "Device supports %d VFs and not %d\n", | ||
2564 | adapter->dev_num_vfs, num_vfs); | ||
2565 | num_vfs = adapter->dev_num_vfs; | ||
2566 | } | ||
2567 | |||
2568 | status = pci_enable_sriov(adapter->pdev, num_vfs); | ||
2569 | if (!status) { | ||
2570 | adapter->num_vfs = num_vfs; | ||
2571 | } else { | ||
2572 | /* Platform doesn't support SRIOV though device supports it */ | ||
2573 | dev_warn(dev, "SRIOV enable failed\n"); | ||
2574 | return 0; | ||
2575 | } | ||
2576 | |||
2577 | status = be_vf_setup_init(adapter); | ||
2578 | if (status) | ||
2579 | goto err; | ||
2564 | 2580 | ||
2565 | cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | | 2581 | cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | |
2566 | BE_IF_FLAGS_MULTICAST; | 2582 | BE_IF_FLAGS_MULTICAST; |
@@ -2571,9 +2587,11 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
2571 | goto err; | 2587 | goto err; |
2572 | } | 2588 | } |
2573 | 2589 | ||
2574 | status = be_vf_eth_addr_config(adapter); | 2590 | if (!enabled_vfs) { |
2575 | if (status) | 2591 | status = be_vf_eth_addr_config(adapter); |
2576 | goto err; | 2592 | if (status) |
2593 | goto err; | ||
2594 | } | ||
2577 | 2595 | ||
2578 | for_all_vfs(adapter, vf_cfg, vf) { | 2596 | for_all_vfs(adapter, vf_cfg, vf) { |
2579 | status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, | 2597 | status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, |
@@ -2630,9 +2648,25 @@ do_none: | |||
2630 | return status; | 2648 | return status; |
2631 | } | 2649 | } |
2632 | 2650 | ||
2651 | /* Routine to query per function resource limits */ | ||
2652 | static int be_get_config(struct be_adapter *adapter) | ||
2653 | { | ||
2654 | int pos; | ||
2655 | u16 dev_num_vfs; | ||
2656 | |||
2657 | pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); | ||
2658 | if (pos) { | ||
2659 | pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, | ||
2660 | &dev_num_vfs); | ||
2661 | adapter->dev_num_vfs = dev_num_vfs; | ||
2662 | } | ||
2663 | return 0; | ||
2664 | } | ||
2665 | |||
2633 | static int be_setup(struct be_adapter *adapter) | 2666 | static int be_setup(struct be_adapter *adapter) |
2634 | { | 2667 | { |
2635 | struct net_device *netdev = adapter->netdev; | 2668 | struct net_device *netdev = adapter->netdev; |
2669 | struct device *dev = &adapter->pdev->dev; | ||
2636 | u32 cap_flags, en_flags; | 2670 | u32 cap_flags, en_flags; |
2637 | u32 tx_fc, rx_fc; | 2671 | u32 tx_fc, rx_fc; |
2638 | int status; | 2672 | int status; |
@@ -2640,6 +2674,8 @@ static int be_setup(struct be_adapter *adapter) | |||
2640 | 2674 | ||
2641 | be_setup_init(adapter); | 2675 | be_setup_init(adapter); |
2642 | 2676 | ||
2677 | be_get_config(adapter); | ||
2678 | |||
2643 | be_cmd_req_native_mode(adapter); | 2679 | be_cmd_req_native_mode(adapter); |
2644 | 2680 | ||
2645 | be_msix_enable(adapter); | 2681 | be_msix_enable(adapter); |
@@ -2718,10 +2754,11 @@ static int be_setup(struct be_adapter *adapter) | |||
2718 | 2754 | ||
2719 | pcie_set_readrq(adapter->pdev, 4096); | 2755 | pcie_set_readrq(adapter->pdev, 4096); |
2720 | 2756 | ||
2721 | if (sriov_enabled(adapter)) { | 2757 | if (be_physfn(adapter) && num_vfs) { |
2722 | status = be_vf_setup(adapter); | 2758 | if (adapter->dev_num_vfs) |
2723 | if (status) | 2759 | be_vf_setup(adapter); |
2724 | goto err; | 2760 | else |
2761 | dev_warn(dev, "device doesn't support SRIOV\n"); | ||
2725 | } | 2762 | } |
2726 | 2763 | ||
2727 | be_cmd_get_phy_info(adapter); | 2764 | be_cmd_get_phy_info(adapter); |
@@ -2731,6 +2768,7 @@ static int be_setup(struct be_adapter *adapter) | |||
2731 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); | 2768 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); |
2732 | adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; | 2769 | adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; |
2733 | 2770 | ||
2771 | pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1); | ||
2734 | return 0; | 2772 | return 0; |
2735 | err: | 2773 | err: |
2736 | be_clear(adapter); | 2774 | be_clear(adapter); |
@@ -3352,8 +3390,6 @@ static void __devexit be_remove(struct pci_dev *pdev) | |||
3352 | 3390 | ||
3353 | be_ctrl_cleanup(adapter); | 3391 | be_ctrl_cleanup(adapter); |
3354 | 3392 | ||
3355 | be_sriov_disable(adapter); | ||
3356 | |||
3357 | pci_set_drvdata(pdev, NULL); | 3393 | pci_set_drvdata(pdev, NULL); |
3358 | pci_release_regions(pdev); | 3394 | pci_release_regions(pdev); |
3359 | pci_disable_device(pdev); | 3395 | pci_disable_device(pdev); |
@@ -3367,7 +3403,7 @@ bool be_is_wol_supported(struct be_adapter *adapter) | |||
3367 | !be_is_wol_excluded(adapter)) ? true : false; | 3403 | !be_is_wol_excluded(adapter)) ? true : false; |
3368 | } | 3404 | } |
3369 | 3405 | ||
3370 | static int be_get_config(struct be_adapter *adapter) | 3406 | static int be_get_initial_config(struct be_adapter *adapter) |
3371 | { | 3407 | { |
3372 | int status; | 3408 | int status; |
3373 | 3409 | ||
@@ -3410,7 +3446,7 @@ static int be_get_config(struct be_adapter *adapter) | |||
3410 | return 0; | 3446 | return 0; |
3411 | } | 3447 | } |
3412 | 3448 | ||
3413 | static int be_dev_family_check(struct be_adapter *adapter) | 3449 | static int be_dev_type_check(struct be_adapter *adapter) |
3414 | { | 3450 | { |
3415 | struct pci_dev *pdev = adapter->pdev; | 3451 | struct pci_dev *pdev = adapter->pdev; |
3416 | u32 sli_intf = 0, if_type; | 3452 | u32 sli_intf = 0, if_type; |
@@ -3443,6 +3479,9 @@ static int be_dev_family_check(struct be_adapter *adapter) | |||
3443 | default: | 3479 | default: |
3444 | adapter->generation = 0; | 3480 | adapter->generation = 0; |
3445 | } | 3481 | } |
3482 | |||
3483 | pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); | ||
3484 | adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; | ||
3446 | return 0; | 3485 | return 0; |
3447 | } | 3486 | } |
3448 | 3487 | ||
@@ -3586,6 +3625,14 @@ reschedule: | |||
3586 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); | 3625 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); |
3587 | } | 3626 | } |
3588 | 3627 | ||
3628 | static bool be_reset_required(struct be_adapter *adapter) | ||
3629 | { | ||
3630 | u32 reg; | ||
3631 | |||
3632 | pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, ®); | ||
3633 | return reg; | ||
3634 | } | ||
3635 | |||
3589 | static int __devinit be_probe(struct pci_dev *pdev, | 3636 | static int __devinit be_probe(struct pci_dev *pdev, |
3590 | const struct pci_device_id *pdev_id) | 3637 | const struct pci_device_id *pdev_id) |
3591 | { | 3638 | { |
@@ -3611,7 +3658,7 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3611 | adapter->pdev = pdev; | 3658 | adapter->pdev = pdev; |
3612 | pci_set_drvdata(pdev, adapter); | 3659 | pci_set_drvdata(pdev, adapter); |
3613 | 3660 | ||
3614 | status = be_dev_family_check(adapter); | 3661 | status = be_dev_type_check(adapter); |
3615 | if (status) | 3662 | if (status) |
3616 | goto free_netdev; | 3663 | goto free_netdev; |
3617 | 3664 | ||
@@ -3629,13 +3676,9 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3629 | } | 3676 | } |
3630 | } | 3677 | } |
3631 | 3678 | ||
3632 | status = be_sriov_enable(adapter); | ||
3633 | if (status) | ||
3634 | goto free_netdev; | ||
3635 | |||
3636 | status = be_ctrl_init(adapter); | 3679 | status = be_ctrl_init(adapter); |
3637 | if (status) | 3680 | if (status) |
3638 | goto disable_sriov; | 3681 | goto free_netdev; |
3639 | 3682 | ||
3640 | if (lancer_chip(adapter)) { | 3683 | if (lancer_chip(adapter)) { |
3641 | status = lancer_wait_ready(adapter); | 3684 | status = lancer_wait_ready(adapter); |
@@ -3662,9 +3705,11 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3662 | if (status) | 3705 | if (status) |
3663 | goto ctrl_clean; | 3706 | goto ctrl_clean; |
3664 | 3707 | ||
3665 | status = be_cmd_reset_function(adapter); | 3708 | if (be_reset_required(adapter)) { |
3666 | if (status) | 3709 | status = be_cmd_reset_function(adapter); |
3667 | goto ctrl_clean; | 3710 | if (status) |
3711 | goto ctrl_clean; | ||
3712 | } | ||
3668 | 3713 | ||
3669 | /* The INTR bit may be set in the card when probed by a kdump kernel | 3714 | /* The INTR bit may be set in the card when probed by a kdump kernel |
3670 | * after a crash. | 3715 | * after a crash. |
@@ -3676,7 +3721,7 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3676 | if (status) | 3721 | if (status) |
3677 | goto ctrl_clean; | 3722 | goto ctrl_clean; |
3678 | 3723 | ||
3679 | status = be_get_config(adapter); | 3724 | status = be_get_initial_config(adapter); |
3680 | if (status) | 3725 | if (status) |
3681 | goto stats_clean; | 3726 | goto stats_clean; |
3682 | 3727 | ||
@@ -3705,8 +3750,6 @@ stats_clean: | |||
3705 | be_stats_cleanup(adapter); | 3750 | be_stats_cleanup(adapter); |
3706 | ctrl_clean: | 3751 | ctrl_clean: |
3707 | be_ctrl_cleanup(adapter); | 3752 | be_ctrl_cleanup(adapter); |
3708 | disable_sriov: | ||
3709 | be_sriov_disable(adapter); | ||
3710 | free_netdev: | 3753 | free_netdev: |
3711 | free_netdev(netdev); | 3754 | free_netdev(netdev); |
3712 | pci_set_drvdata(pdev, NULL); | 3755 | pci_set_drvdata(pdev, NULL); |