diff options
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 164 |
3 files changed, 153 insertions, 64 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 8a250c38fb82..8b04880ee05d 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -3138,6 +3138,39 @@ err: | |||
3138 | return status; | 3138 | return status; |
3139 | } | 3139 | } |
3140 | 3140 | ||
3141 | int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, | ||
3142 | int vf_num) | ||
3143 | { | ||
3144 | struct be_mcc_wrb *wrb; | ||
3145 | struct be_cmd_req_get_iface_list *req; | ||
3146 | struct be_cmd_resp_get_iface_list *resp; | ||
3147 | int status; | ||
3148 | |||
3149 | spin_lock_bh(&adapter->mcc_lock); | ||
3150 | |||
3151 | wrb = wrb_from_mccq(adapter); | ||
3152 | if (!wrb) { | ||
3153 | status = -EBUSY; | ||
3154 | goto err; | ||
3155 | } | ||
3156 | req = embedded_payload(wrb); | ||
3157 | |||
3158 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
3159 | OPCODE_COMMON_GET_IFACE_LIST, sizeof(*resp), | ||
3160 | wrb, NULL); | ||
3161 | req->hdr.domain = vf_num + 1; | ||
3162 | |||
3163 | status = be_mcc_notify_wait(adapter); | ||
3164 | if (!status) { | ||
3165 | resp = (struct be_cmd_resp_get_iface_list *)req; | ||
3166 | vf_cfg->if_handle = le32_to_cpu(resp->if_desc.if_id); | ||
3167 | } | ||
3168 | |||
3169 | err: | ||
3170 | spin_unlock_bh(&adapter->mcc_lock); | ||
3171 | return status; | ||
3172 | } | ||
3173 | |||
3141 | /* Uses sync mcc */ | 3174 | /* Uses sync mcc */ |
3142 | int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) | 3175 | int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) |
3143 | { | 3176 | { |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index d6552e19ffee..96970860c915 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
@@ -203,6 +203,7 @@ struct be_mcc_mailbox { | |||
203 | #define OPCODE_COMMON_GET_FN_PRIVILEGES 170 | 203 | #define OPCODE_COMMON_GET_FN_PRIVILEGES 170 |
204 | #define OPCODE_COMMON_READ_OBJECT 171 | 204 | #define OPCODE_COMMON_READ_OBJECT 171 |
205 | #define OPCODE_COMMON_WRITE_OBJECT 172 | 205 | #define OPCODE_COMMON_WRITE_OBJECT 172 |
206 | #define OPCODE_COMMON_GET_IFACE_LIST 194 | ||
206 | #define OPCODE_COMMON_ENABLE_DISABLE_VF 196 | 207 | #define OPCODE_COMMON_ENABLE_DISABLE_VF 196 |
207 | 208 | ||
208 | #define OPCODE_ETH_RSS_CONFIG 1 | 209 | #define OPCODE_ETH_RSS_CONFIG 1 |
@@ -1795,6 +1796,23 @@ static inline bool check_privilege(struct be_adapter *adapter, u32 flags) | |||
1795 | return flags & adapter->cmd_privileges ? true : false; | 1796 | return flags & adapter->cmd_privileges ? true : false; |
1796 | } | 1797 | } |
1797 | 1798 | ||
1799 | /************** Get IFACE LIST *******************/ | ||
1800 | struct be_if_desc { | ||
1801 | u32 if_id; | ||
1802 | u32 cap_flags; | ||
1803 | u32 en_flags; | ||
1804 | }; | ||
1805 | |||
1806 | struct be_cmd_req_get_iface_list { | ||
1807 | struct be_cmd_req_hdr hdr; | ||
1808 | }; | ||
1809 | |||
1810 | struct be_cmd_resp_get_iface_list { | ||
1811 | struct be_cmd_req_hdr hdr; | ||
1812 | u32 if_cnt; | ||
1813 | struct be_if_desc if_desc; | ||
1814 | }; | ||
1815 | |||
1798 | extern int be_pci_fnum_get(struct be_adapter *adapter); | 1816 | extern int be_pci_fnum_get(struct be_adapter *adapter); |
1799 | extern int be_fw_wait_ready(struct be_adapter *adapter); | 1817 | extern int be_fw_wait_ready(struct be_adapter *adapter); |
1800 | extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, | 1818 | extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, |
@@ -1917,4 +1935,6 @@ extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, | |||
1917 | 1935 | ||
1918 | extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, | 1936 | extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, |
1919 | u8 domain); | 1937 | u8 domain); |
1938 | extern int be_cmd_get_if_id(struct be_adapter *adapter, | ||
1939 | struct be_vf_cfg *vf_cfg, int vf_num); | ||
1920 | extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain); | 1940 | extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain); |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 5c995700e534..7d534818d2fb 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -2597,7 +2597,7 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) | |||
2597 | * These addresses are programmed in the ASIC by the PF and the VF driver | 2597 | * These addresses are programmed in the ASIC by the PF and the VF driver |
2598 | * queries for the MAC address during its probe. | 2598 | * queries for the MAC address during its probe. |
2599 | */ | 2599 | */ |
2600 | static inline int be_vf_eth_addr_config(struct be_adapter *adapter) | 2600 | static int be_vf_eth_addr_config(struct be_adapter *adapter) |
2601 | { | 2601 | { |
2602 | u32 vf; | 2602 | u32 vf; |
2603 | int status = 0; | 2603 | int status = 0; |
@@ -2626,13 +2626,34 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) | |||
2626 | return status; | 2626 | return status; |
2627 | } | 2627 | } |
2628 | 2628 | ||
2629 | static int be_vfs_mac_query(struct be_adapter *adapter) | ||
2630 | { | ||
2631 | int status, vf; | ||
2632 | u8 mac[ETH_ALEN]; | ||
2633 | struct be_vf_cfg *vf_cfg; | ||
2634 | bool active; | ||
2635 | |||
2636 | for_all_vfs(adapter, vf_cfg, vf) { | ||
2637 | be_cmd_get_mac_from_list(adapter, mac, &active, | ||
2638 | &vf_cfg->pmac_id, 0); | ||
2639 | |||
2640 | status = be_cmd_mac_addr_query(adapter, mac, false, | ||
2641 | vf_cfg->if_handle, 0); | ||
2642 | if (status) | ||
2643 | return status; | ||
2644 | memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); | ||
2645 | } | ||
2646 | return 0; | ||
2647 | } | ||
2648 | |||
2629 | static void be_vf_clear(struct be_adapter *adapter) | 2649 | static void be_vf_clear(struct be_adapter *adapter) |
2630 | { | 2650 | { |
2631 | struct be_vf_cfg *vf_cfg; | 2651 | struct be_vf_cfg *vf_cfg; |
2632 | u32 vf; | 2652 | u32 vf; |
2633 | 2653 | ||
2634 | if (be_find_vfs(adapter, ASSIGNED)) { | 2654 | if (be_find_vfs(adapter, ASSIGNED)) { |
2635 | dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n"); | 2655 | dev_warn(&adapter->pdev->dev, |
2656 | "VFs are assigned to VMs: not disabling VFs\n"); | ||
2636 | goto done; | 2657 | goto done; |
2637 | } | 2658 | } |
2638 | 2659 | ||
@@ -2681,21 +2702,29 @@ static int be_clear(struct be_adapter *adapter) | |||
2681 | return 0; | 2702 | return 0; |
2682 | } | 2703 | } |
2683 | 2704 | ||
2684 | static void be_get_vf_if_cap_flags(struct be_adapter *adapter, | 2705 | static int be_vfs_if_create(struct be_adapter *adapter) |
2685 | u32 *cap_flags, u8 domain) | ||
2686 | { | 2706 | { |
2687 | bool profile_present = false; | 2707 | struct be_vf_cfg *vf_cfg; |
2708 | u32 cap_flags, en_flags, vf; | ||
2688 | int status; | 2709 | int status; |
2689 | 2710 | ||
2690 | if (lancer_chip(adapter)) { | 2711 | cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | |
2691 | status = be_cmd_get_profile_config(adapter, cap_flags, domain); | 2712 | BE_IF_FLAGS_MULTICAST; |
2692 | if (!status) | ||
2693 | profile_present = true; | ||
2694 | } | ||
2695 | 2713 | ||
2696 | if (!profile_present) | 2714 | for_all_vfs(adapter, vf_cfg, vf) { |
2697 | *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | | 2715 | if (!BE3_chip(adapter)) |
2698 | BE_IF_FLAGS_MULTICAST; | 2716 | be_cmd_get_profile_config(adapter, &cap_flags, vf + 1); |
2717 | |||
2718 | /* If a FW profile exists, then cap_flags are updated */ | ||
2719 | en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | | ||
2720 | BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST); | ||
2721 | status = be_cmd_if_create(adapter, cap_flags, en_flags, | ||
2722 | &vf_cfg->if_handle, vf + 1); | ||
2723 | if (status) | ||
2724 | goto err; | ||
2725 | } | ||
2726 | err: | ||
2727 | return status; | ||
2699 | } | 2728 | } |
2700 | 2729 | ||
2701 | static int be_vf_setup_init(struct be_adapter *adapter) | 2730 | static int be_vf_setup_init(struct be_adapter *adapter) |
@@ -2718,65 +2747,70 @@ static int be_vf_setup_init(struct be_adapter *adapter) | |||
2718 | static int be_vf_setup(struct be_adapter *adapter) | 2747 | static int be_vf_setup(struct be_adapter *adapter) |
2719 | { | 2748 | { |
2720 | struct be_vf_cfg *vf_cfg; | 2749 | struct be_vf_cfg *vf_cfg; |
2721 | struct device *dev = &adapter->pdev->dev; | ||
2722 | u32 cap_flags, en_flags, vf; | ||
2723 | u16 def_vlan, lnk_speed; | 2750 | u16 def_vlan, lnk_speed; |
2724 | int status, enabled_vfs; | 2751 | int status, old_vfs, vf; |
2725 | 2752 | struct device *dev = &adapter->pdev->dev; | |
2726 | enabled_vfs = be_find_vfs(adapter, ENABLED); | ||
2727 | if (enabled_vfs) { | ||
2728 | dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs); | ||
2729 | dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); | ||
2730 | return 0; | ||
2731 | } | ||
2732 | |||
2733 | if (num_vfs > adapter->dev_num_vfs) { | ||
2734 | dev_warn(dev, "Device supports %d VFs and not %d\n", | ||
2735 | adapter->dev_num_vfs, num_vfs); | ||
2736 | num_vfs = adapter->dev_num_vfs; | ||
2737 | } | ||
2738 | 2753 | ||
2739 | status = pci_enable_sriov(adapter->pdev, num_vfs); | 2754 | old_vfs = be_find_vfs(adapter, ENABLED); |
2740 | if (!status) { | 2755 | if (old_vfs) { |
2741 | adapter->num_vfs = num_vfs; | 2756 | dev_info(dev, "%d VFs are already enabled\n", old_vfs); |
2757 | if (old_vfs != num_vfs) | ||
2758 | dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs); | ||
2759 | adapter->num_vfs = old_vfs; | ||
2742 | } else { | 2760 | } else { |
2743 | /* Platform doesn't support SRIOV though device supports it */ | 2761 | if (num_vfs > adapter->dev_num_vfs) |
2744 | dev_warn(dev, "SRIOV enable failed\n"); | 2762 | dev_info(dev, "Device supports %d VFs and not %d\n", |
2745 | return 0; | 2763 | adapter->dev_num_vfs, num_vfs); |
2764 | adapter->num_vfs = min_t(u16, num_vfs, adapter->dev_num_vfs); | ||
2765 | |||
2766 | status = pci_enable_sriov(adapter->pdev, num_vfs); | ||
2767 | if (status) { | ||
2768 | dev_err(dev, "SRIOV enable failed\n"); | ||
2769 | adapter->num_vfs = 0; | ||
2770 | return 0; | ||
2771 | } | ||
2746 | } | 2772 | } |
2747 | 2773 | ||
2748 | status = be_vf_setup_init(adapter); | 2774 | status = be_vf_setup_init(adapter); |
2749 | if (status) | 2775 | if (status) |
2750 | goto err; | 2776 | goto err; |
2751 | 2777 | ||
2752 | for_all_vfs(adapter, vf_cfg, vf) { | 2778 | if (old_vfs) { |
2753 | be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1); | 2779 | for_all_vfs(adapter, vf_cfg, vf) { |
2754 | 2780 | status = be_cmd_get_if_id(adapter, vf_cfg, vf); | |
2755 | en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | | 2781 | if (status) |
2756 | BE_IF_FLAGS_BROADCAST | | 2782 | goto err; |
2757 | BE_IF_FLAGS_MULTICAST); | 2783 | } |
2758 | 2784 | } else { | |
2759 | status = be_cmd_if_create(adapter, cap_flags, en_flags, | 2785 | status = be_vfs_if_create(adapter); |
2760 | &vf_cfg->if_handle, vf + 1); | ||
2761 | if (status) | 2786 | if (status) |
2762 | goto err; | 2787 | goto err; |
2763 | } | 2788 | } |
2764 | 2789 | ||
2765 | if (!enabled_vfs) { | 2790 | if (old_vfs) { |
2791 | status = be_vfs_mac_query(adapter); | ||
2792 | if (status) | ||
2793 | goto err; | ||
2794 | } else { | ||
2766 | status = be_vf_eth_addr_config(adapter); | 2795 | status = be_vf_eth_addr_config(adapter); |
2767 | if (status) | 2796 | if (status) |
2768 | goto err; | 2797 | goto err; |
2769 | } | 2798 | } |
2770 | 2799 | ||
2771 | for_all_vfs(adapter, vf_cfg, vf) { | 2800 | for_all_vfs(adapter, vf_cfg, vf) { |
2772 | lnk_speed = 1000; | 2801 | /* BE3 FW, by default, caps VF TX-rate to 100mbps. |
2773 | status = be_cmd_set_qos(adapter, lnk_speed, vf + 1); | 2802 | * Allow full available bandwidth |
2774 | if (status) | 2803 | */ |
2775 | goto err; | 2804 | if (BE3_chip(adapter) && !old_vfs) |
2776 | vf_cfg->tx_rate = lnk_speed * 10; | 2805 | be_cmd_set_qos(adapter, 1000, vf+1); |
2806 | |||
2807 | status = be_cmd_link_status_query(adapter, &lnk_speed, | ||
2808 | NULL, vf + 1); | ||
2809 | if (!status) | ||
2810 | vf_cfg->tx_rate = lnk_speed; | ||
2777 | 2811 | ||
2778 | status = be_cmd_get_hsw_config(adapter, &def_vlan, | 2812 | status = be_cmd_get_hsw_config(adapter, &def_vlan, |
2779 | vf + 1, vf_cfg->if_handle); | 2813 | vf + 1, vf_cfg->if_handle); |
2780 | if (status) | 2814 | if (status) |
2781 | goto err; | 2815 | goto err; |
2782 | vf_cfg->def_vid = def_vlan; | 2816 | vf_cfg->def_vid = def_vlan; |
@@ -2785,6 +2819,8 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
2785 | } | 2819 | } |
2786 | return 0; | 2820 | return 0; |
2787 | err: | 2821 | err: |
2822 | dev_err(dev, "VF setup failed\n"); | ||
2823 | be_vf_clear(adapter); | ||
2788 | return status; | 2824 | return status; |
2789 | } | 2825 | } |
2790 | 2826 | ||
@@ -2838,12 +2874,12 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, | |||
2838 | 2874 | ||
2839 | static void be_get_resources(struct be_adapter *adapter) | 2875 | static void be_get_resources(struct be_adapter *adapter) |
2840 | { | 2876 | { |
2841 | int status; | 2877 | u16 dev_num_vfs; |
2878 | int pos, status; | ||
2842 | bool profile_present = false; | 2879 | bool profile_present = false; |
2843 | 2880 | ||
2844 | if (lancer_chip(adapter)) { | 2881 | if (!BEx_chip(adapter)) { |
2845 | status = be_cmd_get_func_config(adapter); | 2882 | status = be_cmd_get_func_config(adapter); |
2846 | |||
2847 | if (!status) | 2883 | if (!status) |
2848 | profile_present = true; | 2884 | profile_present = true; |
2849 | } | 2885 | } |
@@ -2899,13 +2935,21 @@ static void be_get_resources(struct be_adapter *adapter) | |||
2899 | if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) | 2935 | if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) |
2900 | adapter->if_cap_flags |= BE_IF_FLAGS_RSS; | 2936 | adapter->if_cap_flags |= BE_IF_FLAGS_RSS; |
2901 | } | 2937 | } |
2938 | |||
2939 | pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); | ||
2940 | if (pos) { | ||
2941 | pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, | ||
2942 | &dev_num_vfs); | ||
2943 | if (BE3_chip(adapter)) | ||
2944 | dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS); | ||
2945 | adapter->dev_num_vfs = dev_num_vfs; | ||
2946 | } | ||
2902 | } | 2947 | } |
2903 | 2948 | ||
2904 | /* Routine to query per function resource limits */ | 2949 | /* Routine to query per function resource limits */ |
2905 | static int be_get_config(struct be_adapter *adapter) | 2950 | static int be_get_config(struct be_adapter *adapter) |
2906 | { | 2951 | { |
2907 | int pos, status; | 2952 | int status; |
2908 | u16 dev_num_vfs; | ||
2909 | 2953 | ||
2910 | status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, | 2954 | status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, |
2911 | &adapter->function_mode, | 2955 | &adapter->function_mode, |
@@ -2923,14 +2967,6 @@ static int be_get_config(struct be_adapter *adapter) | |||
2923 | goto err; | 2967 | goto err; |
2924 | } | 2968 | } |
2925 | 2969 | ||
2926 | pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); | ||
2927 | if (pos) { | ||
2928 | pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, | ||
2929 | &dev_num_vfs); | ||
2930 | if (!lancer_chip(adapter)) | ||
2931 | dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS); | ||
2932 | adapter->dev_num_vfs = dev_num_vfs; | ||
2933 | } | ||
2934 | err: | 2970 | err: |
2935 | return status; | 2971 | return status; |
2936 | } | 2972 | } |