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