112515907SHans Petter Selasky /*- 212515907SHans Petter Selasky * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. All rights reserved. 312515907SHans Petter Selasky * 412515907SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 512515907SHans Petter Selasky * modification, are permitted provided that the following conditions 612515907SHans Petter Selasky * are met: 712515907SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 812515907SHans Petter Selasky * notice, this list of conditions and the following disclaimer. 912515907SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 1012515907SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 1112515907SHans Petter Selasky * documentation and/or other materials provided with the distribution. 1212515907SHans Petter Selasky * 1312515907SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 1412515907SHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1512515907SHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1612515907SHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 1712515907SHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1812515907SHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1912515907SHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2012515907SHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2112515907SHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2212515907SHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2312515907SHans Petter Selasky * SUCH DAMAGE. 2412515907SHans Petter Selasky * 2512515907SHans Petter Selasky * $FreeBSD$ 2612515907SHans Petter Selasky */ 2712515907SHans Petter Selasky 2870600979SKonstantin Belousov #include "opt_rss.h" 2970600979SKonstantin Belousov #include "opt_ratelimit.h" 3070600979SKonstantin Belousov 318e6e287fSHans Petter Selasky #include <dev/mlx5/vport.h> 3212515907SHans Petter Selasky #include <rdma/ib_mad.h> 3312515907SHans Petter Selasky #include <rdma/ib_smi.h> 3412515907SHans Petter Selasky #include <rdma/ib_pma.h> 3512515907SHans Petter Selasky #include "mlx5_ib.h" 3612515907SHans Petter Selasky 3712515907SHans Petter Selasky enum { 3812515907SHans Petter Selasky MLX5_IB_VENDOR_CLASS1 = 0x9, 3912515907SHans Petter Selasky MLX5_IB_VENDOR_CLASS2 = 0xa 4012515907SHans Petter Selasky }; 4112515907SHans Petter Selasky 4212515907SHans Petter Selasky int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, 438e6e287fSHans Petter Selasky u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, 448e6e287fSHans Petter Selasky const void *in_mad, void *response_mad) 4512515907SHans Petter Selasky { 4612515907SHans Petter Selasky u8 op_modifier = 0; 4712515907SHans Petter Selasky 4812515907SHans Petter Selasky /* Key check traps can't be generated unless we have in_wc to 4912515907SHans Petter Selasky * tell us where to send the trap. 5012515907SHans Petter Selasky */ 5112515907SHans Petter Selasky if (ignore_mkey || !in_wc) 5212515907SHans Petter Selasky op_modifier |= 0x1; 5312515907SHans Petter Selasky if (ignore_bkey || !in_wc) 5412515907SHans Petter Selasky op_modifier |= 0x2; 5512515907SHans Petter Selasky 5612515907SHans Petter Selasky return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port); 5712515907SHans Petter Selasky } 5812515907SHans Petter Selasky 5912515907SHans Petter Selasky static int process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, 608e6e287fSHans Petter Selasky const struct ib_wc *in_wc, const struct ib_grh *in_grh, 618e6e287fSHans Petter Selasky const struct ib_mad *in_mad, struct ib_mad *out_mad) 6212515907SHans Petter Selasky { 6312515907SHans Petter Selasky u16 slid; 6412515907SHans Petter Selasky int err; 6512515907SHans Petter Selasky 6612515907SHans Petter Selasky slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); 6712515907SHans Petter Selasky 6812515907SHans Petter Selasky if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0) 6912515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; 7012515907SHans Petter Selasky 7112515907SHans Petter Selasky if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || 7212515907SHans Petter Selasky in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { 7312515907SHans Petter Selasky if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && 7412515907SHans Petter Selasky in_mad->mad_hdr.method != IB_MGMT_METHOD_SET && 7512515907SHans Petter Selasky in_mad->mad_hdr.method != IB_MGMT_METHOD_TRAP_REPRESS) 7612515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS; 7712515907SHans Petter Selasky 7812515907SHans Petter Selasky /* Don't process SMInfo queries -- the SMA can't handle them. 7912515907SHans Petter Selasky */ 8012515907SHans Petter Selasky if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO) 8112515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS; 8212515907SHans Petter Selasky } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT || 8312515907SHans Petter Selasky in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS1 || 8412515907SHans Petter Selasky in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS2 || 8512515907SHans Petter Selasky in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_CONG_MGMT) { 8612515907SHans Petter Selasky if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && 8712515907SHans Petter Selasky in_mad->mad_hdr.method != IB_MGMT_METHOD_SET) 8812515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS; 8912515907SHans Petter Selasky } else { 9012515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS; 9112515907SHans Petter Selasky } 9212515907SHans Petter Selasky 9312515907SHans Petter Selasky err = mlx5_MAD_IFC(to_mdev(ibdev), 9412515907SHans Petter Selasky mad_flags & IB_MAD_IGNORE_MKEY, 9512515907SHans Petter Selasky mad_flags & IB_MAD_IGNORE_BKEY, 9612515907SHans Petter Selasky port_num, in_wc, in_grh, in_mad, out_mad); 9712515907SHans Petter Selasky if (err) 9812515907SHans Petter Selasky return IB_MAD_RESULT_FAILURE; 9912515907SHans Petter Selasky 10012515907SHans Petter Selasky /* set return bit in status of directed route responses */ 10112515907SHans Petter Selasky if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) 10212515907SHans Petter Selasky out_mad->mad_hdr.status |= cpu_to_be16(1 << 15); 10312515907SHans Petter Selasky 10412515907SHans Petter Selasky if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) 10512515907SHans Petter Selasky /* no response for trap repress */ 10612515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; 10712515907SHans Petter Selasky 10812515907SHans Petter Selasky return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; 10912515907SHans Petter Selasky } 11012515907SHans Petter Selasky 11112515907SHans Petter Selasky static void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext, 1128e6e287fSHans Petter Selasky void *out) 11312515907SHans Petter Selasky { 1148e6e287fSHans Petter Selasky #define MLX5_SUM_CNT(p, cntr1, cntr2) \ 1158e6e287fSHans Petter Selasky (MLX5_GET64(query_vport_counter_out, p, cntr1) + \ 1168e6e287fSHans Petter Selasky MLX5_GET64(query_vport_counter_out, p, cntr2)) 1178e6e287fSHans Petter Selasky 1188e6e287fSHans Petter Selasky pma_cnt_ext->port_xmit_data = 1198e6e287fSHans Petter Selasky cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets, 1208e6e287fSHans Petter Selasky transmitted_ib_multicast.octets) >> 2); 1218e6e287fSHans Petter Selasky pma_cnt_ext->port_rcv_data = 1228e6e287fSHans Petter Selasky cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets, 1238e6e287fSHans Petter Selasky received_ib_multicast.octets) >> 2); 1248e6e287fSHans Petter Selasky pma_cnt_ext->port_xmit_packets = 1258e6e287fSHans Petter Selasky cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.packets, 1268e6e287fSHans Petter Selasky transmitted_ib_multicast.packets)); 1278e6e287fSHans Petter Selasky pma_cnt_ext->port_rcv_packets = 1288e6e287fSHans Petter Selasky cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.packets, 1298e6e287fSHans Petter Selasky received_ib_multicast.packets)); 1308e6e287fSHans Petter Selasky pma_cnt_ext->port_unicast_xmit_packets = 1318e6e287fSHans Petter Selasky MLX5_GET64_BE(query_vport_counter_out, 1328e6e287fSHans Petter Selasky out, transmitted_ib_unicast.packets); 1338e6e287fSHans Petter Selasky pma_cnt_ext->port_unicast_rcv_packets = 1348e6e287fSHans Petter Selasky MLX5_GET64_BE(query_vport_counter_out, 1358e6e287fSHans Petter Selasky out, received_ib_unicast.packets); 1368e6e287fSHans Petter Selasky pma_cnt_ext->port_multicast_xmit_packets = 1378e6e287fSHans Petter Selasky MLX5_GET64_BE(query_vport_counter_out, 1388e6e287fSHans Petter Selasky out, transmitted_ib_multicast.packets); 1398e6e287fSHans Petter Selasky pma_cnt_ext->port_multicast_rcv_packets = 1408e6e287fSHans Petter Selasky MLX5_GET64_BE(query_vport_counter_out, 1418e6e287fSHans Petter Selasky out, received_ib_multicast.packets); 14212515907SHans Petter Selasky } 14312515907SHans Petter Selasky 14412515907SHans Petter Selasky static void pma_cnt_assign(struct ib_pma_portcounters *pma_cnt, 1458e6e287fSHans Petter Selasky void *out) 14612515907SHans Petter Selasky { 1478e6e287fSHans Petter Selasky /* Traffic counters will be reported in 1488e6e287fSHans Petter Selasky * their 64bit form via ib_pma_portcounters_ext by default. 1498e6e287fSHans Petter Selasky */ 1508e6e287fSHans Petter Selasky void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out, 1518e6e287fSHans Petter Selasky counter_set); 1528e6e287fSHans Petter Selasky 1538e6e287fSHans Petter Selasky #define MLX5_ASSIGN_PMA_CNTR(counter_var, counter_name) { \ 1548e6e287fSHans Petter Selasky counter_var = MLX5_GET_BE(typeof(counter_var), \ 1558e6e287fSHans Petter Selasky ib_port_cntrs_grp_data_layout, \ 1568e6e287fSHans Petter Selasky out_pma, counter_name); \ 1578e6e287fSHans Petter Selasky } 1588e6e287fSHans Petter Selasky 1598e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->symbol_error_counter, 1608e6e287fSHans Petter Selasky symbol_error_counter); 1618e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_error_recovery_counter, 1628e6e287fSHans Petter Selasky link_error_recovery_counter); 1638e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_downed_counter, 1648e6e287fSHans Petter Selasky link_downed_counter); 1658e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_errors, 1668e6e287fSHans Petter Selasky port_rcv_errors); 1678e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_remphys_errors, 1688e6e287fSHans Petter Selasky port_rcv_remote_physical_errors); 1698e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_switch_relay_errors, 1708e6e287fSHans Petter Selasky port_rcv_switch_relay_errors); 1718e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_discards, 1728e6e287fSHans Petter Selasky port_xmit_discards); 1738e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_constraint_errors, 1748e6e287fSHans Petter Selasky port_xmit_constraint_errors); 1758e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_constraint_errors, 1768e6e287fSHans Petter Selasky port_rcv_constraint_errors); 1778e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_overrun_errors, 1788e6e287fSHans Petter Selasky link_overrun_errors); 1798e6e287fSHans Petter Selasky MLX5_ASSIGN_PMA_CNTR(pma_cnt->vl15_dropped, 1808e6e287fSHans Petter Selasky vl_15_dropped); 18112515907SHans Petter Selasky } 18212515907SHans Petter Selasky 18312515907SHans Petter Selasky static int process_pma_cmd(struct ib_device *ibdev, u8 port_num, 1848e6e287fSHans Petter Selasky const struct ib_mad *in_mad, struct ib_mad *out_mad) 18512515907SHans Petter Selasky { 18612515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibdev); 18712515907SHans Petter Selasky int err; 1888e6e287fSHans Petter Selasky void *out_cnt; 18912515907SHans Petter Selasky 1908e6e287fSHans Petter Selasky /* Decalring support of extended counters */ 1918e6e287fSHans Petter Selasky if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) { 1928e6e287fSHans Petter Selasky struct ib_class_port_info cpi = {}; 19312515907SHans Petter Selasky 1948e6e287fSHans Petter Selasky cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH; 1958e6e287fSHans Petter Selasky memcpy((out_mad->data + 40), &cpi, sizeof(cpi)); 1968e6e287fSHans Petter Selasky return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; 1978e6e287fSHans Petter Selasky } 19812515907SHans Petter Selasky 1998e6e287fSHans Petter Selasky if (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT) { 20012515907SHans Petter Selasky struct ib_pma_portcounters_ext *pma_cnt_ext = 20112515907SHans Petter Selasky (struct ib_pma_portcounters_ext *)(out_mad->data + 40); 2028e6e287fSHans Petter Selasky int sz = MLX5_ST_SZ_BYTES(query_vport_counter_out); 20312515907SHans Petter Selasky 2048e6e287fSHans Petter Selasky out_cnt = mlx5_vzalloc(sz); 2058e6e287fSHans Petter Selasky if (!out_cnt) 2068e6e287fSHans Petter Selasky return IB_MAD_RESULT_FAILURE; 2078e6e287fSHans Petter Selasky 2088e6e287fSHans Petter Selasky err = mlx5_core_query_vport_counter(dev->mdev, 0, 0, 2098e6e287fSHans Petter Selasky port_num, out_cnt, sz); 2108e6e287fSHans Petter Selasky if (!err) 2118e6e287fSHans Petter Selasky pma_cnt_ext_assign(pma_cnt_ext, out_cnt); 21212515907SHans Petter Selasky } else { 21312515907SHans Petter Selasky struct ib_pma_portcounters *pma_cnt = 21412515907SHans Petter Selasky (struct ib_pma_portcounters *)(out_mad->data + 40); 2158e6e287fSHans Petter Selasky int sz = MLX5_ST_SZ_BYTES(ppcnt_reg); 21612515907SHans Petter Selasky 2178e6e287fSHans Petter Selasky out_cnt = mlx5_vzalloc(sz); 2188e6e287fSHans Petter Selasky if (!out_cnt) 2198e6e287fSHans Petter Selasky return IB_MAD_RESULT_FAILURE; 22012515907SHans Petter Selasky 2218e6e287fSHans Petter Selasky err = mlx5_core_query_ib_ppcnt(dev->mdev, port_num, 2228e6e287fSHans Petter Selasky out_cnt, sz); 2238e6e287fSHans Petter Selasky if (!err) 2248e6e287fSHans Petter Selasky pma_cnt_assign(pma_cnt, out_cnt); 22512515907SHans Petter Selasky } 22612515907SHans Petter Selasky 2278e6e287fSHans Petter Selasky kvfree(out_cnt); 2288e6e287fSHans Petter Selasky if (err) 2298e6e287fSHans Petter Selasky return IB_MAD_RESULT_FAILURE; 2308e6e287fSHans Petter Selasky 2318e6e287fSHans Petter Selasky return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; 23212515907SHans Petter Selasky } 23312515907SHans Petter Selasky 23412515907SHans Petter Selasky int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, 2358e6e287fSHans Petter Selasky const struct ib_wc *in_wc, const struct ib_grh *in_grh, 2368e6e287fSHans Petter Selasky const struct ib_mad_hdr *in, size_t in_mad_size, 2378e6e287fSHans Petter Selasky struct ib_mad_hdr *out, size_t *out_mad_size, 2388e6e287fSHans Petter Selasky u16 *out_mad_pkey_index) 23912515907SHans Petter Selasky { 24012515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibdev); 24112515907SHans Petter Selasky struct mlx5_core_dev *mdev = dev->mdev; 2428e6e287fSHans Petter Selasky const struct ib_mad *in_mad = (const struct ib_mad *)in; 2438e6e287fSHans Petter Selasky struct ib_mad *out_mad = (struct ib_mad *)out; 2448e6e287fSHans Petter Selasky 2458e6e287fSHans Petter Selasky if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || 2468e6e287fSHans Petter Selasky *out_mad_size != sizeof(*out_mad))) 2478e6e287fSHans Petter Selasky return IB_MAD_RESULT_FAILURE; 24812515907SHans Petter Selasky 24912515907SHans Petter Selasky memset(out_mad->data, 0, sizeof(out_mad->data)); 25012515907SHans Petter Selasky 25112515907SHans Petter Selasky if (MLX5_CAP_GEN(mdev, vport_counters) && 25212515907SHans Petter Selasky in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT && 25312515907SHans Petter Selasky in_mad->mad_hdr.method == IB_MGMT_METHOD_GET) { 25412515907SHans Petter Selasky return process_pma_cmd(ibdev, port_num, in_mad, out_mad); 25512515907SHans Petter Selasky } else { 25612515907SHans Petter Selasky return process_mad(ibdev, mad_flags, port_num, in_wc, in_grh, 25712515907SHans Petter Selasky in_mad, out_mad); 25812515907SHans Petter Selasky } 25912515907SHans Petter Selasky } 26012515907SHans Petter Selasky 26112515907SHans Petter Selasky int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port) 26212515907SHans Petter Selasky { 26312515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 26412515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 26512515907SHans Petter Selasky int err = -ENOMEM; 26612515907SHans Petter Selasky u16 packet_error; 26712515907SHans Petter Selasky 26812515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 26912515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 27012515907SHans Petter Selasky if (!in_mad || !out_mad) 27112515907SHans Petter Selasky goto out; 27212515907SHans Petter Selasky 27312515907SHans Petter Selasky init_query_mad(in_mad); 27412515907SHans Petter Selasky in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; 27512515907SHans Petter Selasky in_mad->attr_mod = cpu_to_be32(port); 27612515907SHans Petter Selasky 27712515907SHans Petter Selasky err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 27812515907SHans Petter Selasky 27912515907SHans Petter Selasky packet_error = be16_to_cpu(out_mad->status); 28012515907SHans Petter Selasky 28112515907SHans Petter Selasky dev->mdev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ? 28212515907SHans Petter Selasky MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; 28312515907SHans Petter Selasky 28412515907SHans Petter Selasky out: 28512515907SHans Petter Selasky kfree(in_mad); 28612515907SHans Petter Selasky kfree(out_mad); 28712515907SHans Petter Selasky return err; 28812515907SHans Petter Selasky } 28912515907SHans Petter Selasky 2908e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev, 29112515907SHans Petter Selasky struct ib_smp *out_mad) 29212515907SHans Petter Selasky { 29312515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 29412515907SHans Petter Selasky int err = -ENOMEM; 29512515907SHans Petter Selasky 29612515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 29712515907SHans Petter Selasky if (!in_mad) 29812515907SHans Petter Selasky return -ENOMEM; 29912515907SHans Petter Selasky 30012515907SHans Petter Selasky init_query_mad(in_mad); 30112515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; 30212515907SHans Petter Selasky 30312515907SHans Petter Selasky err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, 30412515907SHans Petter Selasky out_mad); 30512515907SHans Petter Selasky 30612515907SHans Petter Selasky kfree(in_mad); 30712515907SHans Petter Selasky return err; 30812515907SHans Petter Selasky } 30912515907SHans Petter Selasky 3108e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev, 31112515907SHans Petter Selasky __be64 *sys_image_guid) 31212515907SHans Petter Selasky { 31312515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 31412515907SHans Petter Selasky int err = -ENOMEM; 31512515907SHans Petter Selasky 31612515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 31712515907SHans Petter Selasky if (!out_mad) 31812515907SHans Petter Selasky return -ENOMEM; 31912515907SHans Petter Selasky 3208e6e287fSHans Petter Selasky err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); 32112515907SHans Petter Selasky if (err) 32212515907SHans Petter Selasky goto out; 32312515907SHans Petter Selasky 32412515907SHans Petter Selasky memcpy(sys_image_guid, out_mad->data + 4, 8); 32512515907SHans Petter Selasky 32612515907SHans Petter Selasky out: 32712515907SHans Petter Selasky kfree(out_mad); 32812515907SHans Petter Selasky 32912515907SHans Petter Selasky return err; 33012515907SHans Petter Selasky } 33112515907SHans Petter Selasky 3328e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev, 33312515907SHans Petter Selasky u16 *max_pkeys) 33412515907SHans Petter Selasky { 33512515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 33612515907SHans Petter Selasky int err = -ENOMEM; 33712515907SHans Petter Selasky 33812515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 33912515907SHans Petter Selasky if (!out_mad) 34012515907SHans Petter Selasky return -ENOMEM; 34112515907SHans Petter Selasky 3428e6e287fSHans Petter Selasky err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); 34312515907SHans Petter Selasky if (err) 34412515907SHans Petter Selasky goto out; 34512515907SHans Petter Selasky 34612515907SHans Petter Selasky *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28)); 34712515907SHans Petter Selasky 34812515907SHans Petter Selasky out: 34912515907SHans Petter Selasky kfree(out_mad); 35012515907SHans Petter Selasky 35112515907SHans Petter Selasky return err; 35212515907SHans Petter Selasky } 35312515907SHans Petter Selasky 3548e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev, 35512515907SHans Petter Selasky u32 *vendor_id) 35612515907SHans Petter Selasky { 35712515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 35812515907SHans Petter Selasky int err = -ENOMEM; 35912515907SHans Petter Selasky 36012515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 36112515907SHans Petter Selasky if (!out_mad) 36212515907SHans Petter Selasky return -ENOMEM; 36312515907SHans Petter Selasky 3648e6e287fSHans Petter Selasky err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); 36512515907SHans Petter Selasky if (err) 36612515907SHans Petter Selasky goto out; 36712515907SHans Petter Selasky 36812515907SHans Petter Selasky *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff; 36912515907SHans Petter Selasky 37012515907SHans Petter Selasky out: 37112515907SHans Petter Selasky kfree(out_mad); 37212515907SHans Petter Selasky 37312515907SHans Petter Selasky return err; 37412515907SHans Petter Selasky } 37512515907SHans Petter Selasky 3768e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc) 37712515907SHans Petter Selasky { 37812515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 37912515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 38012515907SHans Petter Selasky int err = -ENOMEM; 38112515907SHans Petter Selasky 38212515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 38312515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 38412515907SHans Petter Selasky if (!in_mad || !out_mad) 38512515907SHans Petter Selasky goto out; 38612515907SHans Petter Selasky 38712515907SHans Petter Selasky init_query_mad(in_mad); 38812515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; 38912515907SHans Petter Selasky 39012515907SHans Petter Selasky err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 39112515907SHans Petter Selasky if (err) 39212515907SHans Petter Selasky goto out; 39312515907SHans Petter Selasky 3948e6e287fSHans Petter Selasky memcpy(node_desc, out_mad->data, IB_DEVICE_NODE_DESC_MAX); 39512515907SHans Petter Selasky out: 39612515907SHans Petter Selasky kfree(in_mad); 39712515907SHans Petter Selasky kfree(out_mad); 39812515907SHans Petter Selasky return err; 39912515907SHans Petter Selasky } 40012515907SHans Petter Selasky 4018e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid) 40212515907SHans Petter Selasky { 40312515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 40412515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 40512515907SHans Petter Selasky int err = -ENOMEM; 40612515907SHans Petter Selasky 40712515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 40812515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 40912515907SHans Petter Selasky if (!in_mad || !out_mad) 41012515907SHans Petter Selasky goto out; 41112515907SHans Petter Selasky 41212515907SHans Petter Selasky init_query_mad(in_mad); 41312515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; 41412515907SHans Petter Selasky 41512515907SHans Petter Selasky err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 41612515907SHans Petter Selasky if (err) 41712515907SHans Petter Selasky goto out; 41812515907SHans Petter Selasky 4198e6e287fSHans Petter Selasky memcpy(node_guid, out_mad->data + 12, 8); 42012515907SHans Petter Selasky out: 42112515907SHans Petter Selasky kfree(in_mad); 42212515907SHans Petter Selasky kfree(out_mad); 42312515907SHans Petter Selasky return err; 42412515907SHans Petter Selasky } 42512515907SHans Petter Selasky 4268e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index, 42712515907SHans Petter Selasky u16 *pkey) 42812515907SHans Petter Selasky { 42912515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 43012515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 43112515907SHans Petter Selasky int err = -ENOMEM; 43212515907SHans Petter Selasky 43312515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 43412515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 43512515907SHans Petter Selasky if (!in_mad || !out_mad) 43612515907SHans Petter Selasky goto out; 43712515907SHans Petter Selasky 43812515907SHans Petter Selasky init_query_mad(in_mad); 43912515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; 44012515907SHans Petter Selasky in_mad->attr_mod = cpu_to_be32(index / 32); 44112515907SHans Petter Selasky 44212515907SHans Petter Selasky err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, 44312515907SHans Petter Selasky out_mad); 44412515907SHans Petter Selasky if (err) 44512515907SHans Petter Selasky goto out; 44612515907SHans Petter Selasky 44712515907SHans Petter Selasky *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]); 44812515907SHans Petter Selasky 44912515907SHans Petter Selasky out: 45012515907SHans Petter Selasky kfree(in_mad); 45112515907SHans Petter Selasky kfree(out_mad); 45212515907SHans Petter Selasky return err; 45312515907SHans Petter Selasky } 45412515907SHans Petter Selasky 4558e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index, 45612515907SHans Petter Selasky union ib_gid *gid) 45712515907SHans Petter Selasky { 45812515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 45912515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 46012515907SHans Petter Selasky int err = -ENOMEM; 46112515907SHans Petter Selasky 46212515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 46312515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 46412515907SHans Petter Selasky if (!in_mad || !out_mad) 46512515907SHans Petter Selasky goto out; 46612515907SHans Petter Selasky 46712515907SHans Petter Selasky init_query_mad(in_mad); 46812515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; 46912515907SHans Petter Selasky in_mad->attr_mod = cpu_to_be32(port); 47012515907SHans Petter Selasky 47112515907SHans Petter Selasky err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, 47212515907SHans Petter Selasky out_mad); 47312515907SHans Petter Selasky if (err) 47412515907SHans Petter Selasky goto out; 47512515907SHans Petter Selasky 47612515907SHans Petter Selasky memcpy(gid->raw, out_mad->data + 8, 8); 47712515907SHans Petter Selasky 47812515907SHans Petter Selasky init_query_mad(in_mad); 47912515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; 48012515907SHans Petter Selasky in_mad->attr_mod = cpu_to_be32(index / 8); 48112515907SHans Petter Selasky 48212515907SHans Petter Selasky err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, 48312515907SHans Petter Selasky out_mad); 48412515907SHans Petter Selasky if (err) 48512515907SHans Petter Selasky goto out; 48612515907SHans Petter Selasky 48712515907SHans Petter Selasky memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); 48812515907SHans Petter Selasky 48912515907SHans Petter Selasky out: 49012515907SHans Petter Selasky kfree(in_mad); 49112515907SHans Petter Selasky kfree(out_mad); 49212515907SHans Petter Selasky return err; 49312515907SHans Petter Selasky } 49412515907SHans Petter Selasky 4958e6e287fSHans Petter Selasky int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port, 49612515907SHans Petter Selasky struct ib_port_attr *props) 49712515907SHans Petter Selasky { 49812515907SHans Petter Selasky struct mlx5_ib_dev *dev = to_mdev(ibdev); 49912515907SHans Petter Selasky struct mlx5_core_dev *mdev = dev->mdev; 50012515907SHans Petter Selasky struct ib_smp *in_mad = NULL; 50112515907SHans Petter Selasky struct ib_smp *out_mad = NULL; 50212515907SHans Petter Selasky int ext_active_speed; 50312515907SHans Petter Selasky int err = -ENOMEM; 50412515907SHans Petter Selasky 50512515907SHans Petter Selasky if (port < 1 || port > MLX5_CAP_GEN(mdev, num_ports)) { 50612515907SHans Petter Selasky mlx5_ib_warn(dev, "invalid port number %d\n", port); 50712515907SHans Petter Selasky return -EINVAL; 50812515907SHans Petter Selasky } 50912515907SHans Petter Selasky 51012515907SHans Petter Selasky in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); 51112515907SHans Petter Selasky out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); 51212515907SHans Petter Selasky if (!in_mad || !out_mad) 51312515907SHans Petter Selasky goto out; 51412515907SHans Petter Selasky 51512515907SHans Petter Selasky memset(props, 0, sizeof(*props)); 51612515907SHans Petter Selasky 51712515907SHans Petter Selasky init_query_mad(in_mad); 51812515907SHans Petter Selasky in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; 51912515907SHans Petter Selasky in_mad->attr_mod = cpu_to_be32(port); 52012515907SHans Petter Selasky 52112515907SHans Petter Selasky err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad); 52212515907SHans Petter Selasky if (err) { 52312515907SHans Petter Selasky mlx5_ib_warn(dev, "err %d\n", err); 52412515907SHans Petter Selasky goto out; 52512515907SHans Petter Selasky } 52612515907SHans Petter Selasky 52712515907SHans Petter Selasky props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16)); 52812515907SHans Petter Selasky props->lmc = out_mad->data[34] & 0x7; 52912515907SHans Petter Selasky props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18)); 53012515907SHans Petter Selasky props->sm_sl = out_mad->data[36] & 0xf; 53112515907SHans Petter Selasky props->state = out_mad->data[32] & 0xf; 53212515907SHans Petter Selasky props->phys_state = out_mad->data[33] >> 4; 53312515907SHans Petter Selasky props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20)); 53412515907SHans Petter Selasky props->gid_tbl_len = out_mad->data[50]; 53512515907SHans Petter Selasky props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg); 53612515907SHans Petter Selasky props->pkey_tbl_len = mdev->port_caps[port - 1].pkey_table_len; 53712515907SHans Petter Selasky props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46)); 53812515907SHans Petter Selasky props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48)); 53912515907SHans Petter Selasky props->active_width = out_mad->data[31] & 0xf; 54012515907SHans Petter Selasky props->active_speed = out_mad->data[35] >> 4; 54112515907SHans Petter Selasky props->max_mtu = out_mad->data[41] & 0xf; 54212515907SHans Petter Selasky props->active_mtu = out_mad->data[36] >> 4; 54312515907SHans Petter Selasky props->subnet_timeout = out_mad->data[51] & 0x1f; 54412515907SHans Petter Selasky props->max_vl_num = out_mad->data[37] >> 4; 54512515907SHans Petter Selasky props->init_type_reply = out_mad->data[41] >> 4; 54612515907SHans Petter Selasky 54712515907SHans Petter Selasky /* Check if extended speeds (EDR/FDR/...) are supported */ 54812515907SHans Petter Selasky if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) { 54912515907SHans Petter Selasky ext_active_speed = out_mad->data[62] >> 4; 55012515907SHans Petter Selasky 55112515907SHans Petter Selasky switch (ext_active_speed) { 55212515907SHans Petter Selasky case 1: 55312515907SHans Petter Selasky props->active_speed = 16; /* FDR */ 55412515907SHans Petter Selasky break; 55512515907SHans Petter Selasky case 2: 55612515907SHans Petter Selasky props->active_speed = 32; /* EDR */ 55712515907SHans Petter Selasky break; 55812515907SHans Petter Selasky } 55912515907SHans Petter Selasky } 56012515907SHans Petter Selasky 56112515907SHans Petter Selasky /* If reported active speed is QDR, check if is FDR-10 */ 56212515907SHans Petter Selasky if (props->active_speed == 4) { 56312515907SHans Petter Selasky if (mdev->port_caps[port - 1].ext_port_cap & 56412515907SHans Petter Selasky MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) { 56512515907SHans Petter Selasky init_query_mad(in_mad); 56612515907SHans Petter Selasky in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; 56712515907SHans Petter Selasky in_mad->attr_mod = cpu_to_be32(port); 56812515907SHans Petter Selasky 56912515907SHans Petter Selasky err = mlx5_MAD_IFC(dev, 1, 1, port, 57012515907SHans Petter Selasky NULL, NULL, in_mad, out_mad); 57112515907SHans Petter Selasky if (err) 57212515907SHans Petter Selasky goto out; 57312515907SHans Petter Selasky 57412515907SHans Petter Selasky /* Checking LinkSpeedActive for FDR-10 */ 57512515907SHans Petter Selasky if (out_mad->data[15] & 0x1) 57612515907SHans Petter Selasky props->active_speed = 8; 57712515907SHans Petter Selasky } 57812515907SHans Petter Selasky } 57912515907SHans Petter Selasky 58012515907SHans Petter Selasky out: 58112515907SHans Petter Selasky kfree(in_mad); 58212515907SHans Petter Selasky kfree(out_mad); 58312515907SHans Petter Selasky 58412515907SHans Petter Selasky return err; 58512515907SHans Petter Selasky } 586