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_core/mlx5_port.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) 2013-2018, Mellanox Technologies, Ltd.  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 <linux/module.h>
   32 #include <dev/mlx5/port.h>
   33 #include <dev/mlx5/mlx5_core/mlx5_core.h>
   34 
   35 int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
   36                          int size_in, void *data_out, int size_out,
   37                          u16 reg_num, int arg, int write)
   38 {
   39         int outlen = MLX5_ST_SZ_BYTES(access_register_out) + size_out;
   40         int inlen = MLX5_ST_SZ_BYTES(access_register_in) + size_in;
   41         int err = -ENOMEM;
   42         u32 *out = NULL;
   43         u32 *in = NULL;
   44         void *data;
   45 
   46         in = mlx5_vzalloc(inlen);
   47         out = mlx5_vzalloc(outlen);
   48         if (!in || !out)
   49                 goto out;
   50 
   51         data = MLX5_ADDR_OF(access_register_in, in, register_data);
   52         memcpy(data, data_in, size_in);
   53 
   54         MLX5_SET(access_register_in, in, opcode, MLX5_CMD_OP_ACCESS_REG);
   55         MLX5_SET(access_register_in, in, op_mod, !write);
   56         MLX5_SET(access_register_in, in, argument, arg);
   57         MLX5_SET(access_register_in, in, register_id, reg_num);
   58 
   59         err = mlx5_cmd_exec(dev, in, inlen, out, outlen);
   60         if (err)
   61                 goto out;
   62         data = MLX5_ADDR_OF(access_register_out, out, register_data);
   63         memcpy(data_out, data, size_out);
   64 
   65 out:
   66         kvfree(out);
   67         kvfree(in);
   68         return err;
   69 }
   70 EXPORT_SYMBOL_GPL(mlx5_core_access_reg);
   71 
   72 int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
   73                         u8 feature_group, u8 access_reg_group)
   74 {
   75         u32 in[MLX5_ST_SZ_DW(qcam_reg)] = {};
   76         int sz = MLX5_ST_SZ_BYTES(qcam_reg);
   77 
   78         MLX5_SET(qcam_reg, in, feature_group, feature_group);
   79         MLX5_SET(qcam_reg, in, access_reg_group, access_reg_group);
   80 
   81         return mlx5_core_access_reg(mdev, in, sz, qcam, sz, MLX5_REG_QCAM, 0, 0);
   82 }
   83 EXPORT_SYMBOL_GPL(mlx5_query_qcam_reg);
   84 
   85 int mlx5_query_pcam_reg(struct mlx5_core_dev *dev, u32 *pcam, u8 feature_group,
   86                         u8 access_reg_group)
   87 {
   88         u32 in[MLX5_ST_SZ_DW(pcam_reg)] = {};
   89         int sz = MLX5_ST_SZ_BYTES(pcam_reg);
   90 
   91         MLX5_SET(pcam_reg, in, feature_group, feature_group);
   92         MLX5_SET(pcam_reg, in, access_reg_group, access_reg_group);
   93 
   94         return mlx5_core_access_reg(dev, in, sz, pcam, sz, MLX5_REG_PCAM, 0, 0);
   95 }
   96 
   97 int mlx5_query_mcam_reg(struct mlx5_core_dev *dev, u32 *mcam, u8 feature_group,
   98                         u8 access_reg_group)
   99 {
  100         u32 in[MLX5_ST_SZ_DW(mcam_reg)] = {};
  101         int sz = MLX5_ST_SZ_BYTES(mcam_reg);
  102 
  103         MLX5_SET(mcam_reg, in, feature_group, feature_group);
  104         MLX5_SET(mcam_reg, in, access_reg_group, access_reg_group);
  105 
  106         return mlx5_core_access_reg(dev, in, sz, mcam, sz, MLX5_REG_MCAM, 0, 0);
  107 }
  108 
  109 struct mlx5_reg_pcap {
  110         u8                      rsvd0;
  111         u8                      port_num;
  112         u8                      rsvd1[2];
  113         __be32                  caps_127_96;
  114         __be32                  caps_95_64;
  115         __be32                  caps_63_32;
  116         __be32                  caps_31_0;
  117 };
  118 
  119 /* This function should be used after setting a port register only */
  120 void mlx5_toggle_port_link(struct mlx5_core_dev *dev)
  121 {
  122         enum mlx5_port_status ps;
  123 
  124         mlx5_query_port_admin_status(dev, &ps);
  125         mlx5_set_port_status(dev, MLX5_PORT_DOWN);
  126         if (ps == MLX5_PORT_UP)
  127                 mlx5_set_port_status(dev, MLX5_PORT_UP);
  128 }
  129 EXPORT_SYMBOL_GPL(mlx5_toggle_port_link);
  130 
  131 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
  132 {
  133         struct mlx5_reg_pcap in;
  134         struct mlx5_reg_pcap out;
  135         int err;
  136 
  137         memset(&in, 0, sizeof(in));
  138         in.caps_127_96 = cpu_to_be32(caps);
  139         in.port_num = port_num;
  140 
  141         err = mlx5_core_access_reg(dev, &in, sizeof(in), &out,
  142                                    sizeof(out), MLX5_REG_PCAP, 0, 1);
  143 
  144         return err;
  145 }
  146 EXPORT_SYMBOL_GPL(mlx5_set_port_caps);
  147 
  148 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
  149                          int ptys_size, int proto_mask, u8 local_port)
  150 {
  151         u32 in[MLX5_ST_SZ_DW(ptys_reg)];
  152         int err;
  153 
  154         memset(in, 0, sizeof(in));
  155         MLX5_SET(ptys_reg, in, local_port, local_port);
  156         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
  157 
  158         err = mlx5_core_access_reg(dev, in, sizeof(in), ptys,
  159                                    ptys_size, MLX5_REG_PTYS, 0, 0);
  160 
  161         return err;
  162 }
  163 EXPORT_SYMBOL_GPL(mlx5_query_port_ptys);
  164 
  165 int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev,
  166                               u32 *proto_cap, int proto_mask)
  167 {
  168         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
  169         int err;
  170 
  171         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
  172         if (err)
  173                 return err;
  174 
  175         if (proto_mask == MLX5_PTYS_EN)
  176                 *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
  177         else
  178                 *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability);
  179 
  180         return 0;
  181 }
  182 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap);
  183 
  184 int mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask,
  185                             u8 *an_disable_cap, u8 *an_disable_status)
  186 {
  187         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
  188         int err;
  189 
  190         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
  191         if (err)
  192                 return err;
  193 
  194         *an_disable_status = MLX5_GET(ptys_reg, out, an_disable_admin);
  195         *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
  196 
  197         return 0;
  198 }
  199 EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg);
  200 
  201 int mlx5_set_port_autoneg(struct mlx5_core_dev *dev, bool disable,
  202                           u32 eth_proto_admin, int proto_mask)
  203 {
  204         u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
  205         u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
  206         u8 an_disable_cap;
  207         u8 an_disable_status;
  208         int err;
  209 
  210         err = mlx5_query_port_autoneg(dev, proto_mask, &an_disable_cap,
  211                                       &an_disable_status);
  212         if (err)
  213                 return err;
  214         if (!an_disable_cap)
  215                 return -EPERM;
  216 
  217         MLX5_SET(ptys_reg, in, local_port, 1);
  218         MLX5_SET(ptys_reg, in, an_disable_admin, disable);
  219         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
  220         if (proto_mask == MLX5_PTYS_EN)
  221                 MLX5_SET(ptys_reg, in, eth_proto_admin, eth_proto_admin);
  222 
  223         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  224                                    sizeof(out), MLX5_REG_PTYS, 0, 1);
  225         return err;
  226 }
  227 EXPORT_SYMBOL_GPL(mlx5_set_port_autoneg);
  228 
  229 int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
  230                                 u32 *proto_admin, int proto_mask)
  231 {
  232         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
  233         int err;
  234 
  235         err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1);
  236         if (err)
  237                 return err;
  238 
  239         if (proto_mask == MLX5_PTYS_EN)
  240                 *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
  241         else
  242                 *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
  243 
  244         return 0;
  245 }
  246 EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin);
  247 
  248 int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
  249                                    u32 *proto_oper, u8 local_port)
  250 {
  251         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
  252         int err;
  253 
  254         err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
  255                                    local_port);
  256         if (err)
  257                 return err;
  258 
  259         *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
  260 
  261         return 0;
  262 }
  263 EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
  264 
  265 int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
  266                         int proto_mask, bool ext)
  267 {
  268         u32 in[MLX5_ST_SZ_DW(ptys_reg)] = {0};
  269         u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
  270         int err;
  271 
  272         MLX5_SET(ptys_reg, in, local_port, 1);
  273         MLX5_SET(ptys_reg, in, proto_mask, proto_mask);
  274         if (proto_mask == MLX5_PTYS_EN) {
  275                 if (ext)
  276                         MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
  277                 else
  278                         MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
  279         } else {
  280                 MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin);
  281         }
  282 
  283         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  284                                    sizeof(out), MLX5_REG_PTYS, 0, 1);
  285         return err;
  286 }
  287 EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
  288 
  289 int mlx5_set_port_status(struct mlx5_core_dev *dev,
  290                          enum mlx5_port_status status)
  291 {
  292         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
  293         u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
  294         int err;
  295 
  296         MLX5_SET(paos_reg, in, local_port, 1);
  297 
  298         MLX5_SET(paos_reg, in, admin_status, status);
  299         MLX5_SET(paos_reg, in, ase, 1);
  300 
  301         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  302                                    sizeof(out), MLX5_REG_PAOS, 0, 1);
  303         return err;
  304 }
  305 
  306 int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
  307 {
  308         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
  309         u32 out[MLX5_ST_SZ_DW(paos_reg)] = {0};
  310         int err;
  311 
  312         MLX5_SET(paos_reg, in, local_port, 1);
  313 
  314         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  315                                    sizeof(out), MLX5_REG_PAOS, 0, 0);
  316         if (err)
  317                 return err;
  318 
  319         *status = MLX5_GET(paos_reg, out, oper_status);
  320         return err;
  321 }
  322 
  323 int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
  324                                  enum mlx5_port_status *status)
  325 {
  326         u32 in[MLX5_ST_SZ_DW(paos_reg)] = {0};
  327         u32 out[MLX5_ST_SZ_DW(paos_reg)];
  328         int err;
  329 
  330         MLX5_SET(paos_reg, in, local_port, 1);
  331         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  332                                    sizeof(out), MLX5_REG_PAOS, 0, 0);
  333         if (err)
  334                 return err;
  335         *status = MLX5_GET(paos_reg, out, admin_status);
  336         return 0;
  337 }
  338 EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
  339 
  340 static int mlx5_query_port_mtu(struct mlx5_core_dev *dev,
  341                                int *admin_mtu, int *max_mtu, int *oper_mtu)
  342 {
  343         u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
  344         u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
  345         int err;
  346 
  347         MLX5_SET(pmtu_reg, in, local_port, 1);
  348 
  349         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  350                                    sizeof(out), MLX5_REG_PMTU, 0, 0);
  351         if (err)
  352                 return err;
  353 
  354         if (max_mtu)
  355                 *max_mtu  = MLX5_GET(pmtu_reg, out, max_mtu);
  356         if (oper_mtu)
  357                 *oper_mtu = MLX5_GET(pmtu_reg, out, oper_mtu);
  358         if (admin_mtu)
  359                 *admin_mtu = MLX5_GET(pmtu_reg, out, admin_mtu);
  360 
  361         return err;
  362 }
  363 
  364 int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu)
  365 {
  366         u32 in[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
  367         u32 out[MLX5_ST_SZ_DW(pmtu_reg)] = {0};
  368 
  369         MLX5_SET(pmtu_reg, in, admin_mtu, mtu);
  370         MLX5_SET(pmtu_reg, in, local_port, 1);
  371 
  372         return mlx5_core_access_reg(dev, in, sizeof(in), out,
  373                                    sizeof(out), MLX5_REG_PMTU, 0, 1);
  374 }
  375 EXPORT_SYMBOL_GPL(mlx5_set_port_mtu);
  376 
  377 int mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu)
  378 {
  379         return mlx5_query_port_mtu(dev, NULL, max_mtu, NULL);
  380 }
  381 EXPORT_SYMBOL_GPL(mlx5_query_port_max_mtu);
  382 
  383 int mlx5_set_port_pause_and_pfc(struct mlx5_core_dev *dev, u32 port,
  384                                 u8 rx_pause, u8 tx_pause,
  385                                 u8 pfc_en_rx, u8 pfc_en_tx)
  386 {
  387         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
  388         u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
  389 
  390         if (pfc_en_rx || pfc_en_tx) {
  391                 /* PFC and global pauseframes are incompatible features */
  392                 if (tx_pause || rx_pause)
  393                         return -EINVAL;
  394         }
  395 
  396         MLX5_SET(pfcc_reg, in, local_port, port);
  397         MLX5_SET(pfcc_reg, in, pptx, tx_pause);
  398         MLX5_SET(pfcc_reg, in, pprx, rx_pause);
  399         MLX5_SET(pfcc_reg, in, pfctx, pfc_en_tx);
  400         MLX5_SET(pfcc_reg, in, pfcrx, pfc_en_rx);
  401         MLX5_SET(pfcc_reg, in, prio_mask_tx, pfc_en_tx);
  402         MLX5_SET(pfcc_reg, in, prio_mask_rx, pfc_en_rx);
  403 
  404         return mlx5_core_access_reg(dev, in, sizeof(in), out,
  405                                    sizeof(out), MLX5_REG_PFCC, 0, 1);
  406 }
  407 
  408 int mlx5_query_port_pause(struct mlx5_core_dev *dev, u32 port,
  409                           u32 *rx_pause, u32 *tx_pause)
  410 {
  411         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
  412         u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {0};
  413         int err;
  414 
  415         MLX5_SET(pfcc_reg, in, local_port, port);
  416 
  417         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  418                                    sizeof(out), MLX5_REG_PFCC, 0, 0);
  419         if (err)
  420                 return err;
  421 
  422         *rx_pause = MLX5_GET(pfcc_reg, out, pprx);
  423         *tx_pause = MLX5_GET(pfcc_reg, out, pptx);
  424 
  425         return 0;
  426 }
  427 
  428 int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx)
  429 {
  430         u32 in[MLX5_ST_SZ_DW(pfcc_reg)] = {};
  431         u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
  432         int err;
  433 
  434         MLX5_SET(pfcc_reg, in, local_port, 1);
  435         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  436                                    sizeof(out), MLX5_REG_PFCC, 0, 0);
  437         if (err)
  438                 return err;
  439 
  440         if (pfc_en_tx != NULL)
  441                 *pfc_en_tx = MLX5_GET(pfcc_reg, out, pfctx);
  442         if (pfc_en_rx != NULL)
  443                 *pfc_en_rx = MLX5_GET(pfcc_reg, out, pfcrx);
  444         return 0;
  445 }
  446 EXPORT_SYMBOL_GPL(mlx5_query_port_pfc);
  447 
  448 int mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu)
  449 {
  450         return mlx5_query_port_mtu(dev, NULL, NULL, oper_mtu);
  451 }
  452 EXPORT_SYMBOL_GPL(mlx5_query_port_oper_mtu);
  453 
  454 u8 mlx5_is_wol_supported(struct mlx5_core_dev *dev)
  455 {
  456         u8 wol_supported = 0;
  457 
  458         if (MLX5_CAP_GEN(dev, wol_s))
  459                 wol_supported |= MLX5_WOL_SECURED_MAGIC;
  460         if (MLX5_CAP_GEN(dev, wol_g))
  461                 wol_supported |= MLX5_WOL_MAGIC;
  462         if (MLX5_CAP_GEN(dev, wol_a))
  463                 wol_supported |= MLX5_WOL_ARP;
  464         if (MLX5_CAP_GEN(dev, wol_b))
  465                 wol_supported |= MLX5_WOL_BROADCAST;
  466         if (MLX5_CAP_GEN(dev, wol_m))
  467                 wol_supported |= MLX5_WOL_MULTICAST;
  468         if (MLX5_CAP_GEN(dev, wol_u))
  469                 wol_supported |= MLX5_WOL_UNICAST;
  470         if (MLX5_CAP_GEN(dev, wol_p))
  471                 wol_supported |= MLX5_WOL_PHY_ACTIVITY;
  472 
  473         return wol_supported;
  474 }
  475 EXPORT_SYMBOL_GPL(mlx5_is_wol_supported);
  476 
  477 int mlx5_set_wol(struct mlx5_core_dev *dev, u8 wol_mode)
  478 {
  479         u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0};
  480         u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0};
  481 
  482         MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
  483         MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
  484         MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
  485 
  486         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  487 }
  488 EXPORT_SYMBOL_GPL(mlx5_set_wol);
  489 
  490 int mlx5_query_dropless_mode(struct mlx5_core_dev *dev, u16 *timeout)
  491 {
  492         u32 in[MLX5_ST_SZ_DW(query_delay_drop_params_in)] = {0};
  493         u32 out[MLX5_ST_SZ_DW(query_delay_drop_params_out)] = {0};
  494         int err = 0;
  495 
  496         MLX5_SET(query_delay_drop_params_in, in, opcode,
  497                  MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS);
  498 
  499         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  500         if (err)
  501                 return err;
  502 
  503         *timeout = MLX5_GET(query_delay_drop_params_out, out,
  504                             delay_drop_timeout);
  505 
  506         return 0;
  507 }
  508 EXPORT_SYMBOL_GPL(mlx5_query_dropless_mode);
  509 
  510 int mlx5_set_dropless_mode(struct mlx5_core_dev *dev, u16 timeout)
  511 {
  512         u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {0};
  513         u32 out[MLX5_ST_SZ_DW(set_delay_drop_params_out)] = {0};
  514 
  515         MLX5_SET(set_delay_drop_params_in, in, opcode,
  516                  MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
  517         MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout, timeout);
  518 
  519         return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  520 }
  521 EXPORT_SYMBOL_GPL(mlx5_set_dropless_mode);
  522 
  523 int mlx5_core_access_pvlc(struct mlx5_core_dev *dev,
  524                           struct mlx5_pvlc_reg *pvlc, int write)
  525 {
  526         int sz = MLX5_ST_SZ_BYTES(pvlc_reg);
  527         u8 in[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
  528         u8 out[MLX5_ST_SZ_BYTES(pvlc_reg)] = {0};
  529         int err;
  530 
  531         MLX5_SET(pvlc_reg, in, local_port, pvlc->local_port);
  532         if (write)
  533                 MLX5_SET(pvlc_reg, in, vl_admin, pvlc->vl_admin);
  534 
  535         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PVLC, 0,
  536                                    !!write);
  537         if (err)
  538                 return err;
  539 
  540         if (!write) {
  541                 pvlc->local_port = MLX5_GET(pvlc_reg, out, local_port);
  542                 pvlc->vl_hw_cap = MLX5_GET(pvlc_reg, out, vl_hw_cap);
  543                 pvlc->vl_admin = MLX5_GET(pvlc_reg, out, vl_admin);
  544                 pvlc->vl_operational = MLX5_GET(pvlc_reg, out, vl_operational);
  545         }
  546 
  547         return 0;
  548 }
  549 EXPORT_SYMBOL_GPL(mlx5_core_access_pvlc);
  550 
  551 int mlx5_core_access_ptys(struct mlx5_core_dev *dev,
  552                           struct mlx5_ptys_reg *ptys, int write)
  553 {
  554         int sz = MLX5_ST_SZ_BYTES(ptys_reg);
  555         void *out = NULL;
  556         void *in = NULL;
  557         int err;
  558 
  559         in = mlx5_vzalloc(sz);
  560         if (!in)
  561                 return -ENOMEM;
  562 
  563         out = mlx5_vzalloc(sz);
  564         if (!out) {
  565                 kfree(in);
  566                 return -ENOMEM;
  567         }
  568 
  569         MLX5_SET(ptys_reg, in, local_port, ptys->local_port);
  570         MLX5_SET(ptys_reg, in, proto_mask, ptys->proto_mask);
  571         if (write) {
  572                 MLX5_SET(ptys_reg, in, eth_proto_capability,
  573                          ptys->eth_proto_cap);
  574                 MLX5_SET(ptys_reg, in, ib_link_width_capability,
  575                          ptys->ib_link_width_cap);
  576                 MLX5_SET(ptys_reg, in, ib_proto_capability,
  577                          ptys->ib_proto_cap);
  578                 MLX5_SET(ptys_reg, in, eth_proto_admin, ptys->eth_proto_admin);
  579                 MLX5_SET(ptys_reg, in, ib_link_width_admin,
  580                          ptys->ib_link_width_admin);
  581                 MLX5_SET(ptys_reg, in, ib_proto_admin, ptys->ib_proto_admin);
  582                 MLX5_SET(ptys_reg, in, eth_proto_oper, ptys->eth_proto_oper);
  583                 MLX5_SET(ptys_reg, in, ib_link_width_oper,
  584                          ptys->ib_link_width_oper);
  585                 MLX5_SET(ptys_reg, in, ib_proto_oper, ptys->ib_proto_oper);
  586                 MLX5_SET(ptys_reg, in, eth_proto_lp_advertise,
  587                          ptys->eth_proto_lp_advertise);
  588         }
  589 
  590         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PTYS, 0,
  591                                    !!write);
  592         if (err)
  593                 goto out;
  594 
  595         if (!write) {
  596                 ptys->local_port = MLX5_GET(ptys_reg, out, local_port);
  597                 ptys->proto_mask = MLX5_GET(ptys_reg, out, proto_mask);
  598                 ptys->eth_proto_cap = MLX5_GET(ptys_reg, out,
  599                                                eth_proto_capability);
  600                 ptys->ib_link_width_cap = MLX5_GET(ptys_reg, out,
  601                                            ib_link_width_capability);
  602                 ptys->ib_proto_cap = MLX5_GET(ptys_reg, out,
  603                                               ib_proto_capability);
  604                 ptys->eth_proto_admin = MLX5_GET(ptys_reg, out,
  605                                                  eth_proto_admin);
  606                 ptys->ib_link_width_admin = MLX5_GET(ptys_reg, out,
  607                                                      ib_link_width_admin);
  608                 ptys->ib_proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin);
  609                 ptys->eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
  610                 ptys->ib_link_width_oper = MLX5_GET(ptys_reg, out,
  611                                                     ib_link_width_oper);
  612                 ptys->ib_proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
  613                 ptys->eth_proto_lp_advertise = MLX5_GET(ptys_reg, out,
  614                                                         eth_proto_lp_advertise);
  615         }
  616 
  617 out:
  618         kvfree(in);
  619         kvfree(out);
  620         return err;
  621 }
  622 EXPORT_SYMBOL_GPL(mlx5_core_access_ptys);
  623 
  624 static int mtu_to_ib_mtu(struct mlx5_core_dev *dev, int mtu)
  625 {
  626         switch (mtu) {
  627         case 256: return 1;
  628         case 512: return 2;
  629         case 1024: return 3;
  630         case 2048: return 4;
  631         case 4096: return 5;
  632         default:
  633                 mlx5_core_warn(dev, "invalid mtu\n");
  634                 return -1;
  635         }
  636 }
  637 
  638 int mlx5_core_access_pmtu(struct mlx5_core_dev *dev,
  639                           struct mlx5_pmtu_reg *pmtu, int write)
  640 {
  641         int sz = MLX5_ST_SZ_BYTES(pmtu_reg);
  642         void *out = NULL;
  643         void *in = NULL;
  644         int err;
  645 
  646         in = mlx5_vzalloc(sz);
  647         if (!in)
  648                 return -ENOMEM;
  649 
  650         out = mlx5_vzalloc(sz);
  651         if (!out) {
  652                 kfree(in);
  653                 return -ENOMEM;
  654         }
  655 
  656         MLX5_SET(pmtu_reg, in, local_port, pmtu->local_port);
  657         if (write)
  658                 MLX5_SET(pmtu_reg, in, admin_mtu, pmtu->admin_mtu);
  659 
  660         err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PMTU, 0,
  661                                    !!write);
  662         if (err)
  663                 goto out;
  664 
  665         if (!write) {
  666                 pmtu->local_port = MLX5_GET(pmtu_reg, out, local_port);
  667                 pmtu->max_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
  668                                                        max_mtu));
  669                 pmtu->admin_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
  670                                                          admin_mtu));
  671                 pmtu->oper_mtu = mtu_to_ib_mtu(dev, MLX5_GET(pmtu_reg, out,
  672                                                         oper_mtu));
  673         }
  674 
  675 out:
  676         kvfree(in);
  677         kvfree(out);
  678         return err;
  679 }
  680 EXPORT_SYMBOL_GPL(mlx5_core_access_pmtu);
  681 
  682 int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
  683 {
  684         u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
  685         u32 out[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
  686         int lane = 0;
  687         int err;
  688 
  689         MLX5_SET(pmlp_reg, in, local_port, 1);
  690 
  691         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  692                                    sizeof(out), MLX5_REG_PMLP, 0, 0);
  693         if (err)
  694                 return err;
  695 
  696         lane = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
  697         *module_num = lane & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
  698 
  699         return 0;
  700 }
  701 EXPORT_SYMBOL_GPL(mlx5_query_module_num);
  702 
  703 int mlx5_query_eeprom(struct mlx5_core_dev *dev,
  704                       int i2c_addr, int page_num, int device_addr,
  705                       int size, int module_num, u32 *data, int *size_read)
  706 {
  707         u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {0};
  708         u32 out[MLX5_ST_SZ_DW(mcia_reg)] = {0};
  709         u32 *ptr = (u32 *)MLX5_ADDR_OF(mcia_reg, out, dword_0);
  710         int status;
  711         int err;
  712 
  713         size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
  714 
  715         MLX5_SET(mcia_reg, in, l, 0);
  716         MLX5_SET(mcia_reg, in, module, module_num);
  717         MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
  718         MLX5_SET(mcia_reg, in, page_number, page_num);
  719         MLX5_SET(mcia_reg, in, device_address, device_addr);
  720         MLX5_SET(mcia_reg, in, size, size);
  721 
  722         err = mlx5_core_access_reg(dev, in, sizeof(in), out,
  723                                    sizeof(out), MLX5_REG_MCIA, 0, 0);
  724         if (err)
  725                 return err;
  726 
  727         status = MLX5_GET(mcia_reg, out, status);
  728         if (status)
  729                 return status;
  730 
  731         memcpy(data, ptr, size);
  732         *size_read = size;
  733         return 0;
  734 }
  735 EXPORT_SYMBOL_GPL(mlx5_query_eeprom);
  736 
  737 int mlx5_vxlan_udp_port_add(struct mlx5_core_dev *dev, u16 port)
  738 {
  739         u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
  740         u32 out[MLX5_ST_SZ_DW(add_vxlan_udp_dport_out)] = {0};
  741         int err;
  742 
  743         MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
  744                  MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
  745         MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
  746 
  747         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  748         if (err) {
  749                 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
  750                               mlx5_command_str(MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT),
  751                               port, err);
  752         }
  753 
  754         return err;
  755 }
  756 
  757 int mlx5_vxlan_udp_port_delete(struct mlx5_core_dev *dev, u16 port)
  758 {
  759         u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {0};
  760         u32 out[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_out)] = {0};
  761         int err;
  762 
  763         MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
  764                  MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
  765         MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
  766 
  767         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  768         if (err) {
  769                 mlx5_core_err(dev, "Failed %s, port %u, err - %d",
  770                               mlx5_command_str(MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT),
  771                               port, err);
  772         }
  773 
  774         return err;
  775 }
  776 
  777 int mlx5_query_wol(struct mlx5_core_dev *dev, u8 *wol_mode)
  778 {
  779         u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0};
  780         u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0};
  781         int err;
  782 
  783         MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
  784 
  785         err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
  786 
  787         if (!err)
  788                 *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
  789 
  790         return err;
  791 }
  792 EXPORT_SYMBOL_GPL(mlx5_query_wol);
  793 
  794 int mlx5_query_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
  795                                 int priority, int *is_enable)
  796 {
  797         u32 in[MLX5_ST_SZ_DW(query_cong_status_in)] = {0};
  798         u32 out[MLX5_ST_SZ_DW(query_cong_status_out)] = {0};
  799         int err;
  800 
  801         *is_enable = 0;
  802 
  803         MLX5_SET(query_cong_status_in, in, opcode,
  804                  MLX5_CMD_OP_QUERY_CONG_STATUS);
  805         MLX5_SET(query_cong_status_in, in, cong_protocol, protocol);
  806         MLX5_SET(query_cong_status_in, in, priority, priority);
  807 
  808         err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
  809         if (!err)
  810                 *is_enable = MLX5_GET(query_cong_status_out, out, enable);
  811         return err;
  812 }
  813 
  814 int mlx5_modify_port_cong_status(struct mlx5_core_dev *mdev, int protocol,
  815                                  int priority, int enable)
  816 {
  817         u32 in[MLX5_ST_SZ_DW(modify_cong_status_in)] = {0};
  818         u32 out[MLX5_ST_SZ_DW(modify_cong_status_out)] = {0};
  819 
  820         MLX5_SET(modify_cong_status_in, in, opcode,
  821                  MLX5_CMD_OP_MODIFY_CONG_STATUS);
  822         MLX5_SET(modify_cong_status_in, in, cong_protocol, protocol);
  823         MLX5_SET(modify_cong_status_in, in, priority, priority);
  824         MLX5_SET(modify_cong_status_in, in, enable, enable);
  825 
  826         return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
  827 }
  828 
  829 int mlx5_query_port_cong_params(struct mlx5_core_dev *mdev, int protocol,
  830                                 void *out, int out_size)
  831 {
  832         u32 in[MLX5_ST_SZ_DW(query_cong_params_in)] = {0};
  833 
  834         MLX5_SET(query_cong_params_in, in, opcode,
  835                  MLX5_CMD_OP_QUERY_CONG_PARAMS);
  836         MLX5_SET(query_cong_params_in, in, cong_protocol, protocol);
  837 
  838         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
  839 }
  840 
  841 static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
  842                                      int outlen)
  843 {
  844         u32 in[MLX5_ST_SZ_DW(qetc_reg)];
  845 
  846         if (!MLX5_CAP_GEN(mdev, ets))
  847                 return -ENOTSUPP;
  848 
  849         memset(in, 0, sizeof(in));
  850         return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
  851                                     MLX5_REG_QETCR, 0, 0);
  852 }
  853 
  854 int mlx5_max_tc(struct mlx5_core_dev *mdev)
  855 {
  856         u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8;
  857 
  858         return num_tc - 1;
  859 }
  860 EXPORT_SYMBOL_GPL(mlx5_max_tc);
  861 
  862 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
  863                                    int inlen)
  864 {
  865         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
  866 
  867         if (!MLX5_CAP_GEN(mdev, ets))
  868                 return -ENOTSUPP;
  869 
  870         return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
  871                                     MLX5_REG_QETCR, 0, 1);
  872 }
  873 
  874 int mlx5_query_port_tc_rate_limit(struct mlx5_core_dev *mdev,
  875                                    u8 *max_bw_value,
  876                                    u8 *max_bw_units)
  877 {
  878         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
  879         void *ets_tcn_conf;
  880         int err;
  881         int i;
  882 
  883         err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
  884         if (err)
  885                 return err;
  886 
  887         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
  888                 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
  889 
  890                 max_bw_value[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
  891                                            max_bw_value);
  892                 max_bw_units[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
  893                                            max_bw_units);
  894         }
  895 
  896         return 0;
  897 }
  898 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_rate_limit);
  899 
  900 int mlx5_modify_port_tc_rate_limit(struct mlx5_core_dev *mdev,
  901                                    const u8 *max_bw_value,
  902                                    const u8 *max_bw_units)
  903 {
  904         u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
  905         void *ets_tcn_conf;
  906         int i;
  907 
  908         MLX5_SET(qetc_reg, in, port_number, 1);
  909 
  910         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
  911                 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, in, tc_configuration[i]);
  912 
  913                 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, r, 1);
  914                 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_units,
  915                          max_bw_units[i]);
  916                 MLX5_SET(ets_tcn_config_reg, ets_tcn_conf, max_bw_value,
  917                          max_bw_value[i]);
  918         }
  919 
  920         return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
  921 }
  922 EXPORT_SYMBOL_GPL(mlx5_modify_port_tc_rate_limit);
  923 
  924 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
  925                             u8 prio, u8 *tc)
  926 {
  927         u32 in[MLX5_ST_SZ_DW(qtct_reg)];
  928         u32 out[MLX5_ST_SZ_DW(qtct_reg)];
  929         int err;
  930 
  931         memset(in, 0, sizeof(in));
  932         memset(out, 0, sizeof(out));
  933 
  934         MLX5_SET(qtct_reg, in, port_number, 1);
  935         MLX5_SET(qtct_reg, in, prio, prio);
  936 
  937         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
  938                                    sizeof(out), MLX5_REG_QTCT, 0, 0);
  939         if (!err)
  940                 *tc = MLX5_GET(qtct_reg, out, tclass);
  941 
  942         return err;
  943 }
  944 EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
  945 
  946 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, int prio_index,
  947                           const u8 prio_tc)
  948 {
  949         u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {};
  950         u32 out[MLX5_ST_SZ_DW(qtct_reg)];
  951         int err;
  952 
  953         if (prio_tc > mlx5_max_tc(mdev))
  954                 return -EINVAL;
  955 
  956         MLX5_SET(qtct_reg, in, prio, prio_index);
  957         MLX5_SET(qtct_reg, in, tclass, prio_tc);
  958 
  959         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
  960                                    sizeof(out), MLX5_REG_QTCT, 0, 1);
  961 
  962         return (err);
  963 }
  964 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
  965 
  966 int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, const u8 *tc_group)
  967 {
  968         u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
  969         int i;
  970 
  971         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
  972                 MLX5_SET(qetc_reg, in, tc_configuration[i].g, 1);
  973                 MLX5_SET(qetc_reg, in, tc_configuration[i].group, tc_group[i]);
  974         }
  975 
  976         return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
  977 }
  978 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group);
  979 
  980 int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
  981                              u8 tc, u8 *tc_group)
  982 {
  983         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
  984         void *ets_tcn_conf;
  985         int err;
  986 
  987         err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
  988         if (err)
  989                 return err;
  990 
  991         ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
  992                                     tc_configuration[tc]);
  993 
  994         *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
  995                              group);
  996 
  997         return 0;
  998 }
  999 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group);
 1000 
 1001 int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, const u8 *tc_bw)
 1002 {
 1003         u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {};
 1004         int i;
 1005 
 1006         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
 1007                 MLX5_SET(qetc_reg, in, tc_configuration[i].b, 1);
 1008                 MLX5_SET(qetc_reg, in, tc_configuration[i].bw_allocation, tc_bw[i]);
 1009         }
 1010 
 1011         return mlx5_set_port_qetcr_reg(mdev, in, sizeof(in));
 1012 }
 1013 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
 1014 
 1015 int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *bw_pct)
 1016 {
 1017         u32 out[MLX5_ST_SZ_DW(qetc_reg)];
 1018         void *ets_tcn_conf;
 1019         int err;
 1020         int i;
 1021 
 1022         err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
 1023         if (err)
 1024                 return err;
 1025 
 1026         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
 1027                 ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, tc_configuration[i]);
 1028                 bw_pct[i] = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, bw_allocation);
 1029         }
 1030         return 0;
 1031 }
 1032 EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
 1033 
 1034 int mlx5_modify_port_cong_params(struct mlx5_core_dev *mdev,
 1035                                  void *in, int in_size)
 1036 {
 1037         u32 out[MLX5_ST_SZ_DW(modify_cong_params_out)] = {0};
 1038 
 1039         MLX5_SET(modify_cong_params_in, in, opcode,
 1040                  MLX5_CMD_OP_MODIFY_CONG_PARAMS);
 1041 
 1042         return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
 1043 }
 1044 
 1045 int mlx5_query_port_cong_statistics(struct mlx5_core_dev *mdev, int clear,
 1046                                     void *out, int out_size)
 1047 {
 1048         u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {0};
 1049 
 1050         MLX5_SET(query_cong_statistics_in, in, opcode,
 1051                  MLX5_CMD_OP_QUERY_CONG_STATISTICS);
 1052         MLX5_SET(query_cong_statistics_in, in, clear, clear);
 1053 
 1054         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
 1055 }
 1056 
 1057 int mlx5_set_diagnostic_params(struct mlx5_core_dev *mdev, void *in,
 1058                                int in_size)
 1059 {
 1060         u32 out[MLX5_ST_SZ_DW(set_diagnostic_params_out)] = {0};
 1061 
 1062         MLX5_SET(set_diagnostic_params_in, in, opcode,
 1063                  MLX5_CMD_OP_SET_DIAGNOSTICS);
 1064 
 1065         return mlx5_cmd_exec(mdev, in, in_size, out, sizeof(out));
 1066 }
 1067 
 1068 int mlx5_query_diagnostic_counters(struct mlx5_core_dev *mdev,
 1069                                    u8 num_of_samples, u16 sample_index,
 1070                                    void *out, int out_size)
 1071 {
 1072         u32 in[MLX5_ST_SZ_DW(query_diagnostic_counters_in)] = {0};
 1073 
 1074         MLX5_SET(query_diagnostic_counters_in, in, opcode,
 1075                  MLX5_CMD_OP_QUERY_DIAGNOSTICS);
 1076         MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
 1077                  num_of_samples);
 1078         MLX5_SET(query_diagnostic_counters_in, in, sample_index, sample_index);
 1079 
 1080         return mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
 1081 }
 1082 
 1083 int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
 1084 {
 1085         u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
 1086         u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
 1087         int err;
 1088 
 1089         MLX5_SET(qpts_reg, in, local_port, 1);
 1090         MLX5_SET(qpts_reg, in, trust_state, trust_state);
 1091 
 1092         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
 1093                                    sizeof(out), MLX5_REG_QPTS, 0, 1);
 1094         return err;
 1095 }
 1096 
 1097 int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
 1098 {
 1099         u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
 1100         u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
 1101         int err;
 1102 
 1103         MLX5_SET(qpts_reg, in, local_port, 1);
 1104 
 1105         err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
 1106                                    sizeof(out), MLX5_REG_QPTS, 0, 0);
 1107         if (!err)
 1108                 *trust_state = MLX5_GET(qpts_reg, out, trust_state);
 1109 
 1110         return err;
 1111 }
 1112 
 1113 int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio)
 1114 {
 1115         int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
 1116         void *qpdpm_dscp;
 1117         void *out;
 1118         void *in;
 1119         int err;
 1120         int i;
 1121 
 1122         in = kzalloc(sz, GFP_KERNEL);
 1123         out = kzalloc(sz, GFP_KERNEL);
 1124         if (!in || !out) {
 1125                 err = -ENOMEM;
 1126                 goto out;
 1127         }
 1128 
 1129         MLX5_SET(qpdpm_reg, in, local_port, 1);
 1130         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
 1131         if (err)
 1132                 goto out;
 1133 
 1134         memcpy(in, out, sz);
 1135         MLX5_SET(qpdpm_reg, in, local_port, 1);
 1136 
 1137         /* Update the corresponding dscp entry */
 1138         for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
 1139                 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[i]);
 1140                 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, dscp2prio[i]);
 1141                 MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
 1142         }
 1143         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
 1144 out:
 1145         kfree(in);
 1146         kfree(out);
 1147         return err;
 1148 }
 1149 
 1150 int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
 1151 {
 1152         int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
 1153         void *qpdpm_dscp;
 1154         void *out;
 1155         void *in;
 1156         int err;
 1157         int i;
 1158 
 1159         in = kzalloc(sz, GFP_KERNEL);
 1160         out = kzalloc(sz, GFP_KERNEL);
 1161         if (!in || !out) {
 1162                 err = -ENOMEM;
 1163                 goto out;
 1164         }
 1165 
 1166         MLX5_SET(qpdpm_reg, in, local_port, 1);
 1167         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
 1168         if (err)
 1169                 goto out;
 1170 
 1171         for (i = 0; i < MLX5_MAX_SUPPORTED_DSCP; i++) {
 1172                 qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
 1173                 dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
 1174         }
 1175 out:
 1176         kfree(in);
 1177         kfree(out);
 1178         return err;
 1179 }
 1180 
 1181 static int mlx5_query_pddr(struct mlx5_core_dev *mdev,
 1182     u8 local_port, int page_select, u32 *out, int outlen)
 1183 {
 1184         u32 in[MLX5_ST_SZ_DW(pddr_reg)] = {0};
 1185 
 1186         if (!MLX5_CAP_PCAM_REG(mdev, pddr))
 1187                 return -EOPNOTSUPP;
 1188 
 1189         MLX5_SET(pddr_reg, in, local_port, local_port);
 1190         MLX5_SET(pddr_reg, in, page_select, page_select);
 1191 
 1192         return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen, MLX5_REG_PDDR, 0, 0);
 1193 }
 1194 
 1195 int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type)
 1196 {
 1197         u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
 1198         int error;
 1199         u8 ecc;
 1200         u8 ci;
 1201 
 1202         error = mlx5_query_pddr(mdev, local_port, MLX5_PDDR_MODULE_INFO_PAGE,
 1203             pddr_reg, sizeof(pddr_reg));
 1204         if (error != 0)
 1205                 return (error);
 1206 
 1207         ecc = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.ethernet_compliance_code);
 1208         ci = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_identifier);
 1209 
 1210         switch (ci) {
 1211         case 0: /* QSFP28 */
 1212         case 1: /* QSFP+ */
 1213                 *is_er_type = 0;
 1214                 break;
 1215         case 2: /* SFP28/SFP+ */
 1216         case 3: /* QSA (QSFP->SFP) */
 1217                 *is_er_type = ((ecc & (1 << 7)) != 0);
 1218                 break;
 1219         default:
 1220                 *is_er_type = 0;
 1221                 break;
 1222         }
 1223         return (0);
 1224 }
 1225 EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info);
 1226 
 1227 int mlx5_query_pddr_cable_type(struct mlx5_core_dev *mdev, u8 local_port, u8 *cable_type)
 1228 {
 1229         u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
 1230         int error;
 1231 
 1232         error = mlx5_query_pddr(mdev, local_port, MLX5_PDDR_MODULE_INFO_PAGE,
 1233             pddr_reg, sizeof(pddr_reg));
 1234         if (error != 0)
 1235                 return (error);
 1236 
 1237         *cable_type = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_type);
 1238         return (0);
 1239 }
 1240 EXPORT_SYMBOL_GPL(mlx5_query_pddr_cable_type);
 1241 
 1242 int mlx5_query_pddr_troubleshooting_info(struct mlx5_core_dev *mdev,
 1243     u16 *monitor_opcode, u8 *status_message, size_t sm_len)
 1244 {
 1245         int outlen = MLX5_ST_SZ_BYTES(pddr_reg);
 1246         u32 out[MLX5_ST_SZ_DW(pddr_reg)] = {0};
 1247         int err;
 1248 
 1249         err = mlx5_query_pddr(mdev, MLX5_PDDR_TROUBLESHOOTING_INFO_PAGE, 1,
 1250             out, outlen);
 1251         if (err != 0)
 1252                 return err;
 1253         if (monitor_opcode != NULL) {
 1254                 *monitor_opcode = MLX5_GET(pddr_reg, out,
 1255                     page_data.troubleshooting_info_page.status_opcode.
 1256                     monitor_opcodes);
 1257         }
 1258         if (status_message != NULL) {
 1259                 strlcpy(status_message,
 1260                     MLX5_ADDR_OF(pddr_reg, out,
 1261                     page_data.troubleshooting_info_page.status_message),
 1262                     sm_len);
 1263         }
 1264         return (0);
 1265 }
 1266 
 1267 int
 1268 mlx5_query_mfrl_reg(struct mlx5_core_dev *mdev, u8 *reset_level)
 1269 {
 1270         u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
 1271         int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
 1272         int err;
 1273 
 1274         err = mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
 1275             0, 0);
 1276         if (err == 0)
 1277                 *reset_level = MLX5_GET(mfrl_reg, mfrl, reset_level);
 1278         return (err);
 1279 }
 1280 
 1281 int
 1282 mlx5_set_mfrl_reg(struct mlx5_core_dev *mdev, u8 reset_level)
 1283 {
 1284         u32 mfrl[MLX5_ST_SZ_DW(mfrl_reg)] = {};
 1285         int sz = MLX5_ST_SZ_BYTES(mfrl_reg);
 1286 
 1287         MLX5_SET(mfrl_reg, mfrl, reset_level, reset_level);
 1288 
 1289         return (mlx5_core_access_reg(mdev, mfrl, sz, mfrl, sz, MLX5_REG_MFRL,
 1290             0, 1));
 1291 }
 1292 
 1293 /* speed in units of 1Mb */
 1294 static const u32 mlx5e_link_speed[/*MLX5E_LINK_MODES_NUMBER*/] = {
 1295         [MLX5E_1000BASE_CX_SGMII] = 1000,
 1296         [MLX5E_1000BASE_KX]       = 1000,
 1297         [MLX5E_10GBASE_CX4]       = 10000,
 1298         [MLX5E_10GBASE_KX4]       = 10000,
 1299         [MLX5E_10GBASE_KR]        = 10000,
 1300         [MLX5E_20GBASE_KR2]       = 20000,
 1301         [MLX5E_40GBASE_CR4]       = 40000,
 1302         [MLX5E_40GBASE_KR4]       = 40000,
 1303         [MLX5E_56GBASE_R4]        = 56000,
 1304         [MLX5E_10GBASE_CR]        = 10000,
 1305         [MLX5E_10GBASE_SR]        = 10000,
 1306         [MLX5E_10GBASE_ER_LR]     = 10000,
 1307         [MLX5E_40GBASE_SR4]       = 40000,
 1308         [MLX5E_40GBASE_LR4_ER4]   = 40000,
 1309         [MLX5E_50GBASE_SR2]       = 50000,
 1310         [MLX5E_100GBASE_CR4]      = 100000,
 1311         [MLX5E_100GBASE_SR4]      = 100000,
 1312         [MLX5E_100GBASE_KR4]      = 100000,
 1313         [MLX5E_100GBASE_LR4]      = 100000,
 1314         [MLX5E_100BASE_TX]        = 100,
 1315         [MLX5E_1000BASE_T]        = 1000,
 1316         [MLX5E_10GBASE_T]         = 10000,
 1317         [MLX5E_25GBASE_CR]        = 25000,
 1318         [MLX5E_25GBASE_KR]        = 25000,
 1319         [MLX5E_25GBASE_SR]        = 25000,
 1320         [MLX5E_50GBASE_CR2]       = 50000,
 1321         [MLX5E_50GBASE_KR2]       = 50000,
 1322 };
 1323 
 1324 static const u32 mlx5e_ext_link_speed[/*MLX5E_EXT_LINK_MODES_NUMBER*/] = {
 1325         [MLX5E_SGMII_100M]                      = 100,
 1326         [MLX5E_1000BASE_X_SGMII]                = 1000,
 1327         [MLX5E_5GBASE_R]                        = 5000,
 1328         [MLX5E_10GBASE_XFI_XAUI_1]              = 10000,
 1329         [MLX5E_40GBASE_XLAUI_4_XLPPI_4]         = 40000,
 1330         [MLX5E_25GAUI_1_25GBASE_CR_KR]          = 25000,
 1331         [MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000,
 1332         [MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR]   = 50000,
 1333         [MLX5E_CAUI_4_100GBASE_CR4_KR4]         = 100000,
 1334         [MLX5E_200GAUI_4_200GBASE_CR4_KR4]      = 200000,
 1335         [MLX5E_400GAUI_8]                       = 400000,
 1336 };
 1337 
 1338 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
 1339                                      const u32 **arr, u32 *size)
 1340 {
 1341         bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 1342 
 1343         *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
 1344                       ARRAY_SIZE(mlx5e_link_speed);
 1345         *arr  = ext ? mlx5e_ext_link_speed : mlx5e_link_speed;
 1346 }
 1347 
 1348 u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
 1349 {
 1350         unsigned long temp = eth_proto_oper;
 1351         const u32 *table;
 1352         u32 speed = 0;
 1353         u32 max_size;
 1354         int i;
 1355 
 1356         mlx5e_port_get_speed_arr(mdev, &table, &max_size);
 1357         i = find_first_bit(&temp, max_size);
 1358         if (i < max_size)
 1359                 speed = table[i];
 1360         return speed;
 1361 }
 1362 
 1363 int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
 1364                               struct mlx5e_port_eth_proto *eproto)
 1365 {
 1366         u32 out[MLX5_ST_SZ_DW(ptys_reg)];
 1367         int err;
 1368 
 1369         if (!eproto)
 1370                 return -EINVAL;
 1371 
 1372         err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
 1373         if (err)
 1374                 return err;
 1375 
 1376         eproto->cap   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
 1377                                            eth_proto_capability);
 1378         eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin);
 1379         eproto->oper  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
 1380         return 0;
 1381 }
 1382 
 1383 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
 1384 {
 1385         struct mlx5e_port_eth_proto eproto;
 1386         bool ext;
 1387         int err;
 1388 
 1389         ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 1390         err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
 1391         if (err)
 1392                 goto out;
 1393 
 1394         *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
 1395         if (!(*speed))
 1396                 err = -EINVAL;
 1397 
 1398 out:
 1399         return err;
 1400 }
 1401 
 1402 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
 1403 {
 1404         int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
 1405         void *in;
 1406         int err;
 1407 
 1408         in = kzalloc(sz, GFP_KERNEL);
 1409         if (!in)
 1410                 return -ENOMEM;
 1411 
 1412         MLX5_SET(pbmc_reg, in, local_port, 1);
 1413         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0);
 1414 
 1415         kfree(in);
 1416         return err;
 1417 }
 1418 
 1419 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
 1420 {
 1421         int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
 1422         void *out;
 1423         int err;
 1424 
 1425         out = kzalloc(sz, GFP_KERNEL);
 1426         if (!out)
 1427                 return -ENOMEM;
 1428 
 1429         MLX5_SET(pbmc_reg, in, local_port, 1);
 1430         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1);
 1431 
 1432         kfree(out);
 1433         return err;
 1434 }
 1435 
 1436 /* buffer[i]: buffer that priority i mapped to */
 1437 int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
 1438 {
 1439         int sz = MLX5_ST_SZ_BYTES(pptb_reg);
 1440         u32 prio_x_buff;
 1441         void *out;
 1442         void *in;
 1443         int prio;
 1444         int err;
 1445 
 1446         in = kzalloc(sz, GFP_KERNEL);
 1447         out = kzalloc(sz, GFP_KERNEL);
 1448         if (!in || !out) {
 1449                 err = -ENOMEM;
 1450                 goto out;
 1451         }
 1452 
 1453         MLX5_SET(pptb_reg, in, local_port, 1);
 1454         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
 1455         if (err)
 1456                 goto out;
 1457 
 1458         prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff);
 1459         for (prio = 0; prio < 8; prio++) {
 1460                 buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF;
 1461                 mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]);
 1462         }
 1463 out:
 1464         kfree(in);
 1465         kfree(out);
 1466         return err;
 1467 }
 1468 
 1469 int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
 1470 {
 1471         int sz = MLX5_ST_SZ_BYTES(pptb_reg);
 1472         u32 prio_x_buff;
 1473         void *out;
 1474         void *in;
 1475         int prio;
 1476         int err;
 1477 
 1478         in = kzalloc(sz, GFP_KERNEL);
 1479         out = kzalloc(sz, GFP_KERNEL);
 1480         if (!in || !out) {
 1481                 err = -ENOMEM;
 1482                 goto out;
 1483         }
 1484 
 1485         /* First query the pptb register */
 1486         MLX5_SET(pptb_reg, in, local_port, 1);
 1487         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
 1488         if (err)
 1489                 goto out;
 1490 
 1491         memcpy(in, out, sz);
 1492         MLX5_SET(pptb_reg, in, local_port, 1);
 1493 
 1494         /* Update the pm and prio_x_buff */
 1495         MLX5_SET(pptb_reg, in, pm, 0xFF);
 1496 
 1497         prio_x_buff = 0;
 1498         for (prio = 0; prio < 8; prio++)
 1499                 prio_x_buff |= (buffer[prio] << (4 * prio));
 1500         MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff);
 1501 
 1502         err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);
 1503 
 1504 out:
 1505         kfree(in);
 1506         kfree(out);
 1507         return err;
 1508 }

Cache object: 806cad53a0f7a491b3cbcb6f373d3847


[ 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.