xref: /linux/drivers/infiniband/hw/mlx5/mad.c (revision be121ffb)
1e126ba97SEli Cohen /*
26cf0a15fSSaeed Mahameed  * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
3e126ba97SEli Cohen  *
4e126ba97SEli Cohen  * This software is available to you under a choice of one of two
5e126ba97SEli Cohen  * licenses.  You may choose to be licensed under the terms of the GNU
6e126ba97SEli Cohen  * General Public License (GPL) Version 2, available from the file
7e126ba97SEli Cohen  * COPYING in the main directory of this source tree, or the
8e126ba97SEli Cohen  * OpenIB.org BSD license below:
9e126ba97SEli Cohen  *
10e126ba97SEli Cohen  *     Redistribution and use in source and binary forms, with or
11e126ba97SEli Cohen  *     without modification, are permitted provided that the following
12e126ba97SEli Cohen  *     conditions are met:
13e126ba97SEli Cohen  *
14e126ba97SEli Cohen  *      - Redistributions of source code must retain the above
15e126ba97SEli Cohen  *        copyright notice, this list of conditions and the following
16e126ba97SEli Cohen  *        disclaimer.
17e126ba97SEli Cohen  *
18e126ba97SEli Cohen  *      - Redistributions in binary form must reproduce the above
19e126ba97SEli Cohen  *        copyright notice, this list of conditions and the following
20e126ba97SEli Cohen  *        disclaimer in the documentation and/or other materials
21e126ba97SEli Cohen  *        provided with the distribution.
22e126ba97SEli Cohen  *
23e126ba97SEli Cohen  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24e126ba97SEli Cohen  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25e126ba97SEli Cohen  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26e126ba97SEli Cohen  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27e126ba97SEli Cohen  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28e126ba97SEli Cohen  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29e126ba97SEli Cohen  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30e126ba97SEli Cohen  * SOFTWARE.
31e126ba97SEli Cohen  */
32e126ba97SEli Cohen 
333efd9a11SMeny Yossefi #include <linux/mlx5/vport.h>
34e126ba97SEli Cohen #include <rdma/ib_mad.h>
35e126ba97SEli Cohen #include <rdma/ib_smi.h>
363efd9a11SMeny Yossefi #include <rdma/ib_pma.h>
37e126ba97SEli Cohen #include "mlx5_ib.h"
3873f5a82bSLeon Romanovsky #include "cmd.h"
39e126ba97SEli Cohen 
40e126ba97SEli Cohen enum {
41e126ba97SEli Cohen 	MLX5_IB_VENDOR_CLASS1 = 0x9,
42e126ba97SEli Cohen 	MLX5_IB_VENDOR_CLASS2 = 0xa
43e126ba97SEli Cohen };
44e126ba97SEli Cohen 
can_do_mad_ifc(struct mlx5_ib_dev * dev,u32 port_num,struct ib_mad * in_mad)451fb7f897SMark Bloch static bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u32 port_num,
46c43f1112SMaor Gottlieb 			   struct ib_mad *in_mad)
47c43f1112SMaor Gottlieb {
48c43f1112SMaor Gottlieb 	if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED &&
49c43f1112SMaor Gottlieb 	    in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
50c43f1112SMaor Gottlieb 		return true;
513ce60f44SParav Pandit 	return dev->port_caps[port_num - 1].has_smi;
52c43f1112SMaor Gottlieb }
53c43f1112SMaor Gottlieb 
mlx5_MAD_IFC(struct mlx5_ib_dev * dev,int ignore_mkey,int ignore_bkey,u32 port,const struct ib_wc * in_wc,const struct ib_grh * in_grh,const void * in_mad,void * response_mad)5473f5a82bSLeon Romanovsky static int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey,
551fb7f897SMark Bloch 			int ignore_bkey, u32 port, const struct ib_wc *in_wc,
5673f5a82bSLeon Romanovsky 			const struct ib_grh *in_grh, const void *in_mad,
5773f5a82bSLeon Romanovsky 			void *response_mad)
58e126ba97SEli Cohen {
59e126ba97SEli Cohen 	u8 op_modifier = 0;
60e126ba97SEli Cohen 
61c43f1112SMaor Gottlieb 	if (!can_do_mad_ifc(dev, port, (struct ib_mad *)in_mad))
62c43f1112SMaor Gottlieb 		return -EPERM;
63c43f1112SMaor Gottlieb 
64e126ba97SEli Cohen 	/* Key check traps can't be generated unless we have in_wc to
65e126ba97SEli Cohen 	 * tell us where to send the trap.
66e126ba97SEli Cohen 	 */
67e126ba97SEli Cohen 	if (ignore_mkey || !in_wc)
68e126ba97SEli Cohen 		op_modifier |= 0x1;
69e126ba97SEli Cohen 	if (ignore_bkey || !in_wc)
70e126ba97SEli Cohen 		op_modifier |= 0x2;
71e126ba97SEli Cohen 
7273f5a82bSLeon Romanovsky 	return mlx5_cmd_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier,
7373f5a82bSLeon Romanovsky 				port);
74e126ba97SEli Cohen }
75e126ba97SEli Cohen 
pma_cnt_ext_assign(struct ib_pma_portcounters_ext * pma_cnt_ext,void * out)763efd9a11SMeny Yossefi static void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext,
773efd9a11SMeny Yossefi 			       void *out)
783efd9a11SMeny Yossefi {
793efd9a11SMeny Yossefi #define MLX5_SUM_CNT(p, cntr1, cntr2)	\
803efd9a11SMeny Yossefi 	(MLX5_GET64(query_vport_counter_out, p, cntr1) + \
813efd9a11SMeny Yossefi 	MLX5_GET64(query_vport_counter_out, p, cntr2))
823efd9a11SMeny Yossefi 
833efd9a11SMeny Yossefi 	pma_cnt_ext->port_xmit_data =
843efd9a11SMeny Yossefi 		cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets,
853efd9a11SMeny Yossefi 					 transmitted_ib_multicast.octets) >> 2);
8600bf534fSTalat Batheesh 	pma_cnt_ext->port_rcv_data =
873efd9a11SMeny Yossefi 		cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets,
883efd9a11SMeny Yossefi 					 received_ib_multicast.octets) >> 2);
893efd9a11SMeny Yossefi 	pma_cnt_ext->port_xmit_packets =
903efd9a11SMeny Yossefi 		cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.packets,
913efd9a11SMeny Yossefi 					 transmitted_ib_multicast.packets));
923efd9a11SMeny Yossefi 	pma_cnt_ext->port_rcv_packets =
933efd9a11SMeny Yossefi 		cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.packets,
943efd9a11SMeny Yossefi 					 received_ib_multicast.packets));
953efd9a11SMeny Yossefi 	pma_cnt_ext->port_unicast_xmit_packets =
963efd9a11SMeny Yossefi 		MLX5_GET64_BE(query_vport_counter_out,
973efd9a11SMeny Yossefi 			      out, transmitted_ib_unicast.packets);
983efd9a11SMeny Yossefi 	pma_cnt_ext->port_unicast_rcv_packets =
993efd9a11SMeny Yossefi 		MLX5_GET64_BE(query_vport_counter_out,
1003efd9a11SMeny Yossefi 			      out, received_ib_unicast.packets);
1013efd9a11SMeny Yossefi 	pma_cnt_ext->port_multicast_xmit_packets =
1023efd9a11SMeny Yossefi 		MLX5_GET64_BE(query_vport_counter_out,
1033efd9a11SMeny Yossefi 			      out, transmitted_ib_multicast.packets);
1043efd9a11SMeny Yossefi 	pma_cnt_ext->port_multicast_rcv_packets =
1053efd9a11SMeny Yossefi 		MLX5_GET64_BE(query_vport_counter_out,
1063efd9a11SMeny Yossefi 			      out, received_ib_multicast.packets);
1073efd9a11SMeny Yossefi }
1083efd9a11SMeny Yossefi 
pma_cnt_assign(struct ib_pma_portcounters * pma_cnt,void * out)1093efd9a11SMeny Yossefi static void pma_cnt_assign(struct ib_pma_portcounters *pma_cnt,
1103efd9a11SMeny Yossefi 			   void *out)
1113efd9a11SMeny Yossefi {
1123efd9a11SMeny Yossefi 	/* Traffic counters will be reported in
1133efd9a11SMeny Yossefi 	 * their 64bit form via ib_pma_portcounters_ext by default.
1143efd9a11SMeny Yossefi 	 */
1153efd9a11SMeny Yossefi 	void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out,
1163efd9a11SMeny Yossefi 				     counter_set);
1173efd9a11SMeny Yossefi 
1183efd9a11SMeny Yossefi #define MLX5_ASSIGN_PMA_CNTR(counter_var, counter_name)	{		\
1193efd9a11SMeny Yossefi 	counter_var = MLX5_GET_BE(typeof(counter_var),			\
1203efd9a11SMeny Yossefi 				  ib_port_cntrs_grp_data_layout,	\
1213efd9a11SMeny Yossefi 				  out_pma, counter_name);		\
1223efd9a11SMeny Yossefi 	}
1233efd9a11SMeny Yossefi 
1243efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->symbol_error_counter,
1253efd9a11SMeny Yossefi 			     symbol_error_counter);
1263efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_error_recovery_counter,
1273efd9a11SMeny Yossefi 			     link_error_recovery_counter);
1283efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_downed_counter,
1293efd9a11SMeny Yossefi 			     link_downed_counter);
1303efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_errors,
1313efd9a11SMeny Yossefi 			     port_rcv_errors);
1323efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_remphys_errors,
1333efd9a11SMeny Yossefi 			     port_rcv_remote_physical_errors);
1343efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_switch_relay_errors,
1353efd9a11SMeny Yossefi 			     port_rcv_switch_relay_errors);
1363efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_discards,
1373efd9a11SMeny Yossefi 			     port_xmit_discards);
1383efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_constraint_errors,
1393efd9a11SMeny Yossefi 			     port_xmit_constraint_errors);
140133bea04STim Wright 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_wait,
141133bea04STim Wright 			     port_xmit_wait);
1423efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_constraint_errors,
1433efd9a11SMeny Yossefi 			     port_rcv_constraint_errors);
1443efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_overrun_errors,
1453efd9a11SMeny Yossefi 			     link_overrun_errors);
1463efd9a11SMeny Yossefi 	MLX5_ASSIGN_PMA_CNTR(pma_cnt->vl15_dropped,
1473efd9a11SMeny Yossefi 			     vl_15_dropped);
1483efd9a11SMeny Yossefi }
1493efd9a11SMeny Yossefi 
query_ib_ppcnt(struct mlx5_core_dev * dev,u8 port_num,void * out,size_t sz)1508a2dd123SChris Mi static int query_ib_ppcnt(struct mlx5_core_dev *dev, u8 port_num, void *out,
1518a2dd123SChris Mi 			  size_t sz)
1528a2dd123SChris Mi {
1538a2dd123SChris Mi 	u32 *in;
1548a2dd123SChris Mi 	int err;
1558a2dd123SChris Mi 
1568a2dd123SChris Mi 	in  = kvzalloc(sz, GFP_KERNEL);
1578a2dd123SChris Mi 	if (!in) {
1588a2dd123SChris Mi 		err = -ENOMEM;
1598a2dd123SChris Mi 		return err;
1608a2dd123SChris Mi 	}
1618a2dd123SChris Mi 
1628a2dd123SChris Mi 	MLX5_SET(ppcnt_reg, in, local_port, port_num);
1638a2dd123SChris Mi 
1648a2dd123SChris Mi 	MLX5_SET(ppcnt_reg, in, grp, MLX5_INFINIBAND_PORT_COUNTERS_GROUP);
1658a2dd123SChris Mi 	err = mlx5_core_access_reg(dev, in, sz, out,
1668a2dd123SChris Mi 				   sz, MLX5_REG_PPCNT, 0, 0);
1678a2dd123SChris Mi 
1688a2dd123SChris Mi 	kvfree(in);
1698a2dd123SChris Mi 	return err;
1708a2dd123SChris Mi }
1718a2dd123SChris Mi 
process_pma_cmd(struct mlx5_ib_dev * dev,u32 port_num,const struct ib_mad * in_mad,struct ib_mad * out_mad)1721fb7f897SMark Bloch static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
1733efd9a11SMeny Yossefi 			   const struct ib_mad *in_mad, struct ib_mad *out_mad)
1743efd9a11SMeny Yossefi {
1752f40cf30SParav Pandit 	struct mlx5_core_dev *mdev;
1762f40cf30SParav Pandit 	bool native_port = true;
1771fb7f897SMark Bloch 	u32 mdev_port_num;
1783efd9a11SMeny Yossefi 	void *out_cnt;
1792f40cf30SParav Pandit 	int err;
1803efd9a11SMeny Yossefi 
1812f40cf30SParav Pandit 	mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
1822f40cf30SParav Pandit 	if (!mdev) {
1832f40cf30SParav Pandit 		/* Fail to get the native port, likely due to 2nd port is still
1842f40cf30SParav Pandit 		 * unaffiliated. In such case default to 1st port and attached
1852f40cf30SParav Pandit 		 * PF device.
1862f40cf30SParav Pandit 		 */
1872f40cf30SParav Pandit 		native_port = false;
1882f40cf30SParav Pandit 		mdev = dev->mdev;
1892f40cf30SParav Pandit 		mdev_port_num = 1;
1902f40cf30SParav Pandit 	}
191*be121ffbSMichael Guralnik 	if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
192*be121ffbSMichael Guralnik 	    !mlx5_core_mp_enabled(mdev)) {
19374b30b3aSChris Mi 		/* set local port to one for Function-Per-Port HCA. */
19474b30b3aSChris Mi 		mdev = dev->mdev;
19574b30b3aSChris Mi 		mdev_port_num = 1;
19674b30b3aSChris Mi 	}
19774b30b3aSChris Mi 
1984edf8d5cSTalat Batheesh 	/* Declaring support of extended counters */
1993efd9a11SMeny Yossefi 	if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
2003efd9a11SMeny Yossefi 		struct ib_class_port_info cpi = {};
2013efd9a11SMeny Yossefi 
2023efd9a11SMeny Yossefi 		cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
2033efd9a11SMeny Yossefi 		memcpy((out_mad->data + 40), &cpi, sizeof(cpi));
2042f40cf30SParav Pandit 		err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
2052f40cf30SParav Pandit 		goto done;
2063efd9a11SMeny Yossefi 	}
2073efd9a11SMeny Yossefi 
2083efd9a11SMeny Yossefi 	if (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT) {
2093efd9a11SMeny Yossefi 		struct ib_pma_portcounters_ext *pma_cnt_ext =
2103efd9a11SMeny Yossefi 			(struct ib_pma_portcounters_ext *)(out_mad->data + 40);
2113efd9a11SMeny Yossefi 		int sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2123efd9a11SMeny Yossefi 
2131b9a07eeSLeon Romanovsky 		out_cnt = kvzalloc(sz, GFP_KERNEL);
2142f40cf30SParav Pandit 		if (!out_cnt) {
2152f40cf30SParav Pandit 			err = IB_MAD_RESULT_FAILURE;
2162f40cf30SParav Pandit 			goto done;
2172f40cf30SParav Pandit 		}
2183efd9a11SMeny Yossefi 
2195d1c9a11SLeon Romanovsky 		err = mlx5_core_query_vport_counter(mdev, 0, 0, mdev_port_num,
2205d1c9a11SLeon Romanovsky 						    out_cnt);
2213efd9a11SMeny Yossefi 		if (!err)
2223efd9a11SMeny Yossefi 			pma_cnt_ext_assign(pma_cnt_ext, out_cnt);
2233efd9a11SMeny Yossefi 	} else {
2243efd9a11SMeny Yossefi 		struct ib_pma_portcounters *pma_cnt =
2253efd9a11SMeny Yossefi 			(struct ib_pma_portcounters *)(out_mad->data + 40);
2263efd9a11SMeny Yossefi 		int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
2273efd9a11SMeny Yossefi 
2281b9a07eeSLeon Romanovsky 		out_cnt = kvzalloc(sz, GFP_KERNEL);
2292f40cf30SParav Pandit 		if (!out_cnt) {
2302f40cf30SParav Pandit 			err = IB_MAD_RESULT_FAILURE;
2312f40cf30SParav Pandit 			goto done;
2322f40cf30SParav Pandit 		}
2333efd9a11SMeny Yossefi 
2348a2dd123SChris Mi 		err = query_ib_ppcnt(mdev, mdev_port_num, out_cnt, sz);
2353efd9a11SMeny Yossefi 		if (!err)
2363efd9a11SMeny Yossefi 			pma_cnt_assign(pma_cnt, out_cnt);
2373efd9a11SMeny Yossefi 	}
2383efd9a11SMeny Yossefi 	kvfree(out_cnt);
2392f40cf30SParav Pandit 	err = err ? IB_MAD_RESULT_FAILURE :
2402f40cf30SParav Pandit 		    IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
2412f40cf30SParav Pandit done:
2422f40cf30SParav Pandit 	if (native_port)
2432f40cf30SParav Pandit 		mlx5_ib_put_native_port_mdev(dev, port_num);
2442f40cf30SParav Pandit 	return err;
2453efd9a11SMeny Yossefi }
2463efd9a11SMeny Yossefi 
mlx5_ib_process_mad(struct ib_device * ibdev,int mad_flags,u32 port_num,const struct ib_wc * in_wc,const struct ib_grh * in_grh,const struct ib_mad * in,struct ib_mad * out,size_t * out_mad_size,u16 * out_mad_pkey_index)2471fb7f897SMark Bloch int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u32 port_num,
2483efd9a11SMeny Yossefi 			const struct ib_wc *in_wc, const struct ib_grh *in_grh,
249e26e7b88SLeon Romanovsky 			const struct ib_mad *in, struct ib_mad *out,
250e26e7b88SLeon Romanovsky 			size_t *out_mad_size, u16 *out_mad_pkey_index)
2513efd9a11SMeny Yossefi {
2523efd9a11SMeny Yossefi 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
253e26e7b88SLeon Romanovsky 	u8 mgmt_class = in->mad_hdr.mgmt_class;
254e26e7b88SLeon Romanovsky 	u8 method = in->mad_hdr.method;
255ffa2fd13SLeon Romanovsky 	u16 slid;
256ffa2fd13SLeon Romanovsky 	int err;
2573efd9a11SMeny Yossefi 
258ffa2fd13SLeon Romanovsky 	slid = in_wc ? ib_lid_cpu16(in_wc->slid) :
259ffa2fd13SLeon Romanovsky 		       be16_to_cpu(IB_LID_PERMISSIVE);
260ffa2fd13SLeon Romanovsky 
261ffa2fd13SLeon Romanovsky 	if (method == IB_MGMT_METHOD_TRAP && !slid)
262ffa2fd13SLeon Romanovsky 		return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
263ffa2fd13SLeon Romanovsky 
264ffa2fd13SLeon Romanovsky 	switch (mgmt_class) {
265ffa2fd13SLeon Romanovsky 	case IB_MGMT_CLASS_SUBN_LID_ROUTED:
266ffa2fd13SLeon Romanovsky 	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: {
267ffa2fd13SLeon Romanovsky 		if (method != IB_MGMT_METHOD_GET &&
268ffa2fd13SLeon Romanovsky 		    method != IB_MGMT_METHOD_SET &&
269ffa2fd13SLeon Romanovsky 		    method != IB_MGMT_METHOD_TRAP_REPRESS)
270ffa2fd13SLeon Romanovsky 			return IB_MAD_RESULT_SUCCESS;
271ffa2fd13SLeon Romanovsky 
272ffa2fd13SLeon Romanovsky 		/* Don't process SMInfo queries -- the SMA can't handle them.
273ffa2fd13SLeon Romanovsky 		 */
274e26e7b88SLeon Romanovsky 		if (in->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
275ffa2fd13SLeon Romanovsky 			return IB_MAD_RESULT_SUCCESS;
276ffa2fd13SLeon Romanovsky 	} break;
277ffa2fd13SLeon Romanovsky 	case IB_MGMT_CLASS_PERF_MGMT:
2782f40cf30SParav Pandit 		if (MLX5_CAP_GEN(dev->mdev, vport_counters) &&
279ffa2fd13SLeon Romanovsky 		    method == IB_MGMT_METHOD_GET)
280e26e7b88SLeon Romanovsky 			return process_pma_cmd(dev, port_num, in, out);
281df561f66SGustavo A. R. Silva 		fallthrough;
282ffa2fd13SLeon Romanovsky 	case MLX5_IB_VENDOR_CLASS1:
283ffa2fd13SLeon Romanovsky 	case MLX5_IB_VENDOR_CLASS2:
284ffa2fd13SLeon Romanovsky 	case IB_MGMT_CLASS_CONG_MGMT: {
285ffa2fd13SLeon Romanovsky 		if (method != IB_MGMT_METHOD_GET &&
286ffa2fd13SLeon Romanovsky 		    method != IB_MGMT_METHOD_SET)
287ffa2fd13SLeon Romanovsky 			return IB_MAD_RESULT_SUCCESS;
288ffa2fd13SLeon Romanovsky 	} break;
289ffa2fd13SLeon Romanovsky 	default:
290ffa2fd13SLeon Romanovsky 		return IB_MAD_RESULT_SUCCESS;
2913efd9a11SMeny Yossefi 	}
292ffa2fd13SLeon Romanovsky 
293e26e7b88SLeon Romanovsky 	err = mlx5_MAD_IFC(to_mdev(ibdev), mad_flags & IB_MAD_IGNORE_MKEY,
294e26e7b88SLeon Romanovsky 			   mad_flags & IB_MAD_IGNORE_BKEY, port_num, in_wc,
295e26e7b88SLeon Romanovsky 			   in_grh, in, out);
296ffa2fd13SLeon Romanovsky 	if (err)
297ffa2fd13SLeon Romanovsky 		return IB_MAD_RESULT_FAILURE;
298ffa2fd13SLeon Romanovsky 
299ffa2fd13SLeon Romanovsky 	/* set return bit in status of directed route responses */
300ffa2fd13SLeon Romanovsky 	if (mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
301e26e7b88SLeon Romanovsky 		out->mad_hdr.status |= cpu_to_be16(1 << 15);
302ffa2fd13SLeon Romanovsky 
303ffa2fd13SLeon Romanovsky 	if (method == IB_MGMT_METHOD_TRAP_REPRESS)
304ffa2fd13SLeon Romanovsky 		/* no response for trap repress */
305ffa2fd13SLeon Romanovsky 		return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
306ffa2fd13SLeon Romanovsky 
307ffa2fd13SLeon Romanovsky 	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
3083efd9a11SMeny Yossefi }
3093efd9a11SMeny Yossefi 
mlx5_query_ext_port_caps(struct mlx5_ib_dev * dev,unsigned int port)31013179652SParav Pandit int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, unsigned int port)
311e126ba97SEli Cohen {
312a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
313a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
314e126ba97SEli Cohen 	int err = -ENOMEM;
315e126ba97SEli Cohen 	u16 packet_error;
316e126ba97SEli Cohen 
317e126ba97SEli Cohen 	in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
318e126ba97SEli Cohen 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
319e126ba97SEli Cohen 	if (!in_mad || !out_mad)
320e126ba97SEli Cohen 		goto out;
321e126ba97SEli Cohen 
322d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
323e126ba97SEli Cohen 	in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
324e126ba97SEli Cohen 	in_mad->attr_mod = cpu_to_be32(port);
325e126ba97SEli Cohen 
326e126ba97SEli Cohen 	err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
327e126ba97SEli Cohen 
328e126ba97SEli Cohen 	packet_error = be16_to_cpu(out_mad->status);
329e126ba97SEli Cohen 
3303ce60f44SParav Pandit 	dev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ?
331e126ba97SEli Cohen 		MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
332e126ba97SEli Cohen 
333e126ba97SEli Cohen out:
334e126ba97SEli Cohen 	kfree(in_mad);
335e126ba97SEli Cohen 	kfree(out_mad);
336e126ba97SEli Cohen 	return err;
337e126ba97SEli Cohen }
3381b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device * ibdev,struct ib_smp * out_mad)339559a3eacSParav Pandit static int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev,
3401b5daf11SMajd Dibbiny 						 struct ib_smp *out_mad)
3411b5daf11SMajd Dibbiny {
342a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
343a45e5f18SRuan Jinjie 	int err;
3441b5daf11SMajd Dibbiny 
3451b5daf11SMajd Dibbiny 	in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
3461b5daf11SMajd Dibbiny 	if (!in_mad)
3471b5daf11SMajd Dibbiny 		return -ENOMEM;
3481b5daf11SMajd Dibbiny 
349d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
3501b5daf11SMajd Dibbiny 	in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
3511b5daf11SMajd Dibbiny 
3521b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad,
3531b5daf11SMajd Dibbiny 			   out_mad);
3541b5daf11SMajd Dibbiny 
3551b5daf11SMajd Dibbiny 	kfree(in_mad);
3561b5daf11SMajd Dibbiny 	return err;
3571b5daf11SMajd Dibbiny }
3581b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_system_image_guid(struct ib_device * ibdev,__be64 * sys_image_guid)3591b5daf11SMajd Dibbiny int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev,
3601b5daf11SMajd Dibbiny 					 __be64 *sys_image_guid)
3611b5daf11SMajd Dibbiny {
362a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
363a45e5f18SRuan Jinjie 	int err;
3641b5daf11SMajd Dibbiny 
3651b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
3661b5daf11SMajd Dibbiny 	if (!out_mad)
3671b5daf11SMajd Dibbiny 		return -ENOMEM;
3681b5daf11SMajd Dibbiny 
3691b5daf11SMajd Dibbiny 	err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
3701b5daf11SMajd Dibbiny 	if (err)
3711b5daf11SMajd Dibbiny 		goto out;
3721b5daf11SMajd Dibbiny 
3731b5daf11SMajd Dibbiny 	memcpy(sys_image_guid, out_mad->data + 4, 8);
3741b5daf11SMajd Dibbiny 
3751b5daf11SMajd Dibbiny out:
3761b5daf11SMajd Dibbiny 	kfree(out_mad);
3771b5daf11SMajd Dibbiny 
3781b5daf11SMajd Dibbiny 	return err;
3791b5daf11SMajd Dibbiny }
3801b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_max_pkeys(struct ib_device * ibdev,u16 * max_pkeys)3811b5daf11SMajd Dibbiny int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev,
3821b5daf11SMajd Dibbiny 				 u16 *max_pkeys)
3831b5daf11SMajd Dibbiny {
384a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
385a45e5f18SRuan Jinjie 	int err;
3861b5daf11SMajd Dibbiny 
3871b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
3881b5daf11SMajd Dibbiny 	if (!out_mad)
3891b5daf11SMajd Dibbiny 		return -ENOMEM;
3901b5daf11SMajd Dibbiny 
3911b5daf11SMajd Dibbiny 	err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
3921b5daf11SMajd Dibbiny 	if (err)
3931b5daf11SMajd Dibbiny 		goto out;
3941b5daf11SMajd Dibbiny 
3951b5daf11SMajd Dibbiny 	*max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28));
3961b5daf11SMajd Dibbiny 
3971b5daf11SMajd Dibbiny out:
3981b5daf11SMajd Dibbiny 	kfree(out_mad);
3991b5daf11SMajd Dibbiny 
4001b5daf11SMajd Dibbiny 	return err;
4011b5daf11SMajd Dibbiny }
4021b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_vendor_id(struct ib_device * ibdev,u32 * vendor_id)4031b5daf11SMajd Dibbiny int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev,
4041b5daf11SMajd Dibbiny 				 u32 *vendor_id)
4051b5daf11SMajd Dibbiny {
406a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
407a45e5f18SRuan Jinjie 	int err;
4081b5daf11SMajd Dibbiny 
4091b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
4101b5daf11SMajd Dibbiny 	if (!out_mad)
4111b5daf11SMajd Dibbiny 		return -ENOMEM;
4121b5daf11SMajd Dibbiny 
4131b5daf11SMajd Dibbiny 	err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
4141b5daf11SMajd Dibbiny 	if (err)
4151b5daf11SMajd Dibbiny 		goto out;
4161b5daf11SMajd Dibbiny 
4171b5daf11SMajd Dibbiny 	*vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff;
4181b5daf11SMajd Dibbiny 
4191b5daf11SMajd Dibbiny out:
4201b5daf11SMajd Dibbiny 	kfree(out_mad);
4211b5daf11SMajd Dibbiny 
4221b5daf11SMajd Dibbiny 	return err;
4231b5daf11SMajd Dibbiny }
4241b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev * dev,char * node_desc)4251b5daf11SMajd Dibbiny int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
4261b5daf11SMajd Dibbiny {
427a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
428a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
4291b5daf11SMajd Dibbiny 	int err = -ENOMEM;
4301b5daf11SMajd Dibbiny 
4311b5daf11SMajd Dibbiny 	in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
4321b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
4331b5daf11SMajd Dibbiny 	if (!in_mad || !out_mad)
4341b5daf11SMajd Dibbiny 		goto out;
4351b5daf11SMajd Dibbiny 
436d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
4371b5daf11SMajd Dibbiny 	in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
4381b5daf11SMajd Dibbiny 
4391b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
4401b5daf11SMajd Dibbiny 	if (err)
4411b5daf11SMajd Dibbiny 		goto out;
4421b5daf11SMajd Dibbiny 
443bd99fdeaSYuval Shaia 	memcpy(node_desc, out_mad->data, IB_DEVICE_NODE_DESC_MAX);
4441b5daf11SMajd Dibbiny out:
4451b5daf11SMajd Dibbiny 	kfree(in_mad);
4461b5daf11SMajd Dibbiny 	kfree(out_mad);
4471b5daf11SMajd Dibbiny 	return err;
4481b5daf11SMajd Dibbiny }
4491b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev * dev,__be64 * node_guid)4501b5daf11SMajd Dibbiny int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid)
4511b5daf11SMajd Dibbiny {
452a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
453a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
4541b5daf11SMajd Dibbiny 	int err = -ENOMEM;
4551b5daf11SMajd Dibbiny 
4561b5daf11SMajd Dibbiny 	in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
4571b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
4581b5daf11SMajd Dibbiny 	if (!in_mad || !out_mad)
4591b5daf11SMajd Dibbiny 		goto out;
4601b5daf11SMajd Dibbiny 
461d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
4621b5daf11SMajd Dibbiny 	in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
4631b5daf11SMajd Dibbiny 
4641b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
4651b5daf11SMajd Dibbiny 	if (err)
4661b5daf11SMajd Dibbiny 		goto out;
4671b5daf11SMajd Dibbiny 
4681b5daf11SMajd Dibbiny 	memcpy(node_guid, out_mad->data + 12, 8);
4691b5daf11SMajd Dibbiny out:
4701b5daf11SMajd Dibbiny 	kfree(in_mad);
4711b5daf11SMajd Dibbiny 	kfree(out_mad);
4721b5daf11SMajd Dibbiny 	return err;
4731b5daf11SMajd Dibbiny }
4741b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_pkey(struct ib_device * ibdev,u32 port,u16 index,u16 * pkey)4751fb7f897SMark Bloch int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u32 port, u16 index,
4761b5daf11SMajd Dibbiny 			    u16 *pkey)
4771b5daf11SMajd Dibbiny {
478a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
479a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
4801b5daf11SMajd Dibbiny 	int err = -ENOMEM;
4811b5daf11SMajd Dibbiny 
4821b5daf11SMajd Dibbiny 	in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
4831b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
4841b5daf11SMajd Dibbiny 	if (!in_mad || !out_mad)
4851b5daf11SMajd Dibbiny 		goto out;
4861b5daf11SMajd Dibbiny 
487d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
4881b5daf11SMajd Dibbiny 	in_mad->attr_id  = IB_SMP_ATTR_PKEY_TABLE;
4891b5daf11SMajd Dibbiny 	in_mad->attr_mod = cpu_to_be32(index / 32);
4901b5daf11SMajd Dibbiny 
4911b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
4921b5daf11SMajd Dibbiny 			   out_mad);
4931b5daf11SMajd Dibbiny 	if (err)
4941b5daf11SMajd Dibbiny 		goto out;
4951b5daf11SMajd Dibbiny 
4961b5daf11SMajd Dibbiny 	*pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]);
4971b5daf11SMajd Dibbiny 
4981b5daf11SMajd Dibbiny out:
4991b5daf11SMajd Dibbiny 	kfree(in_mad);
5001b5daf11SMajd Dibbiny 	kfree(out_mad);
5011b5daf11SMajd Dibbiny 	return err;
5021b5daf11SMajd Dibbiny }
5031b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_gids(struct ib_device * ibdev,u32 port,int index,union ib_gid * gid)5041fb7f897SMark Bloch int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u32 port, int index,
5051b5daf11SMajd Dibbiny 			    union ib_gid *gid)
5061b5daf11SMajd Dibbiny {
507a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
508a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
5091b5daf11SMajd Dibbiny 	int err = -ENOMEM;
5101b5daf11SMajd Dibbiny 
5111b5daf11SMajd Dibbiny 	in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
5121b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
5131b5daf11SMajd Dibbiny 	if (!in_mad || !out_mad)
5141b5daf11SMajd Dibbiny 		goto out;
5151b5daf11SMajd Dibbiny 
516d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
5171b5daf11SMajd Dibbiny 	in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
5181b5daf11SMajd Dibbiny 	in_mad->attr_mod = cpu_to_be32(port);
5191b5daf11SMajd Dibbiny 
5201b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
5211b5daf11SMajd Dibbiny 			   out_mad);
5221b5daf11SMajd Dibbiny 	if (err)
5231b5daf11SMajd Dibbiny 		goto out;
5241b5daf11SMajd Dibbiny 
5251b5daf11SMajd Dibbiny 	memcpy(gid->raw, out_mad->data + 8, 8);
5261b5daf11SMajd Dibbiny 
527d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
5281b5daf11SMajd Dibbiny 	in_mad->attr_id  = IB_SMP_ATTR_GUID_INFO;
5291b5daf11SMajd Dibbiny 	in_mad->attr_mod = cpu_to_be32(index / 8);
5301b5daf11SMajd Dibbiny 
5311b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
5321b5daf11SMajd Dibbiny 			   out_mad);
5331b5daf11SMajd Dibbiny 	if (err)
5341b5daf11SMajd Dibbiny 		goto out;
5351b5daf11SMajd Dibbiny 
5361b5daf11SMajd Dibbiny 	memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
5371b5daf11SMajd Dibbiny 
5381b5daf11SMajd Dibbiny out:
5391b5daf11SMajd Dibbiny 	kfree(in_mad);
5401b5daf11SMajd Dibbiny 	kfree(out_mad);
5411b5daf11SMajd Dibbiny 	return err;
5421b5daf11SMajd Dibbiny }
5431b5daf11SMajd Dibbiny 
mlx5_query_mad_ifc_port(struct ib_device * ibdev,u32 port,struct ib_port_attr * props)5441fb7f897SMark Bloch int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u32 port,
5451b5daf11SMajd Dibbiny 			    struct ib_port_attr *props)
5461b5daf11SMajd Dibbiny {
5471b5daf11SMajd Dibbiny 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
5481b5daf11SMajd Dibbiny 	struct mlx5_core_dev *mdev = dev->mdev;
549a45e5f18SRuan Jinjie 	struct ib_smp *in_mad;
550a45e5f18SRuan Jinjie 	struct ib_smp *out_mad;
5511b5daf11SMajd Dibbiny 	int ext_active_speed;
5521b5daf11SMajd Dibbiny 	int err = -ENOMEM;
5531b5daf11SMajd Dibbiny 
5541b5daf11SMajd Dibbiny 	in_mad  = kzalloc(sizeof(*in_mad), GFP_KERNEL);
5551b5daf11SMajd Dibbiny 	out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
5561b5daf11SMajd Dibbiny 	if (!in_mad || !out_mad)
5571b5daf11SMajd Dibbiny 		goto out;
5581b5daf11SMajd Dibbiny 
559c4550c63SOr Gerlitz 	/* props being zeroed by the caller, avoid zeroing it here */
5601b5daf11SMajd Dibbiny 
561d82e2b27SLeon Romanovsky 	ib_init_query_mad(in_mad);
5621b5daf11SMajd Dibbiny 	in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
5631b5daf11SMajd Dibbiny 	in_mad->attr_mod = cpu_to_be32(port);
5641b5daf11SMajd Dibbiny 
5651b5daf11SMajd Dibbiny 	err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad);
5661b5daf11SMajd Dibbiny 	if (err) {
5671b5daf11SMajd Dibbiny 		mlx5_ib_warn(dev, "err %d\n", err);
5681b5daf11SMajd Dibbiny 		goto out;
5691b5daf11SMajd Dibbiny 	}
5701b5daf11SMajd Dibbiny 
5711b5daf11SMajd Dibbiny 	props->lid		= be16_to_cpup((__be16 *)(out_mad->data + 16));
5721b5daf11SMajd Dibbiny 	props->lmc		= out_mad->data[34] & 0x7;
5731b5daf11SMajd Dibbiny 	props->sm_lid		= be16_to_cpup((__be16 *)(out_mad->data + 18));
5741b5daf11SMajd Dibbiny 	props->sm_sl		= out_mad->data[36] & 0xf;
5751b5daf11SMajd Dibbiny 	props->state		= out_mad->data[32] & 0xf;
5761b5daf11SMajd Dibbiny 	props->phys_state	= out_mad->data[33] >> 4;
5771b5daf11SMajd Dibbiny 	props->port_cap_flags	= be32_to_cpup((__be32 *)(out_mad->data + 20));
5781b5daf11SMajd Dibbiny 	props->gid_tbl_len	= out_mad->data[50];
5791b5daf11SMajd Dibbiny 	props->max_msg_sz	= 1 << MLX5_CAP_GEN(mdev, log_max_msg);
5802019d70eSParav Pandit 	props->pkey_tbl_len	= dev->pkey_table_len;
5811b5daf11SMajd Dibbiny 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *)(out_mad->data + 46));
5821b5daf11SMajd Dibbiny 	props->qkey_viol_cntr	= be16_to_cpup((__be16 *)(out_mad->data + 48));
5831b5daf11SMajd Dibbiny 	props->active_width	= out_mad->data[31] & 0xf;
5841b5daf11SMajd Dibbiny 	props->active_speed	= out_mad->data[35] >> 4;
5851b5daf11SMajd Dibbiny 	props->max_mtu		= out_mad->data[41] & 0xf;
5861b5daf11SMajd Dibbiny 	props->active_mtu	= out_mad->data[36] >> 4;
5871b5daf11SMajd Dibbiny 	props->subnet_timeout	= out_mad->data[51] & 0x1f;
5881b5daf11SMajd Dibbiny 	props->max_vl_num	= out_mad->data[37] >> 4;
5891b5daf11SMajd Dibbiny 	props->init_type_reply	= out_mad->data[41] >> 4;
5901b5daf11SMajd Dibbiny 
591d764970bSMichael Guralnik 	if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP) {
5924106a758SMichael Guralnik 		props->port_cap_flags2 =
5934106a758SMichael Guralnik 			be16_to_cpup((__be16 *)(out_mad->data + 60));
5944106a758SMichael Guralnik 
595d764970bSMichael Guralnik 		if (props->port_cap_flags2 & IB_PORT_LINK_WIDTH_2X_SUP)
596d764970bSMichael Guralnik 			props->active_width = out_mad->data[31] & 0x1f;
597d764970bSMichael Guralnik 	}
598d764970bSMichael Guralnik 
5991b5daf11SMajd Dibbiny 	/* Check if extended speeds (EDR/FDR/...) are supported */
6001b5daf11SMajd Dibbiny 	if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
6011b5daf11SMajd Dibbiny 		ext_active_speed = out_mad->data[62] >> 4;
6021b5daf11SMajd Dibbiny 
6031b5daf11SMajd Dibbiny 		switch (ext_active_speed) {
6041b5daf11SMajd Dibbiny 		case 1:
6051b5daf11SMajd Dibbiny 			props->active_speed = 16; /* FDR */
6061b5daf11SMajd Dibbiny 			break;
6071b5daf11SMajd Dibbiny 		case 2:
6081b5daf11SMajd Dibbiny 			props->active_speed = 32; /* EDR */
6091b5daf11SMajd Dibbiny 			break;
610b874155aSMichael Guralnik 		case 4:
611b874155aSMichael Guralnik 			if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
612b874155aSMichael Guralnik 			    props->port_cap_flags2 & IB_PORT_LINK_SPEED_HDR_SUP)
613b874155aSMichael Guralnik 				props->active_speed = IB_SPEED_HDR;
614b874155aSMichael Guralnik 			break;
615fbdb0ba7SMaher Sanalla 		case 8:
616fbdb0ba7SMaher Sanalla 			if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
617fbdb0ba7SMaher Sanalla 			    props->port_cap_flags2 & IB_PORT_LINK_SPEED_NDR_SUP)
618fbdb0ba7SMaher Sanalla 				props->active_speed = IB_SPEED_NDR;
619fbdb0ba7SMaher Sanalla 			break;
6201b5daf11SMajd Dibbiny 		}
6211b5daf11SMajd Dibbiny 	}
6221b5daf11SMajd Dibbiny 
623561b4a3aSOr Har-Toov 	/* Check if extended speeds 2 (XDR/...) are supported */
624561b4a3aSOr Har-Toov 	if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
625561b4a3aSOr Har-Toov 	    props->port_cap_flags2 & IB_PORT_EXTENDED_SPEEDS2_SUP) {
626561b4a3aSOr Har-Toov 		ext_active_speed = (out_mad->data[56] >> 4) & 0x6;
627561b4a3aSOr Har-Toov 
628561b4a3aSOr Har-Toov 		switch (ext_active_speed) {
629561b4a3aSOr Har-Toov 		case 2:
630561b4a3aSOr Har-Toov 			if (props->port_cap_flags2 & IB_PORT_LINK_SPEED_XDR_SUP)
631561b4a3aSOr Har-Toov 				props->active_speed = IB_SPEED_XDR;
632561b4a3aSOr Har-Toov 			break;
633561b4a3aSOr Har-Toov 		}
634561b4a3aSOr Har-Toov 	}
635561b4a3aSOr Har-Toov 
6361b5daf11SMajd Dibbiny 	/* If reported active speed is QDR, check if is FDR-10 */
6371b5daf11SMajd Dibbiny 	if (props->active_speed == 4) {
6383ce60f44SParav Pandit 		if (dev->port_caps[port - 1].ext_port_cap &
6391b5daf11SMajd Dibbiny 		    MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
640d82e2b27SLeon Romanovsky 			ib_init_query_mad(in_mad);
6411b5daf11SMajd Dibbiny 			in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
6421b5daf11SMajd Dibbiny 			in_mad->attr_mod = cpu_to_be32(port);
6431b5daf11SMajd Dibbiny 
6441b5daf11SMajd Dibbiny 			err = mlx5_MAD_IFC(dev, 1, 1, port,
6451b5daf11SMajd Dibbiny 					   NULL, NULL, in_mad, out_mad);
6461b5daf11SMajd Dibbiny 			if (err)
6471b5daf11SMajd Dibbiny 				goto out;
6481b5daf11SMajd Dibbiny 
6491b5daf11SMajd Dibbiny 			/* Checking LinkSpeedActive for FDR-10 */
6501b5daf11SMajd Dibbiny 			if (out_mad->data[15] & 0x1)
6511b5daf11SMajd Dibbiny 				props->active_speed = 8;
6521b5daf11SMajd Dibbiny 		}
6531b5daf11SMajd Dibbiny 	}
6541b5daf11SMajd Dibbiny 
6551b5daf11SMajd Dibbiny out:
6561b5daf11SMajd Dibbiny 	kfree(in_mad);
6571b5daf11SMajd Dibbiny 	kfree(out_mad);
6581b5daf11SMajd Dibbiny 
6591b5daf11SMajd Dibbiny 	return err;
6601b5daf11SMajd Dibbiny }
661