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_ib/mlx5_ib_mad.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-2015, 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 <dev/mlx5/vport.h>
   32 #include <rdma/ib_mad.h>
   33 #include <rdma/ib_smi.h>
   34 #include <rdma/ib_pma.h>
   35 #include <dev/mlx5/mlx5_ib/mlx5_ib.h>
   36 
   37 enum {
   38         MLX5_IB_VENDOR_CLASS1 = 0x9,
   39         MLX5_IB_VENDOR_CLASS2 = 0xa
   40 };
   41 
   42 int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
   43                  u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
   44                  const void *in_mad, void *response_mad)
   45 {
   46         u8 op_modifier = 0;
   47 
   48         /* Key check traps can't be generated unless we have in_wc to
   49          * tell us where to send the trap.
   50          */
   51         if (ignore_mkey || !in_wc)
   52                 op_modifier |= 0x1;
   53         if (ignore_bkey || !in_wc)
   54                 op_modifier |= 0x2;
   55 
   56         return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port);
   57 }
   58 
   59 static int process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
   60                        const struct ib_wc *in_wc, const struct ib_grh *in_grh,
   61                        const struct ib_mad *in_mad, struct ib_mad *out_mad)
   62 {
   63         u16 slid;
   64         int err;
   65 
   66         slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
   67 
   68         if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0)
   69                 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
   70 
   71         if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||
   72             in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
   73                 if (in_mad->mad_hdr.method   != IB_MGMT_METHOD_GET &&
   74                     in_mad->mad_hdr.method   != IB_MGMT_METHOD_SET &&
   75                     in_mad->mad_hdr.method   != IB_MGMT_METHOD_TRAP_REPRESS)
   76                         return IB_MAD_RESULT_SUCCESS;
   77 
   78                 /* Don't process SMInfo queries -- the SMA can't handle them.
   79                  */
   80                 if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
   81                         return IB_MAD_RESULT_SUCCESS;
   82         } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
   83                    in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS1   ||
   84                    in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS2   ||
   85                    in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_CONG_MGMT) {
   86                 if (in_mad->mad_hdr.method  != IB_MGMT_METHOD_GET &&
   87                     in_mad->mad_hdr.method  != IB_MGMT_METHOD_SET)
   88                         return IB_MAD_RESULT_SUCCESS;
   89         } else {
   90                 return IB_MAD_RESULT_SUCCESS;
   91         }
   92 
   93         err = mlx5_MAD_IFC(to_mdev(ibdev),
   94                            mad_flags & IB_MAD_IGNORE_MKEY,
   95                            mad_flags & IB_MAD_IGNORE_BKEY,
   96                            port_num, in_wc, in_grh, in_mad, out_mad);
   97         if (err)
   98                 return IB_MAD_RESULT_FAILURE;
   99 
  100         /* set return bit in status of directed route responses */
  101         if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
  102                 out_mad->mad_hdr.status |= cpu_to_be16(1 << 15);
  103 
  104         if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS)
  105                 /* no response for trap repress */
  106                 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
  107 
  108         return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
  109 }
  110 
  111 static void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext,
  112                                void *out)
  113 {
  114 #define MLX5_SUM_CNT(p, cntr1, cntr2)   \
  115         (MLX5_GET64(query_vport_counter_out, p, cntr1) + \
  116         MLX5_GET64(query_vport_counter_out, p, cntr2))
  117 
  118         pma_cnt_ext->port_xmit_data =
  119                 cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets,
  120                                          transmitted_ib_multicast.octets) >> 2);
  121         pma_cnt_ext->port_rcv_data =
  122                 cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets,
  123                                          received_ib_multicast.octets) >> 2);
  124         pma_cnt_ext->port_xmit_packets =
  125                 cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.packets,
  126                                          transmitted_ib_multicast.packets));
  127         pma_cnt_ext->port_rcv_packets =
  128                 cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.packets,
  129                                          received_ib_multicast.packets));
  130         pma_cnt_ext->port_unicast_xmit_packets =
  131                 MLX5_GET64_BE(query_vport_counter_out,
  132                               out, transmitted_ib_unicast.packets);
  133         pma_cnt_ext->port_unicast_rcv_packets =
  134                 MLX5_GET64_BE(query_vport_counter_out,
  135                               out, received_ib_unicast.packets);
  136         pma_cnt_ext->port_multicast_xmit_packets =
  137                 MLX5_GET64_BE(query_vport_counter_out,
  138                               out, transmitted_ib_multicast.packets);
  139         pma_cnt_ext->port_multicast_rcv_packets =
  140                 MLX5_GET64_BE(query_vport_counter_out,
  141                               out, received_ib_multicast.packets);
  142 }
  143 
  144 static void pma_cnt_assign(struct ib_pma_portcounters *pma_cnt,
  145                            void *out)
  146 {
  147         /* Traffic counters will be reported in
  148          * their 64bit form via ib_pma_portcounters_ext by default.
  149          */
  150         void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out,
  151                                      counter_set);
  152 
  153 #define MLX5_ASSIGN_PMA_CNTR(counter_var, counter_name) {               \
  154         counter_var = MLX5_GET_BE(typeof(counter_var),                  \
  155                                   ib_port_cntrs_grp_data_layout,        \
  156                                   out_pma, counter_name);               \
  157         }
  158 
  159         MLX5_ASSIGN_PMA_CNTR(pma_cnt->symbol_error_counter,
  160                              symbol_error_counter);
  161         MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_error_recovery_counter,
  162                              link_error_recovery_counter);
  163         MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_downed_counter,
  164                              link_downed_counter);
  165         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_errors,
  166                              port_rcv_errors);
  167         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_remphys_errors,
  168                              port_rcv_remote_physical_errors);
  169         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_switch_relay_errors,
  170                              port_rcv_switch_relay_errors);
  171         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_discards,
  172                              port_xmit_discards);
  173         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_constraint_errors,
  174                              port_xmit_constraint_errors);
  175         MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_constraint_errors,
  176                              port_rcv_constraint_errors);
  177         MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_overrun_errors,
  178                              link_overrun_errors);
  179         MLX5_ASSIGN_PMA_CNTR(pma_cnt->vl15_dropped,
  180                              vl_15_dropped);
  181 }
  182 
  183 static int process_pma_cmd(struct ib_device *ibdev, u8 port_num,
  184                            const struct ib_mad *in_mad, struct ib_mad *out_mad)
  185 {
  186         struct mlx5_ib_dev *dev = to_mdev(ibdev);
  187         int err;
  188         void *out_cnt;
  189 
  190         /* Decalring support of extended counters */
  191         if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
  192                 struct ib_class_port_info cpi = {};
  193 
  194                 cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
  195                 memcpy((out_mad->data + 40), &cpi, sizeof(cpi));
  196                 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
  197         }
  198 
  199         if (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT) {
  200                 struct ib_pma_portcounters_ext *pma_cnt_ext =
  201                         (struct ib_pma_portcounters_ext *)(out_mad->data + 40);
  202                 int sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
  203 
  204                 out_cnt = mlx5_vzalloc(sz);
  205                 if (!out_cnt)
  206                         return IB_MAD_RESULT_FAILURE;
  207 
  208                 err = mlx5_core_query_vport_counter(dev->mdev, 0, 0,
  209                                                     port_num, out_cnt, sz);
  210                 if (!err)
  211                         pma_cnt_ext_assign(pma_cnt_ext, out_cnt);
  212         } else {
  213                 struct ib_pma_portcounters *pma_cnt =
  214                         (struct ib_pma_portcounters *)(out_mad->data + 40);
  215                 int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
  216 
  217                 out_cnt = mlx5_vzalloc(sz);
  218                 if (!out_cnt)
  219                         return IB_MAD_RESULT_FAILURE;
  220 
  221                 err = mlx5_core_query_ib_ppcnt(dev->mdev, port_num,
  222                                                out_cnt, sz);
  223                 if (!err)
  224                         pma_cnt_assign(pma_cnt, out_cnt);
  225                 }
  226 
  227         kvfree(out_cnt);
  228         if (err)
  229                 return IB_MAD_RESULT_FAILURE;
  230 
  231         return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
  232 }
  233 
  234 int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
  235                         const struct ib_wc *in_wc, const struct ib_grh *in_grh,
  236                         const struct ib_mad_hdr *in, size_t in_mad_size,
  237                         struct ib_mad_hdr *out, size_t *out_mad_size,
  238                         u16 *out_mad_pkey_index)
  239 {
  240         struct mlx5_ib_dev *dev = to_mdev(ibdev);
  241         struct mlx5_core_dev *mdev = dev->mdev;
  242         const struct ib_mad *in_mad = (const struct ib_mad *)in;
  243         struct ib_mad *out_mad = (struct ib_mad *)out;
  244 
  245         if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
  246                          *out_mad_size != sizeof(*out_mad)))
  247                 return IB_MAD_RESULT_FAILURE;
  248 
  249         memset(out_mad->data, 0, sizeof(out_mad->data));
  250 
  251         if (MLX5_CAP_GEN(mdev, vport_counters) &&
  252             in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT &&
  253             in_mad->mad_hdr.method == IB_MGMT_METHOD_GET) {
  254                 return process_pma_cmd(ibdev, port_num, in_mad, out_mad);
  255         } else {
  256                 return process_mad(ibdev, mad_flags, port_num, in_wc, in_grh,
  257                                    in_mad, out_mad);
  258         }
  259 }
  260 
  261 int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port)
  262 {
  263         struct ib_smp *in_mad  = NULL;
  264         struct ib_smp *out_mad = NULL;
  265         int err = -ENOMEM;
  266         u16 packet_error;
  267 
  268         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  269         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  270         if (!in_mad || !out_mad)
  271                 goto out;
  272 
  273         init_query_mad(in_mad);
  274         in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
  275         in_mad->attr_mod = cpu_to_be32(port);
  276 
  277         err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
  278 
  279         packet_error = be16_to_cpu(out_mad->status);
  280 
  281         dev->mdev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ?
  282                 MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
  283 
  284 out:
  285         kfree(in_mad);
  286         kfree(out_mad);
  287         return err;
  288 }
  289 
  290 int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev,
  291                                           struct ib_smp *out_mad)
  292 {
  293         struct ib_smp *in_mad = NULL;
  294         int err = -ENOMEM;
  295 
  296         in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  297         if (!in_mad)
  298                 return -ENOMEM;
  299 
  300         init_query_mad(in_mad);
  301         in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
  302 
  303         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad,
  304                            out_mad);
  305 
  306         kfree(in_mad);
  307         return err;
  308 }
  309 
  310 int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev,
  311                                          __be64 *sys_image_guid)
  312 {
  313         struct ib_smp *out_mad = NULL;
  314         int err = -ENOMEM;
  315 
  316         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  317         if (!out_mad)
  318                 return -ENOMEM;
  319 
  320         err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
  321         if (err)
  322                 goto out;
  323 
  324         memcpy(sys_image_guid, out_mad->data + 4, 8);
  325 
  326 out:
  327         kfree(out_mad);
  328 
  329         return err;
  330 }
  331 
  332 int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev,
  333                                  u16 *max_pkeys)
  334 {
  335         struct ib_smp *out_mad = NULL;
  336         int err = -ENOMEM;
  337 
  338         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  339         if (!out_mad)
  340                 return -ENOMEM;
  341 
  342         err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
  343         if (err)
  344                 goto out;
  345 
  346         *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28));
  347 
  348 out:
  349         kfree(out_mad);
  350 
  351         return err;
  352 }
  353 
  354 int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev,
  355                                  u32 *vendor_id)
  356 {
  357         struct ib_smp *out_mad = NULL;
  358         int err = -ENOMEM;
  359 
  360         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  361         if (!out_mad)
  362                 return -ENOMEM;
  363 
  364         err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
  365         if (err)
  366                 goto out;
  367 
  368         *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff;
  369 
  370 out:
  371         kfree(out_mad);
  372 
  373         return err;
  374 }
  375 
  376 int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
  377 {
  378         struct ib_smp *in_mad  = NULL;
  379         struct ib_smp *out_mad = NULL;
  380         int err = -ENOMEM;
  381 
  382         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  383         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  384         if (!in_mad || !out_mad)
  385                 goto out;
  386 
  387         init_query_mad(in_mad);
  388         in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
  389 
  390         err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
  391         if (err)
  392                 goto out;
  393 
  394         memcpy(node_desc, out_mad->data, IB_DEVICE_NODE_DESC_MAX);
  395 out:
  396         kfree(in_mad);
  397         kfree(out_mad);
  398         return err;
  399 }
  400 
  401 int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid)
  402 {
  403         struct ib_smp *in_mad  = NULL;
  404         struct ib_smp *out_mad = NULL;
  405         int err = -ENOMEM;
  406 
  407         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  408         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  409         if (!in_mad || !out_mad)
  410                 goto out;
  411 
  412         init_query_mad(in_mad);
  413         in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
  414 
  415         err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
  416         if (err)
  417                 goto out;
  418 
  419         memcpy(node_guid, out_mad->data + 12, 8);
  420 out:
  421         kfree(in_mad);
  422         kfree(out_mad);
  423         return err;
  424 }
  425 
  426 int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index,
  427                             u16 *pkey)
  428 {
  429         struct ib_smp *in_mad  = NULL;
  430         struct ib_smp *out_mad = NULL;
  431         int err = -ENOMEM;
  432 
  433         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  434         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  435         if (!in_mad || !out_mad)
  436                 goto out;
  437 
  438         init_query_mad(in_mad);
  439         in_mad->attr_id  = IB_SMP_ATTR_PKEY_TABLE;
  440         in_mad->attr_mod = cpu_to_be32(index / 32);
  441 
  442         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
  443                            out_mad);
  444         if (err)
  445                 goto out;
  446 
  447         *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]);
  448 
  449 out:
  450         kfree(in_mad);
  451         kfree(out_mad);
  452         return err;
  453 }
  454 
  455 int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index,
  456                             union ib_gid *gid)
  457 {
  458         struct ib_smp *in_mad  = NULL;
  459         struct ib_smp *out_mad = NULL;
  460         int err = -ENOMEM;
  461 
  462         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  463         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  464         if (!in_mad || !out_mad)
  465                 goto out;
  466 
  467         init_query_mad(in_mad);
  468         in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
  469         in_mad->attr_mod = cpu_to_be32(port);
  470 
  471         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
  472                            out_mad);
  473         if (err)
  474                 goto out;
  475 
  476         memcpy(gid->raw, out_mad->data + 8, 8);
  477 
  478         init_query_mad(in_mad);
  479         in_mad->attr_id  = IB_SMP_ATTR_GUID_INFO;
  480         in_mad->attr_mod = cpu_to_be32(index / 8);
  481 
  482         err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
  483                            out_mad);
  484         if (err)
  485                 goto out;
  486 
  487         memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
  488 
  489 out:
  490         kfree(in_mad);
  491         kfree(out_mad);
  492         return err;
  493 }
  494 
  495 int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port,
  496                             struct ib_port_attr *props)
  497 {
  498         struct mlx5_ib_dev *dev = to_mdev(ibdev);
  499         struct mlx5_core_dev *mdev = dev->mdev;
  500         struct ib_smp *in_mad  = NULL;
  501         struct ib_smp *out_mad = NULL;
  502         int ext_active_speed;
  503         int err = -ENOMEM;
  504 
  505         if (port < 1 || port > MLX5_CAP_GEN(mdev, num_ports)) {
  506                 mlx5_ib_warn(dev, "invalid port number %d\n", port);
  507                 return -EINVAL;
  508         }
  509 
  510         in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
  511         out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
  512         if (!in_mad || !out_mad)
  513                 goto out;
  514 
  515         memset(props, 0, sizeof(*props));
  516 
  517         init_query_mad(in_mad);
  518         in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
  519         in_mad->attr_mod = cpu_to_be32(port);
  520 
  521         err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad);
  522         if (err) {
  523                 mlx5_ib_warn(dev, "err %d\n", err);
  524                 goto out;
  525         }
  526 
  527         props->lid              = be16_to_cpup((__be16 *)(out_mad->data + 16));
  528         props->lmc              = out_mad->data[34] & 0x7;
  529         props->sm_lid           = be16_to_cpup((__be16 *)(out_mad->data + 18));
  530         props->sm_sl            = out_mad->data[36] & 0xf;
  531         props->state            = out_mad->data[32] & 0xf;
  532         props->phys_state       = out_mad->data[33] >> 4;
  533         props->port_cap_flags   = be32_to_cpup((__be32 *)(out_mad->data + 20));
  534         props->gid_tbl_len      = out_mad->data[50];
  535         props->max_msg_sz       = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
  536         props->pkey_tbl_len     = mdev->port_caps[port - 1].pkey_table_len;
  537         props->bad_pkey_cntr    = be16_to_cpup((__be16 *)(out_mad->data + 46));
  538         props->qkey_viol_cntr   = be16_to_cpup((__be16 *)(out_mad->data + 48));
  539         props->active_width     = out_mad->data[31] & 0xf;
  540         props->active_speed     = out_mad->data[35] >> 4;
  541         props->max_mtu          = out_mad->data[41] & 0xf;
  542         props->active_mtu       = out_mad->data[36] >> 4;
  543         props->subnet_timeout   = out_mad->data[51] & 0x1f;
  544         props->max_vl_num       = out_mad->data[37] >> 4;
  545         props->init_type_reply  = out_mad->data[41] >> 4;
  546 
  547         /* Check if extended speeds (EDR/FDR/...) are supported */
  548         if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
  549                 ext_active_speed = out_mad->data[62] >> 4;
  550 
  551                 switch (ext_active_speed) {
  552                 case 1:
  553                         props->active_speed = 16; /* FDR */
  554                         break;
  555                 case 2:
  556                         props->active_speed = 32; /* EDR */
  557                         break;
  558                 }
  559         }
  560 
  561         /* If reported active speed is QDR, check if is FDR-10 */
  562         if (props->active_speed == 4) {
  563                 if (mdev->port_caps[port - 1].ext_port_cap &
  564                     MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
  565                         init_query_mad(in_mad);
  566                         in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
  567                         in_mad->attr_mod = cpu_to_be32(port);
  568 
  569                         err = mlx5_MAD_IFC(dev, 1, 1, port,
  570                                            NULL, NULL, in_mad, out_mad);
  571                         if (err)
  572                                 goto out;
  573 
  574                         /* Checking LinkSpeedActive for FDR-10 */
  575                         if (out_mad->data[15] & 0x1)
  576                                 props->active_speed = 8;
  577                 }
  578         }
  579 
  580 out:
  581         kfree(in_mad);
  582         kfree(out_mad);
  583 
  584         return err;
  585 }

Cache object: b8ff06578395033b87f21eaedf841637


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