Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sathya Perla and committed by
David S. Miller
39f1d94d d301e325

+134 -89
+11 -11
drivers/net/ethernet/emulex/benet/be.h
··· 313 313 u32 tx_rate; 314 314 }; 315 315 316 + enum vf_state { 317 + ENABLED = 0, 318 + ASSIGNED = 1 319 + }; 320 + 316 321 #define BE_FLAGS_LINK_STATUS_INIT 1 317 322 #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) 318 323 #define BE_UC_PMAC_COUNT 30 ··· 408 403 u32 flash_status; 409 404 struct completion flash_compl; 410 405 411 - u32 num_vfs; 412 - u8 is_virtfn; 406 + u32 num_vfs; /* Number of VFs provisioned by PF driver */ 407 + u32 dev_num_vfs; /* Number of VFs supported by HW */ 408 + u8 virtfn; 413 409 struct be_vf_cfg *vf_cfg; 414 410 bool be3_native; 415 411 u32 sli_family; ··· 423 417 u32 uc_macs; /* Count of secondary UC MAC programmed */ 424 418 }; 425 419 426 - #define be_physfn(adapter) (!adapter->is_virtfn) 420 + #define be_physfn(adapter) (!adapter->virtfn) 427 421 #define sriov_enabled(adapter) (adapter->num_vfs > 0) 422 + #define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \ 423 + be_physfn(adapter)) 428 424 #define for_all_vfs(adapter, vf_cfg, i) \ 429 425 for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ 430 426 i++, vf_cfg++) ··· 553 545 val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_UDP); 554 546 555 547 return val; 556 - } 557 - 558 - static inline void be_check_sriov_fn_type(struct be_adapter *adapter) 559 - { 560 - u32 sli_intf; 561 - 562 - pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); 563 - adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; 564 548 } 565 549 566 550 static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
+2
drivers/net/ethernet/emulex/benet/be_hw.h
··· 58 58 59 59 #define SLI_PORT_CONTROL_IP_MASK 0x08000000 60 60 61 + #define PCICFG_CUST_SCRATCHPAD_CSR 0x1EC 62 + 61 63 /********* Memory BAR register ************/ 62 64 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc 63 65 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
+121 -78
drivers/net/ethernet/emulex/benet/be_main.c
··· 1049 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 1075 static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) 1053 1076 { 1054 1077 struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); ··· 1812 1789 1813 1790 static int be_num_txqs_want(struct be_adapter *adapter) 1814 1791 { 1815 - if (sriov_enabled(adapter) || be_is_mc(adapter) || 1816 - lancer_chip(adapter) || !be_physfn(adapter) || 1817 - adapter->generation == BE_GEN2) 1792 + if (sriov_want(adapter) || be_is_mc(adapter) || 1793 + lancer_chip(adapter) || !be_physfn(adapter) || 1794 + adapter->generation == BE_GEN2) 1818 1795 return 1; 1819 1796 else 1820 1797 return MAX_TX_QS; ··· 2141 2118 static uint be_num_rss_want(struct be_adapter *adapter) 2142 2119 { 2143 2120 if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && 2144 - adapter->num_vfs == 0 && be_physfn(adapter) && 2121 + !sriov_want(adapter) && be_physfn(adapter) && 2145 2122 !be_is_mc(adapter)) 2146 2123 return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; 2147 2124 else ··· 2173 2150 done: 2174 2151 adapter->num_msix_vec = num_vec; 2175 2152 return; 2176 - } 2177 - 2178 - static int be_sriov_enable(struct be_adapter *adapter) 2179 - { 2180 - be_check_sriov_fn_type(adapter); 2181 - 2182 - #ifdef CONFIG_PCI_IOV 2183 - if (be_physfn(adapter) && num_vfs) { 2184 - int status, pos; 2185 - u16 dev_vfs; 2186 - 2187 - pos = pci_find_ext_capability(adapter->pdev, 2188 - PCI_EXT_CAP_ID_SRIOV); 2189 - pci_read_config_word(adapter->pdev, 2190 - pos + PCI_SRIOV_TOTAL_VF, &dev_vfs); 2191 - 2192 - adapter->num_vfs = min_t(u16, num_vfs, dev_vfs); 2193 - if (adapter->num_vfs != num_vfs) 2194 - dev_info(&adapter->pdev->dev, 2195 - "Device supports %d VFs and not %d\n", 2196 - adapter->num_vfs, num_vfs); 2197 - 2198 - status = pci_enable_sriov(adapter->pdev, adapter->num_vfs); 2199 - if (status) 2200 - adapter->num_vfs = 0; 2201 - 2202 - if (adapter->num_vfs) { 2203 - adapter->vf_cfg = kcalloc(num_vfs, 2204 - sizeof(struct be_vf_cfg), 2205 - GFP_KERNEL); 2206 - if (!adapter->vf_cfg) 2207 - return -ENOMEM; 2208 - } 2209 - } 2210 - #endif 2211 - return 0; 2212 - } 2213 - 2214 - static void be_sriov_disable(struct be_adapter *adapter) 2215 - { 2216 - #ifdef CONFIG_PCI_IOV 2217 - if (sriov_enabled(adapter)) { 2218 - pci_disable_sriov(adapter->pdev); 2219 - kfree(adapter->vf_cfg); 2220 - adapter->num_vfs = 0; 2221 - } 2222 - #endif 2223 2153 } 2224 2154 2225 2155 static inline int be_msix_vec_get(struct be_adapter *adapter, ··· 2476 2500 struct be_vf_cfg *vf_cfg; 2477 2501 u32 vf; 2478 2502 2503 + if (be_find_vfs(adapter, ASSIGNED)) { 2504 + dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n"); 2505 + goto done; 2506 + } 2507 + 2479 2508 for_all_vfs(adapter, vf_cfg, vf) { 2480 2509 if (lancer_chip(adapter)) 2481 2510 be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); ··· 2490 2509 2491 2510 be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); 2492 2511 } 2512 + pci_disable_sriov(adapter->pdev); 2513 + done: 2514 + kfree(adapter->vf_cfg); 2515 + adapter->num_vfs = 0; 2493 2516 } 2494 2517 2495 2518 static int be_clear(struct be_adapter *adapter) ··· 2523 2538 be_cmd_fw_clean(adapter); 2524 2539 2525 2540 be_msix_disable(adapter); 2526 - kfree(adapter->pmac_id); 2541 + pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0); 2527 2542 return 0; 2528 2543 } 2529 2544 2530 - static void be_vf_setup_init(struct be_adapter *adapter) 2545 + static int be_vf_setup_init(struct be_adapter *adapter) 2531 2546 { 2532 2547 struct be_vf_cfg *vf_cfg; 2533 2548 int vf; 2549 + 2550 + adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg), 2551 + GFP_KERNEL); 2552 + if (!adapter->vf_cfg) 2553 + return -ENOMEM; 2534 2554 2535 2555 for_all_vfs(adapter, vf_cfg, vf) { 2536 2556 vf_cfg->if_handle = -1; 2537 2557 vf_cfg->pmac_id = -1; 2538 2558 } 2559 + return 0; 2539 2560 } 2540 2561 2541 2562 static int be_vf_setup(struct be_adapter *adapter) 2542 2563 { 2543 2564 struct be_vf_cfg *vf_cfg; 2565 + struct device *dev = &adapter->pdev->dev; 2544 2566 u32 cap_flags, en_flags, vf; 2545 2567 u16 def_vlan, lnk_speed; 2546 - int status; 2568 + int status, enabled_vfs; 2547 2569 2548 - be_vf_setup_init(adapter); 2570 + enabled_vfs = be_find_vfs(adapter, ENABLED); 2571 + if (enabled_vfs) { 2572 + dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs); 2573 + dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); 2574 + return 0; 2575 + } 2576 + 2577 + if (num_vfs > adapter->dev_num_vfs) { 2578 + dev_warn(dev, "Device supports %d VFs and not %d\n", 2579 + adapter->dev_num_vfs, num_vfs); 2580 + num_vfs = adapter->dev_num_vfs; 2581 + } 2582 + 2583 + status = pci_enable_sriov(adapter->pdev, num_vfs); 2584 + if (!status) { 2585 + adapter->num_vfs = num_vfs; 2586 + } else { 2587 + /* Platform doesn't support SRIOV though device supports it */ 2588 + dev_warn(dev, "SRIOV enable failed\n"); 2589 + return 0; 2590 + } 2591 + 2592 + status = be_vf_setup_init(adapter); 2593 + if (status) 2594 + goto err; 2549 2595 2550 2596 cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | 2551 2597 BE_IF_FLAGS_MULTICAST; ··· 2587 2571 goto err; 2588 2572 } 2589 2573 2590 - status = be_vf_eth_addr_config(adapter); 2591 - if (status) 2592 - goto err; 2574 + if (!enabled_vfs) { 2575 + status = be_vf_eth_addr_config(adapter); 2576 + if (status) 2577 + goto err; 2578 + } 2593 2579 2594 2580 for_all_vfs(adapter, vf_cfg, vf) { 2595 2581 status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, ··· 2648 2630 return status; 2649 2631 } 2650 2632 2633 + /* Routine to query per function resource limits */ 2634 + static int be_get_config(struct be_adapter *adapter) 2635 + { 2636 + int pos; 2637 + u16 dev_num_vfs; 2638 + 2639 + pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); 2640 + if (pos) { 2641 + pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, 2642 + &dev_num_vfs); 2643 + adapter->dev_num_vfs = dev_num_vfs; 2644 + } 2645 + return 0; 2646 + } 2647 + 2651 2648 static int be_setup(struct be_adapter *adapter) 2652 2649 { 2653 2650 struct net_device *netdev = adapter->netdev; 2651 + struct device *dev = &adapter->pdev->dev; 2654 2652 u32 cap_flags, en_flags; 2655 2653 u32 tx_fc, rx_fc; 2656 2654 int status; 2657 2655 u8 mac[ETH_ALEN]; 2658 2656 2659 2657 be_setup_init(adapter); 2658 + 2659 + be_get_config(adapter); 2660 2660 2661 2661 be_cmd_req_native_mode(adapter); 2662 2662 ··· 2754 2718 2755 2719 pcie_set_readrq(adapter->pdev, 4096); 2756 2720 2757 - if (sriov_enabled(adapter)) { 2758 - status = be_vf_setup(adapter); 2759 - if (status) 2760 - goto err; 2721 + if (be_physfn(adapter) && num_vfs) { 2722 + if (adapter->dev_num_vfs) 2723 + be_vf_setup(adapter); 2724 + else 2725 + dev_warn(dev, "device doesn't support SRIOV\n"); 2761 2726 } 2762 2727 2763 2728 be_cmd_get_phy_info(adapter); ··· 2768 2731 schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); 2769 2732 adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; 2770 2733 2734 + pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1); 2771 2735 return 0; 2772 2736 err: 2773 2737 be_clear(adapter); ··· 3390 3352 3391 3353 be_ctrl_cleanup(adapter); 3392 3354 3393 - be_sriov_disable(adapter); 3394 - 3395 3355 pci_set_drvdata(pdev, NULL); 3396 3356 pci_release_regions(pdev); 3397 3357 pci_disable_device(pdev); ··· 3403 3367 !be_is_wol_excluded(adapter)) ? true : false; 3404 3368 } 3405 3369 3406 - static int be_get_config(struct be_adapter *adapter) 3370 + static int be_get_initial_config(struct be_adapter *adapter) 3407 3371 { 3408 3372 int status; 3409 3373 ··· 3446 3410 return 0; 3447 3411 } 3448 3412 3449 - static int be_dev_family_check(struct be_adapter *adapter) 3413 + static int be_dev_type_check(struct be_adapter *adapter) 3450 3414 { 3451 3415 struct pci_dev *pdev = adapter->pdev; 3452 3416 u32 sli_intf = 0, if_type; ··· 3479 3443 default: 3480 3444 adapter->generation = 0; 3481 3445 } 3446 + 3447 + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); 3448 + adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; 3482 3449 return 0; 3483 3450 } 3484 3451 ··· 3625 3586 schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); 3626 3587 } 3627 3588 3589 + static bool be_reset_required(struct be_adapter *adapter) 3590 + { 3591 + u32 reg; 3592 + 3593 + pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, &reg); 3594 + return reg; 3595 + } 3596 + 3628 3597 static int __devinit be_probe(struct pci_dev *pdev, 3629 3598 const struct pci_device_id *pdev_id) 3630 3599 { ··· 3658 3611 adapter->pdev = pdev; 3659 3612 pci_set_drvdata(pdev, adapter); 3660 3613 3661 - status = be_dev_family_check(adapter); 3614 + status = be_dev_type_check(adapter); 3662 3615 if (status) 3663 3616 goto free_netdev; 3664 3617 ··· 3676 3629 } 3677 3630 } 3678 3631 3679 - status = be_sriov_enable(adapter); 3680 - if (status) 3681 - goto free_netdev; 3682 - 3683 3632 status = be_ctrl_init(adapter); 3684 3633 if (status) 3685 - goto disable_sriov; 3634 + goto free_netdev; 3686 3635 3687 3636 if (lancer_chip(adapter)) { 3688 3637 status = lancer_wait_ready(adapter); ··· 3705 3662 if (status) 3706 3663 goto ctrl_clean; 3707 3664 3708 - status = be_cmd_reset_function(adapter); 3709 - if (status) 3710 - goto ctrl_clean; 3665 + if (be_reset_required(adapter)) { 3666 + status = be_cmd_reset_function(adapter); 3667 + if (status) 3668 + goto ctrl_clean; 3669 + } 3711 3670 3712 3671 /* The INTR bit may be set in the card when probed by a kdump kernel 3713 3672 * after a crash. ··· 3721 3676 if (status) 3722 3677 goto ctrl_clean; 3723 3678 3724 - status = be_get_config(adapter); 3679 + status = be_get_initial_config(adapter); 3725 3680 if (status) 3726 3681 goto stats_clean; 3727 3682 ··· 3750 3705 be_stats_cleanup(adapter); 3751 3706 ctrl_clean: 3752 3707 be_ctrl_cleanup(adapter); 3753 - disable_sriov: 3754 - be_sriov_disable(adapter); 3755 3708 free_netdev: 3756 3709 free_netdev(netdev); 3757 3710 pci_set_drvdata(pdev, NULL);