]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c
Move EEPROM information query from a sysctl in mlx5en(4) to an ioctl
[FreeBSD/FreeBSD.git] / sys / dev / mlx5 / mlx5_en / mlx5_en_ethtool.c
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 static const char *mlx5e_params_desc[] = {
905         MLX5E_PARAMS(MLX5E_STATS_DESC)
906 };
907
908 static const char *mlx5e_port_stats_debug_desc[] = {
909         MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
910 };
911
912 static int
913 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)
914 {
915         struct mlx5e_priv *priv;
916         struct sbuf sb;
917         struct mlx5e_channel *c;
918         struct mlx5e_sq *sq;
919         struct mlx5e_rq *rq;
920         int error, i, tc;
921         bool opened;
922
923         priv = arg1;
924         error = sysctl_wire_old_buffer(req, 0);
925         if (error != 0)
926                 return (error);
927         if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL)
928                 return (ENOMEM);
929         sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
930
931         PRIV_LOCK(priv);
932         opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
933
934         sbuf_printf(&sb, "pages irq %d\n",
935             priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector);
936         sbuf_printf(&sb, "command irq %d\n",
937             priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector);
938         sbuf_printf(&sb, "async irq %d\n",
939             priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector);
940
941         for (i = 0; i != priv->params.num_channels; i++) {
942                 int eqn_not_used = -1;
943                 int irqn = MLX5_EQ_VEC_COMP_BASE;
944
945                 if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0)
946                         continue;
947
948                 c = opened ? &priv->channel[i] : NULL;
949                 rq = opened ? &c->rq : NULL;
950                 sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i,
951                     opened ? rq->rqn : -1,
952                     opened ? rq->cq.mcq.cqn : -1,
953                     priv->mdev->priv.msix_arr[irqn].vector);
954
955                 for (tc = 0; tc != priv->num_tc; tc++) {
956                         sq = opened ? &c->sq[tc] : NULL;
957                         sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n",
958                             i, tc,
959                             opened ? sq->sqn : -1,
960                             opened ? sq->cq.mcq.cqn : -1,
961                             priv->mdev->priv.msix_arr[irqn].vector);
962                 }
963         }
964         PRIV_UNLOCK(priv);
965         error = sbuf_finish(&sb);
966         sbuf_delete(&sb);
967         return (error);
968 }
969
970 static int
971 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
972 {
973         struct mlx5e_priv *priv = arg1;
974         int sys_debug;
975         int error;
976
977         PRIV_LOCK(priv);
978         if (priv->gone != 0) {
979                 error = ENODEV;
980                 goto done;
981         }
982         sys_debug = priv->sysctl_debug;
983         error = sysctl_handle_int(oidp, &sys_debug, 0, req);
984         if (error != 0 || !req->newptr)
985                 goto done;
986         sys_debug = sys_debug ? 1 : 0;
987         if (sys_debug == priv->sysctl_debug)
988                 goto done;
989
990         if ((priv->sysctl_debug = sys_debug)) {
991                 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
992                     SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
993                     mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
994                     priv->stats.port_stats_debug.arg);
995                 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx,
996                     SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
997                     "hw_ctx_debug",
998                     CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0,
999                     mlx5e_ethtool_debug_channel_info, "S", "");
1000         } else {
1001                 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
1002         }
1003 done:
1004         PRIV_UNLOCK(priv);
1005         return (error);
1006 }
1007
1008 static void
1009 mlx5e_create_diagnostics(struct mlx5e_priv *priv)
1010 {
1011         struct mlx5_core_diagnostics_entry entry;
1012         struct sysctl_ctx_list *ctx;
1013         struct sysctl_oid *node;
1014         int x;
1015
1016         /* sysctl context we are using */
1017         ctx = &priv->sysctl_ctx;
1018
1019         /* create root node */
1020         node = SYSCTL_ADD_NODE(ctx,
1021             SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1022             "diagnostics", CTLFLAG_RD, NULL, "Diagnostics");
1023         if (node == NULL)
1024                 return;
1025
1026         /* create PCI diagnostics */
1027         for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
1028                 entry = mlx5_core_pci_diagnostics_table[x];
1029                 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
1030                         continue;
1031                 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1032                     entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
1033                     "PCI diagnostics counter");
1034         }
1035
1036         /* create general diagnostics */
1037         for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
1038                 entry = mlx5_core_general_diagnostics_table[x];
1039                 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
1040                         continue;
1041                 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1042                     entry.desc, CTLFLAG_RD, priv->params_general.array + x,
1043                     "General diagnostics counter");
1044         }
1045 }
1046
1047 void
1048 mlx5e_create_ethtool(struct mlx5e_priv *priv)
1049 {
1050         struct sysctl_oid *node, *qos_node;
1051         const char *pnameunit;
1052         struct mlx5e_port_buffer port_buffer;
1053         unsigned x;
1054         int i;
1055
1056         /* set some defaults */
1057         priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
1058         priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
1059         priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
1060         priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
1061         priv->params_ethtool.channels = priv->params.num_channels;
1062         priv->params_ethtool.channels_rsss = priv->params.channels_rsss;
1063         priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
1064         priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
1065         priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
1066         priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
1067         priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
1068         priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
1069         priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
1070         priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
1071         priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
1072         priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
1073         mlx5e_ethtool_sync_tx_completion_fact(priv);
1074
1075         /* get default values for local loopback, if any */
1076         if (MLX5_CAP_GEN(priv->mdev, disable_local_lb)) {
1077                 int err;
1078                 u8 val;
1079
1080                 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val);
1081                 if (err == 0)
1082                         priv->params_ethtool.mc_local_lb = val;
1083
1084                 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val);
1085                 if (err == 0)
1086                         priv->params_ethtool.uc_local_lb = val;
1087         }
1088
1089         /* create root node */
1090         node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1091             SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
1092             "conf", CTLFLAG_RW, NULL, "Configuration");
1093         if (node == NULL)
1094                 return;
1095         for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
1096                 /* check for read-only parameter */
1097                 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL ||
1098                     strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) {
1099                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1100                             mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
1101                             CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1102                             mlx5e_params_desc[2 * x + 1]);
1103                 } else {
1104 #if (__FreeBSD_version < 1100000)
1105                         char path[64];
1106 #endif
1107                         /*
1108                          * NOTE: In FreeBSD-11 and newer the
1109                          * CTLFLAG_RWTUN flag will take care of
1110                          * loading default sysctl value from the
1111                          * kernel environment, if any:
1112                          */
1113                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1114                             mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
1115                             CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
1116                             mlx5e_params_desc[2 * x + 1]);
1117
1118 #if (__FreeBSD_version < 1100000)
1119                         /* compute path for sysctl */
1120                         snprintf(path, sizeof(path), "dev.mce.%d.conf.%s",
1121                             device_get_unit(priv->mdev->pdev->dev.bsddev),
1122                             mlx5e_params_desc[2 * x]);
1123
1124                         /* try to fetch tunable, if any */
1125                         if (TUNABLE_QUAD_FETCH(path, &priv->params_ethtool.arg[x]))
1126                                 mlx5e_ethtool_handler(NULL, priv, x, NULL);
1127 #endif
1128                 }
1129         }
1130
1131         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
1132             "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
1133             0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
1134
1135         pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
1136
1137         SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
1138             OID_AUTO, "device_name", CTLFLAG_RD,
1139             __DECONST(void *, pnameunit), 0,
1140             "PCI device name");
1141
1142         /* Diagnostics support */
1143         mlx5e_create_diagnostics(priv);
1144
1145         /* create qos node */
1146         qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
1147             SYSCTL_CHILDREN(node), OID_AUTO,
1148             "qos", CTLFLAG_RW, NULL, "Quality Of Service configuration");
1149         if (qos_node == NULL)
1150                 return;
1151
1152         /* Priority rate limit support */
1153         if (mlx5e_getmaxrate(priv) == 0) {
1154                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1155                     OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1156                     priv, 0, mlx5e_tc_maxrate_handler, "QU",
1157                     "Max rate for priority, specified in kilobits, where kilo=1000, "
1158                     "max_rate must be divisible by 100000");
1159         }
1160
1161         /* Bandwidth limiting by ratio */
1162         if (mlx5e_get_max_alloc(priv) == 0) {
1163                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1164                     OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1165                     priv, 0, mlx5e_tc_rate_share_handler, "QU",
1166                     "Specify bandwidth ratio from 1 to 100 "
1167                     "for the available traffic classes");
1168         }
1169
1170         /* Priority to traffic class mapping */
1171         if (mlx5e_get_prio_tc(priv) == 0) {
1172                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1173                     OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1174                     priv, 0, mlx5e_prio_to_tc_handler, "CU",
1175                     "Set traffic class 0 to 7 for priority 0 to 7 inclusivly");
1176         }
1177
1178         /* DSCP support */
1179         if (mlx5e_get_dscp(priv) == 0) {
1180                 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) {
1181                         char name[32];
1182                         snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7);
1183                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1184                                 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1185                                 priv, i, mlx5e_dscp_prio_handler, "CU",
1186                                 "Set DSCP to priority mapping, 0..7");
1187                 }
1188 #define A       "Set trust state, 1:PCP 2:DSCP"
1189 #define B       " 3:BOTH"
1190                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1191                     OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1192                     priv, 0, mlx5e_trust_state_handler, "CU",
1193                     MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ?
1194                     A B : A);
1195 #undef B
1196 #undef A
1197         }
1198
1199         if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) {
1200                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1201                     OID_AUTO, "buffers_size",
1202                     CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1203                     priv, 0, mlx5e_buf_size_handler, "IU",
1204                     "Set buffers sizes");
1205                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1206                     OID_AUTO, "buffers_prio",
1207                     CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1208                     priv, 0, mlx5e_buf_prio_handler, "CU",
1209                     "Set prio to buffers mapping");
1210                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
1211                     OID_AUTO, "cable_length",
1212                     CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1213                     priv, 0, mlx5e_cable_length_handler, "IU",
1214                     "Set cable length in meters for xoff threshold calculation");
1215         }
1216 }