The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mlx5/mlx5_en/mlx5_en_ethtool.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2015-2021 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 "opt_rss.h"
   29 #include "opt_ratelimit.h"
   30 
   31 #include <dev/mlx5/mlx5_en/en.h>
   32 #include <dev/mlx5/mlx5_en/port_buffer.h>
   33 
   34 void
   35 mlx5e_create_stats(struct sysctl_ctx_list *ctx,
   36     struct sysctl_oid_list *parent, const char *buffer,
   37     const char **desc, unsigned num, u64 * arg)
   38 {
   39         struct sysctl_oid *node;
   40         unsigned x;
   41 
   42         sysctl_ctx_init(ctx);
   43 
   44         node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
   45             buffer, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics");
   46         if (node == NULL)
   47                 return;
   48         for (x = 0; x != num; x++) {
   49                 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
   50                     desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
   51         }
   52 }
   53 
   54 void
   55 mlx5e_create_counter_stats(struct sysctl_ctx_list *ctx,
   56     struct sysctl_oid_list *parent, const char *buffer,
   57     const char **desc, unsigned num, counter_u64_t *arg)
   58 {
   59         struct sysctl_oid *node;
   60         unsigned x;
   61 
   62         sysctl_ctx_init(ctx);
   63 
   64         node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
   65             buffer, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Statistics");
   66         if (node == NULL)
   67                 return;
   68         for (x = 0; x != num; x++) {
   69                 SYSCTL_ADD_COUNTER_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
   70                     desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
   71         }
   72 }
   73 
   74 static void
   75 mlx5e_ethtool_sync_tx_completion_fact(struct mlx5e_priv *priv)
   76 {
   77         /*
   78          * Limit the maximum distance between completion events to
   79          * half of the currently set TX queue size.
   80          *
   81          * The maximum number of queue entries a single IP packet can
   82          * consume is given by MLX5_SEND_WQE_MAX_WQEBBS.
   83          *
   84          * The worst case max value is then given as below:
   85          */
   86         uint64_t max = priv->params_ethtool.tx_queue_size /
   87             (2 * MLX5_SEND_WQE_MAX_WQEBBS);
   88 
   89         /*
   90          * Update the maximum completion factor value in case the
   91          * tx_queue_size field changed. Ensure we don't overflow
   92          * 16-bits.
   93          */
   94         if (max < 1)
   95                 max = 1;
   96         else if (max > 65535)
   97                 max = 65535;
   98         priv->params_ethtool.tx_completion_fact_max = max;
   99 
  100         /*
  101          * Verify that the current TX completion factor is within the
  102          * given limits:
  103          */
  104         if (priv->params_ethtool.tx_completion_fact < 1)
  105                 priv->params_ethtool.tx_completion_fact = 1;
  106         else if (priv->params_ethtool.tx_completion_fact > max)
  107                 priv->params_ethtool.tx_completion_fact = max;
  108 }
  109 
  110 static int
  111 mlx5e_getmaxrate(struct mlx5e_priv *priv)
  112 {
  113         struct mlx5_core_dev *mdev = priv->mdev;
  114         u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
  115         u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
  116         int err;
  117         int i;
  118 
  119         PRIV_LOCK(priv);
  120         err = -mlx5_query_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
  121         if (err)
  122                 goto done;
  123 
  124         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
  125                 switch (max_bw_unit[i]) {
  126                 case MLX5_100_MBPS_UNIT:
  127                         priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_100MB;
  128                         break;
  129                 case MLX5_GBPS_UNIT:
  130                         priv->params_ethtool.max_bw_value[i] = max_bw_value[i] * MLX5E_1GB;
  131                         break;
  132                 case MLX5_BW_NO_LIMIT:
  133                         priv->params_ethtool.max_bw_value[i] = 0;
  134                         break;
  135                 default:
  136                         priv->params_ethtool.max_bw_value[i] = -1;
  137                         WARN_ONCE(true, "non-supported BW unit");
  138                         break;
  139                 }
  140         }
  141 done:
  142         PRIV_UNLOCK(priv);
  143         return (err);
  144 }
  145 
  146 static int
  147 mlx5e_get_max_alloc(struct mlx5e_priv *priv)
  148 {
  149         struct mlx5_core_dev *mdev = priv->mdev;
  150         int err;
  151         int x;
  152 
  153         PRIV_LOCK(priv);
  154         err = -mlx5_query_port_tc_bw_alloc(mdev, priv->params_ethtool.max_bw_share);
  155         if (err == 0) {
  156                 /* set default value */
  157                 for (x = 0; x != IEEE_8021QAZ_MAX_TCS; x++) {
  158                         priv->params_ethtool.max_bw_share[x] =
  159                             100 / IEEE_8021QAZ_MAX_TCS;
  160                 }
  161                 err = -mlx5_set_port_tc_bw_alloc(mdev,
  162                     priv->params_ethtool.max_bw_share);
  163         }
  164         PRIV_UNLOCK(priv);
  165 
  166         return (err);
  167 }
  168 
  169 static int
  170 mlx5e_get_dscp(struct mlx5e_priv *priv)
  171 {
  172         struct mlx5_core_dev *mdev = priv->mdev;
  173         int err;
  174 
  175         if (MLX5_CAP_GEN(mdev, qcam_reg) == 0 ||
  176             MLX5_CAP_QCAM_REG(mdev, qpts) == 0 ||
  177             MLX5_CAP_QCAM_REG(mdev, qpdpm) == 0)
  178                 return (EOPNOTSUPP);
  179 
  180         PRIV_LOCK(priv);
  181         err = -mlx5_query_dscp2prio(mdev, priv->params_ethtool.dscp2prio);
  182         if (err)
  183                 goto done;
  184 
  185         err = -mlx5_query_trust_state(mdev, &priv->params_ethtool.trust_state);
  186         if (err)
  187                 goto done;
  188 done:
  189         PRIV_UNLOCK(priv);
  190         return (err);
  191 }
  192 
  193 static void
  194 mlx5e_tc_get_parameters(struct mlx5e_priv *priv,
  195     u64 *new_bw_value, u8 *max_bw_value, u8 *max_bw_unit)
  196 {
  197         const u64 upper_limit_mbps = 255 * MLX5E_100MB;
  198         const u64 upper_limit_gbps = 255 * MLX5E_1GB;
  199         u64 temp;
  200         int i;
  201 
  202         memset(max_bw_value, 0, IEEE_8021QAZ_MAX_TCS);
  203         memset(max_bw_unit, 0, IEEE_8021QAZ_MAX_TCS);
  204 
  205         for (i = 0; i <= mlx5_max_tc(priv->mdev); i++) {
  206                 temp = (new_bw_value != NULL) ?
  207                     new_bw_value[i] : priv->params_ethtool.max_bw_value[i];
  208 
  209                 if (!temp) {
  210                         max_bw_unit[i] = MLX5_BW_NO_LIMIT;
  211                 } else if (temp > upper_limit_gbps) {
  212                         max_bw_unit[i] = MLX5_BW_NO_LIMIT;
  213                 } else if (temp <= upper_limit_mbps) {
  214                         max_bw_value[i] = howmany(temp, MLX5E_100MB);
  215                         max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
  216                 } else {
  217                         max_bw_value[i] = howmany(temp, MLX5E_1GB);
  218                         max_bw_unit[i]  = MLX5_GBPS_UNIT;
  219                 }
  220         }
  221 }
  222 
  223 static int
  224 mlx5e_tc_maxrate_handler(SYSCTL_HANDLER_ARGS)
  225 {
  226         struct mlx5e_priv *priv = arg1;
  227         struct mlx5_core_dev *mdev = priv->mdev;
  228         u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
  229         u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
  230         u64 new_bw_value[IEEE_8021QAZ_MAX_TCS];
  231         u8 max_rates = mlx5_max_tc(mdev) + 1;
  232         u8 x;
  233         int err;
  234 
  235         PRIV_LOCK(priv);
  236         err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_value,
  237             sizeof(priv->params_ethtool.max_bw_value[0]) * max_rates);
  238         if (err || !req->newptr)
  239                 goto done;
  240         err = SYSCTL_IN(req, new_bw_value,
  241             sizeof(new_bw_value[0]) * max_rates);
  242         if (err)
  243                 goto done;
  244 
  245         /* range check input value */
  246         for (x = 0; x != max_rates; x++) {
  247                 if (new_bw_value[x] % MLX5E_100MB) {
  248                         err = ERANGE;
  249                         goto done;
  250                 }
  251         }
  252 
  253         mlx5e_tc_get_parameters(priv, new_bw_value, max_bw_value, max_bw_unit);
  254 
  255         err = -mlx5_modify_port_tc_rate_limit(mdev, max_bw_value, max_bw_unit);
  256         if (err)
  257                 goto done;
  258 
  259         memcpy(priv->params_ethtool.max_bw_value, new_bw_value,
  260             sizeof(priv->params_ethtool.max_bw_value));
  261 done:
  262         PRIV_UNLOCK(priv);
  263         return (err);
  264 }
  265 
  266 static int
  267 mlx5e_tc_rate_share_handler(SYSCTL_HANDLER_ARGS)
  268 {
  269         struct mlx5e_priv *priv = arg1;
  270         struct mlx5_core_dev *mdev = priv->mdev;
  271         u8 max_bw_share[IEEE_8021QAZ_MAX_TCS];
  272         u8 max_rates = mlx5_max_tc(mdev) + 1;
  273         int i;
  274         int err;
  275         int sum;
  276 
  277         PRIV_LOCK(priv);
  278         err = SYSCTL_OUT(req, priv->params_ethtool.max_bw_share, max_rates);
  279         if (err || !req->newptr)
  280                 goto done;
  281         err = SYSCTL_IN(req, max_bw_share, max_rates);
  282         if (err)
  283                 goto done;
  284 
  285         /* range check input value */
  286         for (sum = i = 0; i != max_rates; i++) {
  287                 if (max_bw_share[i] < 1 || max_bw_share[i] > 100) {
  288                         err = ERANGE;
  289                         goto done;
  290                 }
  291                 sum += max_bw_share[i];
  292         }
  293 
  294         /* sum of values should be as close to 100 as possible */
  295         if (sum < (100 - max_rates + 1) || sum > 100) {
  296                 err = ERANGE;
  297                 goto done;
  298         }
  299 
  300         err = -mlx5_set_port_tc_bw_alloc(mdev, max_bw_share);
  301         if (err)
  302                 goto done;
  303 
  304         memcpy(priv->params_ethtool.max_bw_share, max_bw_share,
  305             sizeof(priv->params_ethtool.max_bw_share));
  306 done:
  307         PRIV_UNLOCK(priv);
  308         return (err);
  309 }
  310 
  311 static int
  312 mlx5e_get_prio_tc(struct mlx5e_priv *priv)
  313 {
  314         struct mlx5_core_dev *mdev = priv->mdev;
  315         int err = 0;
  316         int i;
  317 
  318         PRIV_LOCK(priv);
  319         if (!MLX5_CAP_GEN(priv->mdev, ets)) {
  320                 PRIV_UNLOCK(priv);
  321                 return (EOPNOTSUPP);
  322         }
  323 
  324         for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
  325                 err = -mlx5_query_port_prio_tc(mdev, i, priv->params_ethtool.prio_tc + i);
  326                 if (err)
  327                         break;
  328         }
  329         PRIV_UNLOCK(priv);
  330         return (err);
  331 }
  332 
  333 static int
  334 mlx5e_prio_to_tc_handler(SYSCTL_HANDLER_ARGS)
  335 {
  336         struct mlx5e_priv *priv = arg1;
  337         struct mlx5_core_dev *mdev = priv->mdev;
  338         uint8_t temp[MLX5E_MAX_PRIORITY];
  339         int err;
  340         int i;
  341 
  342         PRIV_LOCK(priv);
  343         err = SYSCTL_OUT(req, priv->params_ethtool.prio_tc, MLX5E_MAX_PRIORITY);
  344         if (err || !req->newptr)
  345                 goto done;
  346         err = SYSCTL_IN(req, temp, MLX5E_MAX_PRIORITY);
  347         if (err)
  348                 goto done;
  349 
  350         for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
  351                 if (temp[i] > mlx5_max_tc(mdev)) {
  352                         err = ERANGE;
  353                         goto done;
  354                 }
  355         }
  356 
  357         for (i = 0; i != MLX5E_MAX_PRIORITY; i++) {
  358                 if (temp[i] == priv->params_ethtool.prio_tc[i])
  359                         continue;
  360                 err = -mlx5_set_port_prio_tc(mdev, i, temp[i]);
  361                 if (err)
  362                         goto done;
  363                 /* update cached value */
  364                 priv->params_ethtool.prio_tc[i] = temp[i];
  365         }
  366 done:
  367         PRIV_UNLOCK(priv);
  368         return (err);
  369 }
  370 
  371 int
  372 mlx5e_fec_update(struct mlx5e_priv *priv)
  373 {
  374         struct mlx5_core_dev *mdev = priv->mdev;
  375         u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
  376         const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
  377         int err;
  378 
  379         if (!MLX5_CAP_GEN(mdev, pcam_reg))
  380                 return (EOPNOTSUPP);
  381 
  382         if (!MLX5_CAP_PCAM_REG(mdev, pplm))
  383                 return (EOPNOTSUPP);
  384 
  385         MLX5_SET(pplm_reg, in, local_port, 1);
  386 
  387         err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
  388         if (err)
  389                 return (err);
  390 
  391         /* get 10x..25x mask */
  392         priv->params_ethtool.fec_mask_10x_25x[0] =
  393             MLX5_GET(pplm_reg, in, fec_override_admin_10g_40g);
  394         priv->params_ethtool.fec_mask_10x_25x[1] =
  395             MLX5_GET(pplm_reg, in, fec_override_admin_25g) &
  396             MLX5_GET(pplm_reg, in, fec_override_admin_50g);
  397         priv->params_ethtool.fec_mask_10x_25x[2] =
  398             MLX5_GET(pplm_reg, in, fec_override_admin_56g);
  399         priv->params_ethtool.fec_mask_10x_25x[3] =
  400             MLX5_GET(pplm_reg, in, fec_override_admin_100g);
  401 
  402         /* get 10x..25x available bits */
  403         priv->params_ethtool.fec_avail_10x_25x[0] =
  404             MLX5_GET(pplm_reg, in, fec_override_cap_10g_40g);
  405         priv->params_ethtool.fec_avail_10x_25x[1] =
  406             MLX5_GET(pplm_reg, in, fec_override_cap_25g) &
  407             MLX5_GET(pplm_reg, in, fec_override_cap_50g);
  408         priv->params_ethtool.fec_avail_10x_25x[2] =
  409             MLX5_GET(pplm_reg, in, fec_override_cap_56g);
  410         priv->params_ethtool.fec_avail_10x_25x[3] =
  411             MLX5_GET(pplm_reg, in, fec_override_cap_100g);
  412 
  413         /* get 50x mask */
  414         priv->params_ethtool.fec_mask_50x[0] =
  415             MLX5_GET(pplm_reg, in, fec_override_admin_50g_1x);
  416         priv->params_ethtool.fec_mask_50x[1] =
  417             MLX5_GET(pplm_reg, in, fec_override_admin_100g_2x);
  418         priv->params_ethtool.fec_mask_50x[2] =
  419             MLX5_GET(pplm_reg, in, fec_override_admin_200g_4x);
  420         priv->params_ethtool.fec_mask_50x[3] =
  421             MLX5_GET(pplm_reg, in, fec_override_admin_400g_8x);
  422 
  423         /* get 50x available bits */
  424         priv->params_ethtool.fec_avail_50x[0] =
  425             MLX5_GET(pplm_reg, in, fec_override_cap_50g_1x);
  426         priv->params_ethtool.fec_avail_50x[1] =
  427             MLX5_GET(pplm_reg, in, fec_override_cap_100g_2x);
  428         priv->params_ethtool.fec_avail_50x[2] =
  429             MLX5_GET(pplm_reg, in, fec_override_cap_200g_4x);
  430         priv->params_ethtool.fec_avail_50x[3] =
  431             MLX5_GET(pplm_reg, in, fec_override_cap_400g_8x);
  432 
  433         /* get current FEC mask */
  434         priv->params_ethtool.fec_mode_active =
  435             MLX5_GET(pplm_reg, in, fec_mode_active);
  436 
  437         return (0);
  438 }
  439 
  440 static int
  441 mlx5e_fec_mask_10x_25x_handler(SYSCTL_HANDLER_ARGS)
  442 {
  443         struct mlx5e_priv *priv = arg1;
  444         struct mlx5_core_dev *mdev = priv->mdev;
  445         u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
  446         u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
  447         const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
  448         u8 fec_mask_10x_25x[MLX5E_MAX_FEC_10X_25X];
  449         u8 fec_cap_changed = 0;
  450         u8 x;
  451         int err;
  452 
  453         PRIV_LOCK(priv);
  454         err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_10x_25x,
  455             sizeof(priv->params_ethtool.fec_mask_10x_25x));
  456         if (err || !req->newptr)
  457                 goto done;
  458 
  459         err = SYSCTL_IN(req, fec_mask_10x_25x,
  460             sizeof(fec_mask_10x_25x));
  461         if (err)
  462                 goto done;
  463 
  464         if (!MLX5_CAP_GEN(mdev, pcam_reg)) {
  465                 err = EOPNOTSUPP;
  466                 goto done;
  467         }
  468 
  469         if (!MLX5_CAP_PCAM_REG(mdev, pplm)) {
  470                 err = EOPNOTSUPP;
  471                 goto done;
  472         }
  473 
  474         MLX5_SET(pplm_reg, in, local_port, 1);
  475 
  476         err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
  477         if (err)
  478                 goto done;
  479 
  480         /* range check input value */
  481         for (x = 0; x != MLX5E_MAX_FEC_10X_25X; x++) {
  482                 /* check only one bit is set, if any */
  483                 if (fec_mask_10x_25x[x] & (fec_mask_10x_25x[x] - 1)) {
  484                         err = ERANGE;
  485                         goto done;
  486                 }
  487                 /* check a supported bit is set, if any */
  488                 if (fec_mask_10x_25x[x] &
  489                     ~priv->params_ethtool.fec_avail_10x_25x[x]) {
  490                         err = ERANGE;
  491                         goto done;
  492                 }
  493                 fec_cap_changed |= (fec_mask_10x_25x[x] ^
  494                     priv->params_ethtool.fec_mask_10x_25x[x]);
  495         }
  496 
  497         /* check for no changes */
  498         if (fec_cap_changed == 0)
  499                 goto done;
  500 
  501         memset(in, 0, sizeof(in));
  502 
  503         MLX5_SET(pplm_reg, in, local_port, 1);
  504 
  505         /* set new values */
  506         MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, fec_mask_10x_25x[0]);
  507         MLX5_SET(pplm_reg, in, fec_override_admin_25g, fec_mask_10x_25x[1]);
  508         MLX5_SET(pplm_reg, in, fec_override_admin_50g, fec_mask_10x_25x[1]);
  509         MLX5_SET(pplm_reg, in, fec_override_admin_56g, fec_mask_10x_25x[2]);
  510         MLX5_SET(pplm_reg, in, fec_override_admin_100g, fec_mask_10x_25x[3]);
  511 
  512         /* preserve other values */
  513         MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, priv->params_ethtool.fec_mask_50x[0]);
  514         MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, priv->params_ethtool.fec_mask_50x[1]);
  515         MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, priv->params_ethtool.fec_mask_50x[2]);
  516         MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, priv->params_ethtool.fec_mask_50x[3]);
  517 
  518         /* send new value to the firmware */
  519         err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
  520         if (err)
  521                 goto done;
  522 
  523         memcpy(priv->params_ethtool.fec_mask_10x_25x, fec_mask_10x_25x,
  524             sizeof(priv->params_ethtool.fec_mask_10x_25x));
  525 
  526         mlx5_toggle_port_link(priv->mdev);
  527 done:
  528         PRIV_UNLOCK(priv);
  529         return (err);
  530 }
  531 
  532 static int
  533 mlx5e_fec_avail_10x_25x_handler(SYSCTL_HANDLER_ARGS)
  534 {
  535         struct mlx5e_priv *priv = arg1;
  536         int err;
  537 
  538         PRIV_LOCK(priv);
  539         err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_10x_25x,
  540             sizeof(priv->params_ethtool.fec_avail_10x_25x));
  541         PRIV_UNLOCK(priv);
  542         return (err);
  543 }
  544 
  545 static int
  546 mlx5e_fec_mask_50x_handler(SYSCTL_HANDLER_ARGS)
  547 {
  548         struct mlx5e_priv *priv = arg1;
  549         struct mlx5_core_dev *mdev = priv->mdev;
  550         u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
  551         u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
  552         const int sz = MLX5_ST_SZ_BYTES(pplm_reg);
  553         u16 fec_mask_50x[MLX5E_MAX_FEC_50X];
  554         u16 fec_cap_changed = 0;
  555         u8 x;
  556         int err;
  557 
  558         PRIV_LOCK(priv);
  559         err = SYSCTL_OUT(req, priv->params_ethtool.fec_mask_50x,
  560             sizeof(priv->params_ethtool.fec_mask_50x));
  561         if (err || !req->newptr)
  562                 goto done;
  563 
  564         err = SYSCTL_IN(req, fec_mask_50x,
  565             sizeof(fec_mask_50x));
  566         if (err)
  567                 goto done;
  568 
  569         if (!MLX5_CAP_GEN(mdev, pcam_reg)) {
  570                 err = EOPNOTSUPP;
  571                 goto done;
  572         }
  573 
  574         if (!MLX5_CAP_PCAM_REG(mdev, pplm)) {
  575                 err = EOPNOTSUPP;
  576                 goto done;
  577         }
  578 
  579         MLX5_SET(pplm_reg, in, local_port, 1);
  580 
  581         err = -mlx5_core_access_reg(mdev, in, sz, in, sz, MLX5_REG_PPLM, 0, 0);
  582         if (err)
  583                 goto done;
  584 
  585         /* range check input value */
  586         for (x = 0; x != MLX5E_MAX_FEC_50X; x++) {
  587                 /* check only one bit is set, if any */
  588                 if (fec_mask_50x[x] & (fec_mask_50x[x] - 1)) {
  589                         err = ERANGE;
  590                         goto done;
  591                 }
  592                 /* check a supported bit is set, if any */
  593                 if (fec_mask_50x[x] &
  594                     ~priv->params_ethtool.fec_avail_50x[x]) {
  595                         err = ERANGE;
  596                         goto done;
  597                 }
  598                 fec_cap_changed |= (fec_mask_50x[x] ^
  599                     priv->params_ethtool.fec_mask_50x[x]);
  600         }
  601 
  602         /* check for no changes */
  603         if (fec_cap_changed == 0)
  604                 goto done;
  605 
  606         memset(in, 0, sizeof(in));
  607 
  608         MLX5_SET(pplm_reg, in, local_port, 1);
  609 
  610         /* set new values */
  611         MLX5_SET(pplm_reg, in, fec_override_admin_50g_1x, fec_mask_50x[0]);
  612         MLX5_SET(pplm_reg, in, fec_override_admin_100g_2x, fec_mask_50x[1]);
  613         MLX5_SET(pplm_reg, in, fec_override_admin_200g_4x, fec_mask_50x[2]);
  614         MLX5_SET(pplm_reg, in, fec_override_admin_400g_8x, fec_mask_50x[3]);
  615 
  616         /* preserve other values */
  617         MLX5_SET(pplm_reg, in, fec_override_admin_10g_40g, priv->params_ethtool.fec_mask_10x_25x[0]);
  618         MLX5_SET(pplm_reg, in, fec_override_admin_25g, priv->params_ethtool.fec_mask_10x_25x[1]);
  619         MLX5_SET(pplm_reg, in, fec_override_admin_50g, priv->params_ethtool.fec_mask_10x_25x[1]);
  620         MLX5_SET(pplm_reg, in, fec_override_admin_56g, priv->params_ethtool.fec_mask_10x_25x[2]);
  621         MLX5_SET(pplm_reg, in, fec_override_admin_100g, priv->params_ethtool.fec_mask_10x_25x[3]);
  622 
  623         /* send new value to the firmware */
  624         err = -mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
  625         if (err)
  626                 goto done;
  627 
  628         memcpy(priv->params_ethtool.fec_mask_50x, fec_mask_50x,
  629             sizeof(priv->params_ethtool.fec_mask_50x));
  630 
  631         mlx5_toggle_port_link(priv->mdev);
  632 done:
  633         PRIV_UNLOCK(priv);
  634         return (err);
  635 }
  636 
  637 static int
  638 mlx5e_fec_avail_50x_handler(SYSCTL_HANDLER_ARGS)
  639 {
  640         struct mlx5e_priv *priv = arg1;
  641         int err;
  642 
  643         PRIV_LOCK(priv);
  644         err = SYSCTL_OUT(req, priv->params_ethtool.fec_avail_50x,
  645             sizeof(priv->params_ethtool.fec_avail_50x));
  646         PRIV_UNLOCK(priv);
  647         return (err);
  648 }
  649 
  650 static int
  651 mlx5e_trust_state_handler(SYSCTL_HANDLER_ARGS)
  652 {
  653         struct mlx5e_priv *priv = arg1;
  654         struct mlx5_core_dev *mdev = priv->mdev;
  655         int err;
  656         u8 result;
  657 
  658         PRIV_LOCK(priv);
  659         result = priv->params_ethtool.trust_state;
  660         err = sysctl_handle_8(oidp, &result, 0, req);
  661         if (err || !req->newptr ||
  662             result == priv->params_ethtool.trust_state)
  663                 goto done;
  664 
  665         switch (result) {
  666         case MLX5_QPTS_TRUST_PCP:
  667         case MLX5_QPTS_TRUST_DSCP:
  668                 break;
  669         case MLX5_QPTS_TRUST_BOTH:
  670                 if (!MLX5_CAP_QCAM_FEATURE(mdev, qpts_trust_both)) {
  671                         err = EOPNOTSUPP;
  672                         goto done;
  673                 }
  674                 break;
  675         default:
  676                 err = ERANGE;
  677                 goto done;
  678         }
  679 
  680         err = -mlx5_set_trust_state(mdev, result);
  681         if (err)
  682                 goto done;
  683 
  684         priv->params_ethtool.trust_state = result;
  685 
  686         /* update inline mode */
  687         mlx5e_refresh_sq_inline(priv);
  688 #ifdef RATELIMIT
  689         mlx5e_rl_refresh_sq_inline(&priv->rl);
  690 #endif
  691 done:
  692         PRIV_UNLOCK(priv);
  693         return (err);
  694 }
  695 
  696 static int
  697 mlx5e_dscp_prio_handler(SYSCTL_HANDLER_ARGS)
  698 {
  699         struct mlx5e_priv *priv = arg1;
  700         int prio_index = arg2;
  701         struct mlx5_core_dev *mdev = priv->mdev;
  702         uint8_t dscp2prio[MLX5_MAX_SUPPORTED_DSCP];
  703         uint8_t x;
  704         int err;
  705 
  706         PRIV_LOCK(priv);
  707         err = SYSCTL_OUT(req, priv->params_ethtool.dscp2prio + prio_index,
  708             sizeof(priv->params_ethtool.dscp2prio) / 8);
  709         if (err || !req->newptr)
  710                 goto done;
  711 
  712         memcpy(dscp2prio, priv->params_ethtool.dscp2prio, sizeof(dscp2prio));
  713         err = SYSCTL_IN(req, dscp2prio + prio_index, sizeof(dscp2prio) / 8);
  714         if (err)
  715                 goto done;
  716         for (x = 0; x != MLX5_MAX_SUPPORTED_DSCP; x++) {
  717                 if (dscp2prio[x] > 7) {
  718                         err = ERANGE;
  719                         goto done;
  720                 }
  721         }
  722         err = -mlx5_set_dscp2prio(mdev, dscp2prio);
  723         if (err)
  724                 goto done;
  725 
  726         /* update local array */
  727         memcpy(priv->params_ethtool.dscp2prio, dscp2prio,
  728             sizeof(priv->params_ethtool.dscp2prio));
  729 done:
  730         PRIV_UNLOCK(priv);
  731         return (err);
  732 }
  733 
  734 int
  735 mlx5e_update_buf_lossy(struct mlx5e_priv *priv)
  736 {
  737         struct ieee_pfc pfc;
  738 
  739         PRIV_ASSERT_LOCKED(priv);
  740         bzero(&pfc, sizeof(pfc));
  741         pfc.pfc_en = priv->params.rx_priority_flow_control;
  742         return (-mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_PFC,
  743             priv->params_ethtool.hw_mtu, &pfc, NULL, NULL));
  744 }
  745 
  746 static int
  747 mlx5e_buf_size_handler(SYSCTL_HANDLER_ARGS)
  748 {
  749         struct mlx5e_priv *priv;
  750         u32 buf_size[MLX5E_MAX_BUFFER];
  751         struct mlx5e_port_buffer port_buffer;
  752         int error, i;
  753 
  754         priv = arg1;
  755         PRIV_LOCK(priv);
  756         error = -mlx5e_port_query_buffer(priv, &port_buffer);
  757         if (error != 0)
  758                 goto done;
  759         for (i = 0; i < nitems(buf_size); i++)
  760                 buf_size[i] = port_buffer.buffer[i].size;
  761         error = SYSCTL_OUT(req, buf_size, sizeof(buf_size));
  762         if (error != 0 || req->newptr == NULL)
  763                 goto done;
  764         error = SYSCTL_IN(req, buf_size, sizeof(buf_size));
  765         if (error != 0)
  766                 goto done;
  767         error = -mlx5e_port_manual_buffer_config(priv, MLX5E_PORT_BUFFER_SIZE,
  768             priv->params_ethtool.hw_mtu, NULL, buf_size, NULL);
  769 done:
  770         PRIV_UNLOCK(priv);
  771         return (error);
  772 }
  773 
  774 static int
  775 mlx5e_buf_prio_handler(SYSCTL_HANDLER_ARGS)
  776 {
  777         struct mlx5e_priv *priv;
  778         struct mlx5_core_dev *mdev;
  779         u8 buffer[MLX5E_MAX_BUFFER];
  780         int error;
  781 
  782         priv = arg1;
  783         mdev = priv->mdev;
  784         PRIV_LOCK(priv);
  785         error = -mlx5e_port_query_priority2buffer(mdev, buffer);
  786         if (error != 0)
  787                 goto done;
  788         error = SYSCTL_OUT(req, buffer, MLX5E_MAX_BUFFER);
  789         if (error != 0 || req->newptr == NULL)
  790                 goto done;
  791         error = SYSCTL_IN(req, buffer, MLX5E_MAX_BUFFER);
  792         if (error != 0)
  793                 goto done;
  794         error = -mlx5e_port_manual_buffer_config(priv,
  795             MLX5E_PORT_BUFFER_PRIO2BUFFER,
  796             priv->params_ethtool.hw_mtu, NULL, NULL, buffer);
  797         if (error == 0)
  798                 error = mlx5e_update_buf_lossy(priv);
  799 done:
  800         PRIV_UNLOCK(priv);
  801         return (error);
  802 }
  803 
  804 static int
  805 mlx5e_cable_length_handler(SYSCTL_HANDLER_ARGS)
  806 {
  807         struct mlx5e_priv *priv;
  808         u_int cable_len;
  809         int error;
  810 
  811         priv = arg1;
  812         PRIV_LOCK(priv);
  813         cable_len = priv->dcbx.cable_len;
  814         error = sysctl_handle_int(oidp, &cable_len, 0, req);
  815         if (error == 0 && req->newptr != NULL &&
  816             cable_len != priv->dcbx.cable_len) {
  817                 error = -mlx5e_port_manual_buffer_config(priv,
  818                     MLX5E_PORT_BUFFER_CABLE_LEN, priv->params_ethtool.hw_mtu,
  819                     NULL, NULL, NULL);
  820                 if (error == 0)
  821                         priv->dcbx.cable_len = cable_len;
  822         }
  823         PRIV_UNLOCK(priv);
  824         return (error);
  825 }
  826 
  827 static int
  828 mlx5e_hw_temperature_handler(SYSCTL_HANDLER_ARGS)
  829 {
  830         struct mlx5e_priv *priv = arg1;
  831         int err;
  832 
  833         PRIV_LOCK(priv);
  834         err = SYSCTL_OUT(req, priv->params_ethtool.hw_val_temp,
  835             sizeof(priv->params_ethtool.hw_val_temp[0]) *
  836             priv->params_ethtool.hw_num_temp);
  837         if (err == 0 && req->newptr != NULL)
  838                 err = EOPNOTSUPP;
  839         PRIV_UNLOCK(priv);
  840         return (err);
  841 }
  842 
  843 int
  844 mlx5e_hw_temperature_update(struct mlx5e_priv *priv)
  845 {
  846         int err;
  847         u32 x;
  848 
  849         if (priv->params_ethtool.hw_num_temp == 0) {
  850                 u32 out_cap[MLX5_ST_SZ_DW(mtcap)] = {};
  851                 const int sz_cap = MLX5_ST_SZ_BYTES(mtcap);
  852                 u32 value;
  853 
  854                 err = -mlx5_core_access_reg(priv->mdev, NULL, 0, out_cap, sz_cap,
  855                     MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTCAP, 0, 0);
  856                 if (err)
  857                         goto done;
  858                 value = MLX5_GET(mtcap, out_cap, sensor_count);
  859                 if (value == 0)
  860                         return (0);
  861                 if (value > MLX5_MAX_TEMPERATURE)
  862                         value = MLX5_MAX_TEMPERATURE;
  863                 /* update number of temperature sensors */
  864                 priv->params_ethtool.hw_num_temp = value;
  865         }
  866 
  867         for (x = 0; x != priv->params_ethtool.hw_num_temp; x++) {
  868                 u32 out_sensor[MLX5_ST_SZ_DW(mtmp_reg)] = {};
  869                 const int sz_sensor = MLX5_ST_SZ_BYTES(mtmp_reg);
  870 
  871                 MLX5_SET(mtmp_reg, out_sensor, sensor_index, x);
  872 
  873                 err = -mlx5_core_access_reg(priv->mdev, out_sensor, sz_sensor,
  874                     out_sensor, sz_sensor,
  875                     MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MTMP, 0, 0);
  876                 if (err)
  877                         goto done;
  878                 /* convert from 0.125 celsius to millicelsius */
  879                 priv->params_ethtool.hw_val_temp[x] =
  880                     (s16)MLX5_GET(mtmp_reg, out_sensor, temperature) * 125;
  881         }
  882 done:
  883         return (err);
  884 }
  885 
  886 #define MLX5_PARAM_OFFSET(n)                            \
  887     __offsetof(struct mlx5e_priv, params_ethtool.n)
  888 
  889 static int
  890 mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
  891 {
  892         struct mlx5e_priv *priv = arg1;
  893         uint64_t value;
  894         int mode_modify;
  895         int was_opened;
  896         int error;
  897 
  898         PRIV_LOCK(priv);
  899         value = priv->params_ethtool.arg[arg2];
  900         if (req != NULL) {
  901                 error = sysctl_handle_64(oidp, &value, 0, req);
  902                 if (error || req->newptr == NULL ||
  903                     value == priv->params_ethtool.arg[arg2])
  904                         goto done;
  905 
  906                 /* assign new value */
  907                 priv->params_ethtool.arg[arg2] = value;
  908         } else {
  909                 error = 0;
  910         }
  911         /* check if device is gone */
  912         if (priv->gone) {
  913                 error = ENXIO;
  914                 goto done;
  915         }
  916         was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
  917         mode_modify = MLX5_CAP_GEN(priv->mdev, cq_period_mode_modify);
  918 
  919         switch (MLX5_PARAM_OFFSET(arg[arg2])) {
  920         case MLX5_PARAM_OFFSET(rx_coalesce_usecs):
  921                 /* import RX coal time */
  922                 if (priv->params_ethtool.rx_coalesce_usecs < 1)
  923                         priv->params_ethtool.rx_coalesce_usecs = 0;
  924                 else if (priv->params_ethtool.rx_coalesce_usecs >
  925                     MLX5E_FLD_MAX(cqc, cq_period)) {
  926                         priv->params_ethtool.rx_coalesce_usecs =
  927                             MLX5E_FLD_MAX(cqc, cq_period);
  928                 }
  929                 priv->params.rx_cq_moderation_usec =
  930                     priv->params_ethtool.rx_coalesce_usecs;
  931 
  932                 /* check to avoid down and up the network interface */
  933                 if (was_opened)
  934                         error = mlx5e_refresh_channel_params(priv);
  935                 break;
  936 
  937         case MLX5_PARAM_OFFSET(rx_coalesce_pkts):
  938                 /* import RX coal pkts */
  939                 if (priv->params_ethtool.rx_coalesce_pkts < 1)
  940                         priv->params_ethtool.rx_coalesce_pkts = 0;
  941                 else if (priv->params_ethtool.rx_coalesce_pkts >
  942                     MLX5E_FLD_MAX(cqc, cq_max_count)) {
  943                         priv->params_ethtool.rx_coalesce_pkts =
  944                             MLX5E_FLD_MAX(cqc, cq_max_count);
  945                 }
  946                 priv->params.rx_cq_moderation_pkts =
  947                     priv->params_ethtool.rx_coalesce_pkts;
  948 
  949                 /* check to avoid down and up the network interface */
  950                 if (was_opened)
  951                         error = mlx5e_refresh_channel_params(priv);
  952                 break;
  953 
  954         case MLX5_PARAM_OFFSET(tx_coalesce_usecs):
  955                 /* import TX coal time */
  956                 if (priv->params_ethtool.tx_coalesce_usecs < 1)
  957                         priv->params_ethtool.tx_coalesce_usecs = 0;
  958                 else if (priv->params_ethtool.tx_coalesce_usecs >
  959                     MLX5E_FLD_MAX(cqc, cq_period)) {
  960                         priv->params_ethtool.tx_coalesce_usecs =
  961                             MLX5E_FLD_MAX(cqc, cq_period);
  962                 }
  963                 priv->params.tx_cq_moderation_usec =
  964                     priv->params_ethtool.tx_coalesce_usecs;
  965 
  966                 /* check to avoid down and up the network interface */
  967                 if (was_opened)
  968                         error = mlx5e_refresh_channel_params(priv);
  969                 break;
  970 
  971         case MLX5_PARAM_OFFSET(tx_coalesce_pkts):
  972                 /* import TX coal pkts */
  973                 if (priv->params_ethtool.tx_coalesce_pkts < 1)
  974                         priv->params_ethtool.tx_coalesce_pkts = 0;
  975                 else if (priv->params_ethtool.tx_coalesce_pkts >
  976                     MLX5E_FLD_MAX(cqc, cq_max_count)) {
  977                         priv->params_ethtool.tx_coalesce_pkts =
  978                             MLX5E_FLD_MAX(cqc, cq_max_count);
  979                 }
  980                 priv->params.tx_cq_moderation_pkts =
  981                     priv->params_ethtool.tx_coalesce_pkts;
  982 
  983                 /* check to avoid down and up the network interface */
  984                 if (was_opened)
  985                         error = mlx5e_refresh_channel_params(priv);
  986                 break;
  987 
  988         case MLX5_PARAM_OFFSET(tx_queue_size):
  989                 /* network interface must be down */
  990                 if (was_opened)
  991                         mlx5e_close_locked(priv->ifp);
  992 
  993                 /* import TX queue size */
  994                 if (priv->params_ethtool.tx_queue_size <
  995                     (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
  996                         priv->params_ethtool.tx_queue_size =
  997                             (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
  998                 } else if (priv->params_ethtool.tx_queue_size >
  999                     priv->params_ethtool.tx_queue_size_max) {
 1000                         priv->params_ethtool.tx_queue_size =
 1001                             priv->params_ethtool.tx_queue_size_max;
 1002                 }
 1003                 /* store actual TX queue size */
 1004                 priv->params.log_sq_size =
 1005                     order_base_2(priv->params_ethtool.tx_queue_size);
 1006                 priv->params_ethtool.tx_queue_size =
 1007                     1 << priv->params.log_sq_size;
 1008 
 1009                 /* verify TX completion factor */
 1010                 mlx5e_ethtool_sync_tx_completion_fact(priv);
 1011 
 1012                 /* restart network interface, if any */
 1013                 if (was_opened)
 1014                         mlx5e_open_locked(priv->ifp);
 1015                 break;
 1016 
 1017         case MLX5_PARAM_OFFSET(rx_queue_size):
 1018                 /* network interface must be down */
 1019                 if (was_opened)
 1020                         mlx5e_close_locked(priv->ifp);
 1021 
 1022                 /* import RX queue size */
 1023                 if (priv->params_ethtool.rx_queue_size <
 1024                     (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
 1025                         priv->params_ethtool.rx_queue_size =
 1026                             (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
 1027                 } else if (priv->params_ethtool.rx_queue_size >
 1028                     priv->params_ethtool.rx_queue_size_max) {
 1029                         priv->params_ethtool.rx_queue_size =
 1030                             priv->params_ethtool.rx_queue_size_max;
 1031                 }
 1032                 /* store actual RX queue size */
 1033                 priv->params.log_rq_size =
 1034                     order_base_2(priv->params_ethtool.rx_queue_size);
 1035                 priv->params_ethtool.rx_queue_size =
 1036                     1 << priv->params.log_rq_size;
 1037 
 1038                 /* update least number of RX WQEs */
 1039                 priv->params.min_rx_wqes = min(
 1040                     priv->params_ethtool.rx_queue_size - 1,
 1041                     MLX5E_PARAMS_DEFAULT_MIN_RX_WQES);
 1042 
 1043                 /* restart network interface, if any */
 1044                 if (was_opened)
 1045                         mlx5e_open_locked(priv->ifp);
 1046                 break;
 1047 
 1048         case MLX5_PARAM_OFFSET(channels_rsss):
 1049                 /* network interface must be down */
 1050                 if (was_opened)
 1051                         mlx5e_close_locked(priv->ifp);
 1052 
 1053                 /* import number of channels */
 1054                 if (priv->params_ethtool.channels_rsss < 1)
 1055                         priv->params_ethtool.channels_rsss = 1;
 1056                 else if (priv->params_ethtool.channels_rsss > 128)
 1057                         priv->params_ethtool.channels_rsss = 128;
 1058 
 1059                 priv->params.channels_rsss = priv->params_ethtool.channels_rsss;
 1060 
 1061                 /* restart network interface, if any */
 1062                 if (was_opened)
 1063                         mlx5e_open_locked(priv->ifp);
 1064                 break;
 1065 
 1066         case MLX5_PARAM_OFFSET(channels):
 1067                 /* network interface must be down */
 1068                 if (was_opened)
 1069                         mlx5e_close_locked(priv->ifp);
 1070 
 1071                 /* import number of channels */
 1072                 if (priv->params_ethtool.channels < 1)
 1073                         priv->params_ethtool.channels = 1;
 1074                 else if (priv->params_ethtool.channels >
 1075                     (u64) priv->mdev->priv.eq_table.num_comp_vectors) {
 1076                         priv->params_ethtool.channels =
 1077                             (u64) priv->mdev->priv.eq_table.num_comp_vectors;
 1078                 }
 1079                 priv->params.num_channels = priv->params_ethtool.channels;
 1080 
 1081                 /* restart network interface, if any */
 1082                 if (was_opened)
 1083                         mlx5e_open_locked(priv->ifp);
 1084                 break;
 1085 
 1086         case MLX5_PARAM_OFFSET(rx_coalesce_mode):
 1087                 /* network interface must be down */
 1088                 if (was_opened != 0 && mode_modify == 0)
 1089                         mlx5e_close_locked(priv->ifp);
 1090 
 1091                 /* import RX coalesce mode */
 1092                 if (priv->params_ethtool.rx_coalesce_mode > 3)
 1093                         priv->params_ethtool.rx_coalesce_mode = 3;
 1094                 priv->params.rx_cq_moderation_mode =
 1095                     priv->params_ethtool.rx_coalesce_mode;
 1096 
 1097                 /* restart network interface, if any */
 1098                 if (was_opened != 0) {
 1099                         if (mode_modify == 0)
 1100                                 mlx5e_open_locked(priv->ifp);
 1101                         else
 1102                                 error = mlx5e_refresh_channel_params(priv);
 1103                 }
 1104                 break;
 1105 
 1106         case MLX5_PARAM_OFFSET(tx_coalesce_mode):
 1107                 /* network interface must be down */
 1108                 if (was_opened != 0 && mode_modify == 0)
 1109                         mlx5e_close_locked(priv->ifp);
 1110 
 1111                 /* import TX coalesce mode */
 1112                 if (priv->params_ethtool.tx_coalesce_mode != 0)
 1113                         priv->params_ethtool.tx_coalesce_mode = 1;
 1114                 priv->params.tx_cq_moderation_mode =
 1115                     priv->params_ethtool.tx_coalesce_mode;
 1116 
 1117                 /* restart network interface, if any */
 1118                 if (was_opened != 0) {
 1119                         if (mode_modify == 0)
 1120                                 mlx5e_open_locked(priv->ifp);
 1121                         else
 1122                                 error = mlx5e_refresh_channel_params(priv);
 1123                 }
 1124                 break;
 1125 
 1126         case MLX5_PARAM_OFFSET(hw_lro):
 1127                 /* network interface must be down */
 1128                 if (was_opened)
 1129                         mlx5e_close_locked(priv->ifp);
 1130 
 1131                 /* import HW LRO mode */
 1132                 if (priv->params_ethtool.hw_lro != 0 &&
 1133                     MLX5_CAP_ETH(priv->mdev, lro_cap)) {
 1134                         priv->params_ethtool.hw_lro = 1;
 1135                         /* check if feature should actually be enabled */
 1136                         if (priv->ifp->if_capenable & IFCAP_LRO) {
 1137                                 priv->params.hw_lro_en = true;
 1138                         } else {
 1139                                 priv->params.hw_lro_en = false;
 1140 
 1141                                 mlx5_en_warn(priv->ifp, "To enable HW LRO "
 1142                                     "please also enable LRO via ifconfig(8).\n");
 1143                         }
 1144                 } else {
 1145                         /* return an error if HW does not support this feature */
 1146                         if (priv->params_ethtool.hw_lro != 0)
 1147                                 error = EINVAL;
 1148                         priv->params.hw_lro_en = false;
 1149                         priv->params_ethtool.hw_lro = 0;
 1150                 }
 1151                 /* restart network interface, if any */
 1152                 if (was_opened)
 1153                         mlx5e_open_locked(priv->ifp);
 1154                 break;
 1155 
 1156         case MLX5_PARAM_OFFSET(cqe_zipping):
 1157                 /* network interface must be down */
 1158                 if (was_opened)
 1159                         mlx5e_close_locked(priv->ifp);
 1160 
 1161                 /* import CQE zipping mode */
 1162                 if (priv->params_ethtool.cqe_zipping &&
 1163                     MLX5_CAP_GEN(priv->mdev, cqe_compression)) {
 1164                         priv->params.cqe_zipping_en = true;
 1165                         priv->params_ethtool.cqe_zipping = 1;
 1166                 } else {
 1167                         priv->params.cqe_zipping_en = false;
 1168                         priv->params_ethtool.cqe_zipping = 0;
 1169                 }
 1170                 /* restart network interface, if any */
 1171                 if (was_opened)
 1172                         mlx5e_open_locked(priv->ifp);
 1173                 break;
 1174 
 1175         case MLX5_PARAM_OFFSET(tx_completion_fact):
 1176                 /* network interface must be down */
 1177                 if (was_opened)
 1178                         mlx5e_close_locked(priv->ifp);
 1179 
 1180                 /* verify parameter */
 1181                 mlx5e_ethtool_sync_tx_completion_fact(priv);
 1182 
 1183                 /* restart network interface, if any */
 1184                 if (was_opened)
 1185                         mlx5e_open_locked(priv->ifp);
 1186                 break;
 1187 
 1188         case MLX5_PARAM_OFFSET(modify_tx_dma):
 1189                 /* check if network interface is opened */
 1190                 if (was_opened) {
 1191                         priv->params_ethtool.modify_tx_dma =
 1192                             priv->params_ethtool.modify_tx_dma ? 1 : 0;
 1193                         /* modify tx according to value */
 1194                         mlx5e_modify_tx_dma(priv, value != 0);
 1195                 } else {
 1196                         /* if closed force enable tx */
 1197                         priv->params_ethtool.modify_tx_dma = 0;
 1198                 }
 1199                 break;
 1200 
 1201         case MLX5_PARAM_OFFSET(modify_rx_dma):
 1202                 /* check if network interface is opened */
 1203                 if (was_opened) {
 1204                         priv->params_ethtool.modify_rx_dma =
 1205                             priv->params_ethtool.modify_rx_dma ? 1 : 0;
 1206                         /* modify rx according to value */
 1207                         mlx5e_modify_rx_dma(priv, value != 0);
 1208                 } else {
 1209                         /* if closed force enable rx */
 1210                         priv->params_ethtool.modify_rx_dma = 0;
 1211                 }
 1212                 break;
 1213 
 1214         case MLX5_PARAM_OFFSET(diag_pci_enable):
 1215                 priv->params_ethtool.diag_pci_enable =
 1216                     priv->params_ethtool.diag_pci_enable ? 1 : 0;
 1217 
 1218                 error = -mlx5_core_set_diagnostics_full(priv->mdev,
 1219                     priv->params_ethtool.diag_pci_enable,
 1220                     priv->params_ethtool.diag_general_enable);
 1221                 break;
 1222 
 1223         case MLX5_PARAM_OFFSET(diag_general_enable):
 1224                 priv->params_ethtool.diag_general_enable =
 1225                     priv->params_ethtool.diag_general_enable ? 1 : 0;
 1226 
 1227                 error = -mlx5_core_set_diagnostics_full(priv->mdev,
 1228                     priv->params_ethtool.diag_pci_enable,
 1229                     priv->params_ethtool.diag_general_enable);
 1230                 break;
 1231 
 1232         case MLX5_PARAM_OFFSET(mc_local_lb):
 1233                 /* check if mlx5ib is managing this feature */
 1234                 if (MLX5_CAP_GEN(priv->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) {
 1235                         error = EOPNOTSUPP;
 1236                         break;
 1237                 }
 1238 
 1239                 priv->params_ethtool.mc_local_lb =
 1240                     priv->params_ethtool.mc_local_lb ? 1 : 0;
 1241 
 1242                 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_mc)) {
 1243                         error = mlx5_nic_vport_modify_local_lb(priv->mdev,
 1244                             MLX5_LOCAL_MC_LB, priv->params_ethtool.mc_local_lb);
 1245                 } else {
 1246                         error = EOPNOTSUPP;
 1247                 }
 1248                 break;
 1249 
 1250         case MLX5_PARAM_OFFSET(uc_local_lb):
 1251                 /* check if mlx5ib is managing this feature */
 1252                 if (MLX5_CAP_GEN(priv->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) {
 1253                         error = EOPNOTSUPP;
 1254                         break;
 1255                 }
 1256 
 1257                 priv->params_ethtool.uc_local_lb =
 1258                     priv->params_ethtool.uc_local_lb ? 1 : 0;
 1259 
 1260                 if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_uc)) {
 1261                         error = mlx5_nic_vport_modify_local_lb(priv->mdev,
 1262                             MLX5_LOCAL_UC_LB, priv->params_ethtool.uc_local_lb);
 1263                 } else {
 1264                         error = EOPNOTSUPP;
 1265                 }
 1266                 break;
 1267 
 1268         case MLX5_PARAM_OFFSET(irq_cpu_base):
 1269         case MLX5_PARAM_OFFSET(irq_cpu_stride):
 1270                 if (was_opened) {
 1271                         /* network interface must toggled */
 1272                         mlx5e_close_locked(priv->ifp);
 1273                         mlx5e_open_locked(priv->ifp);
 1274                 }
 1275                 break;
 1276 
 1277         default:
 1278                 break;
 1279         }
 1280 done:
 1281         PRIV_UNLOCK(priv);
 1282         return (error);
 1283 }
 1284 
 1285 static const char *mlx5e_params_desc[] = {
 1286         MLX5E_PARAMS(MLX5E_STATS_DESC)
 1287 };
 1288 
 1289 static const char *mlx5e_port_stats_debug_desc[] = {
 1290         MLX5E_PORT_STATS_DEBUG(MLX5E_STATS_DESC)
 1291 };
 1292 
 1293 static int
 1294 mlx5e_ethtool_debug_channel_info(SYSCTL_HANDLER_ARGS)
 1295 {
 1296         struct mlx5e_priv *priv;
 1297         struct sbuf sb;
 1298         struct mlx5e_channel *c;
 1299         struct mlx5e_sq *sq;
 1300         struct mlx5e_rq *rq;
 1301         int error, i, tc;
 1302         bool opened;
 1303 
 1304         priv = arg1;
 1305         error = sysctl_wire_old_buffer(req, 0);
 1306         if (error != 0)
 1307                 return (error);
 1308         if (sbuf_new_for_sysctl(&sb, NULL, 1024, req) == NULL)
 1309                 return (ENOMEM);
 1310         sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
 1311 
 1312         PRIV_LOCK(priv);
 1313         opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
 1314 
 1315         sbuf_printf(&sb, "pages irq %d\n",
 1316             priv->mdev->priv.msix_arr[MLX5_EQ_VEC_PAGES].vector);
 1317         sbuf_printf(&sb, "command irq %d\n",
 1318             priv->mdev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector);
 1319         sbuf_printf(&sb, "async irq %d\n",
 1320             priv->mdev->priv.msix_arr[MLX5_EQ_VEC_ASYNC].vector);
 1321 
 1322         for (i = 0; i != priv->params.num_channels; i++) {
 1323                 int eqn_not_used = -1;
 1324                 int irqn = MLX5_EQ_VEC_COMP_BASE;
 1325 
 1326                 if (mlx5_vector2eqn(priv->mdev, i, &eqn_not_used, &irqn) != 0)
 1327                         continue;
 1328 
 1329                 c = opened ? &priv->channel[i] : NULL;
 1330                 rq = opened ? &c->rq : NULL;
 1331                 sbuf_printf(&sb, "channel %d rq %d cq %d irq %d\n", i,
 1332                     opened ? rq->rqn : -1,
 1333                     opened ? rq->cq.mcq.cqn : -1,
 1334                     priv->mdev->priv.msix_arr[irqn].vector);
 1335 
 1336                 for (tc = 0; tc != priv->num_tc; tc++) {
 1337                         sq = opened ? &c->sq[tc] : NULL;
 1338                         sbuf_printf(&sb, "channel %d tc %d sq %d cq %d irq %d\n",
 1339                             i, tc,
 1340                             opened ? sq->sqn : -1,
 1341                             opened ? sq->cq.mcq.cqn : -1,
 1342                             priv->mdev->priv.msix_arr[irqn].vector);
 1343                 }
 1344         }
 1345         PRIV_UNLOCK(priv);
 1346         error = sbuf_finish(&sb);
 1347         sbuf_delete(&sb);
 1348         return (error);
 1349 }
 1350 
 1351 static int
 1352 mlx5e_ethtool_debug_stats(SYSCTL_HANDLER_ARGS)
 1353 {
 1354         struct mlx5e_priv *priv = arg1;
 1355         int sys_debug;
 1356         int error;
 1357 
 1358         PRIV_LOCK(priv);
 1359         if (priv->gone != 0) {
 1360                 error = ENODEV;
 1361                 goto done;
 1362         }
 1363         sys_debug = priv->sysctl_debug;
 1364         error = sysctl_handle_int(oidp, &sys_debug, 0, req);
 1365         if (error != 0 || !req->newptr)
 1366                 goto done;
 1367         sys_debug = sys_debug ? 1 : 0;
 1368         if (sys_debug == priv->sysctl_debug)
 1369                 goto done;
 1370 
 1371         if ((priv->sysctl_debug = sys_debug)) {
 1372                 mlx5e_create_stats(&priv->stats.port_stats_debug.ctx,
 1373                     SYSCTL_CHILDREN(priv->sysctl_ifnet), "debug_stats",
 1374                     mlx5e_port_stats_debug_desc, MLX5E_PORT_STATS_DEBUG_NUM,
 1375                     priv->stats.port_stats_debug.arg);
 1376                 SYSCTL_ADD_PROC(&priv->stats.port_stats_debug.ctx,
 1377                     SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
 1378                     "hw_ctx_debug",
 1379                     CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_STRING, priv, 0,
 1380                     mlx5e_ethtool_debug_channel_info, "S", "");
 1381         } else {
 1382                 sysctl_ctx_free(&priv->stats.port_stats_debug.ctx);
 1383         }
 1384 done:
 1385         PRIV_UNLOCK(priv);
 1386         return (error);
 1387 }
 1388 
 1389 static void
 1390 mlx5e_create_diagnostics(struct mlx5e_priv *priv)
 1391 {
 1392         struct mlx5_core_diagnostics_entry entry;
 1393         struct sysctl_ctx_list *ctx;
 1394         struct sysctl_oid *node;
 1395         int x;
 1396 
 1397         /* sysctl context we are using */
 1398         ctx = &priv->sysctl_ctx;
 1399 
 1400         /* create root node */
 1401         node = SYSCTL_ADD_NODE(ctx,
 1402             SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
 1403             "diagnostics", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Diagnostics");
 1404         if (node == NULL)
 1405                 return;
 1406 
 1407         /* create PCI diagnostics */
 1408         for (x = 0; x != MLX5_CORE_PCI_DIAGNOSTICS_NUM; x++) {
 1409                 entry = mlx5_core_pci_diagnostics_table[x];
 1410                 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
 1411                         continue;
 1412                 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
 1413                     entry.desc, CTLFLAG_RD, priv->params_pci.array + x,
 1414                     "PCI diagnostics counter");
 1415         }
 1416 
 1417         /* create general diagnostics */
 1418         for (x = 0; x != MLX5_CORE_GENERAL_DIAGNOSTICS_NUM; x++) {
 1419                 entry = mlx5_core_general_diagnostics_table[x];
 1420                 if (mlx5_core_supports_diagnostics(priv->mdev, entry.counter_id) == 0)
 1421                         continue;
 1422                 SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
 1423                     entry.desc, CTLFLAG_RD, priv->params_general.array + x,
 1424                     "General diagnostics counter");
 1425         }
 1426 }
 1427 
 1428 void
 1429 mlx5e_create_ethtool(struct mlx5e_priv *priv)
 1430 {
 1431         struct sysctl_oid *fec_node;
 1432         struct sysctl_oid *qos_node;
 1433         struct sysctl_oid *node;
 1434         const char *pnameunit;
 1435         struct mlx5e_port_buffer port_buffer;
 1436         unsigned x;
 1437         int i;
 1438 
 1439         /* set some defaults */
 1440         priv->params_ethtool.irq_cpu_base = -1; /* disabled */
 1441         priv->params_ethtool.irq_cpu_stride = 1;
 1442         priv->params_ethtool.tx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
 1443         priv->params_ethtool.rx_queue_size_max = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
 1444         priv->params_ethtool.tx_queue_size = 1 << priv->params.log_sq_size;
 1445         priv->params_ethtool.rx_queue_size = 1 << priv->params.log_rq_size;
 1446         priv->params_ethtool.channels = priv->params.num_channels;
 1447         priv->params_ethtool.channels_rsss = priv->params.channels_rsss;
 1448         priv->params_ethtool.coalesce_pkts_max = MLX5E_FLD_MAX(cqc, cq_max_count);
 1449         priv->params_ethtool.coalesce_usecs_max = MLX5E_FLD_MAX(cqc, cq_period);
 1450         priv->params_ethtool.rx_coalesce_mode = priv->params.rx_cq_moderation_mode;
 1451         priv->params_ethtool.rx_coalesce_usecs = priv->params.rx_cq_moderation_usec;
 1452         priv->params_ethtool.rx_coalesce_pkts = priv->params.rx_cq_moderation_pkts;
 1453         priv->params_ethtool.tx_coalesce_mode = priv->params.tx_cq_moderation_mode;
 1454         priv->params_ethtool.tx_coalesce_usecs = priv->params.tx_cq_moderation_usec;
 1455         priv->params_ethtool.tx_coalesce_pkts = priv->params.tx_cq_moderation_pkts;
 1456         priv->params_ethtool.hw_lro = priv->params.hw_lro_en;
 1457         priv->params_ethtool.cqe_zipping = priv->params.cqe_zipping_en;
 1458         mlx5e_ethtool_sync_tx_completion_fact(priv);
 1459 
 1460         /* get default values for local loopback, if any */
 1461         if (MLX5_CAP_GEN(priv->mdev, disable_local_lb_mc) ||
 1462             MLX5_CAP_GEN(priv->mdev, disable_local_lb_uc)) {
 1463                 int err;
 1464                 u8 val;
 1465 
 1466                 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_MC_LB, &val);
 1467                 if (err == 0)
 1468                         priv->params_ethtool.mc_local_lb = val;
 1469 
 1470                 err = mlx5_nic_vport_query_local_lb(priv->mdev, MLX5_LOCAL_UC_LB, &val);
 1471                 if (err == 0)
 1472                         priv->params_ethtool.uc_local_lb = val;
 1473         }
 1474 
 1475         /* create root node */
 1476         node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
 1477             SYSCTL_CHILDREN(priv->sysctl_ifnet), OID_AUTO,
 1478             "conf", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, "Configuration");
 1479         if (node == NULL)
 1480                 return;
 1481         for (x = 0; x != MLX5E_PARAMS_NUM; x++) {
 1482                 /* check for read-only parameter */
 1483                 if (strstr(mlx5e_params_desc[2 * x], "_max") != NULL ||
 1484                     strstr(mlx5e_params_desc[2 * x], "_mtu") != NULL) {
 1485                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
 1486                             mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RD |
 1487                             CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
 1488                             mlx5e_params_desc[2 * x + 1]);
 1489                 } else if (strcmp(mlx5e_params_desc[2 * x], "hw_lro") == 0) {
 1490                         /* read-only, but tunable parameters */
 1491                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
 1492                             mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RDTUN |
 1493                             CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
 1494                             mlx5e_params_desc[2 * x + 1]);
 1495                 } else {
 1496                         /*
 1497                          * NOTE: In FreeBSD-11 and newer the
 1498                          * CTLFLAG_RWTUN flag will take care of
 1499                          * loading default sysctl value from the
 1500                          * kernel environment, if any:
 1501                          */
 1502                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
 1503                             mlx5e_params_desc[2 * x], CTLTYPE_U64 | CTLFLAG_RWTUN |
 1504                             CTLFLAG_MPSAFE, priv, x, &mlx5e_ethtool_handler, "QU",
 1505                             mlx5e_params_desc[2 * x + 1]);
 1506                 }
 1507         }
 1508 
 1509         /* create fec node */
 1510         fec_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
 1511             SYSCTL_CHILDREN(node), OID_AUTO,
 1512             "fec", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
 1513             "Forward Error Correction");
 1514         if (fec_node == NULL)
 1515                 return;
 1516 
 1517         if (mlx5e_fec_update(priv) == 0) {
 1518                 SYSCTL_ADD_U32(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
 1519                     "mode_active", CTLFLAG_RD | CTLFLAG_MPSAFE,
 1520                     &priv->params_ethtool.fec_mode_active, 0,
 1521                     "Current FEC mode bit, if any.");
 1522 
 1523                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
 1524                     "mask_10x_25x", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1525                     priv, 0, &mlx5e_fec_mask_10x_25x_handler, "CU",
 1526                     "Set FEC masks for 10G_40G, 25G_50G, 56G, 100G respectivly. "
 1527                     "0:Auto "
 1528                     "1:NOFEC "
 1529                     "2:FIRECODE "
 1530                     "4:RS");
 1531 
 1532                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
 1533                     "avail_10x_25x", CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE,
 1534                     priv, 0, &mlx5e_fec_avail_10x_25x_handler, "CU",
 1535                     "Get available FEC bits for 10G_40G, 25G_50G, 56G, 100G respectivly. "
 1536                     "0:Auto "
 1537                     "1:NOFEC "
 1538                     "2:FIRECODE "
 1539                     "4:RS");
 1540 
 1541                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
 1542                     "mask_50x", CTLTYPE_U16 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1543                     priv, 0, &mlx5e_fec_mask_50x_handler, "SU",
 1544                     "Set FEC masks for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. "
 1545                     "0:Auto "
 1546                     "128:RS "
 1547                     "512:LL RS");
 1548 
 1549                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(fec_node), OID_AUTO,
 1550                     "avail_50x", CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_MPSAFE,
 1551                     priv, 0, &mlx5e_fec_avail_50x_handler, "SU",
 1552                     "Get available FEC bits for 50G 1x, 100G 2x, 200G 4x, 400G 8x respectivly. "
 1553                     "0:Auto "
 1554                     "128:RS "
 1555                     "512:LL RS");
 1556         }
 1557 
 1558         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(node), OID_AUTO,
 1559             "debug_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv,
 1560             0, &mlx5e_ethtool_debug_stats, "I", "Extended debug statistics");
 1561 
 1562         pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
 1563 
 1564         SYSCTL_ADD_STRING(&priv->sysctl_ctx, SYSCTL_CHILDREN(node),
 1565             OID_AUTO, "device_name", CTLFLAG_RD,
 1566             __DECONST(void *, pnameunit), 0,
 1567             "PCI device name");
 1568 
 1569         /* Diagnostics support */
 1570         mlx5e_create_diagnostics(priv);
 1571 
 1572         /* create qos node */
 1573         qos_node = SYSCTL_ADD_NODE(&priv->sysctl_ctx,
 1574             SYSCTL_CHILDREN(node), OID_AUTO,
 1575             "qos", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
 1576             "Quality Of Service configuration");
 1577         if (qos_node == NULL)
 1578                 return;
 1579 
 1580         /* Priority rate limit support */
 1581         if (mlx5e_getmaxrate(priv) == 0) {
 1582                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1583                     OID_AUTO, "tc_max_rate", CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1584                     priv, 0, mlx5e_tc_maxrate_handler, "QU",
 1585                     "Max rate for priority, specified in kilobits, where kilo=1000, "
 1586                     "max_rate must be divisible by 100000");
 1587         }
 1588 
 1589         /* Bandwidth limiting by ratio */
 1590         if (mlx5e_get_max_alloc(priv) == 0) {
 1591                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1592                     OID_AUTO, "tc_rate_share", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1593                     priv, 0, mlx5e_tc_rate_share_handler, "QU",
 1594                     "Specify bandwidth ratio from 1 to 100 "
 1595                     "for the available traffic classes");
 1596         }
 1597 
 1598         /* Priority to traffic class mapping */
 1599         if (mlx5e_get_prio_tc(priv) == 0) {
 1600                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1601                     OID_AUTO, "prio_0_7_tc", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1602                     priv, 0, mlx5e_prio_to_tc_handler, "CU",
 1603                     "Set traffic class 0 to 7 for priority 0 to 7 inclusivly");
 1604         }
 1605 
 1606         /* DSCP support */
 1607         if (mlx5e_get_dscp(priv) == 0) {
 1608                 for (i = 0; i != MLX5_MAX_SUPPORTED_DSCP; i += 8) {
 1609                         char name[32];
 1610                         snprintf(name, sizeof(name), "dscp_%d_%d_prio", i, i + 7);
 1611                         SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1612                                 OID_AUTO, name, CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1613                                 priv, i, mlx5e_dscp_prio_handler, "CU",
 1614                                 "Set DSCP to priority mapping, 0..7");
 1615                 }
 1616 #define A       "Set trust state, 1:PCP 2:DSCP"
 1617 #define B       " 3:BOTH"
 1618                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1619                     OID_AUTO, "trust_state", CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1620                     priv, 0, mlx5e_trust_state_handler, "CU",
 1621                     MLX5_CAP_QCAM_FEATURE(priv->mdev, qpts_trust_both) ?
 1622                     A B : A);
 1623 #undef B
 1624 #undef A
 1625         }
 1626 
 1627         if (mlx5e_port_query_buffer(priv, &port_buffer) == 0) {
 1628                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1629                     OID_AUTO, "buffers_size",
 1630                     CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1631                     priv, 0, mlx5e_buf_size_handler, "IU",
 1632                     "Set buffers sizes");
 1633                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1634                     OID_AUTO, "buffers_prio",
 1635                     CTLTYPE_U8 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1636                     priv, 0, mlx5e_buf_prio_handler, "CU",
 1637                     "Set prio to buffers mapping");
 1638                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(qos_node),
 1639                     OID_AUTO, "cable_length",
 1640                     CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 1641                     priv, 0, mlx5e_cable_length_handler, "IU",
 1642                     "Set cable length in meters for xoff threshold calculation");
 1643         }
 1644 
 1645         if (mlx5e_hw_temperature_update(priv) == 0) {
 1646                 SYSCTL_ADD_PROC(&priv->sysctl_ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet),
 1647                     OID_AUTO, "hw_temperature",
 1648                     CTLTYPE_S32 | CTLFLAG_RD | CTLFLAG_MPSAFE,
 1649                     priv, 0, mlx5e_hw_temperature_handler, "I",
 1650                     "HW temperature in millicelsius");
 1651         }
 1652 }

Cache object: b54d58fec187430c73bf641ad6ac4896


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.