diff options
author | Sathya Perla <sathya.perla@emulex.com> | 2013-08-27 07:27:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-27 15:57:05 -0400 |
commit | 68d7bdcb4c00ec799ad949f4b4c50985539710e2 (patch) | |
tree | 773f22351be2b8b9460e1593d104737c2b48b5bc /drivers/net | |
parent | 7707133ceb38f590729d0165099555928630af1c (diff) |
be2net: implement ethtool set/get_channel hooks
Support is provided only for combined channels. When SR-IOV is not
enabled, BE3 supports upto 16 channels and Lancer-R/SH-R support upto
32 channels.
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 94 |
3 files changed, 104 insertions, 32 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 8b416355879f..ace5050dba38 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -99,16 +99,17 @@ static inline char *nic_name(struct pci_dev *pdev) | |||
99 | #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ | 99 | #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ |
100 | #define MCC_CQ_LEN 256 | 100 | #define MCC_CQ_LEN 256 |
101 | 101 | ||
102 | #define BE3_MAX_RSS_QS 8 | ||
103 | #define BE2_MAX_RSS_QS 4 | 102 | #define BE2_MAX_RSS_QS 4 |
104 | #define BE3_MAX_TX_QS 8 | 103 | #define BE3_MAX_RSS_QS 16 |
105 | #define MAX_RSS_QS BE3_MAX_RSS_QS | 104 | #define BE3_MAX_TX_QS 16 |
106 | #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ | 105 | #define BE3_MAX_EVT_QS 16 |
107 | #define MAX_EVT_QS MAX_RSS_QS | 106 | |
107 | #define MAX_RX_QS 32 | ||
108 | #define MAX_EVT_QS 32 | ||
109 | #define MAX_TX_QS 32 | ||
108 | 110 | ||
109 | #define MAX_TX_QS 8 | ||
110 | #define MAX_ROCE_EQS 5 | 111 | #define MAX_ROCE_EQS 5 |
111 | #define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */ | 112 | #define MAX_MSIX_VECTORS 32 |
112 | #define MIN_MSIX_VECTORS 1 | 113 | #define MIN_MSIX_VECTORS 1 |
113 | #define BE_TX_BUDGET 256 | 114 | #define BE_TX_BUDGET 256 |
114 | #define BE_NAPI_WEIGHT 64 | 115 | #define BE_NAPI_WEIGHT 64 |
@@ -701,6 +702,8 @@ extern int be_load_fw(struct be_adapter *adapter, u8 *func); | |||
701 | extern bool be_is_wol_supported(struct be_adapter *adapter); | 702 | extern bool be_is_wol_supported(struct be_adapter *adapter); |
702 | extern bool be_pause_supported(struct be_adapter *adapter); | 703 | extern bool be_pause_supported(struct be_adapter *adapter); |
703 | extern u32 be_get_fw_log_level(struct be_adapter *adapter); | 704 | extern u32 be_get_fw_log_level(struct be_adapter *adapter); |
705 | int be_update_queues(struct be_adapter *adapter); | ||
706 | int be_poll(struct napi_struct *napi, int budget); | ||
704 | 707 | ||
705 | /* | 708 | /* |
706 | * internal function to initialize-cleanup roce device. | 709 | * internal function to initialize-cleanup roce device. |
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 4f8c941217cc..b440a1fac77b 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c | |||
@@ -1119,6 +1119,29 @@ static int be_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) | |||
1119 | return status; | 1119 | return status; |
1120 | } | 1120 | } |
1121 | 1121 | ||
1122 | static void be_get_channels(struct net_device *netdev, | ||
1123 | struct ethtool_channels *ch) | ||
1124 | { | ||
1125 | struct be_adapter *adapter = netdev_priv(netdev); | ||
1126 | |||
1127 | ch->combined_count = adapter->num_evt_qs; | ||
1128 | ch->max_combined = be_max_qs(adapter); | ||
1129 | } | ||
1130 | |||
1131 | static int be_set_channels(struct net_device *netdev, | ||
1132 | struct ethtool_channels *ch) | ||
1133 | { | ||
1134 | struct be_adapter *adapter = netdev_priv(netdev); | ||
1135 | |||
1136 | if (ch->rx_count || ch->tx_count || ch->other_count || | ||
1137 | !ch->combined_count || ch->combined_count > be_max_qs(adapter)) | ||
1138 | return -EINVAL; | ||
1139 | |||
1140 | adapter->cfg_num_qs = ch->combined_count; | ||
1141 | |||
1142 | return be_update_queues(adapter); | ||
1143 | } | ||
1144 | |||
1122 | const struct ethtool_ops be_ethtool_ops = { | 1145 | const struct ethtool_ops be_ethtool_ops = { |
1123 | .get_settings = be_get_settings, | 1146 | .get_settings = be_get_settings, |
1124 | .get_drvinfo = be_get_drvinfo, | 1147 | .get_drvinfo = be_get_drvinfo, |
@@ -1145,4 +1168,6 @@ const struct ethtool_ops be_ethtool_ops = { | |||
1145 | .self_test = be_self_test, | 1168 | .self_test = be_self_test, |
1146 | .get_rxnfc = be_get_rxnfc, | 1169 | .get_rxnfc = be_get_rxnfc, |
1147 | .set_rxnfc = be_set_rxnfc, | 1170 | .set_rxnfc = be_set_rxnfc, |
1171 | .get_channels = be_get_channels, | ||
1172 | .set_channels = be_set_channels | ||
1148 | }; | 1173 | }; |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index b08459d268b4..50116f8ed576 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -1913,6 +1913,7 @@ static void be_evt_queues_destroy(struct be_adapter *adapter) | |||
1913 | if (eqo->q.created) { | 1913 | if (eqo->q.created) { |
1914 | be_eq_clean(eqo); | 1914 | be_eq_clean(eqo); |
1915 | be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); | 1915 | be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); |
1916 | netif_napi_del(&eqo->napi); | ||
1916 | } | 1917 | } |
1917 | be_queue_free(adapter, &eqo->q); | 1918 | be_queue_free(adapter, &eqo->q); |
1918 | } | 1919 | } |
@@ -1928,6 +1929,8 @@ static int be_evt_queues_create(struct be_adapter *adapter) | |||
1928 | adapter->cfg_num_qs); | 1929 | adapter->cfg_num_qs); |
1929 | 1930 | ||
1930 | for_all_evt_queues(adapter, eqo, i) { | 1931 | for_all_evt_queues(adapter, eqo, i) { |
1932 | netif_napi_add(adapter->netdev, &eqo->napi, be_poll, | ||
1933 | BE_NAPI_WEIGHT); | ||
1931 | eqo->adapter = adapter; | 1934 | eqo->adapter = adapter; |
1932 | eqo->tx_budget = BE_TX_BUDGET; | 1935 | eqo->tx_budget = BE_TX_BUDGET; |
1933 | eqo->idx = i; | 1936 | eqo->idx = i; |
@@ -2021,12 +2024,6 @@ static int be_tx_qs_create(struct be_adapter *adapter) | |||
2021 | int status, i; | 2024 | int status, i; |
2022 | 2025 | ||
2023 | adapter->num_tx_qs = min(adapter->num_evt_qs, be_max_txqs(adapter)); | 2026 | adapter->num_tx_qs = min(adapter->num_evt_qs, be_max_txqs(adapter)); |
2024 | if (adapter->num_tx_qs != MAX_TX_QS) { | ||
2025 | rtnl_lock(); | ||
2026 | netif_set_real_num_tx_queues(adapter->netdev, | ||
2027 | adapter->num_tx_qs); | ||
2028 | rtnl_unlock(); | ||
2029 | } | ||
2030 | 2027 | ||
2031 | for_all_tx_queues(adapter, txo, i) { | 2028 | for_all_tx_queues(adapter, txo, i) { |
2032 | cq = &txo->cq; | 2029 | cq = &txo->cq; |
@@ -2087,13 +2084,6 @@ static int be_rx_cqs_create(struct be_adapter *adapter) | |||
2087 | if (adapter->num_rx_qs > 1) | 2084 | if (adapter->num_rx_qs > 1) |
2088 | adapter->num_rx_qs++; | 2085 | adapter->num_rx_qs++; |
2089 | 2086 | ||
2090 | if (adapter->num_rx_qs != MAX_RX_QS) { | ||
2091 | rtnl_lock(); | ||
2092 | netif_set_real_num_rx_queues(adapter->netdev, | ||
2093 | adapter->num_rx_qs); | ||
2094 | rtnl_unlock(); | ||
2095 | } | ||
2096 | |||
2097 | adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; | 2087 | adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; |
2098 | for_all_rx_queues(adapter, rxo, i) { | 2088 | for_all_rx_queues(adapter, rxo, i) { |
2099 | rxo->adapter = adapter; | 2089 | rxo->adapter = adapter; |
@@ -2244,7 +2234,7 @@ static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, | |||
2244 | return (work_done < budget); /* Done */ | 2234 | return (work_done < budget); /* Done */ |
2245 | } | 2235 | } |
2246 | 2236 | ||
2247 | static int be_poll(struct napi_struct *napi, int budget) | 2237 | int be_poll(struct napi_struct *napi, int budget) |
2248 | { | 2238 | { |
2249 | struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); | 2239 | struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); |
2250 | struct be_adapter *adapter = eqo->adapter; | 2240 | struct be_adapter *adapter = eqo->adapter; |
@@ -2356,6 +2346,7 @@ static void be_msix_disable(struct be_adapter *adapter) | |||
2356 | if (msix_enabled(adapter)) { | 2346 | if (msix_enabled(adapter)) { |
2357 | pci_disable_msix(adapter->pdev); | 2347 | pci_disable_msix(adapter->pdev); |
2358 | adapter->num_msix_vec = 0; | 2348 | adapter->num_msix_vec = 0; |
2349 | adapter->num_msix_roce_vec = 0; | ||
2359 | } | 2350 | } |
2360 | } | 2351 | } |
2361 | 2352 | ||
@@ -2771,14 +2762,19 @@ static void be_clear_queues(struct be_adapter *adapter) | |||
2771 | be_evt_queues_destroy(adapter); | 2762 | be_evt_queues_destroy(adapter); |
2772 | } | 2763 | } |
2773 | 2764 | ||
2774 | static int be_clear(struct be_adapter *adapter) | 2765 | static void be_cancel_worker(struct be_adapter *adapter) |
2775 | { | 2766 | { |
2776 | int i; | ||
2777 | |||
2778 | if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { | 2767 | if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) { |
2779 | cancel_delayed_work_sync(&adapter->work); | 2768 | cancel_delayed_work_sync(&adapter->work); |
2780 | adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; | 2769 | adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED; |
2781 | } | 2770 | } |
2771 | } | ||
2772 | |||
2773 | static int be_clear(struct be_adapter *adapter) | ||
2774 | { | ||
2775 | int i; | ||
2776 | |||
2777 | be_cancel_worker(adapter); | ||
2782 | 2778 | ||
2783 | if (sriov_enabled(adapter)) | 2779 | if (sriov_enabled(adapter)) |
2784 | be_vf_clear(adapter); | 2780 | be_vf_clear(adapter); |
@@ -2982,7 +2978,7 @@ static void BEx_get_resources(struct be_adapter *adapter, | |||
2982 | BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; | 2978 | BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; |
2983 | res->max_rx_qs = res->max_rss_qs + 1; | 2979 | res->max_rx_qs = res->max_rss_qs + 1; |
2984 | 2980 | ||
2985 | res->max_evt_qs = be_physfn(adapter) ? MAX_EVT_QS : 1; | 2981 | res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1; |
2986 | 2982 | ||
2987 | res->if_cap_flags = BE_IF_CAP_FLAGS_WANT; | 2983 | res->if_cap_flags = BE_IF_CAP_FLAGS_WANT; |
2988 | if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS)) | 2984 | if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS)) |
@@ -3108,8 +3104,15 @@ static int be_mac_setup(struct be_adapter *adapter) | |||
3108 | return 0; | 3104 | return 0; |
3109 | } | 3105 | } |
3110 | 3106 | ||
3107 | static void be_schedule_worker(struct be_adapter *adapter) | ||
3108 | { | ||
3109 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); | ||
3110 | adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; | ||
3111 | } | ||
3112 | |||
3111 | static int be_setup_queues(struct be_adapter *adapter) | 3113 | static int be_setup_queues(struct be_adapter *adapter) |
3112 | { | 3114 | { |
3115 | struct net_device *netdev = adapter->netdev; | ||
3113 | int status; | 3116 | int status; |
3114 | 3117 | ||
3115 | status = be_evt_queues_create(adapter); | 3118 | status = be_evt_queues_create(adapter); |
@@ -3128,12 +3131,56 @@ static int be_setup_queues(struct be_adapter *adapter) | |||
3128 | if (status) | 3131 | if (status) |
3129 | goto err; | 3132 | goto err; |
3130 | 3133 | ||
3134 | status = netif_set_real_num_rx_queues(netdev, adapter->num_rx_qs); | ||
3135 | if (status) | ||
3136 | goto err; | ||
3137 | |||
3138 | status = netif_set_real_num_tx_queues(netdev, adapter->num_tx_qs); | ||
3139 | if (status) | ||
3140 | goto err; | ||
3141 | |||
3131 | return 0; | 3142 | return 0; |
3132 | err: | 3143 | err: |
3133 | dev_err(&adapter->pdev->dev, "queue_setup failed\n"); | 3144 | dev_err(&adapter->pdev->dev, "queue_setup failed\n"); |
3134 | return status; | 3145 | return status; |
3135 | } | 3146 | } |
3136 | 3147 | ||
3148 | int be_update_queues(struct be_adapter *adapter) | ||
3149 | { | ||
3150 | struct net_device *netdev = adapter->netdev; | ||
3151 | int status; | ||
3152 | |||
3153 | if (netif_running(netdev)) | ||
3154 | be_close(netdev); | ||
3155 | |||
3156 | be_cancel_worker(adapter); | ||
3157 | |||
3158 | /* If any vectors have been shared with RoCE we cannot re-program | ||
3159 | * the MSIx table. | ||
3160 | */ | ||
3161 | if (!adapter->num_msix_roce_vec) | ||
3162 | be_msix_disable(adapter); | ||
3163 | |||
3164 | be_clear_queues(adapter); | ||
3165 | |||
3166 | if (!msix_enabled(adapter)) { | ||
3167 | status = be_msix_enable(adapter); | ||
3168 | if (status) | ||
3169 | return status; | ||
3170 | } | ||
3171 | |||
3172 | status = be_setup_queues(adapter); | ||
3173 | if (status) | ||
3174 | return status; | ||
3175 | |||
3176 | be_schedule_worker(adapter); | ||
3177 | |||
3178 | if (netif_running(netdev)) | ||
3179 | status = be_open(netdev); | ||
3180 | |||
3181 | return status; | ||
3182 | } | ||
3183 | |||
3137 | static int be_setup(struct be_adapter *adapter) | 3184 | static int be_setup(struct be_adapter *adapter) |
3138 | { | 3185 | { |
3139 | struct device *dev = &adapter->pdev->dev; | 3186 | struct device *dev = &adapter->pdev->dev; |
@@ -3163,7 +3210,10 @@ static int be_setup(struct be_adapter *adapter) | |||
3163 | if (status) | 3210 | if (status) |
3164 | goto err; | 3211 | goto err; |
3165 | 3212 | ||
3213 | /* Updating real_num_tx/rx_queues() requires rtnl_lock() */ | ||
3214 | rtnl_lock(); | ||
3166 | status = be_setup_queues(adapter); | 3215 | status = be_setup_queues(adapter); |
3216 | rtnl_unlock(); | ||
3167 | if (status) | 3217 | if (status) |
3168 | goto err; | 3218 | goto err; |
3169 | 3219 | ||
@@ -3202,8 +3252,7 @@ static int be_setup(struct be_adapter *adapter) | |||
3202 | if (!status && be_pause_supported(adapter)) | 3252 | if (!status && be_pause_supported(adapter)) |
3203 | adapter->phy.fc_autoneg = 1; | 3253 | adapter->phy.fc_autoneg = 1; |
3204 | 3254 | ||
3205 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); | 3255 | be_schedule_worker(adapter); |
3206 | adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; | ||
3207 | return 0; | 3256 | return 0; |
3208 | err: | 3257 | err: |
3209 | be_clear(adapter); | 3258 | be_clear(adapter); |
@@ -3769,8 +3818,6 @@ static const struct net_device_ops be_netdev_ops = { | |||
3769 | static void be_netdev_init(struct net_device *netdev) | 3818 | static void be_netdev_init(struct net_device *netdev) |
3770 | { | 3819 | { |
3771 | struct be_adapter *adapter = netdev_priv(netdev); | 3820 | struct be_adapter *adapter = netdev_priv(netdev); |
3772 | struct be_eq_obj *eqo; | ||
3773 | int i; | ||
3774 | 3821 | ||
3775 | netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | | 3822 | netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | |
3776 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | | 3823 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | |
@@ -3793,9 +3840,6 @@ static void be_netdev_init(struct net_device *netdev) | |||
3793 | netdev->netdev_ops = &be_netdev_ops; | 3840 | netdev->netdev_ops = &be_netdev_ops; |
3794 | 3841 | ||
3795 | SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); | 3842 | SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); |
3796 | |||
3797 | for_all_evt_queues(adapter, eqo, i) | ||
3798 | netif_napi_add(netdev, &eqo->napi, be_poll, BE_NAPI_WEIGHT); | ||
3799 | } | 3843 | } |
3800 | 3844 | ||
3801 | static void be_unmap_pci_bars(struct be_adapter *adapter) | 3845 | static void be_unmap_pci_bars(struct be_adapter *adapter) |