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