18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 58c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 68c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 78c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 88c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 118c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 128c2ecf20Sopenharmony_ci * conditions are met: 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 158c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 168c2ecf20Sopenharmony_ci * disclaimer. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 198c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 208c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 218c2ecf20Sopenharmony_ci * provided with the distribution. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 248c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 258c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 268c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 278c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 288c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 298c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 308c2ecf20Sopenharmony_ci * SOFTWARE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <linux/mlx5/vport.h> 348c2ecf20Sopenharmony_ci#include <rdma/ib_mad.h> 358c2ecf20Sopenharmony_ci#include <rdma/ib_smi.h> 368c2ecf20Sopenharmony_ci#include <rdma/ib_pma.h> 378c2ecf20Sopenharmony_ci#include "mlx5_ib.h" 388c2ecf20Sopenharmony_ci#include "cmd.h" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cienum { 418c2ecf20Sopenharmony_ci MLX5_IB_VENDOR_CLASS1 = 0x9, 428c2ecf20Sopenharmony_ci MLX5_IB_VENDOR_CLASS2 = 0xa 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u8 port_num, 468c2ecf20Sopenharmony_ci struct ib_mad *in_mad) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED && 498c2ecf20Sopenharmony_ci in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) 508c2ecf20Sopenharmony_ci return true; 518c2ecf20Sopenharmony_ci return dev->mdev->port_caps[port_num - 1].has_smi; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, 558c2ecf20Sopenharmony_ci int ignore_bkey, u8 port, const struct ib_wc *in_wc, 568c2ecf20Sopenharmony_ci const struct ib_grh *in_grh, const void *in_mad, 578c2ecf20Sopenharmony_ci void *response_mad) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci u8 op_modifier = 0; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (!can_do_mad_ifc(dev, port, (struct ib_mad *)in_mad)) 628c2ecf20Sopenharmony_ci return -EPERM; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* Key check traps can't be generated unless we have in_wc to 658c2ecf20Sopenharmony_ci * tell us where to send the trap. 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci if (ignore_mkey || !in_wc) 688c2ecf20Sopenharmony_ci op_modifier |= 0x1; 698c2ecf20Sopenharmony_ci if (ignore_bkey || !in_wc) 708c2ecf20Sopenharmony_ci op_modifier |= 0x2; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return mlx5_cmd_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, 738c2ecf20Sopenharmony_ci port); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext, 778c2ecf20Sopenharmony_ci void *out) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci#define MLX5_SUM_CNT(p, cntr1, cntr2) \ 808c2ecf20Sopenharmony_ci (MLX5_GET64(query_vport_counter_out, p, cntr1) + \ 818c2ecf20Sopenharmony_ci MLX5_GET64(query_vport_counter_out, p, cntr2)) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci pma_cnt_ext->port_xmit_data = 848c2ecf20Sopenharmony_ci cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets, 858c2ecf20Sopenharmony_ci transmitted_ib_multicast.octets) >> 2); 868c2ecf20Sopenharmony_ci pma_cnt_ext->port_rcv_data = 878c2ecf20Sopenharmony_ci cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets, 888c2ecf20Sopenharmony_ci received_ib_multicast.octets) >> 2); 898c2ecf20Sopenharmony_ci pma_cnt_ext->port_xmit_packets = 908c2ecf20Sopenharmony_ci cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.packets, 918c2ecf20Sopenharmony_ci transmitted_ib_multicast.packets)); 928c2ecf20Sopenharmony_ci pma_cnt_ext->port_rcv_packets = 938c2ecf20Sopenharmony_ci cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.packets, 948c2ecf20Sopenharmony_ci received_ib_multicast.packets)); 958c2ecf20Sopenharmony_ci pma_cnt_ext->port_unicast_xmit_packets = 968c2ecf20Sopenharmony_ci MLX5_GET64_BE(query_vport_counter_out, 978c2ecf20Sopenharmony_ci out, transmitted_ib_unicast.packets); 988c2ecf20Sopenharmony_ci pma_cnt_ext->port_unicast_rcv_packets = 998c2ecf20Sopenharmony_ci MLX5_GET64_BE(query_vport_counter_out, 1008c2ecf20Sopenharmony_ci out, received_ib_unicast.packets); 1018c2ecf20Sopenharmony_ci pma_cnt_ext->port_multicast_xmit_packets = 1028c2ecf20Sopenharmony_ci MLX5_GET64_BE(query_vport_counter_out, 1038c2ecf20Sopenharmony_ci out, transmitted_ib_multicast.packets); 1048c2ecf20Sopenharmony_ci pma_cnt_ext->port_multicast_rcv_packets = 1058c2ecf20Sopenharmony_ci MLX5_GET64_BE(query_vport_counter_out, 1068c2ecf20Sopenharmony_ci out, received_ib_multicast.packets); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic void pma_cnt_assign(struct ib_pma_portcounters *pma_cnt, 1108c2ecf20Sopenharmony_ci void *out) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci /* Traffic counters will be reported in 1138c2ecf20Sopenharmony_ci * their 64bit form via ib_pma_portcounters_ext by default. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out, 1168c2ecf20Sopenharmony_ci counter_set); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define MLX5_ASSIGN_PMA_CNTR(counter_var, counter_name) { \ 1198c2ecf20Sopenharmony_ci counter_var = MLX5_GET_BE(typeof(counter_var), \ 1208c2ecf20Sopenharmony_ci ib_port_cntrs_grp_data_layout, \ 1218c2ecf20Sopenharmony_ci out_pma, counter_name); \ 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->symbol_error_counter, 1258c2ecf20Sopenharmony_ci symbol_error_counter); 1268c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_error_recovery_counter, 1278c2ecf20Sopenharmony_ci link_error_recovery_counter); 1288c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_downed_counter, 1298c2ecf20Sopenharmony_ci link_downed_counter); 1308c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_errors, 1318c2ecf20Sopenharmony_ci port_rcv_errors); 1328c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_remphys_errors, 1338c2ecf20Sopenharmony_ci port_rcv_remote_physical_errors); 1348c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_switch_relay_errors, 1358c2ecf20Sopenharmony_ci port_rcv_switch_relay_errors); 1368c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_discards, 1378c2ecf20Sopenharmony_ci port_xmit_discards); 1388c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_constraint_errors, 1398c2ecf20Sopenharmony_ci port_xmit_constraint_errors); 1408c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_wait, 1418c2ecf20Sopenharmony_ci port_xmit_wait); 1428c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_constraint_errors, 1438c2ecf20Sopenharmony_ci port_rcv_constraint_errors); 1448c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_overrun_errors, 1458c2ecf20Sopenharmony_ci link_overrun_errors); 1468c2ecf20Sopenharmony_ci MLX5_ASSIGN_PMA_CNTR(pma_cnt->vl15_dropped, 1478c2ecf20Sopenharmony_ci vl_15_dropped); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic int process_pma_cmd(struct mlx5_ib_dev *dev, u8 port_num, 1518c2ecf20Sopenharmony_ci const struct ib_mad *in_mad, struct ib_mad *out_mad) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct mlx5_core_dev *mdev; 1548c2ecf20Sopenharmony_ci bool native_port = true; 1558c2ecf20Sopenharmony_ci u8 mdev_port_num; 1568c2ecf20Sopenharmony_ci void *out_cnt; 1578c2ecf20Sopenharmony_ci int err; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num); 1608c2ecf20Sopenharmony_ci if (!mdev) { 1618c2ecf20Sopenharmony_ci /* Fail to get the native port, likely due to 2nd port is still 1628c2ecf20Sopenharmony_ci * unaffiliated. In such case default to 1st port and attached 1638c2ecf20Sopenharmony_ci * PF device. 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_ci native_port = false; 1668c2ecf20Sopenharmony_ci mdev = dev->mdev; 1678c2ecf20Sopenharmony_ci mdev_port_num = 1; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) { 1708c2ecf20Sopenharmony_ci /* set local port to one for Function-Per-Port HCA. */ 1718c2ecf20Sopenharmony_ci mdev = dev->mdev; 1728c2ecf20Sopenharmony_ci mdev_port_num = 1; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Declaring support of extended counters */ 1768c2ecf20Sopenharmony_ci if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) { 1778c2ecf20Sopenharmony_ci struct ib_class_port_info cpi = {}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH; 1808c2ecf20Sopenharmony_ci memcpy((out_mad->data + 40), &cpi, sizeof(cpi)); 1818c2ecf20Sopenharmony_ci err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; 1828c2ecf20Sopenharmony_ci goto done; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT) { 1868c2ecf20Sopenharmony_ci struct ib_pma_portcounters_ext *pma_cnt_ext = 1878c2ecf20Sopenharmony_ci (struct ib_pma_portcounters_ext *)(out_mad->data + 40); 1888c2ecf20Sopenharmony_ci int sz = MLX5_ST_SZ_BYTES(query_vport_counter_out); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci out_cnt = kvzalloc(sz, GFP_KERNEL); 1918c2ecf20Sopenharmony_ci if (!out_cnt) { 1928c2ecf20Sopenharmony_ci err = IB_MAD_RESULT_FAILURE; 1938c2ecf20Sopenharmony_ci goto done; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci err = mlx5_core_query_vport_counter(mdev, 0, 0, mdev_port_num, 1978c2ecf20Sopenharmony_ci out_cnt); 1988c2ecf20Sopenharmony_ci if (!err) 1998c2ecf20Sopenharmony_ci pma_cnt_ext_assign(pma_cnt_ext, out_cnt); 2008c2ecf20Sopenharmony_ci } else { 2018c2ecf20Sopenharmony_ci struct ib_pma_portcounters *pma_cnt = 2028c2ecf20Sopenharmony_ci (struct ib_pma_portcounters *)(out_mad->data + 40); 2038c2ecf20Sopenharmony_ci int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci out_cnt = kvzalloc(sz, GFP_KERNEL); 2068c2ecf20Sopenharmony_ci if (!out_cnt) { 2078c2ecf20Sopenharmony_ci err = IB_MAD_RESULT_FAILURE; 2088c2ecf20Sopenharmony_ci goto done; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci err = mlx5_core_query_ib_ppcnt(mdev, mdev_port_num, 2128c2ecf20Sopenharmony_ci out_cnt, sz); 2138c2ecf20Sopenharmony_ci if (!err) 2148c2ecf20Sopenharmony_ci pma_cnt_assign(pma_cnt, out_cnt); 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci kvfree(out_cnt); 2178c2ecf20Sopenharmony_ci err = err ? IB_MAD_RESULT_FAILURE : 2188c2ecf20Sopenharmony_ci IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; 2198c2ecf20Sopenharmony_cidone: 2208c2ecf20Sopenharmony_ci if (native_port) 2218c2ecf20Sopenharmony_ci mlx5_ib_put_native_port_mdev(dev, port_num); 2228c2ecf20Sopenharmony_ci return err; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ciint mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, 2268c2ecf20Sopenharmony_ci const struct ib_wc *in_wc, const struct ib_grh *in_grh, 2278c2ecf20Sopenharmony_ci const struct ib_mad *in, struct ib_mad *out, 2288c2ecf20Sopenharmony_ci size_t *out_mad_size, u16 *out_mad_pkey_index) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct mlx5_ib_dev *dev = to_mdev(ibdev); 2318c2ecf20Sopenharmony_ci u8 mgmt_class = in->mad_hdr.mgmt_class; 2328c2ecf20Sopenharmony_ci u8 method = in->mad_hdr.method; 2338c2ecf20Sopenharmony_ci u16 slid; 2348c2ecf20Sopenharmony_ci int err; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci slid = in_wc ? ib_lid_cpu16(in_wc->slid) : 2378c2ecf20Sopenharmony_ci be16_to_cpu(IB_LID_PERMISSIVE); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (method == IB_MGMT_METHOD_TRAP && !slid) 2408c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci switch (mgmt_class) { 2438c2ecf20Sopenharmony_ci case IB_MGMT_CLASS_SUBN_LID_ROUTED: 2448c2ecf20Sopenharmony_ci case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: { 2458c2ecf20Sopenharmony_ci if (method != IB_MGMT_METHOD_GET && 2468c2ecf20Sopenharmony_ci method != IB_MGMT_METHOD_SET && 2478c2ecf20Sopenharmony_ci method != IB_MGMT_METHOD_TRAP_REPRESS) 2488c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Don't process SMInfo queries -- the SMA can't handle them. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci if (in->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO) 2538c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS; 2548c2ecf20Sopenharmony_ci } break; 2558c2ecf20Sopenharmony_ci case IB_MGMT_CLASS_PERF_MGMT: 2568c2ecf20Sopenharmony_ci if (MLX5_CAP_GEN(dev->mdev, vport_counters) && 2578c2ecf20Sopenharmony_ci method == IB_MGMT_METHOD_GET) 2588c2ecf20Sopenharmony_ci return process_pma_cmd(dev, port_num, in, out); 2598c2ecf20Sopenharmony_ci fallthrough; 2608c2ecf20Sopenharmony_ci case MLX5_IB_VENDOR_CLASS1: 2618c2ecf20Sopenharmony_ci case MLX5_IB_VENDOR_CLASS2: 2628c2ecf20Sopenharmony_ci case IB_MGMT_CLASS_CONG_MGMT: { 2638c2ecf20Sopenharmony_ci if (method != IB_MGMT_METHOD_GET && 2648c2ecf20Sopenharmony_ci method != IB_MGMT_METHOD_SET) 2658c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS; 2668c2ecf20Sopenharmony_ci } break; 2678c2ecf20Sopenharmony_ci default: 2688c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(to_mdev(ibdev), mad_flags & IB_MAD_IGNORE_MKEY, 2728c2ecf20Sopenharmony_ci mad_flags & IB_MAD_IGNORE_BKEY, port_num, in_wc, 2738c2ecf20Sopenharmony_ci in_grh, in, out); 2748c2ecf20Sopenharmony_ci if (err) 2758c2ecf20Sopenharmony_ci return IB_MAD_RESULT_FAILURE; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* set return bit in status of directed route responses */ 2788c2ecf20Sopenharmony_ci if (mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) 2798c2ecf20Sopenharmony_ci out->mad_hdr.status |= cpu_to_be16(1 << 15); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (method == IB_MGMT_METHOD_TRAP_REPRESS) 2828c2ecf20Sopenharmony_ci /* no response for trap repress */ 2838c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ciint mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 2918c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 2928c2ecf20Sopenharmony_ci int err = -ENOMEM; 2938c2ecf20Sopenharmony_ci u16 packet_error; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 2968c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 2978c2ecf20Sopenharmony_ci if (!in_mad || !out_mad) 2988c2ecf20Sopenharmony_ci goto out; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci init_query_mad(in_mad); 3018c2ecf20Sopenharmony_ci in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; 3028c2ecf20Sopenharmony_ci in_mad->attr_mod = cpu_to_be32(port); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci packet_error = be16_to_cpu(out_mad->status); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci dev->mdev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ? 3098c2ecf20Sopenharmony_ci MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ciout: 3128c2ecf20Sopenharmony_ci kfree(in_mad); 3138c2ecf20Sopenharmony_ci kfree(out_mad); 3148c2ecf20Sopenharmony_ci return err; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev, 3188c2ecf20Sopenharmony_ci struct ib_smp *out_mad) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 3218c2ecf20Sopenharmony_ci int err = -ENOMEM; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 3248c2ecf20Sopenharmony_ci if (!in_mad) 3258c2ecf20Sopenharmony_ci return -ENOMEM; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci init_query_mad(in_mad); 3288c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, 3318c2ecf20Sopenharmony_ci out_mad); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci kfree(in_mad); 3348c2ecf20Sopenharmony_ci return err; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev, 3388c2ecf20Sopenharmony_ci __be64 *sys_image_guid) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 3418c2ecf20Sopenharmony_ci int err = -ENOMEM; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 3448c2ecf20Sopenharmony_ci if (!out_mad) 3458c2ecf20Sopenharmony_ci return -ENOMEM; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); 3488c2ecf20Sopenharmony_ci if (err) 3498c2ecf20Sopenharmony_ci goto out; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci memcpy(sys_image_guid, out_mad->data + 4, 8); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ciout: 3548c2ecf20Sopenharmony_ci kfree(out_mad); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return err; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev, 3608c2ecf20Sopenharmony_ci u16 *max_pkeys) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 3638c2ecf20Sopenharmony_ci int err = -ENOMEM; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 3668c2ecf20Sopenharmony_ci if (!out_mad) 3678c2ecf20Sopenharmony_ci return -ENOMEM; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); 3708c2ecf20Sopenharmony_ci if (err) 3718c2ecf20Sopenharmony_ci goto out; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28)); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ciout: 3768c2ecf20Sopenharmony_ci kfree(out_mad); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci return err; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev, 3828c2ecf20Sopenharmony_ci u32 *vendor_id) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 3858c2ecf20Sopenharmony_ci int err = -ENOMEM; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 3888c2ecf20Sopenharmony_ci if (!out_mad) 3898c2ecf20Sopenharmony_ci return -ENOMEM; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); 3928c2ecf20Sopenharmony_ci if (err) 3938c2ecf20Sopenharmony_ci goto out; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ciout: 3988c2ecf20Sopenharmony_ci kfree(out_mad); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return err; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 4068c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 4078c2ecf20Sopenharmony_ci int err = -ENOMEM; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 4108c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 4118c2ecf20Sopenharmony_ci if (!in_mad || !out_mad) 4128c2ecf20Sopenharmony_ci goto out; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci init_query_mad(in_mad); 4158c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 4188c2ecf20Sopenharmony_ci if (err) 4198c2ecf20Sopenharmony_ci goto out; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci memcpy(node_desc, out_mad->data, IB_DEVICE_NODE_DESC_MAX); 4228c2ecf20Sopenharmony_ciout: 4238c2ecf20Sopenharmony_ci kfree(in_mad); 4248c2ecf20Sopenharmony_ci kfree(out_mad); 4258c2ecf20Sopenharmony_ci return err; 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 4318c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 4328c2ecf20Sopenharmony_ci int err = -ENOMEM; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 4358c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 4368c2ecf20Sopenharmony_ci if (!in_mad || !out_mad) 4378c2ecf20Sopenharmony_ci goto out; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci init_query_mad(in_mad); 4408c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 4438c2ecf20Sopenharmony_ci if (err) 4448c2ecf20Sopenharmony_ci goto out; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci memcpy(node_guid, out_mad->data + 12, 8); 4478c2ecf20Sopenharmony_ciout: 4488c2ecf20Sopenharmony_ci kfree(in_mad); 4498c2ecf20Sopenharmony_ci kfree(out_mad); 4508c2ecf20Sopenharmony_ci return err; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index, 4548c2ecf20Sopenharmony_ci u16 *pkey) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 4578c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 4588c2ecf20Sopenharmony_ci int err = -ENOMEM; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 4618c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 4628c2ecf20Sopenharmony_ci if (!in_mad || !out_mad) 4638c2ecf20Sopenharmony_ci goto out; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci init_query_mad(in_mad); 4668c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; 4678c2ecf20Sopenharmony_ci in_mad->attr_mod = cpu_to_be32(index / 32); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, 4708c2ecf20Sopenharmony_ci out_mad); 4718c2ecf20Sopenharmony_ci if (err) 4728c2ecf20Sopenharmony_ci goto out; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ciout: 4778c2ecf20Sopenharmony_ci kfree(in_mad); 4788c2ecf20Sopenharmony_ci kfree(out_mad); 4798c2ecf20Sopenharmony_ci return err; 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index, 4838c2ecf20Sopenharmony_ci union ib_gid *gid) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 4868c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 4878c2ecf20Sopenharmony_ci int err = -ENOMEM; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 4908c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 4918c2ecf20Sopenharmony_ci if (!in_mad || !out_mad) 4928c2ecf20Sopenharmony_ci goto out; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci init_query_mad(in_mad); 4958c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; 4968c2ecf20Sopenharmony_ci in_mad->attr_mod = cpu_to_be32(port); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, 4998c2ecf20Sopenharmony_ci out_mad); 5008c2ecf20Sopenharmony_ci if (err) 5018c2ecf20Sopenharmony_ci goto out; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci memcpy(gid->raw, out_mad->data + 8, 8); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci init_query_mad(in_mad); 5068c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; 5078c2ecf20Sopenharmony_ci in_mad->attr_mod = cpu_to_be32(index / 8); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, 5108c2ecf20Sopenharmony_ci out_mad); 5118c2ecf20Sopenharmony_ci if (err) 5128c2ecf20Sopenharmony_ci goto out; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ciout: 5178c2ecf20Sopenharmony_ci kfree(in_mad); 5188c2ecf20Sopenharmony_ci kfree(out_mad); 5198c2ecf20Sopenharmony_ci return err; 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ciint mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port, 5238c2ecf20Sopenharmony_ci struct ib_port_attr *props) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci struct mlx5_ib_dev *dev = to_mdev(ibdev); 5268c2ecf20Sopenharmony_ci struct mlx5_core_dev *mdev = dev->mdev; 5278c2ecf20Sopenharmony_ci struct ib_smp *in_mad = NULL; 5288c2ecf20Sopenharmony_ci struct ib_smp *out_mad = NULL; 5298c2ecf20Sopenharmony_ci int ext_active_speed; 5308c2ecf20Sopenharmony_ci int err = -ENOMEM; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 5338c2ecf20Sopenharmony_ci out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 5348c2ecf20Sopenharmony_ci if (!in_mad || !out_mad) 5358c2ecf20Sopenharmony_ci goto out; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* props being zeroed by the caller, avoid zeroing it here */ 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci init_query_mad(in_mad); 5408c2ecf20Sopenharmony_ci in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; 5418c2ecf20Sopenharmony_ci in_mad->attr_mod = cpu_to_be32(port); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad); 5448c2ecf20Sopenharmony_ci if (err) { 5458c2ecf20Sopenharmony_ci mlx5_ib_warn(dev, "err %d\n", err); 5468c2ecf20Sopenharmony_ci goto out; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16)); 5508c2ecf20Sopenharmony_ci props->lmc = out_mad->data[34] & 0x7; 5518c2ecf20Sopenharmony_ci props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18)); 5528c2ecf20Sopenharmony_ci props->sm_sl = out_mad->data[36] & 0xf; 5538c2ecf20Sopenharmony_ci props->state = out_mad->data[32] & 0xf; 5548c2ecf20Sopenharmony_ci props->phys_state = out_mad->data[33] >> 4; 5558c2ecf20Sopenharmony_ci props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20)); 5568c2ecf20Sopenharmony_ci props->gid_tbl_len = out_mad->data[50]; 5578c2ecf20Sopenharmony_ci props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg); 5588c2ecf20Sopenharmony_ci props->pkey_tbl_len = mdev->port_caps[port - 1].pkey_table_len; 5598c2ecf20Sopenharmony_ci props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46)); 5608c2ecf20Sopenharmony_ci props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48)); 5618c2ecf20Sopenharmony_ci props->active_width = out_mad->data[31] & 0xf; 5628c2ecf20Sopenharmony_ci props->active_speed = out_mad->data[35] >> 4; 5638c2ecf20Sopenharmony_ci props->max_mtu = out_mad->data[41] & 0xf; 5648c2ecf20Sopenharmony_ci props->active_mtu = out_mad->data[36] >> 4; 5658c2ecf20Sopenharmony_ci props->subnet_timeout = out_mad->data[51] & 0x1f; 5668c2ecf20Sopenharmony_ci props->max_vl_num = out_mad->data[37] >> 4; 5678c2ecf20Sopenharmony_ci props->init_type_reply = out_mad->data[41] >> 4; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP) { 5708c2ecf20Sopenharmony_ci props->port_cap_flags2 = 5718c2ecf20Sopenharmony_ci be16_to_cpup((__be16 *)(out_mad->data + 60)); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci if (props->port_cap_flags2 & IB_PORT_LINK_WIDTH_2X_SUP) 5748c2ecf20Sopenharmony_ci props->active_width = out_mad->data[31] & 0x1f; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci /* Check if extended speeds (EDR/FDR/...) are supported */ 5788c2ecf20Sopenharmony_ci if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) { 5798c2ecf20Sopenharmony_ci ext_active_speed = out_mad->data[62] >> 4; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci switch (ext_active_speed) { 5828c2ecf20Sopenharmony_ci case 1: 5838c2ecf20Sopenharmony_ci props->active_speed = 16; /* FDR */ 5848c2ecf20Sopenharmony_ci break; 5858c2ecf20Sopenharmony_ci case 2: 5868c2ecf20Sopenharmony_ci props->active_speed = 32; /* EDR */ 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci case 4: 5898c2ecf20Sopenharmony_ci if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP && 5908c2ecf20Sopenharmony_ci props->port_cap_flags2 & IB_PORT_LINK_SPEED_HDR_SUP) 5918c2ecf20Sopenharmony_ci props->active_speed = IB_SPEED_HDR; 5928c2ecf20Sopenharmony_ci break; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci /* If reported active speed is QDR, check if is FDR-10 */ 5978c2ecf20Sopenharmony_ci if (props->active_speed == 4) { 5988c2ecf20Sopenharmony_ci if (mdev->port_caps[port - 1].ext_port_cap & 5998c2ecf20Sopenharmony_ci MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) { 6008c2ecf20Sopenharmony_ci init_query_mad(in_mad); 6018c2ecf20Sopenharmony_ci in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; 6028c2ecf20Sopenharmony_ci in_mad->attr_mod = cpu_to_be32(port); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci err = mlx5_MAD_IFC(dev, 1, 1, port, 6058c2ecf20Sopenharmony_ci NULL, NULL, in_mad, out_mad); 6068c2ecf20Sopenharmony_ci if (err) 6078c2ecf20Sopenharmony_ci goto out; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* Checking LinkSpeedActive for FDR-10 */ 6108c2ecf20Sopenharmony_ci if (out_mad->data[15] & 0x1) 6118c2ecf20Sopenharmony_ci props->active_speed = 8; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ciout: 6168c2ecf20Sopenharmony_ci kfree(in_mad); 6178c2ecf20Sopenharmony_ci kfree(out_mad); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci return err; 6208c2ecf20Sopenharmony_ci} 621