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