1 /*
2 * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33 #include <linux/dim.h>
34 #include <linux/ethtool_netlink.h>
35
36 #include "en.h"
37 #include "en/channels.h"
38 #include "en/dim.h"
39 #include "en/port.h"
40 #include "en/params.h"
41 #include "en/ptp.h"
42 #include "lib/clock.h"
43 #include "en/fs_ethtool.h"
44
mlx5e_ethtool_get_drvinfo(struct mlx5e_priv * priv,struct ethtool_drvinfo * drvinfo)45 void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
46 struct ethtool_drvinfo *drvinfo)
47 {
48 struct mlx5_core_dev *mdev = priv->mdev;
49 int count;
50
51 strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
52 count = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
53 "%d.%d.%04d (%.16s)", fw_rev_maj(mdev),
54 fw_rev_min(mdev), fw_rev_sub(mdev), mdev->board_id);
55 if (count >= sizeof(drvinfo->fw_version))
56 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
57 "%d.%d.%04d", fw_rev_maj(mdev),
58 fw_rev_min(mdev), fw_rev_sub(mdev));
59
60 strscpy(drvinfo->bus_info, dev_name(mdev->device),
61 sizeof(drvinfo->bus_info));
62 }
63
mlx5e_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * drvinfo)64 static void mlx5e_get_drvinfo(struct net_device *dev,
65 struct ethtool_drvinfo *drvinfo)
66 {
67 struct mlx5e_priv *priv = netdev_priv(dev);
68
69 mlx5e_ethtool_get_drvinfo(priv, drvinfo);
70 }
71
72 struct ptys2ethtool_config {
73 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
74 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised);
75 };
76
77 static
78 struct ptys2ethtool_config ptys2legacy_ethtool_table[MLX5E_LINK_MODES_NUMBER];
79 static
80 struct ptys2ethtool_config ptys2ext_ethtool_table[MLX5E_EXT_LINK_MODES_NUMBER];
81
82 #define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, table, ...) \
83 ({ \
84 struct ptys2ethtool_config *cfg; \
85 const unsigned int modes[] = { __VA_ARGS__ }; \
86 unsigned int i; \
87 cfg = &ptys2##table##_ethtool_table[reg_]; \
88 bitmap_zero(cfg->supported, \
89 __ETHTOOL_LINK_MODE_MASK_NBITS); \
90 bitmap_zero(cfg->advertised, \
91 __ETHTOOL_LINK_MODE_MASK_NBITS); \
92 for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \
93 bitmap_set(cfg->supported, modes[i], 1); \
94 bitmap_set(cfg->advertised, modes[i], 1); \
95 } \
96 })
97
mlx5e_build_ptys2ethtool_map(void)98 void mlx5e_build_ptys2ethtool_map(void)
99 {
100 memset(ptys2legacy_ethtool_table, 0, sizeof(ptys2legacy_ethtool_table));
101 memset(ptys2ext_ethtool_table, 0, sizeof(ptys2ext_ethtool_table));
102 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, legacy,
103 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
104 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, legacy,
105 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
106 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, legacy,
107 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);
108 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, legacy,
109 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);
110 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, legacy,
111 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
112 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, legacy,
113 ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT);
114 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, legacy,
115 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT);
116 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, legacy,
117 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT);
118 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, legacy,
119 ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT);
120 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, legacy,
121 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
122 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, legacy,
123 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
124 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, legacy,
125 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
126 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, legacy,
127 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT);
128 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, legacy,
129 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT);
130 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, legacy,
131 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT);
132 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, legacy,
133 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT);
134 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, legacy,
135 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT);
136 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, legacy,
137 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT);
138 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, legacy,
139 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT);
140 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100BASE_TX, legacy,
141 ETHTOOL_LINK_MODE_100baseT_Full_BIT);
142 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_T, legacy,
143 ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
144 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, legacy,
145 ETHTOOL_LINK_MODE_10000baseT_Full_BIT);
146 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, legacy,
147 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT);
148 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, legacy,
149 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT);
150 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, legacy,
151 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT);
152 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, legacy,
153 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT);
154 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, legacy,
155 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT);
156 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_SGMII_100M, ext,
157 ETHTOOL_LINK_MODE_100baseT_Full_BIT);
158 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_X_SGMII, ext,
159 ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
160 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
161 ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
162 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_5GBASE_R, ext,
163 ETHTOOL_LINK_MODE_5000baseT_Full_BIT);
164 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_XFI_XAUI_1, ext,
165 ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
166 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
167 ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
168 ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
169 ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
170 ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
171 ETHTOOL_LINK_MODE_10000baseER_Full_BIT);
172 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_XLAUI_4_XLPPI_4, ext,
173 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
174 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
175 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
176 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT);
177 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GAUI_1_25GBASE_CR_KR, ext,
178 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
179 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
180 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT);
181 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
182 ext,
183 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
184 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
185 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT);
186 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR, ext,
187 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
188 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
189 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
190 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
191 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT);
192 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_CAUI_4_100GBASE_CR4_KR4, ext,
193 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
194 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
195 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
196 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT);
197 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GAUI_2_100GBASE_CR2_KR2, ext,
198 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
199 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
200 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
201 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
202 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT);
203 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_200GAUI_4_200GBASE_CR4_KR4, ext,
204 ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
205 ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
206 ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
207 ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
208 ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT);
209 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_400GAUI_8_400GBASE_CR8, ext,
210 ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
211 ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
212 ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
213 ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
214 ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT);
215 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GAUI_1_100GBASE_CR_KR, ext,
216 ETHTOOL_LINK_MODE_100000baseKR_Full_BIT,
217 ETHTOOL_LINK_MODE_100000baseSR_Full_BIT,
218 ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT,
219 ETHTOOL_LINK_MODE_100000baseDR_Full_BIT,
220 ETHTOOL_LINK_MODE_100000baseCR_Full_BIT);
221 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_200GAUI_2_200GBASE_CR2_KR2, ext,
222 ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT,
223 ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT,
224 ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT,
225 ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT,
226 ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT);
227 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_400GAUI_4_400GBASE_CR4_KR4, ext,
228 ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT,
229 ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT,
230 ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT,
231 ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT,
232 ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT);
233 MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_800GAUI_8_800GBASE_CR8_KR8, ext,
234 ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT,
235 ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT,
236 ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT,
237 ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT,
238 ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT,
239 ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT);
240 }
241
mlx5e_ethtool_get_speed_arr(struct mlx5_core_dev * mdev,struct ptys2ethtool_config ** arr,u32 * size)242 static void mlx5e_ethtool_get_speed_arr(struct mlx5_core_dev *mdev,
243 struct ptys2ethtool_config **arr,
244 u32 *size)
245 {
246 bool ext = mlx5_ptys_ext_supported(mdev);
247
248 *arr = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
249 *size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
250 ARRAY_SIZE(ptys2legacy_ethtool_table);
251 }
252
253 typedef int (*mlx5e_pflag_handler)(struct net_device *netdev, bool enable);
254
255 struct pflag_desc {
256 char name[ETH_GSTRING_LEN];
257 mlx5e_pflag_handler handler;
258 };
259
260 static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS];
261
mlx5e_ethtool_get_sset_count(struct mlx5e_priv * priv,int sset)262 int mlx5e_ethtool_get_sset_count(struct mlx5e_priv *priv, int sset)
263 {
264 switch (sset) {
265 case ETH_SS_STATS:
266 return mlx5e_stats_total_num(priv);
267 case ETH_SS_PRIV_FLAGS:
268 return MLX5E_NUM_PFLAGS;
269 case ETH_SS_TEST:
270 return mlx5e_self_test_num(priv);
271 default:
272 return -EOPNOTSUPP;
273 }
274 }
275
mlx5e_get_sset_count(struct net_device * dev,int sset)276 static int mlx5e_get_sset_count(struct net_device *dev, int sset)
277 {
278 struct mlx5e_priv *priv = netdev_priv(dev);
279
280 return mlx5e_ethtool_get_sset_count(priv, sset);
281 }
282
mlx5e_ethtool_get_strings(struct mlx5e_priv * priv,u32 stringset,u8 * data)283 void mlx5e_ethtool_get_strings(struct mlx5e_priv *priv, u32 stringset, u8 *data)
284 {
285 int i;
286
287 switch (stringset) {
288 case ETH_SS_PRIV_FLAGS:
289 for (i = 0; i < MLX5E_NUM_PFLAGS; i++)
290 ethtool_puts(&data, mlx5e_priv_flags[i].name);
291 break;
292
293 case ETH_SS_TEST:
294 mlx5e_self_test_fill_strings(priv, data);
295 break;
296
297 case ETH_SS_STATS:
298 mlx5e_stats_fill_strings(priv, data);
299 break;
300 }
301 }
302
mlx5e_get_strings(struct net_device * dev,u32 stringset,u8 * data)303 static void mlx5e_get_strings(struct net_device *dev, u32 stringset, u8 *data)
304 {
305 struct mlx5e_priv *priv = netdev_priv(dev);
306
307 mlx5e_ethtool_get_strings(priv, stringset, data);
308 }
309
mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv * priv,struct ethtool_stats * stats,u64 * data)310 void mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv *priv,
311 struct ethtool_stats *stats, u64 *data)
312 {
313 int idx = 0;
314
315 mutex_lock(&priv->state_lock);
316 mlx5e_stats_update(priv);
317 mutex_unlock(&priv->state_lock);
318
319 mlx5e_stats_fill(priv, data, idx);
320 }
321
mlx5e_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)322 static void mlx5e_get_ethtool_stats(struct net_device *dev,
323 struct ethtool_stats *stats,
324 u64 *data)
325 {
326 struct mlx5e_priv *priv = netdev_priv(dev);
327
328 mlx5e_ethtool_get_ethtool_stats(priv, stats, data);
329 }
330
mlx5e_ethtool_get_ringparam(struct mlx5e_priv * priv,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param)331 void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv,
332 struct ethtool_ringparam *param,
333 struct kernel_ethtool_ringparam *kernel_param)
334 {
335 /* Limitation for regular RQ. XSK RQ may clamp the queue length in
336 * mlx5e_mpwqe_get_log_rq_size.
337 */
338 u8 max_log_mpwrq_pkts = mlx5e_mpwrq_max_log_rq_pkts(priv->mdev,
339 PAGE_SHIFT,
340 MLX5E_MPWRQ_UMR_MODE_ALIGNED);
341
342 param->rx_max_pending = 1 << min_t(u8, MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE,
343 max_log_mpwrq_pkts);
344 param->tx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
345 param->rx_pending = 1 << priv->channels.params.log_rq_mtu_frames;
346 param->tx_pending = 1 << priv->channels.params.log_sq_size;
347
348 kernel_param->tcp_data_split =
349 (priv->channels.params.packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO) ?
350 ETHTOOL_TCP_DATA_SPLIT_ENABLED :
351 ETHTOOL_TCP_DATA_SPLIT_DISABLED;
352 }
353
mlx5e_get_ringparam(struct net_device * dev,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param,struct netlink_ext_ack * extack)354 static void mlx5e_get_ringparam(struct net_device *dev,
355 struct ethtool_ringparam *param,
356 struct kernel_ethtool_ringparam *kernel_param,
357 struct netlink_ext_ack *extack)
358 {
359 struct mlx5e_priv *priv = netdev_priv(dev);
360
361 mlx5e_ethtool_get_ringparam(priv, param, kernel_param);
362 }
363
mlx5e_ethtool_set_ringparam(struct mlx5e_priv * priv,struct ethtool_ringparam * param,struct netlink_ext_ack * extack)364 int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv,
365 struct ethtool_ringparam *param,
366 struct netlink_ext_ack *extack)
367 {
368 struct mlx5e_params new_params;
369 u8 log_rq_size;
370 u8 log_sq_size;
371 int err = 0;
372
373 if (param->rx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
374 NL_SET_ERR_MSG_FMT_MOD(extack, "rx (%d) < min (%d)",
375 param->rx_pending,
376 1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
377 return -EINVAL;
378 }
379
380 if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
381 NL_SET_ERR_MSG_FMT_MOD(extack, "tx (%d) < min (%d)",
382 param->tx_pending,
383 1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
384 return -EINVAL;
385 }
386
387 log_rq_size = order_base_2(param->rx_pending);
388 log_sq_size = order_base_2(param->tx_pending);
389
390 if (log_rq_size == priv->channels.params.log_rq_mtu_frames &&
391 log_sq_size == priv->channels.params.log_sq_size)
392 return 0;
393
394 mutex_lock(&priv->state_lock);
395
396 new_params = priv->channels.params;
397 new_params.log_rq_mtu_frames = log_rq_size;
398 new_params.log_sq_size = log_sq_size;
399
400 err = mlx5e_validate_params(priv->mdev, &new_params);
401 if (err)
402 goto unlock;
403
404 err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
405
406 unlock:
407 mutex_unlock(&priv->state_lock);
408
409 return err;
410 }
411
mlx5e_set_ringparam(struct net_device * dev,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param,struct netlink_ext_ack * extack)412 static int mlx5e_set_ringparam(struct net_device *dev,
413 struct ethtool_ringparam *param,
414 struct kernel_ethtool_ringparam *kernel_param,
415 struct netlink_ext_ack *extack)
416 {
417 struct mlx5e_priv *priv = netdev_priv(dev);
418
419 return mlx5e_ethtool_set_ringparam(priv, param, extack);
420 }
421
mlx5e_ethtool_get_channels(struct mlx5e_priv * priv,struct ethtool_channels * ch)422 void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv,
423 struct ethtool_channels *ch)
424 {
425 mutex_lock(&priv->state_lock);
426 ch->max_combined = priv->max_nch;
427 ch->combined_count = priv->channels.params.num_channels;
428 mutex_unlock(&priv->state_lock);
429 }
430
mlx5e_get_channels(struct net_device * dev,struct ethtool_channels * ch)431 static void mlx5e_get_channels(struct net_device *dev,
432 struct ethtool_channels *ch)
433 {
434 struct mlx5e_priv *priv = netdev_priv(dev);
435
436 mlx5e_ethtool_get_channels(priv, ch);
437 }
438
mlx5e_ethtool_set_channels(struct mlx5e_priv * priv,struct ethtool_channels * ch)439 int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
440 struct ethtool_channels *ch)
441 {
442 struct mlx5e_params *cur_params = &priv->channels.params;
443 unsigned int count = ch->combined_count;
444 struct mlx5e_params new_params;
445 bool arfs_enabled;
446 bool opened;
447 int err = 0;
448
449 if (!count) {
450 netdev_info(priv->netdev, "%s: combined_count=0 not supported\n",
451 __func__);
452 return -EINVAL;
453 }
454
455 if (cur_params->num_channels == count)
456 return 0;
457
458 mutex_lock(&priv->state_lock);
459
460 if (mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc == ETH_RSS_HASH_XOR) {
461 unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();
462
463 if (count > xor8_max_channels) {
464 err = -EINVAL;
465 netdev_err(priv->netdev, "%s: Requested number of channels (%d) exceeds the maximum allowed by the XOR8 RSS hfunc (%d)\n",
466 __func__, count, xor8_max_channels);
467 goto out;
468 }
469 }
470
471 /* If RXFH is configured, changing the channels number is allowed only if
472 * it does not require resizing the RSS table. This is because the previous
473 * configuration may no longer be compatible with the new RSS table.
474 */
475 if (netif_is_rxfh_configured(priv->netdev)) {
476 int cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels);
477 int new_rqt_size = mlx5e_rqt_size(priv->mdev, count);
478
479 if (new_rqt_size != cur_rqt_size) {
480 err = -EINVAL;
481 netdev_err(priv->netdev,
482 "%s: RXFH is configured, block changing channels number that affects RSS table size (new: %d, current: %d)\n",
483 __func__, new_rqt_size, cur_rqt_size);
484 goto out;
485 }
486 }
487
488 /* Don't allow changing the number of channels if HTB offload is active,
489 * because the numeration of the QoS SQs will change, while per-queue
490 * qdiscs are attached.
491 */
492 if (mlx5e_selq_is_htb_enabled(&priv->selq)) {
493 err = -EINVAL;
494 netdev_err(priv->netdev, "%s: HTB offload is active, cannot change the number of channels\n",
495 __func__);
496 goto out;
497 }
498
499 /* Don't allow changing the number of channels if MQPRIO mode channel offload is active,
500 * because it defines a partition over the channels queues.
501 */
502 if (cur_params->mqprio.mode == TC_MQPRIO_MODE_CHANNEL) {
503 err = -EINVAL;
504 netdev_err(priv->netdev, "%s: MQPRIO mode channel offload is active, cannot change the number of channels\n",
505 __func__);
506 goto out;
507 }
508
509 new_params = *cur_params;
510 new_params.num_channels = count;
511
512 opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
513
514 arfs_enabled = opened && mlx5e_fs_want_arfs(priv->netdev);
515 if (arfs_enabled)
516 mlx5e_arfs_disable(priv->fs);
517
518 /* Switch to new channels, set new parameters and close old ones */
519 err = mlx5e_safe_switch_params(priv, &new_params,
520 mlx5e_num_channels_changed_ctx, NULL, true);
521
522 if (arfs_enabled) {
523 int err2 = mlx5e_arfs_enable(priv->fs);
524
525 if (err2)
526 netdev_err(priv->netdev, "%s: mlx5e_arfs_enable failed: %d\n",
527 __func__, err2);
528 }
529
530 out:
531 mutex_unlock(&priv->state_lock);
532
533 return err;
534 }
535
mlx5e_set_channels(struct net_device * dev,struct ethtool_channels * ch)536 static int mlx5e_set_channels(struct net_device *dev,
537 struct ethtool_channels *ch)
538 {
539 struct mlx5e_priv *priv = netdev_priv(dev);
540
541 return mlx5e_ethtool_set_channels(priv, ch);
542 }
543
mlx5e_ethtool_get_coalesce(struct mlx5e_priv * priv,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)544 int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv,
545 struct ethtool_coalesce *coal,
546 struct kernel_ethtool_coalesce *kernel_coal,
547 struct netlink_ext_ack *extack)
548 {
549 struct dim_cq_moder *rx_moder, *tx_moder;
550
551 if (!MLX5_CAP_GEN(priv->mdev, cq_moderation)) {
552 NL_SET_ERR_MSG_MOD(extack, "CQ moderation not supported");
553 return -EOPNOTSUPP;
554 }
555
556 rx_moder = &priv->channels.params.rx_cq_moderation;
557 coal->rx_coalesce_usecs = rx_moder->usec;
558 coal->rx_max_coalesced_frames = rx_moder->pkts;
559 coal->use_adaptive_rx_coalesce = priv->channels.params.rx_dim_enabled;
560 kernel_coal->use_cqe_mode_rx = priv->channels.params.rx_moder_use_cqe_mode;
561
562 tx_moder = &priv->channels.params.tx_cq_moderation;
563 coal->tx_coalesce_usecs = tx_moder->usec;
564 coal->tx_max_coalesced_frames = tx_moder->pkts;
565 coal->use_adaptive_tx_coalesce = priv->channels.params.tx_dim_enabled;
566 kernel_coal->use_cqe_mode_tx = priv->channels.params.tx_moder_use_cqe_mode;
567
568 return 0;
569 }
570
mlx5e_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)571 static int mlx5e_get_coalesce(struct net_device *netdev,
572 struct ethtool_coalesce *coal,
573 struct kernel_ethtool_coalesce *kernel_coal,
574 struct netlink_ext_ack *extack)
575 {
576 struct mlx5e_priv *priv = netdev_priv(netdev);
577
578 return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal, extack);
579 }
580
mlx5e_ethtool_get_per_queue_coalesce(struct mlx5e_priv * priv,u32 queue,struct ethtool_coalesce * coal)581 static int mlx5e_ethtool_get_per_queue_coalesce(struct mlx5e_priv *priv, u32 queue,
582 struct ethtool_coalesce *coal)
583 {
584 struct dim_cq_moder cur_moder;
585 struct mlx5e_channels *chs;
586 struct mlx5e_channel *c;
587
588 if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
589 return -EOPNOTSUPP;
590
591 mutex_lock(&priv->state_lock);
592
593 chs = &priv->channels;
594 if (chs->num <= queue) {
595 mutex_unlock(&priv->state_lock);
596 return -EINVAL;
597 }
598
599 c = chs->c[queue];
600
601 coal->use_adaptive_rx_coalesce = !!c->rq.dim;
602 if (coal->use_adaptive_rx_coalesce) {
603 cur_moder = net_dim_get_rx_moderation(c->rq.dim->mode,
604 c->rq.dim->profile_ix);
605
606 coal->rx_coalesce_usecs = cur_moder.usec;
607 coal->rx_max_coalesced_frames = cur_moder.pkts;
608 } else {
609 coal->rx_coalesce_usecs = c->rx_cq_moder.usec;
610 coal->rx_max_coalesced_frames = c->rx_cq_moder.pkts;
611 }
612
613 coal->use_adaptive_tx_coalesce = !!c->sq[0].dim;
614 if (coal->use_adaptive_tx_coalesce) {
615 /* NOTE: Will only display DIM coalesce profile information of
616 * first channel. The current interface cannot display this
617 * information for all tc.
618 */
619 cur_moder = net_dim_get_tx_moderation(c->sq[0].dim->mode,
620 c->sq[0].dim->profile_ix);
621
622 coal->tx_coalesce_usecs = cur_moder.usec;
623 coal->tx_max_coalesced_frames = cur_moder.pkts;
624
625 } else {
626 coal->tx_coalesce_usecs = c->tx_cq_moder.usec;
627 coal->tx_max_coalesced_frames = c->tx_cq_moder.pkts;
628 }
629
630 mutex_unlock(&priv->state_lock);
631
632 return 0;
633 }
634
mlx5e_get_per_queue_coalesce(struct net_device * dev,u32 queue,struct ethtool_coalesce * coal)635 int mlx5e_get_per_queue_coalesce(struct net_device *dev, u32 queue,
636 struct ethtool_coalesce *coal)
637 {
638 struct mlx5e_priv *priv = netdev_priv(dev);
639
640 return mlx5e_ethtool_get_per_queue_coalesce(priv, queue, coal);
641 }
642
643 #define MLX5E_MAX_COAL_TIME MLX5_MAX_CQ_PERIOD
644 #define MLX5E_MAX_COAL_FRAMES MLX5_MAX_CQ_COUNT
645
646 static void
mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv * priv,struct dim_cq_moder * moder)647 mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct dim_cq_moder *moder)
648 {
649 int tc;
650 int i;
651
652 for (i = 0; i < priv->channels.num; ++i) {
653 struct mlx5e_channel *c = priv->channels.c[i];
654 struct mlx5_core_dev *mdev = c->mdev;
655 enum mlx5_cq_period_mode mode;
656
657 mode = mlx5e_cq_period_mode(moder->cq_period_mode);
658 c->tx_cq_moder = *moder;
659
660 for (tc = 0; tc < c->num_tc; tc++) {
661 mlx5e_modify_cq_moderation(mdev, &c->sq[tc].cq.mcq,
662 moder->usec, moder->pkts,
663 mode);
664 }
665 }
666 }
667
668 static void
mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv * priv,struct dim_cq_moder * moder)669 mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct dim_cq_moder *moder)
670 {
671 int i;
672
673 for (i = 0; i < priv->channels.num; ++i) {
674 struct mlx5e_channel *c = priv->channels.c[i];
675 struct mlx5_core_dev *mdev = c->mdev;
676 enum mlx5_cq_period_mode mode;
677
678 mode = mlx5e_cq_period_mode(moder->cq_period_mode);
679 c->rx_cq_moder = *moder;
680
681 mlx5e_modify_cq_moderation(mdev, &c->rq.cq.mcq, moder->usec, moder->pkts,
682 mode);
683 }
684 }
685
mlx5e_ethtool_set_coalesce(struct mlx5e_priv * priv,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)686 int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
687 struct ethtool_coalesce *coal,
688 struct kernel_ethtool_coalesce *kernel_coal,
689 struct netlink_ext_ack *extack)
690 {
691 struct dim_cq_moder *rx_moder, *tx_moder;
692 struct mlx5_core_dev *mdev = priv->mdev;
693 bool rx_dim_enabled, tx_dim_enabled;
694 struct mlx5e_params new_params;
695 bool reset_rx, reset_tx;
696 u8 cq_period_mode;
697 int err = 0;
698
699 if (!MLX5_CAP_GEN(mdev, cq_moderation) ||
700 !MLX5_CAP_GEN(mdev, cq_period_mode_modify)) {
701 NL_SET_ERR_MSG_MOD(extack, "CQ moderation not supported");
702 return -EOPNOTSUPP;
703 }
704
705 if (coal->tx_coalesce_usecs > MLX5E_MAX_COAL_TIME ||
706 coal->rx_coalesce_usecs > MLX5E_MAX_COAL_TIME) {
707 NL_SET_ERR_MSG_FMT_MOD(
708 extack,
709 "Max coalesce time %lu usecs, tx-usecs (%u) rx-usecs (%u)",
710 MLX5E_MAX_COAL_TIME, coal->tx_coalesce_usecs,
711 coal->rx_coalesce_usecs);
712 return -ERANGE;
713 }
714
715 if (coal->tx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES ||
716 coal->rx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES) {
717 NL_SET_ERR_MSG_FMT_MOD(
718 extack,
719 "Max coalesce frames %lu, tx-frames (%u) rx-frames (%u)",
720 MLX5E_MAX_COAL_FRAMES, coal->tx_max_coalesced_frames,
721 coal->rx_max_coalesced_frames);
722 return -ERANGE;
723 }
724
725 if ((kernel_coal->use_cqe_mode_rx || kernel_coal->use_cqe_mode_tx) &&
726 !MLX5_CAP_GEN(priv->mdev, cq_period_start_from_cqe)) {
727 NL_SET_ERR_MSG_MOD(extack, "cqe-mode-rx/tx is not supported on this device");
728 return -EOPNOTSUPP;
729 }
730
731 rx_dim_enabled = !!coal->use_adaptive_rx_coalesce;
732 tx_dim_enabled = !!coal->use_adaptive_tx_coalesce;
733
734 mutex_lock(&priv->state_lock);
735 new_params = priv->channels.params;
736
737 cq_period_mode = mlx5e_dim_cq_period_mode(kernel_coal->use_cqe_mode_rx);
738 reset_rx = mlx5e_reset_rx_channels_moderation(&priv->channels, cq_period_mode,
739 rx_dim_enabled, false);
740 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_CQE_BASED_MODER, cq_period_mode);
741
742 cq_period_mode = mlx5e_dim_cq_period_mode(kernel_coal->use_cqe_mode_tx);
743 reset_tx = mlx5e_reset_tx_channels_moderation(&priv->channels, cq_period_mode,
744 tx_dim_enabled, false);
745 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_TX_CQE_BASED_MODER, cq_period_mode);
746
747 reset_rx |= rx_dim_enabled != new_params.rx_dim_enabled;
748 reset_tx |= tx_dim_enabled != new_params.tx_dim_enabled;
749
750 /* Solely used for global ethtool get coalesce */
751 rx_moder = &new_params.rx_cq_moderation;
752 new_params.rx_dim_enabled = rx_dim_enabled;
753 new_params.rx_moder_use_cqe_mode = kernel_coal->use_cqe_mode_rx;
754
755 tx_moder = &new_params.tx_cq_moderation;
756 new_params.tx_dim_enabled = tx_dim_enabled;
757 new_params.tx_moder_use_cqe_mode = kernel_coal->use_cqe_mode_tx;
758
759 if (reset_rx) {
760 mlx5e_channels_rx_change_dim(&priv->channels, false);
761 mlx5e_reset_rx_moderation(rx_moder, new_params.rx_moder_use_cqe_mode,
762 rx_dim_enabled);
763
764 mlx5e_set_priv_channels_rx_coalesce(priv, rx_moder);
765 } else if (!rx_dim_enabled) {
766 rx_moder->usec = coal->rx_coalesce_usecs;
767 rx_moder->pkts = coal->rx_max_coalesced_frames;
768
769 mlx5e_set_priv_channels_rx_coalesce(priv, rx_moder);
770 }
771
772 if (reset_tx) {
773 mlx5e_channels_tx_change_dim(&priv->channels, false);
774 mlx5e_reset_tx_moderation(tx_moder, new_params.tx_moder_use_cqe_mode,
775 tx_dim_enabled);
776
777 mlx5e_set_priv_channels_tx_coalesce(priv, tx_moder);
778 } else if (!tx_dim_enabled) {
779 tx_moder->usec = coal->tx_coalesce_usecs;
780 tx_moder->pkts = coal->tx_max_coalesced_frames;
781
782 mlx5e_set_priv_channels_tx_coalesce(priv, tx_moder);
783 }
784
785 /* DIM enable/disable Rx and Tx channels */
786 err = mlx5e_channels_rx_change_dim(&priv->channels, rx_dim_enabled);
787 if (err)
788 goto state_unlock;
789 err = mlx5e_channels_tx_change_dim(&priv->channels, tx_dim_enabled);
790 if (err)
791 goto state_unlock;
792
793 err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, false);
794 state_unlock:
795 mutex_unlock(&priv->state_lock);
796 return err;
797 }
798
mlx5e_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)799 static int mlx5e_set_coalesce(struct net_device *netdev,
800 struct ethtool_coalesce *coal,
801 struct kernel_ethtool_coalesce *kernel_coal,
802 struct netlink_ext_ack *extack)
803 {
804 struct mlx5e_priv *priv = netdev_priv(netdev);
805
806 return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack);
807 }
808
mlx5e_ethtool_set_per_queue_coalesce(struct mlx5e_priv * priv,u32 queue,struct ethtool_coalesce * coal)809 static int mlx5e_ethtool_set_per_queue_coalesce(struct mlx5e_priv *priv, u32 queue,
810 struct ethtool_coalesce *coal)
811 {
812 struct mlx5_core_dev *mdev = priv->mdev;
813 bool rx_dim_enabled, tx_dim_enabled;
814 struct mlx5e_channels *chs;
815 struct mlx5e_channel *c;
816 int err = 0;
817 int tc;
818
819 if (!MLX5_CAP_GEN(mdev, cq_moderation))
820 return -EOPNOTSUPP;
821
822 if (coal->tx_coalesce_usecs > MLX5E_MAX_COAL_TIME ||
823 coal->rx_coalesce_usecs > MLX5E_MAX_COAL_TIME) {
824 netdev_info(priv->netdev, "%s: maximum coalesce time supported is %lu usecs\n",
825 __func__, MLX5E_MAX_COAL_TIME);
826 return -ERANGE;
827 }
828
829 if (coal->tx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES ||
830 coal->rx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES) {
831 netdev_info(priv->netdev, "%s: maximum coalesced frames supported is %lu\n",
832 __func__, MLX5E_MAX_COAL_FRAMES);
833 return -ERANGE;
834 }
835
836 rx_dim_enabled = !!coal->use_adaptive_rx_coalesce;
837 tx_dim_enabled = !!coal->use_adaptive_tx_coalesce;
838
839 mutex_lock(&priv->state_lock);
840
841 chs = &priv->channels;
842 if (chs->num <= queue) {
843 mutex_unlock(&priv->state_lock);
844 return -EINVAL;
845 }
846
847 c = chs->c[queue];
848
849 err = mlx5e_dim_rx_change(&c->rq, rx_dim_enabled);
850 if (err)
851 goto state_unlock;
852
853 for (tc = 0; tc < c->num_tc; tc++) {
854 err = mlx5e_dim_tx_change(&c->sq[tc], tx_dim_enabled);
855 if (err)
856 goto state_unlock;
857 }
858
859 if (!rx_dim_enabled) {
860 c->rx_cq_moder.usec = coal->rx_coalesce_usecs;
861 c->rx_cq_moder.pkts = coal->rx_max_coalesced_frames;
862
863 mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq,
864 coal->rx_coalesce_usecs,
865 coal->rx_max_coalesced_frames);
866 }
867
868 if (!tx_dim_enabled) {
869 c->tx_cq_moder.usec = coal->tx_coalesce_usecs;
870 c->tx_cq_moder.pkts = coal->tx_max_coalesced_frames;
871
872 for (tc = 0; tc < c->num_tc; tc++)
873 mlx5_core_modify_cq_moderation(mdev, &c->sq[tc].cq.mcq,
874 coal->tx_coalesce_usecs,
875 coal->tx_max_coalesced_frames);
876 }
877
878 state_unlock:
879 mutex_unlock(&priv->state_lock);
880 return err;
881 }
882
mlx5e_set_per_queue_coalesce(struct net_device * dev,u32 queue,struct ethtool_coalesce * coal)883 int mlx5e_set_per_queue_coalesce(struct net_device *dev, u32 queue,
884 struct ethtool_coalesce *coal)
885 {
886 struct mlx5e_priv *priv = netdev_priv(dev);
887
888 return mlx5e_ethtool_set_per_queue_coalesce(priv, queue, coal);
889 }
890
ptys2ethtool_supported_link(struct mlx5_core_dev * mdev,unsigned long * supported_modes,u32 eth_proto_cap)891 static void ptys2ethtool_supported_link(struct mlx5_core_dev *mdev,
892 unsigned long *supported_modes,
893 u32 eth_proto_cap)
894 {
895 unsigned long proto_cap = eth_proto_cap;
896 struct ptys2ethtool_config *table;
897 u32 max_size;
898 int proto;
899
900 mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size);
901 for_each_set_bit(proto, &proto_cap, max_size)
902 bitmap_or(supported_modes, supported_modes,
903 table[proto].supported,
904 __ETHTOOL_LINK_MODE_MASK_NBITS);
905 }
906
ptys2ethtool_adver_link(unsigned long * advertising_modes,u32 eth_proto_cap,bool ext)907 static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
908 u32 eth_proto_cap, bool ext)
909 {
910 unsigned long proto_cap = eth_proto_cap;
911 struct ptys2ethtool_config *table;
912 u32 max_size;
913 int proto;
914
915 table = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
916 max_size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
917 ARRAY_SIZE(ptys2legacy_ethtool_table);
918
919 for_each_set_bit(proto, &proto_cap, max_size)
920 bitmap_or(advertising_modes, advertising_modes,
921 table[proto].advertised,
922 __ETHTOOL_LINK_MODE_MASK_NBITS);
923 }
924
925 static const u32 pplm_fec_2_ethtool[] = {
926 [MLX5E_FEC_NOFEC] = ETHTOOL_FEC_OFF,
927 [MLX5E_FEC_FIRECODE] = ETHTOOL_FEC_BASER,
928 [MLX5E_FEC_RS_528_514] = ETHTOOL_FEC_RS,
929 [MLX5E_FEC_RS_544_514] = ETHTOOL_FEC_RS,
930 [MLX5E_FEC_LLRS_272_257_1] = ETHTOOL_FEC_LLRS,
931 };
932
pplm2ethtool_fec(u_long fec_mode,unsigned long size)933 static u32 pplm2ethtool_fec(u_long fec_mode, unsigned long size)
934 {
935 int mode = 0;
936
937 if (!fec_mode)
938 return ETHTOOL_FEC_AUTO;
939
940 mode = find_first_bit(&fec_mode, size);
941
942 if (mode < ARRAY_SIZE(pplm_fec_2_ethtool))
943 return pplm_fec_2_ethtool[mode];
944
945 return 0;
946 }
947
948 #define MLX5E_ADVERTISE_SUPPORTED_FEC(mlx5_fec, ethtool_fec) \
949 do { \
950 if (mlx5e_fec_in_caps(dev, 1 << (mlx5_fec))) \
951 __set_bit(ethtool_fec, \
952 link_ksettings->link_modes.supported);\
953 } while (0)
954
955 static const u32 pplm_fec_2_ethtool_linkmodes[] = {
956 [MLX5E_FEC_NOFEC] = ETHTOOL_LINK_MODE_FEC_NONE_BIT,
957 [MLX5E_FEC_FIRECODE] = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
958 [MLX5E_FEC_RS_528_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
959 [MLX5E_FEC_RS_544_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
960 [MLX5E_FEC_LLRS_272_257_1] = ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
961 };
962
get_fec_supported_advertised(struct mlx5_core_dev * dev,struct ethtool_link_ksettings * link_ksettings)963 static int get_fec_supported_advertised(struct mlx5_core_dev *dev,
964 struct ethtool_link_ksettings *link_ksettings)
965 {
966 unsigned long active_fec_long;
967 u32 active_fec;
968 u32 bitn;
969 int err;
970
971 err = mlx5e_get_fec_mode(dev, &active_fec, NULL);
972 if (err)
973 return (err == -EOPNOTSUPP) ? 0 : err;
974
975 MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_NOFEC,
976 ETHTOOL_LINK_MODE_FEC_NONE_BIT);
977 MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_FIRECODE,
978 ETHTOOL_LINK_MODE_FEC_BASER_BIT);
979 MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_RS_528_514,
980 ETHTOOL_LINK_MODE_FEC_RS_BIT);
981 MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_LLRS_272_257_1,
982 ETHTOOL_LINK_MODE_FEC_LLRS_BIT);
983
984 active_fec_long = active_fec;
985 /* active fec is a bit set, find out which bit is set and
986 * advertise the corresponding ethtool bit
987 */
988 bitn = find_first_bit(&active_fec_long, sizeof(active_fec_long) * BITS_PER_BYTE);
989 if (bitn < ARRAY_SIZE(pplm_fec_2_ethtool_linkmodes))
990 __set_bit(pplm_fec_2_ethtool_linkmodes[bitn],
991 link_ksettings->link_modes.advertising);
992
993 return 0;
994 }
995
ptys2ethtool_supported_advertised_port(struct mlx5_core_dev * mdev,struct ethtool_link_ksettings * link_ksettings,u32 eth_proto_cap,u8 connector_type)996 static void ptys2ethtool_supported_advertised_port(struct mlx5_core_dev *mdev,
997 struct ethtool_link_ksettings *link_ksettings,
998 u32 eth_proto_cap, u8 connector_type)
999 {
1000 if (!MLX5_CAP_PCAM_FEATURE(mdev, ptys_connector_type)) {
1001 if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
1002 | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
1003 | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
1004 | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
1005 | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
1006 | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
1007 ethtool_link_ksettings_add_link_mode(link_ksettings,
1008 supported,
1009 FIBRE);
1010 ethtool_link_ksettings_add_link_mode(link_ksettings,
1011 advertising,
1012 FIBRE);
1013 }
1014
1015 if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4)
1016 | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
1017 | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
1018 | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
1019 | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) {
1020 ethtool_link_ksettings_add_link_mode(link_ksettings,
1021 supported,
1022 Backplane);
1023 ethtool_link_ksettings_add_link_mode(link_ksettings,
1024 advertising,
1025 Backplane);
1026 }
1027 return;
1028 }
1029
1030 switch (connector_type) {
1031 case MLX5E_PORT_TP:
1032 ethtool_link_ksettings_add_link_mode(link_ksettings,
1033 supported, TP);
1034 ethtool_link_ksettings_add_link_mode(link_ksettings,
1035 advertising, TP);
1036 break;
1037 case MLX5E_PORT_AUI:
1038 ethtool_link_ksettings_add_link_mode(link_ksettings,
1039 supported, AUI);
1040 ethtool_link_ksettings_add_link_mode(link_ksettings,
1041 advertising, AUI);
1042 break;
1043 case MLX5E_PORT_BNC:
1044 ethtool_link_ksettings_add_link_mode(link_ksettings,
1045 supported, BNC);
1046 ethtool_link_ksettings_add_link_mode(link_ksettings,
1047 advertising, BNC);
1048 break;
1049 case MLX5E_PORT_MII:
1050 ethtool_link_ksettings_add_link_mode(link_ksettings,
1051 supported, MII);
1052 ethtool_link_ksettings_add_link_mode(link_ksettings,
1053 advertising, MII);
1054 break;
1055 case MLX5E_PORT_FIBRE:
1056 ethtool_link_ksettings_add_link_mode(link_ksettings,
1057 supported, FIBRE);
1058 ethtool_link_ksettings_add_link_mode(link_ksettings,
1059 advertising, FIBRE);
1060 break;
1061 case MLX5E_PORT_DA:
1062 ethtool_link_ksettings_add_link_mode(link_ksettings,
1063 supported, Backplane);
1064 ethtool_link_ksettings_add_link_mode(link_ksettings,
1065 advertising, Backplane);
1066 break;
1067 case MLX5E_PORT_NONE:
1068 case MLX5E_PORT_OTHER:
1069 default:
1070 break;
1071 }
1072 }
1073
get_speed_duplex(struct net_device * netdev,u32 eth_proto_oper,bool force_legacy,u16 data_rate_oper,struct ethtool_link_ksettings * link_ksettings)1074 static void get_speed_duplex(struct net_device *netdev,
1075 u32 eth_proto_oper, bool force_legacy,
1076 u16 data_rate_oper,
1077 struct ethtool_link_ksettings *link_ksettings)
1078 {
1079 struct mlx5e_priv *priv = netdev_priv(netdev);
1080 u32 speed = SPEED_UNKNOWN;
1081 u8 duplex = DUPLEX_UNKNOWN;
1082
1083 if (!netif_carrier_ok(netdev))
1084 goto out;
1085
1086 speed = mlx5_port_ptys2speed(priv->mdev, eth_proto_oper, force_legacy);
1087 if (!speed) {
1088 if (data_rate_oper)
1089 speed = 100 * data_rate_oper;
1090 else
1091 speed = SPEED_UNKNOWN;
1092 goto out;
1093 }
1094
1095 duplex = DUPLEX_FULL;
1096
1097 out:
1098 link_ksettings->base.speed = speed;
1099 link_ksettings->base.duplex = duplex;
1100 }
1101
get_supported(struct mlx5_core_dev * mdev,u32 eth_proto_cap,struct ethtool_link_ksettings * link_ksettings)1102 static void get_supported(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
1103 struct ethtool_link_ksettings *link_ksettings)
1104 {
1105 unsigned long *supported = link_ksettings->link_modes.supported;
1106 ptys2ethtool_supported_link(mdev, supported, eth_proto_cap);
1107
1108 ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
1109 }
1110
get_advertising(u32 eth_proto_cap,u8 tx_pause,u8 rx_pause,struct ethtool_link_ksettings * link_ksettings,bool ext)1111 static void get_advertising(u32 eth_proto_cap, u8 tx_pause, u8 rx_pause,
1112 struct ethtool_link_ksettings *link_ksettings,
1113 bool ext)
1114 {
1115 unsigned long *advertising = link_ksettings->link_modes.advertising;
1116 ptys2ethtool_adver_link(advertising, eth_proto_cap, ext);
1117
1118 if (rx_pause)
1119 ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
1120 if (tx_pause ^ rx_pause)
1121 ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
1122 }
1123
1124 static int ptys2connector_type[MLX5E_CONNECTOR_TYPE_NUMBER] = {
1125 [MLX5E_PORT_UNKNOWN] = PORT_OTHER,
1126 [MLX5E_PORT_NONE] = PORT_NONE,
1127 [MLX5E_PORT_TP] = PORT_TP,
1128 [MLX5E_PORT_AUI] = PORT_AUI,
1129 [MLX5E_PORT_BNC] = PORT_BNC,
1130 [MLX5E_PORT_MII] = PORT_MII,
1131 [MLX5E_PORT_FIBRE] = PORT_FIBRE,
1132 [MLX5E_PORT_DA] = PORT_DA,
1133 [MLX5E_PORT_OTHER] = PORT_OTHER,
1134 };
1135
get_connector_port(struct mlx5_core_dev * mdev,u32 eth_proto,u8 connector_type)1136 static u8 get_connector_port(struct mlx5_core_dev *mdev, u32 eth_proto, u8 connector_type)
1137 {
1138 if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_connector_type))
1139 return ptys2connector_type[connector_type];
1140
1141 if (eth_proto &
1142 (MLX5E_PROT_MASK(MLX5E_10GBASE_SR) |
1143 MLX5E_PROT_MASK(MLX5E_40GBASE_SR4) |
1144 MLX5E_PROT_MASK(MLX5E_100GBASE_SR4) |
1145 MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
1146 return PORT_FIBRE;
1147 }
1148
1149 if (eth_proto &
1150 (MLX5E_PROT_MASK(MLX5E_40GBASE_CR4) |
1151 MLX5E_PROT_MASK(MLX5E_10GBASE_CR) |
1152 MLX5E_PROT_MASK(MLX5E_100GBASE_CR4))) {
1153 return PORT_DA;
1154 }
1155
1156 if (eth_proto &
1157 (MLX5E_PROT_MASK(MLX5E_10GBASE_KX4) |
1158 MLX5E_PROT_MASK(MLX5E_10GBASE_KR) |
1159 MLX5E_PROT_MASK(MLX5E_40GBASE_KR4) |
1160 MLX5E_PROT_MASK(MLX5E_100GBASE_KR4))) {
1161 return PORT_NONE;
1162 }
1163
1164 return PORT_OTHER;
1165 }
1166
get_lp_advertising(struct mlx5_core_dev * mdev,u32 eth_proto_lp,struct ethtool_link_ksettings * link_ksettings)1167 static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp,
1168 struct ethtool_link_ksettings *link_ksettings)
1169 {
1170 unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
1171 bool ext = mlx5_ptys_ext_supported(mdev);
1172
1173 ptys2ethtool_adver_link(lp_advertising, eth_proto_lp, ext);
1174 }
1175
mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv * priv,struct ethtool_link_ksettings * link_ksettings)1176 static int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
1177 struct ethtool_link_ksettings *link_ksettings)
1178 {
1179 struct mlx5_core_dev *mdev = priv->mdev;
1180 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {};
1181 u32 eth_proto_admin;
1182 u8 an_disable_admin;
1183 u16 data_rate_oper;
1184 u32 eth_proto_oper;
1185 u32 eth_proto_cap;
1186 u8 connector_type;
1187 u32 rx_pause = 0;
1188 u32 tx_pause = 0;
1189 u32 eth_proto_lp;
1190 bool admin_ext;
1191 u8 an_status;
1192 bool ext;
1193 int err;
1194
1195 err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1, 0);
1196 if (err) {
1197 netdev_err(priv->netdev, "%s: query port ptys failed: %d\n",
1198 __func__, err);
1199 goto err_query_regs;
1200 }
1201 ext = !!MLX5_GET_ETH_PROTO(ptys_reg, out, true, eth_proto_capability);
1202 eth_proto_cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
1203 eth_proto_capability);
1204 eth_proto_admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
1205 eth_proto_admin);
1206 /* Fields: eth_proto_admin and ext_eth_proto_admin are
1207 * mutually exclusive. Hence try reading legacy advertising
1208 * when extended advertising is zero.
1209 * admin_ext indicates which proto_admin (ext vs. legacy)
1210 * should be read and interpreted
1211 */
1212 admin_ext = ext;
1213 if (ext && !eth_proto_admin) {
1214 eth_proto_admin = MLX5_GET_ETH_PROTO(ptys_reg, out, false,
1215 eth_proto_admin);
1216 admin_ext = false;
1217 }
1218
1219 eth_proto_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, admin_ext,
1220 eth_proto_oper);
1221 eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
1222 an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
1223 an_status = MLX5_GET(ptys_reg, out, an_status);
1224 connector_type = MLX5_GET(ptys_reg, out, connector_type);
1225 data_rate_oper = MLX5_GET(ptys_reg, out, data_rate_oper);
1226
1227 mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
1228
1229 ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
1230 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
1231
1232 get_supported(mdev, eth_proto_cap, link_ksettings);
1233 get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
1234 admin_ext);
1235 get_speed_duplex(priv->netdev, eth_proto_oper, !admin_ext,
1236 data_rate_oper, link_ksettings);
1237
1238 eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
1239 connector_type = connector_type < MLX5E_CONNECTOR_TYPE_NUMBER ?
1240 connector_type : MLX5E_PORT_UNKNOWN;
1241 link_ksettings->base.port = get_connector_port(mdev, eth_proto_oper, connector_type);
1242 ptys2ethtool_supported_advertised_port(mdev, link_ksettings, eth_proto_admin,
1243 connector_type);
1244 get_lp_advertising(mdev, eth_proto_lp, link_ksettings);
1245
1246 if (an_status == MLX5_AN_COMPLETE)
1247 ethtool_link_ksettings_add_link_mode(link_ksettings,
1248 lp_advertising, Autoneg);
1249
1250 link_ksettings->base.autoneg = an_disable_admin ? AUTONEG_DISABLE :
1251 AUTONEG_ENABLE;
1252 ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
1253 Autoneg);
1254
1255 err = get_fec_supported_advertised(mdev, link_ksettings);
1256 if (err) {
1257 netdev_dbg(priv->netdev, "%s: FEC caps query failed: %d\n",
1258 __func__, err);
1259 err = 0; /* don't fail caps query because of FEC error */
1260 }
1261
1262 if (!an_disable_admin)
1263 ethtool_link_ksettings_add_link_mode(link_ksettings,
1264 advertising, Autoneg);
1265
1266 err_query_regs:
1267 return err;
1268 }
1269
mlx5e_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * link_ksettings)1270 static int mlx5e_get_link_ksettings(struct net_device *netdev,
1271 struct ethtool_link_ksettings *link_ksettings)
1272 {
1273 struct mlx5e_priv *priv = netdev_priv(netdev);
1274
1275 return mlx5e_ethtool_get_link_ksettings(priv, link_ksettings);
1276 }
1277
mlx5e_speed_validate(struct net_device * netdev,bool ext,const unsigned long link_modes,u8 autoneg)1278 static int mlx5e_speed_validate(struct net_device *netdev, bool ext,
1279 const unsigned long link_modes, u8 autoneg)
1280 {
1281 /* Extended link-mode has no speed limitations. */
1282 if (ext)
1283 return 0;
1284
1285 if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
1286 autoneg != AUTONEG_ENABLE) {
1287 netdev_err(netdev, "%s: 56G link speed requires autoneg enabled\n",
1288 __func__);
1289 return -EINVAL;
1290 }
1291 return 0;
1292 }
1293
mlx5e_ethtool2ptys_adver_link(const unsigned long * link_modes)1294 static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes)
1295 {
1296 u32 i, ptys_modes = 0;
1297
1298 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
1299 if (bitmap_empty(ptys2legacy_ethtool_table[i].advertised,
1300 __ETHTOOL_LINK_MODE_MASK_NBITS))
1301 continue;
1302 if (bitmap_intersects(ptys2legacy_ethtool_table[i].advertised,
1303 link_modes,
1304 __ETHTOOL_LINK_MODE_MASK_NBITS))
1305 ptys_modes |= MLX5E_PROT_MASK(i);
1306 }
1307
1308 return ptys_modes;
1309 }
1310
mlx5e_ethtool2ptys_ext_adver_link(const unsigned long * link_modes)1311 static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes)
1312 {
1313 u32 i, ptys_modes = 0;
1314 __ETHTOOL_DECLARE_LINK_MODE_MASK(modes);
1315
1316 for (i = 0; i < MLX5E_EXT_LINK_MODES_NUMBER; ++i) {
1317 if (bitmap_empty(ptys2ext_ethtool_table[i].advertised,
1318 __ETHTOOL_LINK_MODE_MASK_NBITS))
1319 continue;
1320 bitmap_zero(modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
1321 bitmap_and(modes, ptys2ext_ethtool_table[i].advertised,
1322 link_modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
1323
1324 if (bitmap_equal(modes, ptys2ext_ethtool_table[i].advertised,
1325 __ETHTOOL_LINK_MODE_MASK_NBITS))
1326 ptys_modes |= MLX5E_PROT_MASK(i);
1327 }
1328 return ptys_modes;
1329 }
1330
ext_link_mode_requested(const unsigned long * adver)1331 static bool ext_link_mode_requested(const unsigned long *adver)
1332 {
1333 #define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
1334 int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT;
1335 __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = {0,};
1336
1337 bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size);
1338 return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
1339 }
1340
ext_requested(u8 autoneg,const unsigned long * adver,bool ext_supported)1341 static bool ext_requested(u8 autoneg, const unsigned long *adver, bool ext_supported)
1342 {
1343 bool ext_link_mode = ext_link_mode_requested(adver);
1344
1345 return autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_supported;
1346 }
1347
mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv * priv,const struct ethtool_link_ksettings * link_ksettings)1348 static int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
1349 const struct ethtool_link_ksettings *link_ksettings)
1350 {
1351 struct mlx5_core_dev *mdev = priv->mdev;
1352 struct mlx5_port_eth_proto eproto;
1353 const unsigned long *adver;
1354 bool an_changes = false;
1355 u8 an_disable_admin;
1356 bool ext_supported;
1357 u8 an_disable_cap;
1358 bool an_disable;
1359 u32 link_modes;
1360 u8 an_status;
1361 u8 autoneg;
1362 u32 speed;
1363 bool ext;
1364 int err;
1365
1366 u32 (*ethtool2ptys_adver_func)(const unsigned long *adver);
1367
1368 adver = link_ksettings->link_modes.advertising;
1369 autoneg = link_ksettings->base.autoneg;
1370 speed = link_ksettings->base.speed;
1371
1372 ext_supported = mlx5_ptys_ext_supported(mdev);
1373 ext = ext_requested(autoneg, adver, ext_supported);
1374 if (!ext_supported && ext)
1375 return -EOPNOTSUPP;
1376
1377 ethtool2ptys_adver_func = ext ? mlx5e_ethtool2ptys_ext_adver_link :
1378 mlx5e_ethtool2ptys_adver_link;
1379 err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
1380 if (err) {
1381 netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
1382 __func__, err);
1383 goto out;
1384 }
1385 link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
1386 mlx5_port_speed2linkmodes(mdev, speed, !ext);
1387
1388 err = mlx5e_speed_validate(priv->netdev, ext, link_modes, autoneg);
1389 if (err)
1390 goto out;
1391
1392 link_modes = link_modes & eproto.cap;
1393 if (!link_modes) {
1394 netdev_err(priv->netdev, "%s: Not supported link mode(s) requested",
1395 __func__);
1396 err = -EINVAL;
1397 goto out;
1398 }
1399
1400 mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap,
1401 &an_disable_admin);
1402
1403 an_disable = autoneg == AUTONEG_DISABLE;
1404 an_changes = ((!an_disable && an_disable_admin) ||
1405 (an_disable && !an_disable_admin));
1406
1407 if (!an_changes && link_modes == eproto.admin)
1408 goto out;
1409
1410 err = mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
1411 if (err) {
1412 netdev_err(priv->netdev, "%s: failed to set ptys reg: %d\n", __func__, err);
1413 goto out;
1414 }
1415
1416 mlx5_toggle_port_link(mdev);
1417
1418 out:
1419 return err;
1420 }
1421
mlx5e_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * link_ksettings)1422 static int mlx5e_set_link_ksettings(struct net_device *netdev,
1423 const struct ethtool_link_ksettings *link_ksettings)
1424 {
1425 struct mlx5e_priv *priv = netdev_priv(netdev);
1426
1427 return mlx5e_ethtool_set_link_ksettings(priv, link_ksettings);
1428 }
1429
mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv * priv)1430 u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv)
1431 {
1432 return sizeof_field(struct mlx5e_rss_params_hash, toeplitz_hash_key);
1433 }
1434
mlx5e_get_rxfh_key_size(struct net_device * netdev)1435 static u32 mlx5e_get_rxfh_key_size(struct net_device *netdev)
1436 {
1437 struct mlx5e_priv *priv = netdev_priv(netdev);
1438
1439 return mlx5e_ethtool_get_rxfh_key_size(priv);
1440 }
1441
mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv * priv)1442 u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv)
1443 {
1444 return mlx5e_rqt_size(priv->mdev, priv->channels.params.num_channels);
1445 }
1446
mlx5e_get_rxfh_indir_size(struct net_device * netdev)1447 static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
1448 {
1449 struct mlx5e_priv *priv = netdev_priv(netdev);
1450
1451 return mlx5e_ethtool_get_rxfh_indir_size(priv);
1452 }
1453
mlx5e_get_rxfh(struct net_device * netdev,struct ethtool_rxfh_param * rxfh)1454 static int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
1455 {
1456 struct mlx5e_priv *priv = netdev_priv(netdev);
1457 u32 rss_context = rxfh->rss_context;
1458 int err;
1459
1460 mutex_lock(&priv->state_lock);
1461 err = mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rss_context,
1462 rxfh->indir, rxfh->key, &rxfh->hfunc);
1463 mutex_unlock(&priv->state_lock);
1464 return err;
1465 }
1466
mlx5e_set_rxfh(struct net_device * dev,struct ethtool_rxfh_param * rxfh,struct netlink_ext_ack * extack)1467 static int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
1468 struct netlink_ext_ack *extack)
1469 {
1470 struct mlx5e_priv *priv = netdev_priv(dev);
1471 u32 *rss_context = &rxfh->rss_context;
1472 u8 hfunc = rxfh->hfunc;
1473 unsigned int count;
1474 int err;
1475
1476 mutex_lock(&priv->state_lock);
1477
1478 count = priv->channels.params.num_channels;
1479
1480 if (hfunc == ETH_RSS_HASH_XOR) {
1481 unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();
1482
1483 if (count > xor8_max_channels) {
1484 err = -EINVAL;
1485 netdev_err(priv->netdev, "%s: Cannot set RSS hash function to XOR, current number of channels (%d) exceeds the maximum allowed for XOR8 RSS hfunc (%d)\n",
1486 __func__, count, xor8_max_channels);
1487 goto unlock;
1488 }
1489 }
1490
1491 if (*rss_context && rxfh->rss_delete) {
1492 err = mlx5e_rx_res_rss_destroy(priv->rx_res, *rss_context);
1493 goto unlock;
1494 }
1495
1496 if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) {
1497 err = mlx5e_rx_res_rss_init(priv->rx_res, rss_context, count);
1498 if (err)
1499 goto unlock;
1500 }
1501
1502 err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, *rss_context,
1503 rxfh->indir, rxfh->key,
1504 hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc);
1505
1506 unlock:
1507 mutex_unlock(&priv->state_lock);
1508 return err;
1509 }
1510
1511 #define MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC 100
1512 #define MLX5E_PFC_PREVEN_TOUT_MAX_MSEC 8000
1513 #define MLX5E_PFC_PREVEN_MINOR_PRECENT 85
1514 #define MLX5E_PFC_PREVEN_TOUT_MIN_MSEC 80
1515 #define MLX5E_DEVICE_STALL_MINOR_WATERMARK(critical_tout) \
1516 max_t(u16, MLX5E_PFC_PREVEN_TOUT_MIN_MSEC, \
1517 (critical_tout * MLX5E_PFC_PREVEN_MINOR_PRECENT) / 100)
1518
mlx5e_get_pfc_prevention_tout(struct net_device * netdev,u16 * pfc_prevention_tout)1519 static int mlx5e_get_pfc_prevention_tout(struct net_device *netdev,
1520 u16 *pfc_prevention_tout)
1521 {
1522 struct mlx5e_priv *priv = netdev_priv(netdev);
1523 struct mlx5_core_dev *mdev = priv->mdev;
1524
1525 if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask) ||
1526 !MLX5_CAP_DEBUG((priv)->mdev, stall_detect))
1527 return -EOPNOTSUPP;
1528
1529 return mlx5_query_port_stall_watermark(mdev, pfc_prevention_tout, NULL);
1530 }
1531
mlx5e_set_pfc_prevention_tout(struct net_device * netdev,u16 pfc_preven)1532 static int mlx5e_set_pfc_prevention_tout(struct net_device *netdev,
1533 u16 pfc_preven)
1534 {
1535 struct mlx5e_priv *priv = netdev_priv(netdev);
1536 struct mlx5_core_dev *mdev = priv->mdev;
1537 u16 critical_tout;
1538 u16 minor;
1539
1540 if (!MLX5_CAP_PCAM_FEATURE((priv)->mdev, pfcc_mask) ||
1541 !MLX5_CAP_DEBUG((priv)->mdev, stall_detect))
1542 return -EOPNOTSUPP;
1543
1544 critical_tout = (pfc_preven == PFC_STORM_PREVENTION_AUTO) ?
1545 MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC :
1546 pfc_preven;
1547
1548 if (critical_tout != PFC_STORM_PREVENTION_DISABLE &&
1549 (critical_tout > MLX5E_PFC_PREVEN_TOUT_MAX_MSEC ||
1550 critical_tout < MLX5E_PFC_PREVEN_TOUT_MIN_MSEC)) {
1551 netdev_info(netdev, "%s: pfc prevention tout not in range (%d-%d)\n",
1552 __func__, MLX5E_PFC_PREVEN_TOUT_MIN_MSEC,
1553 MLX5E_PFC_PREVEN_TOUT_MAX_MSEC);
1554 return -EINVAL;
1555 }
1556
1557 minor = MLX5E_DEVICE_STALL_MINOR_WATERMARK(critical_tout);
1558 return mlx5_set_port_stall_watermark(mdev, critical_tout,
1559 minor);
1560 }
1561
mlx5e_get_tunable(struct net_device * dev,const struct ethtool_tunable * tuna,void * data)1562 static int mlx5e_get_tunable(struct net_device *dev,
1563 const struct ethtool_tunable *tuna,
1564 void *data)
1565 {
1566 int err;
1567
1568 switch (tuna->id) {
1569 case ETHTOOL_PFC_PREVENTION_TOUT:
1570 err = mlx5e_get_pfc_prevention_tout(dev, data);
1571 break;
1572 default:
1573 err = -EINVAL;
1574 break;
1575 }
1576
1577 return err;
1578 }
1579
mlx5e_set_tunable(struct net_device * dev,const struct ethtool_tunable * tuna,const void * data)1580 static int mlx5e_set_tunable(struct net_device *dev,
1581 const struct ethtool_tunable *tuna,
1582 const void *data)
1583 {
1584 struct mlx5e_priv *priv = netdev_priv(dev);
1585 int err;
1586
1587 mutex_lock(&priv->state_lock);
1588
1589 switch (tuna->id) {
1590 case ETHTOOL_PFC_PREVENTION_TOUT:
1591 err = mlx5e_set_pfc_prevention_tout(dev, *(u16 *)data);
1592 break;
1593 default:
1594 err = -EINVAL;
1595 break;
1596 }
1597
1598 mutex_unlock(&priv->state_lock);
1599 return err;
1600 }
1601
mlx5e_get_pause_stats(struct net_device * netdev,struct ethtool_pause_stats * pause_stats)1602 static void mlx5e_get_pause_stats(struct net_device *netdev,
1603 struct ethtool_pause_stats *pause_stats)
1604 {
1605 struct mlx5e_priv *priv = netdev_priv(netdev);
1606
1607 mlx5e_stats_pause_get(priv, pause_stats);
1608 }
1609
mlx5e_ethtool_get_pauseparam(struct mlx5e_priv * priv,struct ethtool_pauseparam * pauseparam)1610 static void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
1611 struct ethtool_pauseparam *pauseparam)
1612 {
1613 struct mlx5_core_dev *mdev = priv->mdev;
1614 int err;
1615
1616 err = mlx5_query_port_pause(mdev, &pauseparam->rx_pause,
1617 &pauseparam->tx_pause);
1618 if (err) {
1619 netdev_err(priv->netdev, "%s: mlx5_query_port_pause failed:0x%x\n",
1620 __func__, err);
1621 }
1622 }
1623
mlx5e_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pauseparam)1624 static void mlx5e_get_pauseparam(struct net_device *netdev,
1625 struct ethtool_pauseparam *pauseparam)
1626 {
1627 struct mlx5e_priv *priv = netdev_priv(netdev);
1628
1629 mlx5e_ethtool_get_pauseparam(priv, pauseparam);
1630 }
1631
mlx5e_ethtool_set_pauseparam(struct mlx5e_priv * priv,struct ethtool_pauseparam * pauseparam)1632 static int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
1633 struct ethtool_pauseparam *pauseparam)
1634 {
1635 struct mlx5_core_dev *mdev = priv->mdev;
1636 int err;
1637
1638 if (!MLX5_CAP_GEN(mdev, vport_group_manager))
1639 return -EOPNOTSUPP;
1640
1641 if (pauseparam->autoneg)
1642 return -EINVAL;
1643
1644 err = mlx5_set_port_pause(mdev,
1645 pauseparam->rx_pause ? 1 : 0,
1646 pauseparam->tx_pause ? 1 : 0);
1647 if (err) {
1648 netdev_err(priv->netdev, "%s: mlx5_set_port_pause failed:0x%x\n",
1649 __func__, err);
1650 }
1651
1652 return err;
1653 }
1654
mlx5e_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pauseparam)1655 static int mlx5e_set_pauseparam(struct net_device *netdev,
1656 struct ethtool_pauseparam *pauseparam)
1657 {
1658 struct mlx5e_priv *priv = netdev_priv(netdev);
1659
1660 return mlx5e_ethtool_set_pauseparam(priv, pauseparam);
1661 }
1662
mlx5e_ethtool_get_ts_info(struct mlx5e_priv * priv,struct kernel_ethtool_ts_info * info)1663 int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
1664 struct kernel_ethtool_ts_info *info)
1665 {
1666 struct mlx5_core_dev *mdev = priv->mdev;
1667
1668 info->phc_index = mlx5_clock_get_ptp_index(mdev);
1669
1670 if (!MLX5_CAP_GEN(priv->mdev, device_frequency_khz) ||
1671 info->phc_index == -1)
1672 return 0;
1673
1674 info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
1675 SOF_TIMESTAMPING_RX_HARDWARE |
1676 SOF_TIMESTAMPING_RAW_HARDWARE;
1677
1678 info->tx_types = BIT(HWTSTAMP_TX_OFF) |
1679 BIT(HWTSTAMP_TX_ON);
1680
1681 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
1682 BIT(HWTSTAMP_FILTER_ALL);
1683
1684 return 0;
1685 }
1686
mlx5e_get_ts_info(struct net_device * dev,struct kernel_ethtool_ts_info * info)1687 static int mlx5e_get_ts_info(struct net_device *dev,
1688 struct kernel_ethtool_ts_info *info)
1689 {
1690 struct mlx5e_priv *priv = netdev_priv(dev);
1691
1692 return mlx5e_ethtool_get_ts_info(priv, info);
1693 }
1694
mlx5e_get_wol_supported(struct mlx5_core_dev * mdev)1695 static __u32 mlx5e_get_wol_supported(struct mlx5_core_dev *mdev)
1696 {
1697 __u32 ret = 0;
1698
1699 if (MLX5_CAP_GEN(mdev, wol_g))
1700 ret |= WAKE_MAGIC;
1701
1702 if (MLX5_CAP_GEN(mdev, wol_s))
1703 ret |= WAKE_MAGICSECURE;
1704
1705 if (MLX5_CAP_GEN(mdev, wol_a))
1706 ret |= WAKE_ARP;
1707
1708 if (MLX5_CAP_GEN(mdev, wol_b))
1709 ret |= WAKE_BCAST;
1710
1711 if (MLX5_CAP_GEN(mdev, wol_m))
1712 ret |= WAKE_MCAST;
1713
1714 if (MLX5_CAP_GEN(mdev, wol_u))
1715 ret |= WAKE_UCAST;
1716
1717 if (MLX5_CAP_GEN(mdev, wol_p))
1718 ret |= WAKE_PHY;
1719
1720 return ret;
1721 }
1722
mlx5e_reformat_wol_mode_mlx5_to_linux(u8 mode)1723 static __u32 mlx5e_reformat_wol_mode_mlx5_to_linux(u8 mode)
1724 {
1725 __u32 ret = 0;
1726
1727 if (mode & MLX5_WOL_MAGIC)
1728 ret |= WAKE_MAGIC;
1729
1730 if (mode & MLX5_WOL_SECURED_MAGIC)
1731 ret |= WAKE_MAGICSECURE;
1732
1733 if (mode & MLX5_WOL_ARP)
1734 ret |= WAKE_ARP;
1735
1736 if (mode & MLX5_WOL_BROADCAST)
1737 ret |= WAKE_BCAST;
1738
1739 if (mode & MLX5_WOL_MULTICAST)
1740 ret |= WAKE_MCAST;
1741
1742 if (mode & MLX5_WOL_UNICAST)
1743 ret |= WAKE_UCAST;
1744
1745 if (mode & MLX5_WOL_PHY_ACTIVITY)
1746 ret |= WAKE_PHY;
1747
1748 return ret;
1749 }
1750
mlx5e_reformat_wol_mode_linux_to_mlx5(__u32 mode)1751 static u8 mlx5e_reformat_wol_mode_linux_to_mlx5(__u32 mode)
1752 {
1753 u8 ret = 0;
1754
1755 if (mode & WAKE_MAGIC)
1756 ret |= MLX5_WOL_MAGIC;
1757
1758 if (mode & WAKE_MAGICSECURE)
1759 ret |= MLX5_WOL_SECURED_MAGIC;
1760
1761 if (mode & WAKE_ARP)
1762 ret |= MLX5_WOL_ARP;
1763
1764 if (mode & WAKE_BCAST)
1765 ret |= MLX5_WOL_BROADCAST;
1766
1767 if (mode & WAKE_MCAST)
1768 ret |= MLX5_WOL_MULTICAST;
1769
1770 if (mode & WAKE_UCAST)
1771 ret |= MLX5_WOL_UNICAST;
1772
1773 if (mode & WAKE_PHY)
1774 ret |= MLX5_WOL_PHY_ACTIVITY;
1775
1776 return ret;
1777 }
1778
mlx5e_get_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)1779 static void mlx5e_get_wol(struct net_device *netdev,
1780 struct ethtool_wolinfo *wol)
1781 {
1782 struct mlx5e_priv *priv = netdev_priv(netdev);
1783 struct mlx5_core_dev *mdev = priv->mdev;
1784 u8 mlx5_wol_mode;
1785 int err;
1786
1787 memset(wol, 0, sizeof(*wol));
1788
1789 wol->supported = mlx5e_get_wol_supported(mdev);
1790 if (!wol->supported)
1791 return;
1792
1793 err = mlx5_query_port_wol(mdev, &mlx5_wol_mode);
1794 if (err)
1795 return;
1796
1797 wol->wolopts = mlx5e_reformat_wol_mode_mlx5_to_linux(mlx5_wol_mode);
1798 }
1799
mlx5e_set_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)1800 static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
1801 {
1802 struct mlx5e_priv *priv = netdev_priv(netdev);
1803 struct mlx5_core_dev *mdev = priv->mdev;
1804 __u32 wol_supported = mlx5e_get_wol_supported(mdev);
1805 u32 mlx5_wol_mode;
1806
1807 if (!wol_supported)
1808 return -EOPNOTSUPP;
1809
1810 if (wol->wolopts & ~wol_supported)
1811 return -EINVAL;
1812
1813 mlx5_wol_mode = mlx5e_reformat_wol_mode_linux_to_mlx5(wol->wolopts);
1814
1815 return mlx5_set_port_wol(mdev, mlx5_wol_mode);
1816 }
1817
mlx5e_get_fec_stats(struct net_device * netdev,struct ethtool_fec_stats * fec_stats)1818 static void mlx5e_get_fec_stats(struct net_device *netdev,
1819 struct ethtool_fec_stats *fec_stats)
1820 {
1821 struct mlx5e_priv *priv = netdev_priv(netdev);
1822
1823 mlx5e_stats_fec_get(priv, fec_stats);
1824 }
1825
mlx5e_get_fecparam(struct net_device * netdev,struct ethtool_fecparam * fecparam)1826 static int mlx5e_get_fecparam(struct net_device *netdev,
1827 struct ethtool_fecparam *fecparam)
1828 {
1829 struct mlx5e_priv *priv = netdev_priv(netdev);
1830 struct mlx5_core_dev *mdev = priv->mdev;
1831 u16 fec_configured;
1832 u32 fec_active;
1833 int err;
1834
1835 err = mlx5e_get_fec_mode(mdev, &fec_active, &fec_configured);
1836
1837 if (err)
1838 return err;
1839
1840 fecparam->active_fec = pplm2ethtool_fec((unsigned long)fec_active,
1841 sizeof(unsigned long) * BITS_PER_BYTE);
1842
1843 if (!fecparam->active_fec)
1844 return -EOPNOTSUPP;
1845
1846 fecparam->fec = pplm2ethtool_fec((unsigned long)fec_configured,
1847 sizeof(unsigned long) * BITS_PER_BYTE);
1848
1849 return 0;
1850 }
1851
mlx5e_set_fecparam(struct net_device * netdev,struct ethtool_fecparam * fecparam)1852 static int mlx5e_set_fecparam(struct net_device *netdev,
1853 struct ethtool_fecparam *fecparam)
1854 {
1855 struct mlx5e_priv *priv = netdev_priv(netdev);
1856 struct mlx5_core_dev *mdev = priv->mdev;
1857 unsigned long fec_bitmap;
1858 u16 fec_policy = 0;
1859 int mode;
1860 int err;
1861
1862 bitmap_from_arr32(&fec_bitmap, &fecparam->fec, sizeof(fecparam->fec) * BITS_PER_BYTE);
1863 if (bitmap_weight(&fec_bitmap, ETHTOOL_FEC_LLRS_BIT + 1) > 1)
1864 return -EOPNOTSUPP;
1865
1866 for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
1867 if (!(pplm_fec_2_ethtool[mode] & fecparam->fec))
1868 continue;
1869 fec_policy |= (1 << mode);
1870 break;
1871 }
1872
1873 err = mlx5e_set_fec_mode(mdev, fec_policy);
1874
1875 if (err)
1876 return err;
1877
1878 mlx5_toggle_port_link(mdev);
1879
1880 return 0;
1881 }
1882
mlx5e_set_phys_id(struct net_device * dev,enum ethtool_phys_id_state state)1883 static int mlx5e_set_phys_id(struct net_device *dev,
1884 enum ethtool_phys_id_state state)
1885 {
1886 struct mlx5e_priv *priv = netdev_priv(dev);
1887 struct mlx5_core_dev *mdev = priv->mdev;
1888 u16 beacon_duration;
1889
1890 if (!MLX5_CAP_GEN(mdev, beacon_led))
1891 return -EOPNOTSUPP;
1892
1893 switch (state) {
1894 case ETHTOOL_ID_ACTIVE:
1895 beacon_duration = MLX5_BEACON_DURATION_INF;
1896 break;
1897 case ETHTOOL_ID_INACTIVE:
1898 beacon_duration = MLX5_BEACON_DURATION_OFF;
1899 break;
1900 default:
1901 return -EOPNOTSUPP;
1902 }
1903
1904 return mlx5_set_port_beacon(mdev, beacon_duration);
1905 }
1906
mlx5e_get_module_info(struct net_device * netdev,struct ethtool_modinfo * modinfo)1907 static int mlx5e_get_module_info(struct net_device *netdev,
1908 struct ethtool_modinfo *modinfo)
1909 {
1910 struct mlx5e_priv *priv = netdev_priv(netdev);
1911 struct mlx5_core_dev *dev = priv->mdev;
1912 int size_read = 0;
1913 u8 data[4] = {0};
1914
1915 size_read = mlx5_query_module_eeprom(dev, 0, 2, data);
1916 if (size_read < 2)
1917 return -EIO;
1918
1919 /* data[0] = identifier byte */
1920 switch (data[0]) {
1921 case MLX5_MODULE_ID_QSFP:
1922 modinfo->type = ETH_MODULE_SFF_8436;
1923 modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
1924 break;
1925 case MLX5_MODULE_ID_QSFP_PLUS:
1926 case MLX5_MODULE_ID_QSFP28:
1927 /* data[1] = revision id */
1928 if (data[0] == MLX5_MODULE_ID_QSFP28 || data[1] >= 0x3) {
1929 modinfo->type = ETH_MODULE_SFF_8636;
1930 modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
1931 } else {
1932 modinfo->type = ETH_MODULE_SFF_8436;
1933 modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
1934 }
1935 break;
1936 case MLX5_MODULE_ID_SFP:
1937 modinfo->type = ETH_MODULE_SFF_8472;
1938 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
1939 break;
1940 default:
1941 netdev_err(priv->netdev, "%s: cable type not recognized:0x%x\n",
1942 __func__, data[0]);
1943 return -EINVAL;
1944 }
1945
1946 return 0;
1947 }
1948
mlx5e_get_module_eeprom(struct net_device * netdev,struct ethtool_eeprom * ee,u8 * data)1949 static int mlx5e_get_module_eeprom(struct net_device *netdev,
1950 struct ethtool_eeprom *ee,
1951 u8 *data)
1952 {
1953 struct mlx5e_priv *priv = netdev_priv(netdev);
1954 struct mlx5_core_dev *mdev = priv->mdev;
1955 int offset = ee->offset;
1956 int size_read;
1957 int i = 0;
1958
1959 if (!ee->len)
1960 return -EINVAL;
1961
1962 memset(data, 0, ee->len);
1963
1964 while (i < ee->len) {
1965 size_read = mlx5_query_module_eeprom(mdev, offset, ee->len - i,
1966 data + i);
1967
1968 if (!size_read)
1969 /* Done reading */
1970 return 0;
1971
1972 if (size_read < 0) {
1973 netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n",
1974 __func__, size_read);
1975 return size_read;
1976 }
1977
1978 i += size_read;
1979 offset += size_read;
1980 }
1981
1982 return 0;
1983 }
1984
mlx5e_get_module_eeprom_by_page(struct net_device * netdev,const struct ethtool_module_eeprom * page_data,struct netlink_ext_ack * extack)1985 static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev,
1986 const struct ethtool_module_eeprom *page_data,
1987 struct netlink_ext_ack *extack)
1988 {
1989 struct mlx5e_priv *priv = netdev_priv(netdev);
1990 struct mlx5_module_eeprom_query_params query;
1991 struct mlx5_core_dev *mdev = priv->mdev;
1992 u8 *data = page_data->data;
1993 int size_read;
1994 int i = 0;
1995
1996 if (!page_data->length)
1997 return -EINVAL;
1998
1999 memset(data, 0, page_data->length);
2000
2001 query.offset = page_data->offset;
2002 query.i2c_address = page_data->i2c_address;
2003 query.bank = page_data->bank;
2004 query.page = page_data->page;
2005 while (i < page_data->length) {
2006 query.size = page_data->length - i;
2007 size_read = mlx5_query_module_eeprom_by_page(mdev, &query, data + i);
2008
2009 /* Done reading, return how many bytes was read */
2010 if (!size_read)
2011 return i;
2012
2013 if (size_read == -EINVAL)
2014 return -EINVAL;
2015 if (size_read < 0) {
2016 NL_SET_ERR_MSG_FMT_MOD(
2017 extack,
2018 "Query module eeprom by page failed, read %u bytes, err %d\n",
2019 i, size_read);
2020 return i;
2021 }
2022
2023 i += size_read;
2024 query.offset += size_read;
2025 }
2026
2027 return i;
2028 }
2029
mlx5e_ethtool_flash_device(struct mlx5e_priv * priv,struct ethtool_flash * flash)2030 int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
2031 struct ethtool_flash *flash)
2032 {
2033 struct mlx5_core_dev *mdev = priv->mdev;
2034 struct net_device *dev = priv->netdev;
2035 const struct firmware *fw;
2036 int err;
2037
2038 if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
2039 return -EOPNOTSUPP;
2040
2041 err = request_firmware_direct(&fw, flash->data, &dev->dev);
2042 if (err)
2043 return err;
2044
2045 dev_hold(dev);
2046 rtnl_unlock();
2047
2048 err = mlx5_firmware_flash(mdev, fw, NULL);
2049 release_firmware(fw);
2050
2051 rtnl_lock();
2052 dev_put(dev);
2053 return err;
2054 }
2055
mlx5e_flash_device(struct net_device * dev,struct ethtool_flash * flash)2056 static int mlx5e_flash_device(struct net_device *dev,
2057 struct ethtool_flash *flash)
2058 {
2059 struct mlx5e_priv *priv = netdev_priv(dev);
2060
2061 return mlx5e_ethtool_flash_device(priv, flash);
2062 }
2063
set_pflag_cqe_based_moder(struct net_device * netdev,bool enable,bool is_rx_cq)2064 static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
2065 bool is_rx_cq)
2066 {
2067 struct mlx5e_priv *priv = netdev_priv(netdev);
2068 u8 cq_period_mode, current_cq_period_mode;
2069 struct mlx5e_params new_params;
2070
2071 if (enable && !MLX5_CAP_GEN(priv->mdev, cq_period_start_from_cqe))
2072 return -EOPNOTSUPP;
2073
2074 cq_period_mode = mlx5e_dim_cq_period_mode(enable);
2075
2076 current_cq_period_mode = is_rx_cq ?
2077 priv->channels.params.rx_cq_moderation.cq_period_mode :
2078 priv->channels.params.tx_cq_moderation.cq_period_mode;
2079
2080 if (cq_period_mode == current_cq_period_mode)
2081 return 0;
2082
2083 new_params = priv->channels.params;
2084 if (is_rx_cq) {
2085 mlx5e_reset_rx_channels_moderation(&priv->channels, cq_period_mode,
2086 false, true);
2087 mlx5e_channels_rx_toggle_dim(&priv->channels);
2088 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_CQE_BASED_MODER,
2089 cq_period_mode);
2090 } else {
2091 mlx5e_reset_tx_channels_moderation(&priv->channels, cq_period_mode,
2092 false, true);
2093 mlx5e_channels_tx_toggle_dim(&priv->channels);
2094 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_TX_CQE_BASED_MODER,
2095 cq_period_mode);
2096 }
2097
2098 /* Update pflags of existing channels without resetting them */
2099 return mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, false);
2100 }
2101
set_pflag_tx_cqe_based_moder(struct net_device * netdev,bool enable)2102 static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable)
2103 {
2104 return set_pflag_cqe_based_moder(netdev, enable, false);
2105 }
2106
set_pflag_rx_cqe_based_moder(struct net_device * netdev,bool enable)2107 static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
2108 {
2109 return set_pflag_cqe_based_moder(netdev, enable, true);
2110 }
2111
mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv * priv,bool new_val,bool rx_filter)2112 int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val, bool rx_filter)
2113 {
2114 bool curr_val = MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS);
2115 struct mlx5e_params new_params;
2116 int err = 0;
2117
2118 if (!MLX5_CAP_GEN(priv->mdev, cqe_compression))
2119 return new_val ? -EOPNOTSUPP : 0;
2120
2121 if (curr_val == new_val)
2122 return 0;
2123
2124 if (new_val && !mlx5e_profile_feature_cap(priv->profile, PTP_RX) && rx_filter) {
2125 netdev_err(priv->netdev,
2126 "Profile doesn't support enabling of CQE compression while hardware time-stamping is enabled.\n");
2127 return -EINVAL;
2128 }
2129
2130 if (priv->channels.params.packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO) {
2131 netdev_warn(priv->netdev, "Can't set CQE compression with HW-GRO, disable it first.\n");
2132 return -EINVAL;
2133 }
2134
2135 new_params = priv->channels.params;
2136 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_CQE_COMPRESS, new_val);
2137 if (rx_filter)
2138 new_params.ptp_rx = new_val;
2139
2140 if (new_params.ptp_rx == priv->channels.params.ptp_rx)
2141 err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
2142 else
2143 err = mlx5e_safe_switch_params(priv, &new_params, mlx5e_ptp_rx_manage_fs_ctx,
2144 &new_params.ptp_rx, true);
2145 if (err)
2146 return err;
2147
2148 netdev_dbg(priv->netdev, "MLX5E: RxCqeCmprss was turned %s\n",
2149 MLX5E_GET_PFLAG(&priv->channels.params,
2150 MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF");
2151
2152 return 0;
2153 }
2154
set_pflag_rx_cqe_compress(struct net_device * netdev,bool enable)2155 static int set_pflag_rx_cqe_compress(struct net_device *netdev,
2156 bool enable)
2157 {
2158 struct mlx5e_priv *priv = netdev_priv(netdev);
2159 struct mlx5_core_dev *mdev = priv->mdev;
2160 bool rx_filter;
2161 int err;
2162
2163 if (!MLX5_CAP_GEN(mdev, cqe_compression))
2164 return -EOPNOTSUPP;
2165
2166 rx_filter = priv->tstamp.rx_filter != HWTSTAMP_FILTER_NONE;
2167 err = mlx5e_modify_rx_cqe_compression_locked(priv, enable, rx_filter);
2168 if (err)
2169 return err;
2170
2171 priv->channels.params.rx_cqe_compress_def = enable;
2172
2173 return 0;
2174 }
2175
set_pflag_rx_striding_rq(struct net_device * netdev,bool enable)2176 static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable)
2177 {
2178 struct mlx5e_priv *priv = netdev_priv(netdev);
2179 struct mlx5_core_dev *mdev = priv->mdev;
2180 struct mlx5e_params new_params;
2181 int err;
2182
2183 if (enable) {
2184 /* Checking the regular RQ here; mlx5e_validate_xsk_param called
2185 * from mlx5e_open_xsk will check for each XSK queue, and
2186 * mlx5e_safe_switch_params will be reverted if any check fails.
2187 */
2188 int err = mlx5e_mpwrq_validate_regular(mdev, &priv->channels.params);
2189
2190 if (err)
2191 return err;
2192 } else if (priv->channels.params.packet_merge.type != MLX5E_PACKET_MERGE_NONE) {
2193 netdev_warn(netdev, "Can't set legacy RQ with HW-GRO/LRO, disable them first\n");
2194 return -EINVAL;
2195 }
2196
2197 new_params = priv->channels.params;
2198
2199 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_STRIDING_RQ, enable);
2200 mlx5e_set_rq_type(mdev, &new_params);
2201
2202 err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
2203 if (err)
2204 return err;
2205
2206 /* update XDP supported features */
2207 mlx5e_set_xdp_feature(netdev);
2208
2209 return 0;
2210 }
2211
set_pflag_rx_no_csum_complete(struct net_device * netdev,bool enable)2212 static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
2213 {
2214 struct mlx5e_priv *priv = netdev_priv(netdev);
2215 struct mlx5e_channels *channels = &priv->channels;
2216 struct mlx5e_channel *c;
2217 int i;
2218
2219 if (!test_bit(MLX5E_STATE_OPENED, &priv->state) ||
2220 priv->channels.params.xdp_prog)
2221 return 0;
2222
2223 for (i = 0; i < channels->num; i++) {
2224 c = channels->c[i];
2225 if (enable)
2226 __set_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state);
2227 else
2228 __clear_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state);
2229 }
2230
2231 return 0;
2232 }
2233
set_pflag_tx_mpwqe_common(struct net_device * netdev,u32 flag,bool enable)2234 static int set_pflag_tx_mpwqe_common(struct net_device *netdev, u32 flag, bool enable)
2235 {
2236 struct mlx5e_priv *priv = netdev_priv(netdev);
2237 struct mlx5_core_dev *mdev = priv->mdev;
2238 struct mlx5e_params new_params;
2239
2240 if (enable && !mlx5e_tx_mpwqe_supported(mdev))
2241 return -EOPNOTSUPP;
2242
2243 new_params = priv->channels.params;
2244
2245 MLX5E_SET_PFLAG(&new_params, flag, enable);
2246
2247 return mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
2248 }
2249
set_pflag_xdp_tx_mpwqe(struct net_device * netdev,bool enable)2250 static int set_pflag_xdp_tx_mpwqe(struct net_device *netdev, bool enable)
2251 {
2252 return set_pflag_tx_mpwqe_common(netdev, MLX5E_PFLAG_XDP_TX_MPWQE, enable);
2253 }
2254
set_pflag_skb_tx_mpwqe(struct net_device * netdev,bool enable)2255 static int set_pflag_skb_tx_mpwqe(struct net_device *netdev, bool enable)
2256 {
2257 return set_pflag_tx_mpwqe_common(netdev, MLX5E_PFLAG_SKB_TX_MPWQE, enable);
2258 }
2259
set_pflag_tx_port_ts(struct net_device * netdev,bool enable)2260 static int set_pflag_tx_port_ts(struct net_device *netdev, bool enable)
2261 {
2262 struct mlx5e_priv *priv = netdev_priv(netdev);
2263 struct mlx5_core_dev *mdev = priv->mdev;
2264 struct mlx5e_params new_params;
2265 int err;
2266
2267 if (!MLX5_CAP_GEN(mdev, ts_cqe_to_dest_cqn) ||
2268 !MLX5_CAP_GEN_2(mdev, ts_cqe_metadata_size2wqe_counter))
2269 return -EOPNOTSUPP;
2270
2271 /* Don't allow changing the PTP state if HTB offload is active, because
2272 * the numeration of the QoS SQs will change, while per-queue qdiscs are
2273 * attached.
2274 */
2275 if (mlx5e_selq_is_htb_enabled(&priv->selq)) {
2276 netdev_err(priv->netdev, "%s: HTB offload is active, cannot change the PTP state\n",
2277 __func__);
2278 return -EINVAL;
2279 }
2280
2281 new_params = priv->channels.params;
2282 /* Don't allow enabling TX-port-TS if MQPRIO mode channel offload is
2283 * active, since it defines explicitly which TC accepts the packet.
2284 * This conflicts with TX-port-TS hijacking the PTP traffic to a specific
2285 * HW TX-queue.
2286 */
2287 if (enable && new_params.mqprio.mode == TC_MQPRIO_MODE_CHANNEL) {
2288 netdev_err(priv->netdev,
2289 "%s: MQPRIO mode channel offload is active, cannot set the TX-port-TS\n",
2290 __func__);
2291 return -EINVAL;
2292 }
2293 MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_TX_PORT_TS, enable);
2294 /* No need to verify SQ stop room as
2295 * ptpsq.txqsq.stop_room <= generic_sq->stop_room, and both
2296 * has the same log_sq_size.
2297 */
2298
2299 err = mlx5e_safe_switch_params(priv, &new_params,
2300 mlx5e_update_tc_and_tx_queues_ctx, NULL, true);
2301 if (!err)
2302 priv->tx_ptp_opened = true;
2303
2304 return err;
2305 }
2306
2307 static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS] = {
2308 { "rx_cqe_moder", set_pflag_rx_cqe_based_moder },
2309 { "tx_cqe_moder", set_pflag_tx_cqe_based_moder },
2310 { "rx_cqe_compress", set_pflag_rx_cqe_compress },
2311 { "rx_striding_rq", set_pflag_rx_striding_rq },
2312 { "rx_no_csum_complete", set_pflag_rx_no_csum_complete },
2313 { "xdp_tx_mpwqe", set_pflag_xdp_tx_mpwqe },
2314 { "skb_tx_mpwqe", set_pflag_skb_tx_mpwqe },
2315 { "tx_port_ts", set_pflag_tx_port_ts },
2316 };
2317
mlx5e_handle_pflag(struct net_device * netdev,u32 wanted_flags,enum mlx5e_priv_flag flag)2318 static int mlx5e_handle_pflag(struct net_device *netdev,
2319 u32 wanted_flags,
2320 enum mlx5e_priv_flag flag)
2321 {
2322 struct mlx5e_priv *priv = netdev_priv(netdev);
2323 bool enable = !!(wanted_flags & BIT(flag));
2324 u32 changes = wanted_flags ^ priv->channels.params.pflags;
2325 int err;
2326
2327 if (!(changes & BIT(flag)))
2328 return 0;
2329
2330 err = mlx5e_priv_flags[flag].handler(netdev, enable);
2331 if (err) {
2332 netdev_err(netdev, "%s private flag '%s' failed err %d\n",
2333 enable ? "Enable" : "Disable", mlx5e_priv_flags[flag].name, err);
2334 return err;
2335 }
2336
2337 MLX5E_SET_PFLAG(&priv->channels.params, flag, enable);
2338 return 0;
2339 }
2340
mlx5e_set_priv_flags(struct net_device * netdev,u32 pflags)2341 static int mlx5e_set_priv_flags(struct net_device *netdev, u32 pflags)
2342 {
2343 struct mlx5e_priv *priv = netdev_priv(netdev);
2344 enum mlx5e_priv_flag pflag;
2345 int err;
2346
2347 mutex_lock(&priv->state_lock);
2348
2349 for (pflag = 0; pflag < MLX5E_NUM_PFLAGS; pflag++) {
2350 err = mlx5e_handle_pflag(netdev, pflags, pflag);
2351 if (err)
2352 break;
2353 }
2354
2355 mutex_unlock(&priv->state_lock);
2356
2357 /* Need to fix some features.. */
2358 netdev_update_features(netdev);
2359
2360 return err;
2361 }
2362
mlx5e_get_priv_flags(struct net_device * netdev)2363 static u32 mlx5e_get_priv_flags(struct net_device *netdev)
2364 {
2365 struct mlx5e_priv *priv = netdev_priv(netdev);
2366
2367 return priv->channels.params.pflags;
2368 }
2369
mlx5e_get_rxnfc(struct net_device * dev,struct ethtool_rxnfc * info,u32 * rule_locs)2370 static int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
2371 u32 *rule_locs)
2372 {
2373 struct mlx5e_priv *priv = netdev_priv(dev);
2374
2375 /* ETHTOOL_GRXRINGS is needed by ethtool -x which is not part
2376 * of rxnfc. We keep this logic out of mlx5e_ethtool_get_rxnfc,
2377 * to avoid breaking "ethtool -x" when mlx5e_ethtool_get_rxnfc
2378 * is compiled out via CONFIG_MLX5_EN_RXNFC=n.
2379 */
2380 if (info->cmd == ETHTOOL_GRXRINGS) {
2381 info->data = priv->channels.params.num_channels;
2382 return 0;
2383 }
2384
2385 return mlx5e_ethtool_get_rxnfc(priv, info, rule_locs);
2386 }
2387
mlx5e_set_rxnfc(struct net_device * dev,struct ethtool_rxnfc * cmd)2388 static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
2389 {
2390 struct mlx5e_priv *priv = netdev_priv(dev);
2391
2392 return mlx5e_ethtool_set_rxnfc(priv, cmd);
2393 }
2394
query_port_status_opcode(struct mlx5_core_dev * mdev,u32 * status_opcode)2395 static int query_port_status_opcode(struct mlx5_core_dev *mdev, u32 *status_opcode)
2396 {
2397 struct mlx5_ifc_pddr_troubleshooting_page_bits *pddr_troubleshooting_page;
2398 u32 in[MLX5_ST_SZ_DW(pddr_reg)] = {};
2399 u32 out[MLX5_ST_SZ_DW(pddr_reg)];
2400 int err;
2401
2402 MLX5_SET(pddr_reg, in, local_port, 1);
2403 MLX5_SET(pddr_reg, in, page_select,
2404 MLX5_PDDR_REG_PAGE_SELECT_TROUBLESHOOTING_INFO_PAGE);
2405
2406 pddr_troubleshooting_page = MLX5_ADDR_OF(pddr_reg, in, page_data);
2407 MLX5_SET(pddr_troubleshooting_page, pddr_troubleshooting_page,
2408 group_opcode, MLX5_PDDR_REG_TRBLSH_GROUP_OPCODE_MONITOR);
2409 err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
2410 sizeof(out), MLX5_REG_PDDR, 0, 0);
2411 if (err)
2412 return err;
2413
2414 pddr_troubleshooting_page = MLX5_ADDR_OF(pddr_reg, out, page_data);
2415 *status_opcode = MLX5_GET(pddr_troubleshooting_page, pddr_troubleshooting_page,
2416 status_opcode);
2417 return 0;
2418 }
2419
2420 struct mlx5e_ethtool_link_ext_state_opcode_mapping {
2421 u32 status_opcode;
2422 enum ethtool_link_ext_state link_ext_state;
2423 u8 link_ext_substate;
2424 };
2425
2426 static const struct mlx5e_ethtool_link_ext_state_opcode_mapping
2427 mlx5e_link_ext_state_opcode_map[] = {
2428 /* States relating to the autonegotiation or issues therein */
2429 {2, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2430 ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED},
2431 {3, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2432 ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED},
2433 {4, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2434 ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED},
2435 {36, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2436 ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE},
2437 {38, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2438 ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE},
2439 {39, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2440 ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD},
2441
2442 /* Failure during link training */
2443 {5, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2444 ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED},
2445 {6, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2446 ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT},
2447 {7, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2448 ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY},
2449 {8, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 0},
2450 {14, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2451 ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT},
2452
2453 /* Logical mismatch in physical coding sublayer or forward error correction sublayer */
2454 {9, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2455 ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK},
2456 {10, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2457 ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK},
2458 {11, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2459 ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS},
2460 {12, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2461 ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED},
2462 {13, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2463 ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED},
2464
2465 /* Signal integrity issues */
2466 {15, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, 0},
2467 {17, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
2468 ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS},
2469 {42, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
2470 ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE},
2471
2472 /* No cable connected */
2473 {1024, ETHTOOL_LINK_EXT_STATE_NO_CABLE, 0},
2474
2475 /* Failure is related to cable, e.g., unsupported cable */
2476 {16, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
2477 ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
2478 {20, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
2479 ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
2480 {29, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
2481 ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
2482 {1025, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
2483 ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
2484 {1029, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
2485 ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
2486 {1031, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 0},
2487
2488 /* Failure is related to EEPROM, e.g., failure during reading or parsing the data */
2489 {1027, ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, 0},
2490
2491 /* Failure during calibration algorithm */
2492 {23, ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, 0},
2493
2494 /* The hardware is not able to provide the power required from cable or module */
2495 {1032, ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, 0},
2496
2497 /* The module is overheated */
2498 {1030, ETHTOOL_LINK_EXT_STATE_OVERHEAT, 0},
2499 };
2500
2501 static void
mlx5e_set_link_ext_state(struct mlx5e_ethtool_link_ext_state_opcode_mapping link_ext_state_mapping,struct ethtool_link_ext_state_info * link_ext_state_info)2502 mlx5e_set_link_ext_state(struct mlx5e_ethtool_link_ext_state_opcode_mapping
2503 link_ext_state_mapping,
2504 struct ethtool_link_ext_state_info *link_ext_state_info)
2505 {
2506 switch (link_ext_state_mapping.link_ext_state) {
2507 case ETHTOOL_LINK_EXT_STATE_AUTONEG:
2508 link_ext_state_info->autoneg =
2509 link_ext_state_mapping.link_ext_substate;
2510 break;
2511 case ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE:
2512 link_ext_state_info->link_training =
2513 link_ext_state_mapping.link_ext_substate;
2514 break;
2515 case ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH:
2516 link_ext_state_info->link_logical_mismatch =
2517 link_ext_state_mapping.link_ext_substate;
2518 break;
2519 case ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY:
2520 link_ext_state_info->bad_signal_integrity =
2521 link_ext_state_mapping.link_ext_substate;
2522 break;
2523 case ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE:
2524 link_ext_state_info->cable_issue =
2525 link_ext_state_mapping.link_ext_substate;
2526 break;
2527 default:
2528 break;
2529 }
2530
2531 link_ext_state_info->link_ext_state = link_ext_state_mapping.link_ext_state;
2532 }
2533
2534 static int
mlx5e_get_link_ext_state(struct net_device * dev,struct ethtool_link_ext_state_info * link_ext_state_info)2535 mlx5e_get_link_ext_state(struct net_device *dev,
2536 struct ethtool_link_ext_state_info *link_ext_state_info)
2537 {
2538 struct mlx5e_ethtool_link_ext_state_opcode_mapping link_ext_state_mapping;
2539 struct mlx5e_priv *priv = netdev_priv(dev);
2540 u32 status_opcode = 0;
2541 int i;
2542
2543 /* Exit without data if the interface state is OK, since no extended data is
2544 * available in such case
2545 */
2546 if (netif_carrier_ok(dev))
2547 return -ENODATA;
2548
2549 if (query_port_status_opcode(priv->mdev, &status_opcode) ||
2550 !status_opcode)
2551 return -ENODATA;
2552
2553 for (i = 0; i < ARRAY_SIZE(mlx5e_link_ext_state_opcode_map); i++) {
2554 link_ext_state_mapping = mlx5e_link_ext_state_opcode_map[i];
2555 if (link_ext_state_mapping.status_opcode == status_opcode) {
2556 mlx5e_set_link_ext_state(link_ext_state_mapping,
2557 link_ext_state_info);
2558 return 0;
2559 }
2560 }
2561
2562 return -ENODATA;
2563 }
2564
mlx5e_get_eth_phy_stats(struct net_device * netdev,struct ethtool_eth_phy_stats * phy_stats)2565 static void mlx5e_get_eth_phy_stats(struct net_device *netdev,
2566 struct ethtool_eth_phy_stats *phy_stats)
2567 {
2568 struct mlx5e_priv *priv = netdev_priv(netdev);
2569
2570 mlx5e_stats_eth_phy_get(priv, phy_stats);
2571 }
2572
mlx5e_get_eth_mac_stats(struct net_device * netdev,struct ethtool_eth_mac_stats * mac_stats)2573 static void mlx5e_get_eth_mac_stats(struct net_device *netdev,
2574 struct ethtool_eth_mac_stats *mac_stats)
2575 {
2576 struct mlx5e_priv *priv = netdev_priv(netdev);
2577
2578 mlx5e_stats_eth_mac_get(priv, mac_stats);
2579 }
2580
mlx5e_get_eth_ctrl_stats(struct net_device * netdev,struct ethtool_eth_ctrl_stats * ctrl_stats)2581 static void mlx5e_get_eth_ctrl_stats(struct net_device *netdev,
2582 struct ethtool_eth_ctrl_stats *ctrl_stats)
2583 {
2584 struct mlx5e_priv *priv = netdev_priv(netdev);
2585
2586 mlx5e_stats_eth_ctrl_get(priv, ctrl_stats);
2587 }
2588
mlx5e_get_rmon_stats(struct net_device * netdev,struct ethtool_rmon_stats * rmon_stats,const struct ethtool_rmon_hist_range ** ranges)2589 static void mlx5e_get_rmon_stats(struct net_device *netdev,
2590 struct ethtool_rmon_stats *rmon_stats,
2591 const struct ethtool_rmon_hist_range **ranges)
2592 {
2593 struct mlx5e_priv *priv = netdev_priv(netdev);
2594
2595 mlx5e_stats_rmon_get(priv, rmon_stats, ranges);
2596 }
2597
mlx5e_get_ts_stats(struct net_device * netdev,struct ethtool_ts_stats * ts_stats)2598 static void mlx5e_get_ts_stats(struct net_device *netdev,
2599 struct ethtool_ts_stats *ts_stats)
2600 {
2601 struct mlx5e_priv *priv = netdev_priv(netdev);
2602
2603 mlx5e_stats_ts_get(priv, ts_stats);
2604 }
2605
2606 const struct ethtool_ops mlx5e_ethtool_ops = {
2607 .cap_rss_ctx_supported = true,
2608 .rxfh_per_ctx_key = true,
2609 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2610 ETHTOOL_COALESCE_MAX_FRAMES |
2611 ETHTOOL_COALESCE_USE_ADAPTIVE |
2612 ETHTOOL_COALESCE_USE_CQE,
2613 .get_drvinfo = mlx5e_get_drvinfo,
2614 .get_link = ethtool_op_get_link,
2615 .get_link_ext_state = mlx5e_get_link_ext_state,
2616 .get_strings = mlx5e_get_strings,
2617 .get_sset_count = mlx5e_get_sset_count,
2618 .get_ethtool_stats = mlx5e_get_ethtool_stats,
2619 .get_ringparam = mlx5e_get_ringparam,
2620 .set_ringparam = mlx5e_set_ringparam,
2621 .get_channels = mlx5e_get_channels,
2622 .set_channels = mlx5e_set_channels,
2623 .get_coalesce = mlx5e_get_coalesce,
2624 .set_coalesce = mlx5e_set_coalesce,
2625 .get_per_queue_coalesce = mlx5e_get_per_queue_coalesce,
2626 .set_per_queue_coalesce = mlx5e_set_per_queue_coalesce,
2627 .get_link_ksettings = mlx5e_get_link_ksettings,
2628 .set_link_ksettings = mlx5e_set_link_ksettings,
2629 .get_rxfh_key_size = mlx5e_get_rxfh_key_size,
2630 .get_rxfh_indir_size = mlx5e_get_rxfh_indir_size,
2631 .get_rxfh = mlx5e_get_rxfh,
2632 .set_rxfh = mlx5e_set_rxfh,
2633 .get_rxnfc = mlx5e_get_rxnfc,
2634 .set_rxnfc = mlx5e_set_rxnfc,
2635 .get_tunable = mlx5e_get_tunable,
2636 .set_tunable = mlx5e_set_tunable,
2637 .get_pause_stats = mlx5e_get_pause_stats,
2638 .get_pauseparam = mlx5e_get_pauseparam,
2639 .set_pauseparam = mlx5e_set_pauseparam,
2640 .get_ts_info = mlx5e_get_ts_info,
2641 .set_phys_id = mlx5e_set_phys_id,
2642 .get_wol = mlx5e_get_wol,
2643 .set_wol = mlx5e_set_wol,
2644 .get_module_info = mlx5e_get_module_info,
2645 .get_module_eeprom = mlx5e_get_module_eeprom,
2646 .get_module_eeprom_by_page = mlx5e_get_module_eeprom_by_page,
2647 .flash_device = mlx5e_flash_device,
2648 .get_priv_flags = mlx5e_get_priv_flags,
2649 .set_priv_flags = mlx5e_set_priv_flags,
2650 .self_test = mlx5e_self_test,
2651 .get_fec_stats = mlx5e_get_fec_stats,
2652 .get_fecparam = mlx5e_get_fecparam,
2653 .set_fecparam = mlx5e_set_fecparam,
2654 .get_eth_phy_stats = mlx5e_get_eth_phy_stats,
2655 .get_eth_mac_stats = mlx5e_get_eth_mac_stats,
2656 .get_eth_ctrl_stats = mlx5e_get_eth_ctrl_stats,
2657 .get_rmon_stats = mlx5e_get_rmon_stats,
2658 .get_ts_stats = mlx5e_get_ts_stats,
2659 .get_link_ext_stats = mlx5e_get_link_ext_stats
2660 };
2661