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