xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c (revision 6deb0b1e94c6afc20ddbeed5c1336874612bc5d8)
1 /*-
2  * Copyright (c) 2015-2019 Mellanox Technologies. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27 
28 #include "en.h"
29 #include "port_buffer.h"
30 #include <net/sff8472.h>
31 
32 void
33 mlx5e_create_stats(struct sysctl_ctx_list *ctx,
34     struct sysctl_oid_list *parent, const char *buffer,
35     const char **desc, unsigned num, u64 * arg)
36 {
37 	struct sysctl_oid *node;
38 	unsigned x;
39 
40 	sysctl_ctx_init(ctx);
41 
42 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
43 	    buffer, CTLFLAG_RD, NULL, "Statistics");
44 	if (node == NULL)
45 		return;
46 	for (x = 0; x != num; x++) {
47 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
48 		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
49 	}
50 }
51 
52 static void
53 mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv)
54 {
55 	/*
56 	 * Limit the maximum distance between completion events to
57 	 * half of the currently set TX queue size.
58 	 *
59 	 * The maximum number of queue entries a single IP packet can
60 	 * consume is given by MLX5_SEND_WQE_MAX_WQEBBS.
61 	 *
62 	 * The worst case max value is then given as below:
63 	 */
64 	uint64_t max = priv->params_ethtool.tx_queue_size /
65 	    (2 * MLX5_SEND_WQE_MAX_WQEBBS);
66 
67 	/*
68 	 * Update the maximum completion factor value in case the
69 	 * tx_queue_size field changed. Ensure we don't overflow
70 	 * 16-bits.
71 	 */
72 	if (max < 1)
73 		max = 1;
74 	else if (max > 65535)
75 		max = 65535;
76 	priv->params_ethtool.tx_completion_fact_max = max;
77 
78 	/*
79 	 * Verify that the current TX completion factor is within the
80 	 * given limits:
81 	 */
82 	if (priv->params_ethtool.tx_completion_fact < 1)
83 		priv->params_ethtool.tx_completion_fact = 1;
84 	else if (priv->params_ethtool.tx_completion_fact > max)
85 		priv->params_ethtool.tx_completion_fact = max;
86 }
87 
88 static int
89 mlx5e_getmaxrate(struct mlx5e_priv *priv)
90 {
91 	struct mlx5_core_dev *mdev = priv->mdev;
92 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
93 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
94 	int err;
95 	int i;
96 
97 	PRIV_LOCK(priv);
98 	err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
99 	if (err)
100 		goto done;
101 
102 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
103 		switch (max_bw_unit[i]) {
104 		case MLX5_100_MBPS_UNIT:
105 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB;
106 			break;
107 		case MLX5_GBPS_UNIT:
108 			priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB;
109 			break;
110 		case MLX5_BW_NO_LIMIT:
111 			priv->params_ethtool.max_bw_value[i] = 0;
112 			break;
113 		default:
114 			priv->params_ethtool.max_bw_value[i] = -1;
115 			WARN_ONCE(true, "non-supported BW unit");
116 			break;
117 		}
118 	}
119 done:
120 	PRIV_UNLOCK(priv);
121 	return (err);
122 }
123 
124 static int
125 mlx5e_get_max_alloc(struct mlx5e_priv *priv)
126 {
127 	struct mlx5_core_dev *mdev = priv->mdev;
128 	int err;
129 	int x;
130 
131 	PRIV_LOCK(priv);
132 	err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share);
133 	if (err == 0) {
134 		/* set default value */
135 		for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) {
136 			priv->params_ethtool.max_bw_share[x] =
137 			    100 / IEEE_8021QAZ_MAX_TCS;
138 		}
139 		err = -mlx5_set_port_tc_bw_alloc(mdev,
140 		    priv->params_ethtool.max_bw_share);
141 	}
142 	PRIV_UNLOCK(priv);
143 
144 	return (err);
145 }
146 
147 static int
148 mlx5e_get_dscp(struct mlx5e_priv *priv)
149 {
150 	struct mlx5_core_dev *mdev = priv->mdev;
151 	int err;
152 
153 	if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 ||
154 	    MLX5_CAP_QCAM_REG(mdev, qpts) == 0 ||
155 	    MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0)
156 		return (EOPNOTSUPP);
157 
158 	PRIV_LOCK(priv);
159 	err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio);
160 	if (err)
161 		goto done;
162 
163 	err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state);
164 	if (err)
165 		goto done;
166 done:
167 	PRIV_UNLOCK(priv);
168 	return (err);
169 }
170 
171 static void
172 mlx5e_tc_get_parameters(struct mlx5e_priv *priv,
173     u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit)
174 {
175 	const u64 upper_limit_mbps = 255 * MLX5E_100MB;
176 	const u64 upper_limit_gbps = 255 * MLX5E_1GB;
177 	u64 temp;
178 	int i;
179 
180 	memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS);
181 	memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS);
182 
183 	for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) {
184 		temp = (new_bw_value != NULL) ?
185 		    new_bw_value[i] : priv->params_ethtool.max_bw_value[i];
186 
187 		if (!temp) {
188 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
189 		} else if (temp > upper_limit_gbps) {
190 			max_bw_unit[i] = MLX5_BW_NO_LIMIT;
191 		} else if (temp <= upper_limit_mbps) {
192 			max_bw_value[i] = howmany(temp, MLX5E_100MB);
193 			max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
194 		} else {
195 			max_bw_value[i] = howmany(temp, MLX5E_1GB);
196 			max_bw_unit[i]  = MLX5_GBPS_UNIT;
197 		}
198 	}
199 }
200 
201 static int
202 mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS)
203 {
204 	struct mlx5e_priv *priv = arg1;
205 	struct mlx5_core_dev *mdev = priv->mdev;
206 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
207 	u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
208 	u64 new_bw_value[IEEE_8021QAZ_MAX_TCS];
209 	u8 max_rates = mlx5_max_tc(mdev) + 1;
210 	u8 x;
211 	int err;
212 
213 	PRIV_LOCK(priv);
214 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value,
215 	    sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates);
216 	if (err || !req->newptr)
217 		goto done;
218 	err = SYSCTL_IN(req, new_bw_value,
219 	    sizeof(new_bw_value[0]) * max_rates);
220 	if (err)
221 		goto done;
222 
223 	/* range check input value */
224 	for (x = 0; x != max_rates; x++) {
225 		if (new_bw_value[x] % MLX5E_100MB) {
226 			err = ERANGE;
227 			goto done;
228 		}
229 	}
230 
231 	mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit);
232 
233 	err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
234 	if (err)
235 		goto done;
236 
237 	memcpy(priv->params_ethtool.max_bw_value, new_bw_value,
238 	    sizeof(priv->params_ethtool.max_bw_value));
239 done:
240 	PRIV_UNLOCK(priv);
241 	return (err);
242 }
243 
244 static int
245 mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS)
246 {
247 	struct mlx5e_priv *priv = arg1;
248 	struct mlx5_core_dev *mdev = priv->mdev;
249 	u8 max_bw_share[IEEE_8021QAZ_MAX_TCS];
250 	u8 max_rates = mlx5_max_tc(mdev) + 1;
251 	int i;
252 	int err;
253 	int sum;
254 
255 	PRIV_LOCK(priv);
256 	err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates);
257 	if (err || !req->newptr)
258 		goto done;
259 	err = SYSCTL_IN(req, max_bw_share, max_rates);
260 	if (err)
261 		goto done;
262 
263 	/* range check input value */
264 	for (sum = i = 0; i != max_rates; i++) {
265 		if (max_bw_share[i] < 1 || max_bw_share[i] > 100) {
266 			err = ERANGE;
267 			goto done;
268 		}
269 		sum += max_bw_share[i];
270 	}
271 
272 	/* sum of values should be as close to 100 as possible */
273 	if (sum < (100 - max_rates + 1) || sum > 100) {
274 		err = ERANGE;
275 		goto done;
276 	}
277 
278 	err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share);
279 	if (err)
280 		goto done;
281 
282 	memcpy(priv->params_ethtool.max_bw_share, max_bw_share,
283 	    sizeof(priv->params_ethtool.max_bw_share));
284 done:
285 	PRIV_UNLOCK(priv);
286 	return (err);
287 }
288 
289 static int
290 mlx5e_get_prio_tc(struct mlx5e_priv *priv)
291 {
292 	struct mlx5_core_dev *mdev = priv->mdev;
293 	int err = 0;
294 	int i;
295 
296 	PRIV_LOCK(priv);
297 	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
298 		PRIV_UNLOCK(priv);
299 		return (EOPNOTSUPP);
300 	}
301 
302 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
303 		err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i);
304 		if (err)
305 			break;
306 	}
307 	PRIV_UNLOCK(priv);
308 	return (err);
309 }
310 
311 static int
312 mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS)
313 {
314 	struct mlx5e_priv *priv = arg1;
315 	struct mlx5_core_dev *mdev = priv->mdev;
316 	uint8_t temp[MLX5E_MAX_PRIORITY];
317 	int err;
318 	int i;
319 
320 	PRIV_LOCK(priv);
321 	err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY);
322 	if (err || !req->newptr)
323 		goto done;
324 	err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY);
325 	if (err)
326 		goto done;
327 
328 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
329 		if (temp[i] > mlx5_max_tc(mdev)) {
330 			err = ERANGE;
331 			goto done;
332 		}
333 	}
334 
335 	for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
336 		if (temp[i] == priv->params_ethtool.prio_tc[i])
337 			continue;
338 		err = -mlx5_set_port_prio_tc(mdev, i, temp[i]);
339 		if (err)
340 			goto done;
341 		/* update cached value */
342 		priv->params_ethtool.prio_tc[i] = temp[i];
343 	}
344 done:
345 	PRIV_UNLOCK(priv);
346 	return (err);
347 }
348 
349 static int
350 mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS)
351 {
352 	struct mlx5e_priv *priv = arg1;
353 	struct mlx5_core_dev *mdev = priv->mdev;
354 	int err;
355 	u8 result;
356 
357 	PRIV_LOCK(priv);
358 	result = priv->params_ethtool.trust_state;
359 	err = sysctl_handle_8(oidp, &result, 0, req);
360 	if (err || !req->newptr ||
361 	    result == priv->params_ethtool.trust_state)
362 		goto done;
363 
364 	switch (result) {
365 	case MLX5_QPTS_TRUST_PCP:
366 	case MLX5_QPTS_TRUST_DSCP:
367 		break;
368 	case MLX5_QPTS_TRUST_BOTH:
369 		if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) {
370 			err = EOPNOTSUPP;
371 			goto done;
372 		}
373 		break;
374 	default:
375 		err = ERANGE;
376 		goto done;
377 	}
378 
379 	err = -mlx5_set_trust_state(mdev, result);
380 	if (err)
381 		goto done;
382 
383 	priv->params_ethtool.trust_state = result;
384 
385 	/* update inline mode */
386 	mlx5e_refresh_sq_inline(priv);
387 #ifdef RATELIMIT
388 	mlx5e_rl_refresh_sq_inline(&priv->rl);
389 #endif
390 done:
391 	PRIV_UNLOCK(priv);
392 	return (err);
393 }
394 
395 static int
396 mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS)
397 {
398 	struct mlx5e_priv *priv = arg1;
399 	int prio_index = arg2;
400 	struct mlx5_core_dev *mdev = priv->mdev;
401 	uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP];
402 	uint8_t x;
403 	int err;
404 
405 	PRIV_LOCK(priv);
406 	err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index,
407 	    sizeof(priv->params_ethtool.dscp2prio) / 8);
408 	if (err || !req->newptr)
409 		goto done;
410 
411 	memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio));
412 	err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8);
413 	if (err)
414 		goto done;
415 	for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) {
416 		if (dscp2prio[x] > 7) {
417 			err = ERANGE;
418 			goto done;
419 		}
420 	}
421 	err = -mlx5_set_dscp2prio(mdev, dscp2prio);
422 	if (err)
423 		goto done;
424 
425 	/* update local array */
426 	memcpy(priv->params_ethtool.dscp2prio, dscp2prio,
427 	    sizeof(priv->params_ethtool.dscp2prio));
428 done:
429 	PRIV_UNLOCK(priv);
430 	return (err);
431 }
432 
433 int
434 mlx5e_update_buf_lossy(struct mlx5e_priv *priv)
435 {
436 	struct ieee_pfc pfc;
437 
438 	PRIV_ASSERT_LOCKED(priv);
439 	bzero(&pfc, sizeof(pfc));
440 	pfc.pfc_en = priv->params.rx_priority_flow_control;
441 	return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC,
442 	    priv->params_ethtool.hw_mtu, &pfc, NULL, NULL));
443 }
444 
445 static int
446 mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS)
447 {
448 	struct mlx5e_priv *priv;
449 	u32 buf_size[MLX5E_MAX_BUFFER];
450 	struct mlx5e_port_buffer port_buffer;
451 	int error, i;
452 
453 	priv = arg1;
454 	PRIV_LOCK(priv);
455 	error = -mlx5e_port_query_buffer(priv, &port_buffer);
456 	if (error != 0)
457 		goto done;
458 	for (i = 0; i < nitems(buf_size); i++)
459 		buf_size[i] = port_buffer.buffer[i].size;
460 	error = SYSCTL_OUT(req, buf_size, sizeof(buf_size));
461 	if (error != 0 || req->newptr == NULL)
462 		goto done;
463 	error = SYSCTL_IN(req, buf_size, sizeof(buf_size));
464 	if (error != 0)
465 		goto done;
466 	error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE,
467 	    priv->params_ethtool.hw_mtu, NULL, buf_size, NULL);
468 done:
469 	PRIV_UNLOCK(priv);
470 	return (error);
471 }
472 
473 static int
474 mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS)
475 {
476 	struct mlx5e_priv *priv;
477 	struct mlx5_core_dev *mdev;
478 	u8 buffer[MLX5E_MAX_BUFFER];
479 	int error;
480 
481 	priv = arg1;
482 	mdev = priv->mdev;
483 	PRIV_LOCK(priv);
484 	error = -mlx5e_port_query_priority2buffer(mdev, buffer);
485 	if (error != 0)
486 		goto done;
487 	error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER);
488 	if (error != 0 || req->newptr == NULL)
489 		goto done;
490 	error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER);
491 	if (error != 0)
492 		goto done;
493 	error = -mlx5e_port_manual_buffer_config(priv,
494 	    MLX5E_PORT_BUFFER_PRIO2BUFFER,
495 	    priv->params_ethtool.hw_mtu, NULL, NULL, buffer);
496 	if (error == 0)
497 		error = mlx5e_update_buf_lossy(priv);
498 done:
499 	PRIV_UNLOCK(priv);
500 	return (error);
501 }
502 
503 static int
504 mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS)
505 {
506 	struct mlx5e_priv *priv;
507 	u_int cable_len;
508 	int error;
509 
510 	priv = arg1;
511 	PRIV_LOCK(priv);
512 	cable_len = priv->dcbx.cable_len;
513 	error = sysctl_handle_int(oidp, &cable_len, 0, req);
514 	if (error == 0 && req->newptr != NULL &&
515 	    cable_len != priv->dcbx.cable_len) {
516 		error = -mlx5e_port_manual_buffer_config(priv,
517 		    MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu,
518 		    NULL, NULL, NULL);
519 		if (error == 0)
520 			priv->dcbx.cable_len = cable_len;
521 	}
522 	PRIV_UNLOCK(priv);
523 	return (error);
524 }
525 
526 #define	MLX5_PARAM_OFFSET(n)				\
527     __offsetof(struct mlx5e_priv, params_ethtool.n)
528 
529 static int
530 mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
531 {
532 	struct mlx5e_priv *priv = arg1;
533 	uint64_t value;
534 	int mode_modify;
535 	int was_opened;
536 	int error;
537 
538 	PRIV_LOCK(priv);
539 	value = priv->params_ethtool.arg[arg2];
540 	if (req != NULL) {
541 		error = sysctl_handle_64(oidp, &value, 0, req);
542 		if (error || req->newptr == NULL ||
543 		    value == priv->params_ethtool.arg[arg2])
544 			goto done;
545 
546 		/* assign new value */
547 		priv->params_ethtool.arg[arg2] = value;
548 	} else {
549 		error = 0;
550 	}
551 	/* check if device is gone */
552 	if (priv->gone) {
553 		error = ENXIO;
554 		goto done;
555 	}
556 	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
557 	mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify);
558 
559 	switch (MLX5_PARAM_OFFSET(arg[arg2])) {
560 	case MLX5_PARAM_OFFSET(rx_coalesce_usecs):
561 		/* import RX coal time */
562 		if (priv->params_ethtool.rx_coalesce_usecs < 1)
563 			priv->params_ethtool.rx_coalesce_usecs = 0;
564 		else if (priv->params_ethtool.rx_coalesce_usecs >
565 		    MLX5E_FLD_MAX(cqc, cq_period)) {
566 			priv->params_ethtool.rx_coalesce_usecs =
567 			    MLX5E_FLD_MAX(cqc, cq_period);
568 		}
569 		priv->params.rx_cq_moderation_usec =
570 		    priv->params_ethtool.rx_coalesce_usecs;
571 
572 		/* check to avoid down and up the network interface */
573 		if (was_opened)
574 			error = mlx5e_refresh_channel_params(priv);
575 		break;
576 
577 	case MLX5_PARAM_OFFSET(rx_coalesce_pkts):
578 		/* import RX coal pkts */
579 		if (priv->params_ethtool.rx_coalesce_pkts < 1)
580 			priv->params_ethtool.rx_coalesce_pkts = 0;
581 		else if (priv->params_ethtool.rx_coalesce_pkts >
582 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
583 			priv->params_ethtool.rx_coalesce_pkts =
584 			    MLX5E_FLD_MAX(cqc, cq_max_count);
585 		}
586 		priv->params.rx_cq_moderation_pkts =
587 		    priv->params_ethtool.rx_coalesce_pkts;
588 
589 		/* check to avoid down and up the network interface */
590 		if (was_opened)
591 			error = mlx5e_refresh_channel_params(priv);
592 		break;
593 
594 	case MLX5_PARAM_OFFSET(tx_coalesce_usecs):
595 		/* import TX coal time */
596 		if (priv->params_ethtool.tx_coalesce_usecs < 1)
597 			priv->params_ethtool.tx_coalesce_usecs = 0;
598 		else if (priv->params_ethtool.tx_coalesce_usecs >
599 		    MLX5E_FLD_MAX(cqc, cq_period)) {
600 			priv->params_ethtool.tx_coalesce_usecs =
601 			    MLX5E_FLD_MAX(cqc, cq_period);
602 		}
603 		priv->params.tx_cq_moderation_usec =
604 		    priv->params_ethtool.tx_coalesce_usecs;
605 
606 		/* check to avoid down and up the network interface */
607 		if (was_opened)
608 			error = mlx5e_refresh_channel_params(priv);
609 		break;
610 
611 	case MLX5_PARAM_OFFSET(tx_coalesce_pkts):
612 		/* import TX coal pkts */
613 		if (priv->params_ethtool.tx_coalesce_pkts < 1)
614 			priv->params_ethtool.tx_coalesce_pkts = 0;
615 		else if (priv->params_ethtool.tx_coalesce_pkts >
616 		    MLX5E_FLD_MAX(cqc, cq_max_count)) {
617 			priv->params_ethtool.tx_coalesce_pkts =
618 			    MLX5E_FLD_MAX(cqc, cq_max_count);
619 		}
620 		priv->params.tx_cq_moderation_pkts =
621 		    priv->params_ethtool.tx_coalesce_pkts;
622 
623 		/* check to avoid down and up the network interface */
624 		if (was_opened)
625 			error = mlx5e_refresh_channel_params(priv);
626 		break;
627 
628 	case MLX5_PARAM_OFFSET(tx_queue_size):
629 		/* network interface must be down */
630 		if (was_opened)
631 			mlx5e_close_locked(priv->ifp);
632 
633 		/* import TX queue size */
634 		if (priv->params_ethtool.tx_queue_size <
635 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
636 			priv->params_ethtool.tx_queue_size =
637 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
638 		} else if (priv->params_ethtool.tx_queue_size >
639 		    priv->params_ethtool.tx_queue_size_max) {
640 			priv->params_ethtool.tx_queue_size =
641 			    priv->params_ethtool.tx_queue_size_max;
642 		}
643 		/* store actual TX queue size */
644 		priv->params.log_sq_size =
645 		    order_base_2(priv->params_ethtool.tx_queue_size);
646 		priv->params_ethtool.tx_queue_size =
647 		    1 << priv->params.log_sq_size;
648 
649 		/* verify TX completion factor */
650 		mlx5e_ethtool_sync_tx_completion_fact(priv);
651 
652 		/* restart network interface, if any */
653 		if (was_opened)
654 			mlx5e_open_locked(priv->ifp);
655 		break;
656 
657 	case MLX5_PARAM_OFFSET(rx_queue_size):
658 		/* network interface must be down */
659 		if (was_opened)
660 			mlx5e_close_locked(priv->ifp);
661 
662 		/* import RX queue size */
663 		if (priv->params_ethtool.rx_queue_size <
664 		    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
665 			priv->params_ethtool.rx_queue_size =
666 			    (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
667 		} else if (priv->params_ethtool.rx_queue_size >
668 		    priv->params_ethtool.rx_queue_size_max) {
669 			priv->params_ethtool.rx_queue_size =
670 			    priv->params_ethtool.rx_queue_size_max;
671 		}
672 		/* store actual RX queue size */
673 		priv->params.log_rq_size =
674 		    order_base_2(priv->params_ethtool.rx_queue_size);
675 		priv->params_ethtool.rx_queue_size =
676 		    1 << priv->params.log_rq_size;
677 
678 		/* update least number of RX WQEs */
679 		priv->params.min_rx_wqes = min(
680 		    priv->params_ethtool.rx_queue_size - 1,
681 		    MLX5E_PARAMS_DEFAULT_MIN_RX_WQES);
682 
683 		/* restart network interface, if any */
684 		if (was_opened)
685 			mlx5e_open_locked(priv->ifp);
686 		break;
687 
688 	case MLX5_PARAM_OFFSET(channels_rsss):
689 		/* network interface must be down */
690 		if (was_opened)
691 			mlx5e_close_locked(priv->ifp);
692 
693 		/* import number of channels */
694 		if (priv->params_ethtool.channels_rsss < 1)
695 			priv->params_ethtool.channels_rsss = 1;
696 		else if (priv->params_ethtool.channels_rsss > 128)
697 			priv->params_ethtool.channels_rsss = 128;
698 
699 		priv->params.channels_rsss = priv->params_ethtool.channels_rsss;
700 
701 		/* restart network interface, if any */
702 		if (was_opened)
703 			mlx5e_open_locked(priv->ifp);
704 		break;
705 
706 	case MLX5_PARAM_OFFSET(channels):
707 		/* network interface must be down */
708 		if (was_opened)
709 			mlx5e_close_locked(priv->ifp);
710 
711 		/* import number of channels */
712 		if (priv->params_ethtool.channels < 1)
713 			priv->params_ethtool.channels = 1;
714 		else if (priv->params_ethtool.channels >
715 		    (u64) priv->mdev->priv.eq_table.num_comp_vectors) {
716 			priv->params_ethtool.channels =
717 			    (u64) priv->mdev->priv.eq_table.num_comp_vectors;
718 		}
719 		priv->params.num_channels = priv->params_ethtool.channels;
720 
721 		/* restart network interface, if any */
722 		if (was_opened)
723 			mlx5e_open_locked(priv->ifp);
724 		break;
725 
726 	case MLX5_PARAM_OFFSET(rx_coalesce_mode):
727 		/* network interface must be down */
728 		if (was_opened != 0 && mode_modify == 0)
729 			mlx5e_close_locked(priv->ifp);
730 
731 		/* import RX coalesce mode */
732 		if (priv->params_ethtool.rx_coalesce_mode > 3)
733 			priv->params_ethtool.rx_coalesce_mode = 3;
734 		priv->params.rx_cq_moderation_mode =
735 		    priv->params_ethtool.rx_coalesce_mode;
736 
737 		/* restart network interface, if any */
738 		if (was_opened != 0) {
739 			if (mode_modify == 0)
740 				mlx5e_open_locked(priv->ifp);
741 			else
742 				error = mlx5e_refresh_channel_params(priv);
743 		}
744 		break;
745 
746 	case MLX5_PARAM_OFFSET(tx_coalesce_mode):
747 		/* network interface must be down */
748 		if (was_opened != 0 && mode_modify == 0)
749 			mlx5e_close_locked(priv->ifp);
750 
751 		/* import TX coalesce mode */
752 		if (priv->params_ethtool.tx_coalesce_mode != 0)
753 			priv->params_ethtool.tx_coalesce_mode = 1;
754 		priv->params.tx_cq_moderation_mode =
755 		    priv->params_ethtool.tx_coalesce_mode;
756 
757 		/* restart network interface, if any */
758 		if (was_opened != 0) {
759 			if (mode_modify == 0)
760 				mlx5e_open_locked(priv->ifp);
761 			else
762 				error = mlx5e_refresh_channel_params(priv);
763 		}
764 		break;
765 
766 	case MLX5_PARAM_OFFSET(hw_lro):
767 		/* network interface must be down */
768 		if (was_opened)
769 			mlx5e_close_locked(priv->ifp);
770 
771 		/* import HW LRO mode */
772 		if (priv->params_ethtool.hw_lro != 0 &&
773 		    MLX5_CAP_ETH(priv->mdev, lro_cap)) {
774 			priv->params_ethtool.hw_lro = 1;
775 			/* check if feature should actually be enabled */
776 			if (priv->ifp->if_capenable & IFCAP_LRO) {
777 				priv->params.hw_lro_en = true;
778 			} else {
779 				priv->params.hw_lro_en = false;
780 
781 				mlx5_en_warn(priv->ifp, "To enable HW LRO "
782 				    "please also enable LRO via ifconfig(8).\n");
783 			}
784 		} else {
785 			/* return an error if HW does not support this feature */
786 			if (priv->params_ethtool.hw_lro != 0)
787 				error = EINVAL;
788 			priv->params.hw_lro_en = false;
789 			priv->params_ethtool.hw_lro = 0;
790 		}
791 		/* restart network interface, if any */
792 		if (was_opened)
793 			mlx5e_open_locked(priv->ifp);
794 		break;
795 
796 	case MLX5_PARAM_OFFSET(cqe_zipping):
797 		/* network interface must be down */
798 		if (was_opened)
799 			mlx5e_close_locked(priv->ifp);
800 
801 		/* import CQE zipping mode */
802 		if (priv->params_ethtool.cqe_zipping &&
803 		    MLX5_CAP_GEN(priv->mdev, cqe_compression)) {
804 			priv->params.cqe_zipping_en = true;
805 			priv->params_ethtool.cqe_zipping = 1;
806 		} else {
807 			priv->params.cqe_zipping_en = false;
808 			priv->params_ethtool.cqe_zipping = 0;
809 		}
810 		/* restart network interface, if any */
811 		if (was_opened)
812 			mlx5e_open_locked(priv->ifp);
813 		break;
814 
815 	case MLX5_PARAM_OFFSET(tx_completion_fact):
816 		/* network interface must be down */
817 		if (was_opened)
818 			mlx5e_close_locked(priv->ifp);
819 
820 		/* verify parameter */
821 		mlx5e_ethtool_sync_tx_completion_fact(priv);
822 
823 		/* restart network interface, if any */
824 		if (was_opened)
825 			mlx5e_open_locked(priv->ifp);
826 		break;
827 
828 	case MLX5_PARAM_OFFSET(modify_tx_dma):
829 		/* check if network interface is opened */
830 		if (was_opened) {
831 			priv->params_ethtool.modify_tx_dma =
832 			    priv->params_ethtool.modify_tx_dma ? 1 : 0;
833 			/* modify tx according to value */
834 			mlx5e_modify_tx_dma(priv, value != 0);
835 		} else {
836 			/* if closed force enable tx */
837 			priv->params_ethtool.modify_tx_dma = 0;
838 		}
839 		break;
840 
841 	case MLX5_PARAM_OFFSET(modify_rx_dma):
842 		/* check if network interface is opened */
843 		if (was_opened) {
844 			priv->params_ethtool.modify_rx_dma =
845 			    priv->params_ethtool.modify_rx_dma ? 1 : 0;
846 			/* modify rx according to value */
847 			mlx5e_modify_rx_dma(priv, value != 0);
848 		} else {
849 			/* if closed force enable rx */
850 			priv->params_ethtool.modify_rx_dma = 0;
851 		}
852 		break;
853 
854 	case MLX5_PARAM_OFFSET(diag_pci_enable):
855 		priv->params_ethtool.diag_pci_enable =
856 		    priv->params_ethtool.diag_pci_enable ? 1 : 0;
857 
858 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
859 		    priv->params_ethtool.diag_pci_enable,
860 		    priv->params_ethtool.diag_general_enable);
861 		break;
862 
863 	case MLX5_PARAM_OFFSET(diag_general_enable):
864 		priv->params_ethtool.diag_general_enable =
865 		    priv->params_ethtool.diag_general_enable ? 1 : 0;
866 
867 		error = -mlx5_core_set_diagnostics_full(priv->mdev,
868 		    priv->params_ethtool.diag_pci_enable,
869 		    priv->params_ethtool.diag_general_enable);
870 		break;
871 
872 	case MLX5_PARAM_OFFSET(mc_local_lb):
873 		priv->params_ethtool.mc_local_lb =
874 		    priv->params_ethtool.mc_local_lb ? 1 : 0;
875 
876 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
877 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
878 			    MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb);
879 		} else {
880 			error = EOPNOTSUPP;
881 		}
882 		break;
883 
884 	case MLX5_PARAM_OFFSET(uc_local_lb):
885 		priv->params_ethtool.uc_local_lb =
886 		    priv->params_ethtool.uc_local_lb ? 1 : 0;
887 
888 		if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
889 			error = mlx5_nic_vport_modify_local_lb(priv->mdev,
890 			    MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb);
891 		} else {
892 			error = EOPNOTSUPP;
893 		}
894 		break;
895 
896 	default:
897 		break;
898 	}
899 done:
900 	PRIV_UNLOCK(priv);
901 	return (error);
902 }
903 
904 /*
905  * Read the first three bytes of the eeprom in order to get the needed info
906  * for the whole reading.
907  * Byte 0 - Identifier byte
908  * Byte 1 - Revision byte
909  * Byte 2 - Status byte
910  */
911 static int
912 mlx5e_get_eeprom_info(struct mlx5e_priv *priv, struct mlx5e_eeprom *eeprom)
913 {
914 	struct mlx5_core_dev *dev = priv->mdev;
915 	u32 data = 0;
916 	int size_read = 0;
917 	int ret;
918 
919 	ret = mlx5_query_module_num(dev, &eeprom->module_num);
920 	if (ret) {
921 		mlx5_en_err(priv->ifp, "Failed query module error=%d\n",
922 		    ret);
923 		return (ret);
924 	}
925 
926 	/* Read the first three bytes to get Identifier, Revision and Status */
927 	ret = mlx5_query_eeprom(dev, eeprom->i2c_addr, eeprom->page_num,
928 	    eeprom->device_addr, MLX5E_EEPROM_INFO_BYTES, eeprom->module_num, &data,
929 	    &size_read);
930 	if (ret) {
931 		mlx5_en_err(priv->ifp,
932 		    "Failed query eeprom module error=0x%x\n", ret);
933 		return (ret);
934 	}
935 
936 	switch (data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) {
937 	case SFF_8024_ID_QSFP:
938 		eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
939 		eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
940 		break;
941 	case SFF_8024_ID_QSFPPLUS:
942 	case SFF_8024_ID_QSFP28:
943 		if ((data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK) == SFF_8024_ID_QSFP28 ||
944 		    ((data & MLX5_EEPROM_REVISION_ID_BYTE_MASK) >> 8) >= 0x3) {
945 			eeprom->type = MLX5E_ETH_MODULE_SFF_8636;
946 			eeprom->len = MLX5E_ETH_MODULE_SFF_8636_LEN;
947 		} else {
948 			eeprom->type = MLX5E_ETH_MODULE_SFF_8436;
949 			eeprom->len = MLX5E_ETH_MODULE_SFF_8436_LEN;
950 		}
951 		if ((data & MLX5_EEPROM_PAGE_3_VALID_BIT_MASK) == 0)
952 			eeprom->page_valid = 1;
953 		break;
954 	case SFF_8024_ID_SFP:
955 		eeprom->type = MLX5E_ETH_MODULE_SFF_8472;
956 		eeprom->len = MLX5E_ETH_MODULE_SFF_8472_LEN;
957 		break;
958 	default:
959 		mlx5_en_err(priv->ifp,
960 		    "Not recognized cable type = 0x%x(%s)\n",
961 		    data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK,
962 		    sff_8024_id[data & MLX5_EEPROM_IDENTIFIER_BYTE_MASK]);
963 		return (EINVAL);
964 	}
965 	return (0);
966 }
967 
968 /* Read both low and high pages of the eeprom */
969 static int
970 mlx5e_get_eeprom(struct mlx5e_priv *priv, struct mlx5e_eeprom *ee)
971 {
972 	struct mlx5_core_dev *dev = priv->mdev;
973 	int size_read = 0;
974 	int ret;
975 
976 	if (ee->len == 0)
977 		return (EINVAL);
978 
979 	/* Read low page of the eeprom */
980 	while (ee->device_addr < ee->len) {
981 		ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num, ee->device_addr,
982 		    ee->len - ee->device_addr, ee->module_num,
983 		    ee->data + (ee->device_addr / 4), &size_read);
984 		if (ret) {
985 			mlx5_en_err(priv->ifp,
986 			    "Failed reading eeprom, error = 0x%02x\n",ret);
987 			return (ret);
988 		}
989 		ee->device_addr += size_read;
990 	}
991 
992 	/* Read high page of the eeprom */
993 	if (ee->page_valid) {
994 		ee->device_addr = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
995 		ee->page_num = MLX5E_EEPROM_HIGH_PAGE;
996 		size_read = 0;
997 		while (ee->device_addr < MLX5E_EEPROM_PAGE_LENGTH) {
998 			ret = mlx5_query_eeprom(dev, ee->i2c_addr, ee->page_num,
999 			    ee->device_addr, MLX5E_EEPROM_PAGE_LENGTH - ee->device_addr,
1000 			    ee->module_num, ee->data + (ee->len / 4) +
1001 			    ((ee->device_addr - MLX5E_EEPROM_HIGH_PAGE_OFFSET) / 4),
1002 			    &size_read);
1003 			if (ret) {
1004 				mlx5_en_err(priv->ifp,
1005 				    "Failed reading eeprom, error = 0x%02x\n",
1006 				    ret);
1007 				return (ret);
1008 			}
1009 			ee->device_addr += size_read;
1010 		}
1011 	}
1012 	return (0);
1013 }
1014 
1015 static void
1016 mlx5e_print_eeprom(struct mlx5e_eeprom *eeprom)
1017 {
1018 	int row;
1019 	int index_in_row;
1020 	int byte_to_write = 0;
1021 	int line_length = 16;
1022 
1023 	printf("\nOffset\t\tValues\n");
1024 	printf("------\t\t------");
1025 	while (byte_to_write < eeprom->len) {
1026 		printf("\n0x%04X\t\t", byte_to_write);
1027 		for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
1028 			printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
1029 			byte_to_write++;
1030 		}
1031 	}
1032 
1033 	if (eeprom->page_valid) {
1034 		row = MLX5E_EEPROM_HIGH_PAGE_OFFSET;
1035 		printf("\n\nUpper Page 0x03\n");
1036 		printf("\nOffset\t\tValues\n");
1037 		printf("------\t\t------");
1038 		while (row < MLX5E_EEPROM_PAGE_LENGTH) {
1039 			printf("\n0x%04X\t\t", row);
1040 			for (index_in_row = 0; index_in_row < line_length; index_in_row++) {
1041 				printf("%02X ", ((u8 *)eeprom->data)[byte_to_write]);
1042 				byte_to_write++;
1043 				row++;
1044 			}
1045 		}
1046 	}
1047 }
1048 
1049 /*
1050  * Read cable EEPROM module information by first inspecting the first
1051  * three bytes to get the initial information for a whole reading.
1052  * Information will be printed to dmesg.
1053  */
1054 static int
1055 mlx5e_read_eeprom(SYSCTL_HANDLER_ARGS)
1056 {
1057 	struct mlx5e_priv *priv = arg1;
1058 	struct mlx5e_eeprom eeprom;
1059 	int error;
1060 	int result = 0;
1061 
1062 	PRIV_LOCK(priv);
1063 	error = sysctl_handle_int(oidp, &result, 0, req);
1064 	if (error || !req->newptr)
1065 		goto done;
1066 
1067 	/* Check if device is gone */
1068 	if (priv->gone) {
1069 		error = ENXIO;
1070 		goto done;
1071 	}
1072 
1073 	if (result == 1) {
1074 		eeprom.i2c_addr = MLX5E_I2C_ADDR_LOW;
1075 		eeprom.device_addr = 0;
1076 		eeprom.page_num = MLX5E_EEPROM_LOW_PAGE;
1077 		eeprom.page_valid = 0;
1078 
1079 		/* Read three first bytes to get important info */
1080 		error = mlx5e_get_eeprom_info(priv, &eeprom);
1081 		if (error) {
1082 			mlx5_en_err(priv->ifp,
1083 			    "Failed reading eeprom's initial information\n");
1084 			error = 0;
1085 			goto done;
1086 		}
1087 		/*
1088 		 * Allocate needed length buffer and additional space for
1089 		 * page 0x03
1090 		 */
1091 		eeprom.data = malloc(eeprom.len + MLX5E_EEPROM_PAGE_LENGTH,
1092 		    M_MLX5EN, M_WAITOK | M_ZERO);
1093 
1094 		/* Read the whole eeprom information */
1095 		error = mlx5e_get_eeprom(priv, &eeprom);
1096 		if (error) {
1097 			mlx5_en_err(priv->ifp, "Failed reading eeprom\n");
1098 			error = 0;
1099 			/*
1100 			 * Continue printing partial information in case of
1101 			 * an error
1102 			 */
1103 		}
1104 		mlx5e_print_eeprom(&eeprom);
1105 		free(eeprom.data, M_MLX5EN);
1106 	}
1107 done:
1108 	PRIV_UNLOCK(priv);
1109 	return (error);
1110 }
1111 
1112 static const char *mlx5e_params_desc[] = {
1113 	MLX5E_PARAMS(MLX5E_STATS_DESC)
1114 };
1115 
1116 static const char *mlx5e_port_stats_debug_desc[] = {
1117 	MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
1118 };
1119 
1120 static int
1121 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)
1122 {
1123 	struct mlx5e_priv *priv;
1124 	struct sbuf sb;
1125 	struct mlx5e_channel *c;
1126 	struct mlx5e_sq *sq;
1127 	struct mlx5e_rq *rq;
1128 	int error, i, tc;
1129 	bool opened;
1130 
1131 	priv = arg1;
1132 	error = sysctl_wire_old_buffer(req, 0);
1133 	if (error != 0)
1134 		return (error);
1135 	if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL)
1136 		return (ENOMEM);
1137 	sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
1138 
1139 	PRIV_LOCK(priv);
1140 	opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
1141 
1142 	sbuf_printf(&sb, "pages irq %d\n",
1143 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector);
1144 	sbuf_printf(&sb, "command irq %d\n",
1145 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector);
1146 	sbuf_printf(&sb, "async irq %d\n",
1147 	    priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector);
1148 
1149 	for (i = 0; i != priv->params.num_channels; i++) {
1150 		int eqn_not_used = -1;
1151 		int irqn = MLX5_EQ_VEC_COMP_BASE;
1152 
1153 		if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0)
1154 			continue;
1155 
1156 		c = opened ? &priv->channel[i] : NULL;
1157 		rq = opened ? &c->rq : NULL;
1158 		sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i,
1159 		    opened ? rq->rqn : -1,
1160 		    opened ? rq->cq.mcq.cqn : -1,
1161 		    priv->mdev->priv.msix_arr[irqn].vector);
1162 
1163 		for (tc = 0; tc != priv->num_tc; tc++) {
1164 			sq = opened ? &c->sq[tc] : NULL;
1165 			sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n",
1166 			    i, tc,
1167 			    opened ? sq->sqn : -1,
1168 			    opened ? sq->cq.mcq.cqn : -1,
1169 			    priv->mdev->priv.msix_arr[irqn].vector);
1170 		}
1171 	}
1172 	PRIV_UNLOCK(priv);
1173 	error = sbuf_finish(&sb);
1174 	sbuf_delete(&sb);
1175 	return (error);
1176 }
1177 
1178 static int
1179 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
1180 {
1181 	struct mlx5e_priv *priv = arg1;
1182 	int sys_debug;
1183 	int error;
1184 
1185 	PRIV_LOCK(priv);
1186 	if (priv->gone != 0) {
1187 		error = ENODEV;
1188 		goto done;
1189 	}
1190 	sys_debug = priv->sysctl_debug;
1191 	error = sysctl_handle_int(oidp, &sys_debug, 0, req);
1192 	if (error != 0 || !req->newptr)
1193 		goto done;
1194 	sys_debug = sys_debug ? 1 : 0;
1195 	if (sys_debug == priv->sysctl_debug)
1196 		goto done;
1197 
1198 	if ((priv->sysctl_debug = sys_debug)) {
1199 		mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
1200 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
1201 		    mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
1202 		    priv->stats.port_stats_debug.arg);
1203 		SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx,
1204 		    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1205 		    "hw_ctx_debug",
1206 		    CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0,
1207 		    mlx5e_ethtool_debug_channel_info, "S", "");
1208 	} else {
1209 		sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
1210 	}
1211 done:
1212 	PRIV_UNLOCK(priv);
1213 	return (error);
1214 }
1215 
1216 static void
1217 mlx5e_create_diagnostics(struct mlx5e_priv *priv)
1218 {
1219 	struct mlx5_core_diagnostics_entry entry;
1220 	struct sysctl_ctx_list *ctx;
1221 	struct sysctl_oid *node;
1222 	int x;
1223 
1224 	/* sysctl context we are using */
1225 	ctx = &priv->sysctl_ctx;
1226 
1227 	/* create root node */
1228 	node = SYSCTL_ADD_NODE(ctx,
1229 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1230 	    "diagnostics", CTLFLAG_RD, NULL, "Diagnostics");
1231 	if (node == NULL)
1232 		return;
1233 
1234 	/* create PCI diagnostics */
1235 	for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
1236 		entry = mlx5_core_pci_diagnostics_table[x];
1237 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
1238 			continue;
1239 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1240 		    entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
1241 		    "PCI diagnostics counter");
1242 	}
1243 
1244 	/* create general diagnostics */
1245 	for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
1246 		entry = mlx5_core_general_diagnostics_table[x];
1247 		if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
1248 			continue;
1249 		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1250 		    entry.desc, CTLFLAG_RD, priv->params_general.array + x,
1251 		    "General diagnostics counter");
1252 	}
1253 }
1254 
1255 void
1256 mlx5e_create_ethtool(struct mlx5e_priv *priv)
1257 {
1258 	struct sysctl_oid *node, *qos_node;
1259 	const char *pnameunit;
1260 	struct mlx5e_port_buffer port_buffer;
1261 	unsigned x;
1262 	int i;
1263 
1264 	/* set some defaults */
1265 	priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
1266 	priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
1267 	priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
1268 	priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
1269 	priv->params_ethtool.channels = priv->params.num_channels;
1270 	priv->params_ethtool.channels_rsss = priv->params.channels_rsss;
1271 	priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
1272 	priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
1273 	priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
1274 	priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
1275 	priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
1276 	priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
1277 	priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
1278 	priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
1279 	priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
1280 	priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
1281 	mlx5e_ethtool_sync_tx_completion_fact(priv);
1282 
1283 	/* get default values for local loopback, if any */
1284 	if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
1285 		int err;
1286 		u8 val;
1287 
1288 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val);
1289 		if (err == 0)
1290 			priv->params_ethtool.mc_local_lb = val;
1291 
1292 		err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val);
1293 		if (err == 0)
1294 			priv->params_ethtool.uc_local_lb = val;
1295 	}
1296 
1297 	/* create root node */
1298 	node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1299 	    SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1300 	    "conf", CTLFLAG_RW, NULL, "Configuration");
1301 	if (node == NULL)
1302 		return;
1303 	for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
1304 		/* check for read-only parameter */
1305 		if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL ||
1306 		    strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) {
1307 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1308 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
1309 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1310 			    mlx5e_params_desc[2 * x + 1]);
1311 		} else {
1312 #if (__FreeBSD_version < 1100000)
1313 			char path[64];
1314 #endif
1315 			/*
1316 			 * NOTE: In FreeBSD-11 and newer the
1317 			 * CTLFLAG_RWTUN flag will take care of
1318 			 * loading default sysctl value from the
1319 			 * kernel environment, if any:
1320 			 */
1321 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1322 			    mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
1323 			    CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1324 			    mlx5e_params_desc[2 * x + 1]);
1325 
1326 #if (__FreeBSD_version < 1100000)
1327 			/* compute path for sysctl */
1328 			snprintf(path, sizeof(path), "dev.mce.%d.conf.%s",
1329 			    device_get_unit(priv->mdev->pdev->dev.bsddev),
1330 			    mlx5e_params_desc[2 * x]);
1331 
1332 			/* try to fetch tunable, if any */
1333 			if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x]))
1334 				mlx5e_ethtool_handler(NULL, priv, x, NULL);
1335 #endif
1336 		}
1337 	}
1338 
1339 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1340 	    "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
1341 	    0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
1342 
1343 	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
1344 
1345 	SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
1346 	    OID_AUTO, "device_name", CTLFLAG_RD,
1347 	    __DECONST(void *, pnameunit), 0,
1348 	    "PCI device name");
1349 
1350 	/* EEPROM support */
1351 	SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO, "eeprom_info",
1352 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
1353 	    mlx5e_read_eeprom, "I", "EEPROM information");
1354 
1355 	/* Diagnostics support */
1356 	mlx5e_create_diagnostics(priv);
1357 
1358 	/* create qos node */
1359 	qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1360 	    SYSCTL_CHILDREN(node), OID_AUTO,
1361 	    "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration");
1362 	if (qos_node == NULL)
1363 		return;
1364 
1365 	/* Priority rate limit support */
1366 	if (mlx5e_getmaxrate(priv) == 0) {
1367 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1368 		    OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1369 		    priv, 0, mlx5e_tc_maxrate_handler, "QU",
1370 		    "Max rate for priority, specified in kilobits, where kilo=1000, "
1371 		    "max_rate must be divisible by 100000");
1372 	}
1373 
1374 	/* Bandwidth limiting by ratio */
1375 	if (mlx5e_get_max_alloc(priv) == 0) {
1376 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1377 		    OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1378 		    priv, 0, mlx5e_tc_rate_share_handler, "QU",
1379 		    "Specify bandwidth ratio from 1 to 100 "
1380 		    "for the available traffic classes");
1381 	}
1382 
1383 	/* Priority to traffic class mapping */
1384 	if (mlx5e_get_prio_tc(priv) == 0) {
1385 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1386 		    OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1387 		    priv, 0, mlx5e_prio_to_tc_handler, "CU",
1388 		    "Set traffic class 0 to 7 for priority 0 to 7 inclusivly");
1389 	}
1390 
1391 	/* DSCP support */
1392 	if (mlx5e_get_dscp(priv) == 0) {
1393 		for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) {
1394 			char name[32];
1395 			snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7);
1396 			SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1397 				OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1398 				priv, i, mlx5e_dscp_prio_handler, "CU",
1399 				"Set DSCP to priority mapping, 0..7");
1400 		}
1401 #define	A	"Set trust state, 1:PCP 2:DSCP"
1402 #define	B	" 3:BOTH"
1403 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1404 		    OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1405 		    priv, 0, mlx5e_trust_state_handler, "CU",
1406 		    MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ?
1407 		    A B : A);
1408 #undef B
1409 #undef A
1410 	}
1411 
1412 	if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) {
1413 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1414 		    OID_AUTO, "buffers_size",
1415 		    CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1416 		    priv, 0, mlx5e_buf_size_handler, "IU",
1417 		    "Set buffers sizes");
1418 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1419 		    OID_AUTO, "buffers_prio",
1420 		    CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1421 		    priv, 0, mlx5e_buf_prio_handler, "CU",
1422 		    "Set prio to buffers mapping");
1423 		SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1424 		    OID_AUTO, "cable_length",
1425 		    CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1426 		    priv, 0, mlx5e_cable_length_handler, "IU",
1427 		    "Set cable length in meters for xoff threshold calculation");
1428 	}
1429 }
1430