xref: /linux/drivers/net/ethernet/mellanox/mlx4/fw.c (revision 40fb4fc1e18bc641a0d0887ac21943fd194c1fa9)
15a2cc190SJeff Kirsher /*
25a2cc190SJeff Kirsher  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
35a2cc190SJeff Kirsher  * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
45a2cc190SJeff Kirsher  * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc.  All rights reserved.
55a2cc190SJeff Kirsher  *
65a2cc190SJeff Kirsher  * This software is available to you under a choice of one of two
75a2cc190SJeff Kirsher  * licenses.  You may choose to be licensed under the terms of the GNU
85a2cc190SJeff Kirsher  * General Public License (GPL) Version 2, available from the file
95a2cc190SJeff Kirsher  * COPYING in the main directory of this source tree, or the
105a2cc190SJeff Kirsher  * OpenIB.org BSD license below:
115a2cc190SJeff Kirsher  *
125a2cc190SJeff Kirsher  *     Redistribution and use in source and binary forms, with or
135a2cc190SJeff Kirsher  *     without modification, are permitted provided that the following
145a2cc190SJeff Kirsher  *     conditions are met:
155a2cc190SJeff Kirsher  *
165a2cc190SJeff Kirsher  *      - Redistributions of source code must retain the above
175a2cc190SJeff Kirsher  *        copyright notice, this list of conditions and the following
185a2cc190SJeff Kirsher  *        disclaimer.
195a2cc190SJeff Kirsher  *
205a2cc190SJeff Kirsher  *      - Redistributions in binary form must reproduce the above
215a2cc190SJeff Kirsher  *        copyright notice, this list of conditions and the following
225a2cc190SJeff Kirsher  *        disclaimer in the documentation and/or other materials
235a2cc190SJeff Kirsher  *        provided with the distribution.
245a2cc190SJeff Kirsher  *
255a2cc190SJeff Kirsher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
265a2cc190SJeff Kirsher  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
275a2cc190SJeff Kirsher  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
285a2cc190SJeff Kirsher  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
295a2cc190SJeff Kirsher  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
305a2cc190SJeff Kirsher  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
315a2cc190SJeff Kirsher  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
325a2cc190SJeff Kirsher  * SOFTWARE.
335a2cc190SJeff Kirsher  */
345a2cc190SJeff Kirsher 
355cc914f1SMarcel Apfelbaum #include <linux/etherdevice.h>
365a2cc190SJeff Kirsher #include <linux/mlx4/cmd.h>
379d9779e7SPaul Gortmaker #include <linux/module.h>
385a2cc190SJeff Kirsher #include <linux/cache.h>
395a2cc190SJeff Kirsher 
405a2cc190SJeff Kirsher #include "fw.h"
415a2cc190SJeff Kirsher #include "icm.h"
425a2cc190SJeff Kirsher 
435a2cc190SJeff Kirsher enum {
445a2cc190SJeff Kirsher 	MLX4_COMMAND_INTERFACE_MIN_REV		= 2,
455a2cc190SJeff Kirsher 	MLX4_COMMAND_INTERFACE_MAX_REV		= 3,
465a2cc190SJeff Kirsher 	MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS	= 3,
475a2cc190SJeff Kirsher };
485a2cc190SJeff Kirsher 
495a2cc190SJeff Kirsher extern void __buggy_use_of_MLX4_GET(void);
505a2cc190SJeff Kirsher extern void __buggy_use_of_MLX4_PUT(void);
515a2cc190SJeff Kirsher 
5272da2e91SMoshe Lazer static bool enable_qos;
535a2cc190SJeff Kirsher module_param(enable_qos, bool, 0444);
5472da2e91SMoshe Lazer MODULE_PARM_DESC(enable_qos, "Enable Enhanced QoS support (default: off)");
555a2cc190SJeff Kirsher 
565a2cc190SJeff Kirsher #define MLX4_GET(dest, source, offset)				      \
575a2cc190SJeff Kirsher 	do {							      \
585a2cc190SJeff Kirsher 		void *__p = (char *) (source) + (offset);	      \
5917d5ceb6SDavid Ahern 		u64 val;                                              \
605a2cc190SJeff Kirsher 		switch (sizeof (dest)) {			      \
615a2cc190SJeff Kirsher 		case 1: (dest) = *(u8 *) __p;	    break;	      \
625a2cc190SJeff Kirsher 		case 2: (dest) = be16_to_cpup(__p); break;	      \
635a2cc190SJeff Kirsher 		case 4: (dest) = be32_to_cpup(__p); break;	      \
6417d5ceb6SDavid Ahern 		case 8: val = get_unaligned((u64 *)__p);              \
6517d5ceb6SDavid Ahern 			(dest) = be64_to_cpu(val);  break;            \
665a2cc190SJeff Kirsher 		default: __buggy_use_of_MLX4_GET();		      \
675a2cc190SJeff Kirsher 		}						      \
685a2cc190SJeff Kirsher 	} while (0)
695a2cc190SJeff Kirsher 
705a2cc190SJeff Kirsher #define MLX4_PUT(dest, source, offset)				      \
715a2cc190SJeff Kirsher 	do {							      \
725a2cc190SJeff Kirsher 		void *__d = ((char *) (dest) + (offset));	      \
735a2cc190SJeff Kirsher 		switch (sizeof(source)) {			      \
745a2cc190SJeff Kirsher 		case 1: *(u8 *) __d = (source);		       break; \
755a2cc190SJeff Kirsher 		case 2:	*(__be16 *) __d = cpu_to_be16(source); break; \
765a2cc190SJeff Kirsher 		case 4:	*(__be32 *) __d = cpu_to_be32(source); break; \
775a2cc190SJeff Kirsher 		case 8:	*(__be64 *) __d = cpu_to_be64(source); break; \
785a2cc190SJeff Kirsher 		default: __buggy_use_of_MLX4_PUT();		      \
795a2cc190SJeff Kirsher 		}						      \
805a2cc190SJeff Kirsher 	} while (0)
815a2cc190SJeff Kirsher 
825a2cc190SJeff Kirsher static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
835a2cc190SJeff Kirsher {
845a2cc190SJeff Kirsher 	static const char *fname[] = {
855a2cc190SJeff Kirsher 		[ 0] = "RC transport",
865a2cc190SJeff Kirsher 		[ 1] = "UC transport",
875a2cc190SJeff Kirsher 		[ 2] = "UD transport",
885a2cc190SJeff Kirsher 		[ 3] = "XRC transport",
895a2cc190SJeff Kirsher 		[ 6] = "SRQ support",
905a2cc190SJeff Kirsher 		[ 7] = "IPoIB checksum offload",
915a2cc190SJeff Kirsher 		[ 8] = "P_Key violation counter",
925a2cc190SJeff Kirsher 		[ 9] = "Q_Key violation counter",
934d531aa8SOr Gerlitz 		[12] = "Dual Port Different Protocol (DPDP) support",
945a2cc190SJeff Kirsher 		[15] = "Big LSO headers",
955a2cc190SJeff Kirsher 		[16] = "MW support",
965a2cc190SJeff Kirsher 		[17] = "APM support",
975a2cc190SJeff Kirsher 		[18] = "Atomic ops support",
985a2cc190SJeff Kirsher 		[19] = "Raw multicast support",
995a2cc190SJeff Kirsher 		[20] = "Address vector port checking support",
1005a2cc190SJeff Kirsher 		[21] = "UD multicast support",
1015a2cc190SJeff Kirsher 		[30] = "IBoE support",
1025a2cc190SJeff Kirsher 		[32] = "Unicast loopback support",
103f3a9d1f2SYevgeny Petrilin 		[34] = "FCS header control",
104cb2147a9SOr Gerlitz 		[37] = "Wake On LAN (port1) support",
105cb2147a9SOr Gerlitz 		[38] = "Wake On LAN (port2) support",
1065a2cc190SJeff Kirsher 		[40] = "UDP RSS support",
1075a2cc190SJeff Kirsher 		[41] = "Unicast VEP steering support",
1085a2cc190SJeff Kirsher 		[42] = "Multicast VEP steering support",
1095a2cc190SJeff Kirsher 		[48] = "Counters support",
110802f42a8SIdo Shamay 		[52] = "RSS IP fragments support",
111540b3a39SOr Gerlitz 		[53] = "Port ETS Scheduler support",
1124d531aa8SOr Gerlitz 		[55] = "Port link type sensing support",
11300f5ce99SJack Morgenstein 		[59] = "Port management change event support",
11408ff3235SOr Gerlitz 		[61] = "64 byte EQE support",
11508ff3235SOr Gerlitz 		[62] = "64 byte CQE support",
1165a2cc190SJeff Kirsher 	};
1175a2cc190SJeff Kirsher 	int i;
1185a2cc190SJeff Kirsher 
1195a2cc190SJeff Kirsher 	mlx4_dbg(dev, "DEV_CAP flags:\n");
1205a2cc190SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(fname); ++i)
1215a2cc190SJeff Kirsher 		if (fname[i] && (flags & (1LL << i)))
1225a2cc190SJeff Kirsher 			mlx4_dbg(dev, "    %s\n", fname[i]);
1235a2cc190SJeff Kirsher }
1245a2cc190SJeff Kirsher 
125b3416f44SShlomo Pongratz static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
126b3416f44SShlomo Pongratz {
127b3416f44SShlomo Pongratz 	static const char * const fname[] = {
128b3416f44SShlomo Pongratz 		[0] = "RSS support",
129b3416f44SShlomo Pongratz 		[1] = "RSS Toeplitz Hash Function support",
1300ff1fb65SHadar Hen Zion 		[2] = "RSS XOR Hash Function support",
13156cb4567SOr Gerlitz 		[3] = "Device managed flow steering support",
132d998735fSEugenia Emantayev 		[4] = "Automatic MAC reassignment support",
1334e8cf5b8SOr Gerlitz 		[5] = "Time stamping support",
1344e8cf5b8SOr Gerlitz 		[6] = "VST (control vlan insertion/stripping) support",
135b01978caSJack Morgenstein 		[7] = "FSM (MAC anti-spoofing) support",
1367ffdf726SOr Gerlitz 		[8] = "Dynamic QP updates support",
13756cb4567SOr Gerlitz 		[9] = "Device managed flow steering IPoIB support",
138114840c3SJack Morgenstein 		[10] = "TCP/IP offloads/flow-steering for VXLAN support",
13977507aa2SIdo Shamay 		[11] = "MAD DEMUX (Secure-Host) support",
14077507aa2SIdo Shamay 		[12] = "Large cache line (>64B) CQE stride support",
141adbc7ac5SSaeed Mahameed 		[13] = "Large cache line (>64B) EQE stride support",
142a53e3e8cSSaeed Mahameed 		[14] = "Ethernet protocol control support",
143d475c95bSMatan Barak 		[15] = "Ethernet Backplane autoneg support",
1447ae0e400SMatan Barak 		[16] = "CONFIG DEV support",
145de966c59SMatan Barak 		[17] = "Asymmetric EQs support",
1467d077cd3SMatan Barak 		[18] = "More than 80 VFs support",
147be6a6b43SJack Morgenstein 		[19] = "Performance optimized for limited rule configuration flow steering support",
14859e14e32SMoni Shoua 		[20] = "Recoverable error events support",
149d237baa1SShani Michaeli 		[21] = "Port Remap support",
150fc31e256SOr Gerlitz 		[22] = "QCN support",
1510b131561SMatan Barak 		[23] = "QP rate limiting support",
152d019fcb2SIdo Shamay 		[24] = "Ethernet Flow control statistics support",
153d019fcb2SIdo Shamay 		[25] = "Granular QoS per VF support",
1543742cc65SIdo Shamay 		[26] = "Port ETS Scheduler support",
15551af33cfSIdo Shamay 		[27] = "Port beacon support",
15678500b8cSMuhammad Mahajna 		[28] = "RX-ALL support",
15777fc29c4SHadar Hen Zion 		[29] = "802.1ad offload support",
1589a892835SMaor Gottlieb 		[31] = "Modifying loopback source checks using UPDATE_QP support",
1599a892835SMaor Gottlieb 		[32] = "Loopback source checks support",
1600e451e88SMarina Varshaver 		[33] = "RoCEv2 support",
1617c3d21c8SMoshe Shemesh 		[34] = "DMFS Sniffer support (UC & MC)",
1627c3d21c8SMoshe Shemesh 		[35] = "QinQ VST mode support",
163fd10ed8eSJack Morgenstein 		[36] = "sl to vl mapping table change event support"
164b3416f44SShlomo Pongratz 	};
165b3416f44SShlomo Pongratz 	int i;
166b3416f44SShlomo Pongratz 
167b3416f44SShlomo Pongratz 	for (i = 0; i < ARRAY_SIZE(fname); ++i)
168b3416f44SShlomo Pongratz 		if (fname[i] && (flags & (1LL << i)))
169b3416f44SShlomo Pongratz 			mlx4_dbg(dev, "    %s\n", fname[i]);
170b3416f44SShlomo Pongratz }
171b3416f44SShlomo Pongratz 
1725a2cc190SJeff Kirsher int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
1735a2cc190SJeff Kirsher {
1745a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
1755a2cc190SJeff Kirsher 	u32 *inbox;
1765a2cc190SJeff Kirsher 	int err = 0;
1775a2cc190SJeff Kirsher 
1785a2cc190SJeff Kirsher #define MOD_STAT_CFG_IN_SIZE		0x100
1795a2cc190SJeff Kirsher 
1805a2cc190SJeff Kirsher #define MOD_STAT_CFG_PG_SZ_M_OFFSET	0x002
1815a2cc190SJeff Kirsher #define MOD_STAT_CFG_PG_SZ_OFFSET	0x003
1825a2cc190SJeff Kirsher 
1835a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
1845a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
1855a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
1865a2cc190SJeff Kirsher 	inbox = mailbox->buf;
1875a2cc190SJeff Kirsher 
1885a2cc190SJeff Kirsher 	MLX4_PUT(inbox, cfg->log_pg_sz, MOD_STAT_CFG_PG_SZ_OFFSET);
1895a2cc190SJeff Kirsher 	MLX4_PUT(inbox, cfg->log_pg_sz_m, MOD_STAT_CFG_PG_SZ_M_OFFSET);
1905a2cc190SJeff Kirsher 
1915a2cc190SJeff Kirsher 	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_MOD_STAT_CFG,
192f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1935a2cc190SJeff Kirsher 
1945a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
1955a2cc190SJeff Kirsher 	return err;
1965a2cc190SJeff Kirsher }
1975a2cc190SJeff Kirsher 
198e8c4265bSMatan Barak int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave)
199e8c4265bSMatan Barak {
200e8c4265bSMatan Barak 	struct mlx4_cmd_mailbox *mailbox;
201e8c4265bSMatan Barak 	u32 *outbox;
202e8c4265bSMatan Barak 	u8 in_modifier;
203e8c4265bSMatan Barak 	u8 field;
204e8c4265bSMatan Barak 	u16 field16;
205e8c4265bSMatan Barak 	int err;
206e8c4265bSMatan Barak 
207e8c4265bSMatan Barak #define QUERY_FUNC_BUS_OFFSET			0x00
208e8c4265bSMatan Barak #define QUERY_FUNC_DEVICE_OFFSET		0x01
209e8c4265bSMatan Barak #define QUERY_FUNC_FUNCTION_OFFSET		0x01
210e8c4265bSMatan Barak #define QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET	0x03
211e8c4265bSMatan Barak #define QUERY_FUNC_RSVD_EQS_OFFSET		0x04
212e8c4265bSMatan Barak #define QUERY_FUNC_MAX_EQ_OFFSET		0x06
213e8c4265bSMatan Barak #define QUERY_FUNC_RSVD_UARS_OFFSET		0x0b
214e8c4265bSMatan Barak 
215e8c4265bSMatan Barak 	mailbox = mlx4_alloc_cmd_mailbox(dev);
216e8c4265bSMatan Barak 	if (IS_ERR(mailbox))
217e8c4265bSMatan Barak 		return PTR_ERR(mailbox);
218e8c4265bSMatan Barak 	outbox = mailbox->buf;
219e8c4265bSMatan Barak 
220e8c4265bSMatan Barak 	in_modifier = slave;
221e8c4265bSMatan Barak 
222e8c4265bSMatan Barak 	err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, 0,
223e8c4265bSMatan Barak 			   MLX4_CMD_QUERY_FUNC,
224e8c4265bSMatan Barak 			   MLX4_CMD_TIME_CLASS_A,
225e8c4265bSMatan Barak 			   MLX4_CMD_NATIVE);
226e8c4265bSMatan Barak 	if (err)
227e8c4265bSMatan Barak 		goto out;
228e8c4265bSMatan Barak 
229e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_BUS_OFFSET);
230e8c4265bSMatan Barak 	func->bus = field & 0xf;
231e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_DEVICE_OFFSET);
232e8c4265bSMatan Barak 	func->device = field & 0xf1;
233e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_FUNCTION_OFFSET);
234e8c4265bSMatan Barak 	func->function = field & 0x7;
235e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET);
236e8c4265bSMatan Barak 	func->physical_function = field & 0xf;
237e8c4265bSMatan Barak 	MLX4_GET(field16, outbox, QUERY_FUNC_RSVD_EQS_OFFSET);
238e8c4265bSMatan Barak 	func->rsvd_eqs = field16 & 0xffff;
239e8c4265bSMatan Barak 	MLX4_GET(field16, outbox, QUERY_FUNC_MAX_EQ_OFFSET);
240e8c4265bSMatan Barak 	func->max_eq = field16 & 0xffff;
241e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_RSVD_UARS_OFFSET);
242e8c4265bSMatan Barak 	func->rsvd_uars = field & 0x0f;
243e8c4265bSMatan Barak 
244e8c4265bSMatan Barak 	mlx4_dbg(dev, "Bus: %d, Device: %d, Function: %d, Physical function: %d, Max EQs: %d, Reserved EQs: %d, Reserved UARs: %d\n",
245e8c4265bSMatan Barak 		 func->bus, func->device, func->function, func->physical_function,
246e8c4265bSMatan Barak 		 func->max_eq, func->rsvd_eqs, func->rsvd_uars);
247e8c4265bSMatan Barak 
248e8c4265bSMatan Barak out:
249e8c4265bSMatan Barak 	mlx4_free_cmd_mailbox(dev, mailbox);
250e8c4265bSMatan Barak 	return err;
251e8c4265bSMatan Barak }
252e8c4265bSMatan Barak 
253b42959dcSMoshe Shemesh static int mlx4_activate_vst_qinq(struct mlx4_priv *priv, int slave, int port)
254b42959dcSMoshe Shemesh {
255b42959dcSMoshe Shemesh 	struct mlx4_vport_oper_state *vp_oper;
256b42959dcSMoshe Shemesh 	struct mlx4_vport_state *vp_admin;
257b42959dcSMoshe Shemesh 	int err;
258b42959dcSMoshe Shemesh 
259b42959dcSMoshe Shemesh 	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
260b42959dcSMoshe Shemesh 	vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
261b42959dcSMoshe Shemesh 
262b42959dcSMoshe Shemesh 	if (vp_admin->default_vlan != vp_oper->state.default_vlan) {
263b42959dcSMoshe Shemesh 		err = __mlx4_register_vlan(&priv->dev, port,
264b42959dcSMoshe Shemesh 					   vp_admin->default_vlan,
265b42959dcSMoshe Shemesh 					   &vp_oper->vlan_idx);
266b42959dcSMoshe Shemesh 		if (err) {
267b42959dcSMoshe Shemesh 			vp_oper->vlan_idx = NO_INDX;
268b42959dcSMoshe Shemesh 			mlx4_warn(&priv->dev,
269b42959dcSMoshe Shemesh 				  "No vlan resources slave %d, port %d\n",
270b42959dcSMoshe Shemesh 				  slave, port);
271b42959dcSMoshe Shemesh 			return err;
272b42959dcSMoshe Shemesh 		}
273b42959dcSMoshe Shemesh 		mlx4_dbg(&priv->dev, "alloc vlan %d idx  %d slave %d port %d\n",
274b42959dcSMoshe Shemesh 			 (int)(vp_oper->state.default_vlan),
275b42959dcSMoshe Shemesh 			 vp_oper->vlan_idx, slave, port);
276b42959dcSMoshe Shemesh 	}
277b42959dcSMoshe Shemesh 	vp_oper->state.vlan_proto   = vp_admin->vlan_proto;
278b42959dcSMoshe Shemesh 	vp_oper->state.default_vlan = vp_admin->default_vlan;
279b42959dcSMoshe Shemesh 	vp_oper->state.default_qos  = vp_admin->default_qos;
280b42959dcSMoshe Shemesh 
281b42959dcSMoshe Shemesh 	return 0;
282b42959dcSMoshe Shemesh }
283b42959dcSMoshe Shemesh 
284b42959dcSMoshe Shemesh static int mlx4_handle_vst_qinq(struct mlx4_priv *priv, int slave, int port)
285b42959dcSMoshe Shemesh {
286b42959dcSMoshe Shemesh 	struct mlx4_vport_oper_state *vp_oper;
287b42959dcSMoshe Shemesh 	struct mlx4_slave_state *slave_state;
288b42959dcSMoshe Shemesh 	struct mlx4_vport_state *vp_admin;
289b42959dcSMoshe Shemesh 	int err;
290b42959dcSMoshe Shemesh 
291b42959dcSMoshe Shemesh 	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
292b42959dcSMoshe Shemesh 	vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
293b42959dcSMoshe Shemesh 	slave_state = &priv->mfunc.master.slave_state[slave];
294b42959dcSMoshe Shemesh 
295b42959dcSMoshe Shemesh 	if ((vp_admin->vlan_proto != htons(ETH_P_8021AD)) ||
296b42959dcSMoshe Shemesh 	    (!slave_state->active))
297b42959dcSMoshe Shemesh 		return 0;
298b42959dcSMoshe Shemesh 
299b42959dcSMoshe Shemesh 	if (vp_oper->state.vlan_proto == vp_admin->vlan_proto &&
300b42959dcSMoshe Shemesh 	    vp_oper->state.default_vlan == vp_admin->default_vlan &&
301b42959dcSMoshe Shemesh 	    vp_oper->state.default_qos == vp_admin->default_qos)
302b42959dcSMoshe Shemesh 		return 0;
303b42959dcSMoshe Shemesh 
304b42959dcSMoshe Shemesh 	if (!slave_state->vst_qinq_supported) {
305b42959dcSMoshe Shemesh 		/* Warn and revert the request to set vst QinQ mode */
306b42959dcSMoshe Shemesh 		vp_admin->vlan_proto   = vp_oper->state.vlan_proto;
307b42959dcSMoshe Shemesh 		vp_admin->default_vlan = vp_oper->state.default_vlan;
308b42959dcSMoshe Shemesh 		vp_admin->default_qos  = vp_oper->state.default_qos;
309b42959dcSMoshe Shemesh 
310b42959dcSMoshe Shemesh 		mlx4_warn(&priv->dev,
311b42959dcSMoshe Shemesh 			  "Slave %d does not support VST QinQ mode\n", slave);
312b42959dcSMoshe Shemesh 		return 0;
313b42959dcSMoshe Shemesh 	}
314b42959dcSMoshe Shemesh 
315b42959dcSMoshe Shemesh 	err = mlx4_activate_vst_qinq(priv, slave, port);
316b42959dcSMoshe Shemesh 	return err;
317b42959dcSMoshe Shemesh }
318b42959dcSMoshe Shemesh 
3195cc914f1SMarcel Apfelbaum int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
3205cc914f1SMarcel Apfelbaum 				struct mlx4_vhcr *vhcr,
3215cc914f1SMarcel Apfelbaum 				struct mlx4_cmd_mailbox *inbox,
3225cc914f1SMarcel Apfelbaum 				struct mlx4_cmd_mailbox *outbox,
3235cc914f1SMarcel Apfelbaum 				struct mlx4_cmd_info *cmd)
3245cc914f1SMarcel Apfelbaum {
3255a0d0a61SJack Morgenstein 	struct mlx4_priv *priv = mlx4_priv(dev);
32699ec41d0SJack Morgenstein 	u8	field, port;
32799ec41d0SJack Morgenstein 	u32	size, proxy_qp, qkey;
3285cc914f1SMarcel Apfelbaum 	int	err = 0;
3297ae0e400SMatan Barak 	struct mlx4_func func;
3305cc914f1SMarcel Apfelbaum 
3315cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_FLAGS_OFFSET		0x0
3325cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET		0x1
3335cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PF_BHVR_OFFSET		0x4
334105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_OFFSET		0x8
335eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP	0x10
336eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP	0x14
337eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP	0x18
338eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP	0x20
339eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP	0x24
340eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP	0x28
3415cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_MAX_EQ_OFFSET		0x2c
34269612b9fSRoland Dreier #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET	0x30
343f0ce0615SJack Morgenstein #define QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET	0x48
3445cc914f1SMarcel Apfelbaum 
345eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET		0x50
346eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET		0x54
347eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET		0x58
348eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET		0x60
349eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET		0x64
350eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET		0x68
351eb456a68SJack Morgenstein 
352ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET	0x6c
353ddae0349SEugenia Emantayev 
354105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_FLAG			0x80
355105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RDMA		0x40
356105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_ETH			0x80
357eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_QUOTAS		0x10
358f0ce0615SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RESD_LKEY		0x08
359ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX	0x04
360ddae0349SEugenia Emantayev 
361ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG	(1UL << 31)
362d57febe1SMatan Barak #define QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG	(1UL << 30)
363105c320fSJack Morgenstein 
364105c320fSJack Morgenstein /* when opcode modifier = 1 */
3655cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET		0x3
36699ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET	0x4
36773e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_OFFSET		0x8
36873e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_OFFSET		0xc
3695cc914f1SMarcel Apfelbaum 
37047605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_TUNNEL		0x10
37147605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_PROXY		0x14
37247605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_TUNNEL		0x18
37347605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_PROXY		0x1c
3748e1a28e8SHadar Hen Zion #define QUERY_FUNC_CAP_PHYS_PORT_ID		0x28
37547605df9SJack Morgenstein 
37673e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_MAC		0x40
37773e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN	0x80
378eb17711bSHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_NIC_INFO			0x10
37999ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_VF_ENABLE_QP0		0x08
380105c320fSJack Morgenstein 
38173e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80
38277fc29c4SHadar Hen Zion #define QUERY_FUNC_CAP_PHV_BIT			0x40
3837c3d21c8SMoshe Shemesh #define QUERY_FUNC_CAP_VLAN_OFFLOAD_DISABLE	0x20
384105c320fSJack Morgenstein 
385b42959dcSMoshe Shemesh #define QUERY_FUNC_CAP_SUPPORTS_VST_QINQ	BIT(30)
386b42959dcSMoshe Shemesh #define QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS BIT(31)
387b42959dcSMoshe Shemesh 
3885cc914f1SMarcel Apfelbaum 	if (vhcr->op_modifier == 1) {
389449fc488SMatan Barak 		struct mlx4_active_ports actv_ports =
390449fc488SMatan Barak 			mlx4_get_active_ports(dev, slave);
391449fc488SMatan Barak 		int converted_port = mlx4_slave_convert_port(
392449fc488SMatan Barak 				dev, slave, vhcr->in_modifier);
393b42959dcSMoshe Shemesh 		struct mlx4_vport_oper_state *vp_oper;
394449fc488SMatan Barak 
395449fc488SMatan Barak 		if (converted_port < 0)
396449fc488SMatan Barak 			return -EINVAL;
397449fc488SMatan Barak 
398449fc488SMatan Barak 		vhcr->in_modifier = converted_port;
399449fc488SMatan Barak 		/* phys-port = logical-port */
400449fc488SMatan Barak 		field = vhcr->in_modifier -
401449fc488SMatan Barak 			find_first_bit(actv_ports.ports, dev->caps.num_ports);
40247605df9SJack Morgenstein 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
40347605df9SJack Morgenstein 
40499ec41d0SJack Morgenstein 		port = vhcr->in_modifier;
40599ec41d0SJack Morgenstein 		proxy_qp = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1;
40699ec41d0SJack Morgenstein 
40799ec41d0SJack Morgenstein 		/* Set nic_info bit to mark new fields support */
40899ec41d0SJack Morgenstein 		field  = QUERY_FUNC_CAP_FLAGS1_NIC_INFO;
40999ec41d0SJack Morgenstein 
41099ec41d0SJack Morgenstein 		if (mlx4_vf_smi_enabled(dev, slave, port) &&
41199ec41d0SJack Morgenstein 		    !mlx4_get_parav_qkey(dev, proxy_qp, &qkey)) {
41299ec41d0SJack Morgenstein 			field |= QUERY_FUNC_CAP_VF_ENABLE_QP0;
41399ec41d0SJack Morgenstein 			MLX4_PUT(outbox->buf, qkey,
41499ec41d0SJack Morgenstein 				 QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);
41599ec41d0SJack Morgenstein 		}
41699ec41d0SJack Morgenstein 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET);
41799ec41d0SJack Morgenstein 
41847605df9SJack Morgenstein 		/* size is now the QP number */
41999ec41d0SJack Morgenstein 		size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1;
42047605df9SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL);
42147605df9SJack Morgenstein 
42247605df9SJack Morgenstein 		size += 2;
42347605df9SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL);
42447605df9SJack Morgenstein 
42599ec41d0SJack Morgenstein 		MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP0_PROXY);
42699ec41d0SJack Morgenstein 		proxy_qp += 2;
42799ec41d0SJack Morgenstein 		MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP1_PROXY);
42847605df9SJack Morgenstein 
4298e1a28e8SHadar Hen Zion 		MLX4_PUT(outbox->buf, dev->caps.phys_port_id[vhcr->in_modifier],
4308e1a28e8SHadar Hen Zion 			 QUERY_FUNC_CAP_PHYS_PORT_ID);
4318e1a28e8SHadar Hen Zion 
432b42959dcSMoshe Shemesh 		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
433b42959dcSMoshe Shemesh 		err = mlx4_handle_vst_qinq(priv, slave, port);
434b42959dcSMoshe Shemesh 		if (err)
435b42959dcSMoshe Shemesh 			return err;
436b42959dcSMoshe Shemesh 
4377c3d21c8SMoshe Shemesh 		field = 0;
4387c3d21c8SMoshe Shemesh 		if (dev->caps.phv_bit[port])
4397c3d21c8SMoshe Shemesh 			field |= QUERY_FUNC_CAP_PHV_BIT;
4407c3d21c8SMoshe Shemesh 		if (vp_oper->state.vlan_proto == htons(ETH_P_8021AD))
4417c3d21c8SMoshe Shemesh 			field |= QUERY_FUNC_CAP_VLAN_OFFLOAD_DISABLE;
4427c3d21c8SMoshe Shemesh 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS0_OFFSET);
44377fc29c4SHadar Hen Zion 
4445cc914f1SMarcel Apfelbaum 	} else if (vhcr->op_modifier == 0) {
445449fc488SMatan Barak 		struct mlx4_active_ports actv_ports =
446449fc488SMatan Barak 			mlx4_get_active_ports(dev, slave);
447b42959dcSMoshe Shemesh 		struct mlx4_slave_state *slave_state =
448b42959dcSMoshe Shemesh 			&priv->mfunc.master.slave_state[slave];
449b42959dcSMoshe Shemesh 
450f0ce0615SJack Morgenstein 		/* enable rdma and ethernet interfaces, new quota locations,
451f0ce0615SJack Morgenstein 		 * and reserved lkey
452f0ce0615SJack Morgenstein 		 */
453eb456a68SJack Morgenstein 		field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA |
454f0ce0615SJack Morgenstein 			 QUERY_FUNC_CAP_FLAG_QUOTAS | QUERY_FUNC_CAP_FLAG_VALID_MAILBOX |
455f0ce0615SJack Morgenstein 			 QUERY_FUNC_CAP_FLAG_RESD_LKEY);
4565cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
4575cc914f1SMarcel Apfelbaum 
458449fc488SMatan Barak 		field = min(
459449fc488SMatan Barak 			bitmap_weight(actv_ports.ports, dev->caps.num_ports),
460449fc488SMatan Barak 			dev->caps.num_ports);
4615cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
4625cc914f1SMarcel Apfelbaum 
46308ff3235SOr Gerlitz 		size = dev->caps.function_caps; /* set PF behaviours */
4645cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
4655cc914f1SMarcel Apfelbaum 
466105c320fSJack Morgenstein 		field = 0; /* protected FMR support not available as yet */
467105c320fSJack Morgenstein 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET);
468105c320fSJack Morgenstein 
4695a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave];
4705cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
471eb456a68SJack Morgenstein 		size = dev->caps.num_qps;
472eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
4735cc914f1SMarcel Apfelbaum 
4745a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave];
4755cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
476eb456a68SJack Morgenstein 		size = dev->caps.num_srqs;
477eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
4785cc914f1SMarcel Apfelbaum 
4795a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave];
4805cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
481eb456a68SJack Morgenstein 		size = dev->caps.num_cqs;
482eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
4835cc914f1SMarcel Apfelbaum 
4847ae0e400SMatan Barak 		if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) ||
4857ae0e400SMatan Barak 		    mlx4_QUERY_FUNC(dev, &func, slave)) {
4867ae0e400SMatan Barak 			size = vhcr->in_modifier &
4877ae0e400SMatan Barak 				QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ?
4887ae0e400SMatan Barak 				dev->caps.num_eqs :
4897ae0e400SMatan Barak 				rounddown_pow_of_two(dev->caps.num_eqs);
4905cc914f1SMarcel Apfelbaum 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
4915cc914f1SMarcel Apfelbaum 			size = dev->caps.reserved_eqs;
4925cc914f1SMarcel Apfelbaum 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
4937ae0e400SMatan Barak 		} else {
4947ae0e400SMatan Barak 			size = vhcr->in_modifier &
4957ae0e400SMatan Barak 				QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ?
4967ae0e400SMatan Barak 				func.max_eq :
4977ae0e400SMatan Barak 				rounddown_pow_of_two(func.max_eq);
4987ae0e400SMatan Barak 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
4997ae0e400SMatan Barak 			size = func.rsvd_eqs;
5007ae0e400SMatan Barak 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
5017ae0e400SMatan Barak 		}
5025cc914f1SMarcel Apfelbaum 
5035a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave];
5045cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
505eb456a68SJack Morgenstein 		size = dev->caps.num_mpts;
506eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
5075cc914f1SMarcel Apfelbaum 
5085a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave];
5095cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
510eb456a68SJack Morgenstein 		size = dev->caps.num_mtts;
511eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
5125cc914f1SMarcel Apfelbaum 
5135cc914f1SMarcel Apfelbaum 		size = dev->caps.num_mgms + dev->caps.num_amgms;
5145cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
515eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
5165cc914f1SMarcel Apfelbaum 
517d57febe1SMatan Barak 		size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG |
518d57febe1SMatan Barak 			QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG;
519ddae0349SEugenia Emantayev 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET);
520f0ce0615SJack Morgenstein 
521f0ce0615SJack Morgenstein 		size = dev->caps.reserved_lkey + ((slave << 8) & 0xFF00);
522f0ce0615SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET);
523b42959dcSMoshe Shemesh 
524b42959dcSMoshe Shemesh 		if (vhcr->in_modifier & QUERY_FUNC_CAP_SUPPORTS_VST_QINQ)
525b42959dcSMoshe Shemesh 			slave_state->vst_qinq_supported = true;
526b42959dcSMoshe Shemesh 
5275cc914f1SMarcel Apfelbaum 	} else
5285cc914f1SMarcel Apfelbaum 		err = -EINVAL;
5295cc914f1SMarcel Apfelbaum 
5305cc914f1SMarcel Apfelbaum 	return err;
5315cc914f1SMarcel Apfelbaum }
5325cc914f1SMarcel Apfelbaum 
533225c6c8cSMatan Barak int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,
53447605df9SJack Morgenstein 			struct mlx4_func_cap *func_cap)
5355cc914f1SMarcel Apfelbaum {
5365cc914f1SMarcel Apfelbaum 	struct mlx4_cmd_mailbox *mailbox;
5375cc914f1SMarcel Apfelbaum 	u32			*outbox;
53847605df9SJack Morgenstein 	u8			field, op_modifier;
53999ec41d0SJack Morgenstein 	u32			size, qkey;
540eb456a68SJack Morgenstein 	int			err = 0, quotas = 0;
5417ae0e400SMatan Barak 	u32                     in_modifier;
542b42959dcSMoshe Shemesh 	u32			slave_caps;
5435cc914f1SMarcel Apfelbaum 
54447605df9SJack Morgenstein 	op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
545b42959dcSMoshe Shemesh 	slave_caps = QUERY_FUNC_CAP_SUPPORTS_VST_QINQ |
5467ae0e400SMatan Barak 		QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS;
547b42959dcSMoshe Shemesh 	in_modifier = op_modifier ? gen_or_port : slave_caps;
5485cc914f1SMarcel Apfelbaum 
5495cc914f1SMarcel Apfelbaum 	mailbox = mlx4_alloc_cmd_mailbox(dev);
5505cc914f1SMarcel Apfelbaum 	if (IS_ERR(mailbox))
5515cc914f1SMarcel Apfelbaum 		return PTR_ERR(mailbox);
5525cc914f1SMarcel Apfelbaum 
5537ae0e400SMatan Barak 	err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, op_modifier,
55447605df9SJack Morgenstein 			   MLX4_CMD_QUERY_FUNC_CAP,
5555cc914f1SMarcel Apfelbaum 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
5565cc914f1SMarcel Apfelbaum 	if (err)
5575cc914f1SMarcel Apfelbaum 		goto out;
5585cc914f1SMarcel Apfelbaum 
5595cc914f1SMarcel Apfelbaum 	outbox = mailbox->buf;
5605cc914f1SMarcel Apfelbaum 
56147605df9SJack Morgenstein 	if (!op_modifier) {
5625cc914f1SMarcel Apfelbaum 		MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET);
563105c320fSJack Morgenstein 		if (!(field & (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA))) {
564105c320fSJack Morgenstein 			mlx4_err(dev, "The host supports neither eth nor rdma interfaces\n");
5655cc914f1SMarcel Apfelbaum 			err = -EPROTONOSUPPORT;
5665cc914f1SMarcel Apfelbaum 			goto out;
5675cc914f1SMarcel Apfelbaum 		}
568105c320fSJack Morgenstein 		func_cap->flags = field;
569eb456a68SJack Morgenstein 		quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS);
5705cc914f1SMarcel Apfelbaum 
5715cc914f1SMarcel Apfelbaum 		MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
5725cc914f1SMarcel Apfelbaum 		func_cap->num_ports = field;
5735cc914f1SMarcel Apfelbaum 
5745cc914f1SMarcel Apfelbaum 		MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
5755cc914f1SMarcel Apfelbaum 		func_cap->pf_context_behaviour = size;
5765cc914f1SMarcel Apfelbaum 
577eb456a68SJack Morgenstein 		if (quotas) {
5785cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
5795cc914f1SMarcel Apfelbaum 			func_cap->qp_quota = size & 0xFFFFFF;
5805cc914f1SMarcel Apfelbaum 
5815cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
5825cc914f1SMarcel Apfelbaum 			func_cap->srq_quota = size & 0xFFFFFF;
5835cc914f1SMarcel Apfelbaum 
5845cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
5855cc914f1SMarcel Apfelbaum 			func_cap->cq_quota = size & 0xFFFFFF;
5865cc914f1SMarcel Apfelbaum 
5875cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
5885cc914f1SMarcel Apfelbaum 			func_cap->mpt_quota = size & 0xFFFFFF;
5895cc914f1SMarcel Apfelbaum 
5905cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
5915cc914f1SMarcel Apfelbaum 			func_cap->mtt_quota = size & 0xFFFFFF;
5925cc914f1SMarcel Apfelbaum 
5935cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
5945cc914f1SMarcel Apfelbaum 			func_cap->mcg_quota = size & 0xFFFFFF;
595eb456a68SJack Morgenstein 
596eb456a68SJack Morgenstein 		} else {
597eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
598eb456a68SJack Morgenstein 			func_cap->qp_quota = size & 0xFFFFFF;
599eb456a68SJack Morgenstein 
600eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
601eb456a68SJack Morgenstein 			func_cap->srq_quota = size & 0xFFFFFF;
602eb456a68SJack Morgenstein 
603eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
604eb456a68SJack Morgenstein 			func_cap->cq_quota = size & 0xFFFFFF;
605eb456a68SJack Morgenstein 
606eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
607eb456a68SJack Morgenstein 			func_cap->mpt_quota = size & 0xFFFFFF;
608eb456a68SJack Morgenstein 
609eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
610eb456a68SJack Morgenstein 			func_cap->mtt_quota = size & 0xFFFFFF;
611eb456a68SJack Morgenstein 
612eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
613eb456a68SJack Morgenstein 			func_cap->mcg_quota = size & 0xFFFFFF;
614eb456a68SJack Morgenstein 		}
615eb456a68SJack Morgenstein 		MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
616eb456a68SJack Morgenstein 		func_cap->max_eq = size & 0xFFFFFF;
617eb456a68SJack Morgenstein 
618eb456a68SJack Morgenstein 		MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
619eb456a68SJack Morgenstein 		func_cap->reserved_eq = size & 0xFFFFFF;
620eb456a68SJack Morgenstein 
621f0ce0615SJack Morgenstein 		if (func_cap->flags & QUERY_FUNC_CAP_FLAG_RESD_LKEY) {
622f0ce0615SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET);
623f0ce0615SJack Morgenstein 			func_cap->reserved_lkey = size;
624f0ce0615SJack Morgenstein 		} else {
625f0ce0615SJack Morgenstein 			func_cap->reserved_lkey = 0;
626f0ce0615SJack Morgenstein 		}
627f0ce0615SJack Morgenstein 
628ddae0349SEugenia Emantayev 		func_cap->extra_flags = 0;
629ddae0349SEugenia Emantayev 
630ddae0349SEugenia Emantayev 		/* Mailbox data from 0x6c and onward should only be treated if
631ddae0349SEugenia Emantayev 		 * QUERY_FUNC_CAP_FLAG_VALID_MAILBOX is set in func_cap->flags
632ddae0349SEugenia Emantayev 		 */
633ddae0349SEugenia Emantayev 		if (func_cap->flags & QUERY_FUNC_CAP_FLAG_VALID_MAILBOX) {
634ddae0349SEugenia Emantayev 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET);
635ddae0349SEugenia Emantayev 			if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG)
636ddae0349SEugenia Emantayev 				func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP;
637d57febe1SMatan Barak 			if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG)
638d57febe1SMatan Barak 				func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_A0_RES_QP;
639ddae0349SEugenia Emantayev 		}
640ddae0349SEugenia Emantayev 
6415cc914f1SMarcel Apfelbaum 		goto out;
64247605df9SJack Morgenstein 	}
6435cc914f1SMarcel Apfelbaum 
64447605df9SJack Morgenstein 	/* logical port query */
64547605df9SJack Morgenstein 	if (gen_or_port > dev->caps.num_ports) {
64647605df9SJack Morgenstein 		err = -EINVAL;
64747605df9SJack Morgenstein 		goto out;
64847605df9SJack Morgenstein 	}
64947605df9SJack Morgenstein 
650eb17711bSHadar Hen Zion 	MLX4_GET(func_cap->flags1, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET);
65147605df9SJack Morgenstein 	if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_ETH) {
652bc82878bSJack Morgenstein 		if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN) {
6535cc914f1SMarcel Apfelbaum 			mlx4_err(dev, "VLAN is enforced on this port\n");
6545cc914f1SMarcel Apfelbaum 			err = -EPROTONOSUPPORT;
6555cc914f1SMarcel Apfelbaum 			goto out;
6565cc914f1SMarcel Apfelbaum 		}
6575cc914f1SMarcel Apfelbaum 
658eb17711bSHadar Hen Zion 		if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_MAC) {
6595cc914f1SMarcel Apfelbaum 			mlx4_err(dev, "Force mac is enabled on this port\n");
6605cc914f1SMarcel Apfelbaum 			err = -EPROTONOSUPPORT;
6615cc914f1SMarcel Apfelbaum 			goto out;
6625cc914f1SMarcel Apfelbaum 		}
66347605df9SJack Morgenstein 	} else if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_IB) {
66473e74ab4SHadar Hen Zion 		MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET);
66573e74ab4SHadar Hen Zion 		if (field & QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID) {
6661a91de28SJoe Perches 			mlx4_err(dev, "phy_wqe_gid is enforced on this ib port\n");
667105c320fSJack Morgenstein 			err = -EPROTONOSUPPORT;
668105c320fSJack Morgenstein 			goto out;
669105c320fSJack Morgenstein 		}
670105c320fSJack Morgenstein 	}
6715cc914f1SMarcel Apfelbaum 
6725cc914f1SMarcel Apfelbaum 	MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
67347605df9SJack Morgenstein 	func_cap->physical_port = field;
67447605df9SJack Morgenstein 	if (func_cap->physical_port != gen_or_port) {
67572b8eaabSTariq Toukan 		err = -EINVAL;
67647605df9SJack Morgenstein 		goto out;
6775cc914f1SMarcel Apfelbaum 	}
6785cc914f1SMarcel Apfelbaum 
67999ec41d0SJack Morgenstein 	if (func_cap->flags1 & QUERY_FUNC_CAP_VF_ENABLE_QP0) {
68099ec41d0SJack Morgenstein 		MLX4_GET(qkey, outbox, QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);
68199ec41d0SJack Morgenstein 		func_cap->qp0_qkey = qkey;
68299ec41d0SJack Morgenstein 	} else {
68399ec41d0SJack Morgenstein 		func_cap->qp0_qkey = 0;
68499ec41d0SJack Morgenstein 	}
68599ec41d0SJack Morgenstein 
68647605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL);
68747605df9SJack Morgenstein 	func_cap->qp0_tunnel_qpn = size & 0xFFFFFF;
68847605df9SJack Morgenstein 
68947605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_PROXY);
69047605df9SJack Morgenstein 	func_cap->qp0_proxy_qpn = size & 0xFFFFFF;
69147605df9SJack Morgenstein 
69247605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_TUNNEL);
69347605df9SJack Morgenstein 	func_cap->qp1_tunnel_qpn = size & 0xFFFFFF;
69447605df9SJack Morgenstein 
69547605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_PROXY);
69647605df9SJack Morgenstein 	func_cap->qp1_proxy_qpn = size & 0xFFFFFF;
69747605df9SJack Morgenstein 
6988e1a28e8SHadar Hen Zion 	if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_NIC_INFO)
6998e1a28e8SHadar Hen Zion 		MLX4_GET(func_cap->phys_port_id, outbox,
7008e1a28e8SHadar Hen Zion 			 QUERY_FUNC_CAP_PHYS_PORT_ID);
7018e1a28e8SHadar Hen Zion 
702c9cc599aSMoshe Shemesh 	MLX4_GET(func_cap->flags0, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET);
70377fc29c4SHadar Hen Zion 
7045cc914f1SMarcel Apfelbaum 	/* All other resources are allocated by the master, but we still report
7055cc914f1SMarcel Apfelbaum 	 * 'num' and 'reserved' capabilities as follows:
7065cc914f1SMarcel Apfelbaum 	 * - num remains the maximum resource index
7075cc914f1SMarcel Apfelbaum 	 * - 'num - reserved' is the total available objects of a resource, but
7085cc914f1SMarcel Apfelbaum 	 *   resource indices may be less than 'reserved'
7095cc914f1SMarcel Apfelbaum 	 * TODO: set per-resource quotas */
7105cc914f1SMarcel Apfelbaum 
7115cc914f1SMarcel Apfelbaum out:
7125cc914f1SMarcel Apfelbaum 	mlx4_free_cmd_mailbox(dev, mailbox);
7135cc914f1SMarcel Apfelbaum 
7145cc914f1SMarcel Apfelbaum 	return err;
7155cc914f1SMarcel Apfelbaum }
7165cc914f1SMarcel Apfelbaum 
717d8ae9141SMoni Shoua static void disable_unsupported_roce_caps(void *buf);
718d8ae9141SMoni Shoua 
7195a2cc190SJeff Kirsher int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
7205a2cc190SJeff Kirsher {
7215a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
7225a2cc190SJeff Kirsher 	u32 *outbox;
7235a2cc190SJeff Kirsher 	u8 field;
7245a2cc190SJeff Kirsher 	u32 field32, flags, ext_flags;
7255a2cc190SJeff Kirsher 	u16 size;
7265a2cc190SJeff Kirsher 	u16 stat_rate;
7275a2cc190SJeff Kirsher 	int err;
7285a2cc190SJeff Kirsher 	int i;
7295a2cc190SJeff Kirsher 
7305a2cc190SJeff Kirsher #define QUERY_DEV_CAP_OUT_SIZE		       0x100
7315a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET		0x10
7325a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET		0x11
7335a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_QP_OFFSET		0x12
7345a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_OFFSET		0x13
7355a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_SRQ_OFFSET		0x14
7365a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_OFFSET		0x15
7375a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EEC_OFFSET		0x16
7385a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EEC_OFFSET		0x17
7395a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET		0x19
7405a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_CQ_OFFSET		0x1a
7415a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_OFFSET		0x1b
7425a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MPT_OFFSET		0x1d
7435a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EQ_OFFSET		0x1e
7445a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EQ_OFFSET		0x1f
7455a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MTT_OFFSET		0x20
7465a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET		0x21
7475a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MRW_OFFSET		0x22
7485a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET	0x23
7497ae0e400SMatan Barak #define QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET		0x26
7505a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_AV_OFFSET		0x27
7515a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET		0x29
7525a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET		0x2b
7535a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GSO_OFFSET		0x2d
754b3416f44SShlomo Pongratz #define QUERY_DEV_CAP_RSS_OFFSET		0x2e
7555a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RDMA_OFFSET		0x2f
7565a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET		0x33
75751af33cfSIdo Shamay #define QUERY_DEV_CAP_PORT_BEACON_OFFSET	0x34
7585a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ACK_DELAY_OFFSET		0x35
7595a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET		0x36
7605a2cc190SJeff Kirsher #define QUERY_DEV_CAP_VL_PORT_OFFSET		0x37
7615a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET		0x38
7625a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GID_OFFSET		0x3b
7635a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET	0x3c
764d998735fSEugenia Emantayev #define QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET	0x3e
7655a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PKEY_OFFSET		0x3f
7665a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EXT_FLAGS_OFFSET		0x40
7675a2cc190SJeff Kirsher #define QUERY_DEV_CAP_FLAGS_OFFSET		0x44
7685a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_UAR_OFFSET		0x48
7695a2cc190SJeff Kirsher #define QUERY_DEV_CAP_UAR_SZ_OFFSET		0x49
7705a2cc190SJeff Kirsher #define QUERY_DEV_CAP_PAGE_SZ_OFFSET		0x4b
7715a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BF_OFFSET			0x4c
7725a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET	0x4d
7735a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET	0x4e
7745a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET	0x4f
7755a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET		0x51
7765a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET	0x52
7775a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET		0x55
7785a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET	0x56
7797c3d21c8SMoshe Shemesh #define QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET	0x5D
7805a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET		0x61
7815a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MCG_OFFSET		0x62
7825a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MCG_OFFSET		0x63
7835a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_PD_OFFSET		0x64
7845a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PD_OFFSET		0x65
785f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_RSVD_XRC_OFFSET		0x66
786f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_MAX_XRC_OFFSET		0x67
7875a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET	0x68
7880b131561SMatan Barak #define QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET	0x70
7893f7fb021SRony Efraim #define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET	0x70
7904de65803SMatan Barak #define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET	0x74
7910ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET	0x76
7920ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET	0x77
793fd10ed8eSJack Morgenstein #define QUERY_DEV_CAP_SL2VL_EVENT_OFFSET	0x78
79477507aa2SIdo Shamay #define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE	0x7a
795d237baa1SShani Michaeli #define QUERY_DEV_CAP_ECN_QCN_VER_OFFSET	0x7b
7965a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
7975a2cc190SJeff Kirsher #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET	0x82
7985a2cc190SJeff Kirsher #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET	0x84
7995a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET	0x86
8005a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET	0x88
8015a2cc190SJeff Kirsher #define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET	0x8a
8025a2cc190SJeff Kirsher #define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET	0x8c
8035a2cc190SJeff Kirsher #define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET	0x8e
8045a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET	0x90
8055a2cc190SJeff Kirsher #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET	0x92
8065a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET		0x94
807d475c95bSMatan Barak #define QUERY_DEV_CAP_CONFIG_DEV_OFFSET		0x94
80877fc29c4SHadar Hen Zion #define QUERY_DEV_CAP_PHV_EN_OFFSET		0x96
8095a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET		0x98
8105a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET		0xa0
811a53e3e8cSSaeed Mahameed #define QUERY_DEV_CAP_ETH_BACKPL_OFFSET		0x9c
812c7c122edSMark Bloch #define QUERY_DEV_CAP_DIAG_RPRT_PER_PORT	0x9c
813955154faSMatan Barak #define QUERY_DEV_CAP_FW_REASSIGN_MAC		0x9d
8147ffdf726SOr Gerlitz #define QUERY_DEV_CAP_VXLAN			0x9e
815114840c3SJack Morgenstein #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET		0xb0
8167d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET	0xa8
8177d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET	0xac
818fc31e256SOr Gerlitz #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET	0xcc
819fc31e256SOr Gerlitz #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET	0xd0
820fc31e256SOr Gerlitz #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET	0xd2
821fc31e256SOr Gerlitz 
8225a2cc190SJeff Kirsher 
823b3416f44SShlomo Pongratz 	dev_cap->flags2 = 0;
8245a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
8255a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
8265a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
8275a2cc190SJeff Kirsher 	outbox = mailbox->buf;
8285a2cc190SJeff Kirsher 
8295a2cc190SJeff Kirsher 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
830401453a3SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
8315a2cc190SJeff Kirsher 	if (err)
8325a2cc190SJeff Kirsher 		goto out;
8335a2cc190SJeff Kirsher 
834d8ae9141SMoni Shoua 	if (mlx4_is_mfunc(dev))
835d8ae9141SMoni Shoua 		disable_unsupported_roce_caps(outbox);
8365a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET);
8375a2cc190SJeff Kirsher 	dev_cap->reserved_qps = 1 << (field & 0xf);
8385a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET);
8395a2cc190SJeff Kirsher 	dev_cap->max_qps = 1 << (field & 0x1f);
8405a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET);
8415a2cc190SJeff Kirsher 	dev_cap->reserved_srqs = 1 << (field >> 4);
8425a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET);
8435a2cc190SJeff Kirsher 	dev_cap->max_srqs = 1 << (field & 0x1f);
8445a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET);
8455a2cc190SJeff Kirsher 	dev_cap->max_cq_sz = 1 << field;
8465a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET);
8475a2cc190SJeff Kirsher 	dev_cap->reserved_cqs = 1 << (field & 0xf);
8485a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET);
8495a2cc190SJeff Kirsher 	dev_cap->max_cqs = 1 << (field & 0x1f);
8505a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET);
8515a2cc190SJeff Kirsher 	dev_cap->max_mpts = 1 << (field & 0x3f);
8525a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET);
8537c68dd43SMatan Barak 	dev_cap->reserved_eqs = 1 << (field & 0xf);
8545a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET);
8555a2cc190SJeff Kirsher 	dev_cap->max_eqs = 1 << (field & 0xf);
8565a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
8575a2cc190SJeff Kirsher 	dev_cap->reserved_mtts = 1 << (field >> 4);
8585a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET);
8595a2cc190SJeff Kirsher 	dev_cap->reserved_mrws = 1 << (field & 0xf);
8607ae0e400SMatan Barak 	MLX4_GET(size, outbox, QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET);
8617ae0e400SMatan Barak 	dev_cap->num_sys_eqs = size & 0xfff;
8625a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET);
8635a2cc190SJeff Kirsher 	dev_cap->max_requester_per_qp = 1 << (field & 0x3f);
8645a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET);
8655a2cc190SJeff Kirsher 	dev_cap->max_responder_per_qp = 1 << (field & 0x3f);
8665a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET);
8675a2cc190SJeff Kirsher 	field &= 0x1f;
8685a2cc190SJeff Kirsher 	if (!field)
8695a2cc190SJeff Kirsher 		dev_cap->max_gso_sz = 0;
8705a2cc190SJeff Kirsher 	else
8715a2cc190SJeff Kirsher 		dev_cap->max_gso_sz = 1 << field;
8725a2cc190SJeff Kirsher 
873b3416f44SShlomo Pongratz 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET);
874b3416f44SShlomo Pongratz 	if (field & 0x20)
875b3416f44SShlomo Pongratz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR;
876b3416f44SShlomo Pongratz 	if (field & 0x10)
877b3416f44SShlomo Pongratz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP;
878b3416f44SShlomo Pongratz 	field &= 0xf;
879b3416f44SShlomo Pongratz 	if (field) {
880b3416f44SShlomo Pongratz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS;
881b3416f44SShlomo Pongratz 		dev_cap->max_rss_tbl_sz = 1 << field;
882b3416f44SShlomo Pongratz 	} else
883b3416f44SShlomo Pongratz 		dev_cap->max_rss_tbl_sz = 0;
8845a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
8855a2cc190SJeff Kirsher 	dev_cap->max_rdma_global = 1 << (field & 0x3f);
8865a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
8875a2cc190SJeff Kirsher 	dev_cap->local_ca_ack_delay = field & 0x1f;
8885a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
8895a2cc190SJeff Kirsher 	dev_cap->num_ports = field & 0xf;
8905a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
891fab9adfbSEran Ben Elisha 	dev_cap->max_msg_sz = 1 << (field & 0x1f);
8920b131561SMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET);
8930b131561SMatan Barak 	if (field & 0x10)
8940b131561SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN;
8950ff1fb65SHadar Hen Zion 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
8960ff1fb65SHadar Hen Zion 	if (field & 0x80)
8970ff1fb65SHadar Hen Zion 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
8980ff1fb65SHadar Hen Zion 	dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f;
8990e451e88SMarina Varshaver 	if (field & 0x20)
9000e451e88SMarina Varshaver 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_UC_MC_SNIFFER;
90151af33cfSIdo Shamay 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_BEACON_OFFSET);
90251af33cfSIdo Shamay 	if (field & 0x80)
90351af33cfSIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_PORT_BEACON;
9044de65803SMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
9054de65803SMatan Barak 	if (field & 0x80)
9064de65803SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB;
9070ff1fb65SHadar Hen Zion 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
9080ff1fb65SHadar Hen Zion 	dev_cap->fs_max_num_qp_per_entry = field;
909fd10ed8eSJack Morgenstein 	MLX4_GET(field, outbox, QUERY_DEV_CAP_SL2VL_EVENT_OFFSET);
910fd10ed8eSJack Morgenstein 	if (field & (1 << 5))
911fd10ed8eSJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SL_TO_VL_CHANGE_EVENT;
912d237baa1SShani Michaeli 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
913d237baa1SShani Michaeli 	if (field & 0x1)
914d237baa1SShani Michaeli 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QCN;
9155a2cc190SJeff Kirsher 	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
9165a2cc190SJeff Kirsher 	dev_cap->stat_rate_support = stat_rate;
917d998735fSEugenia Emantayev 	MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
918d998735fSEugenia Emantayev 	if (field & 0x80)
919d998735fSEugenia Emantayev 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS;
9205a2cc190SJeff Kirsher 	MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
9215a2cc190SJeff Kirsher 	MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
9225a2cc190SJeff Kirsher 	dev_cap->flags = flags | (u64)ext_flags << 32;
9235a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
9245a2cc190SJeff Kirsher 	dev_cap->reserved_uars = field >> 4;
9255a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET);
9265a2cc190SJeff Kirsher 	dev_cap->uar_size = 1 << ((field & 0x3f) + 20);
9275a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET);
9285a2cc190SJeff Kirsher 	dev_cap->min_page_sz = 1 << field;
9295a2cc190SJeff Kirsher 
9305a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET);
9315a2cc190SJeff Kirsher 	if (field & 0x80) {
9325a2cc190SJeff Kirsher 		MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET);
9335a2cc190SJeff Kirsher 		dev_cap->bf_reg_size = 1 << (field & 0x1f);
9345a2cc190SJeff Kirsher 		MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET);
9355a2cc190SJeff Kirsher 		if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size))
9365a2cc190SJeff Kirsher 			field = 3;
9375a2cc190SJeff Kirsher 		dev_cap->bf_regs_per_page = 1 << (field & 0x3f);
9385a2cc190SJeff Kirsher 	} else {
9395a2cc190SJeff Kirsher 		dev_cap->bf_reg_size = 0;
9405a2cc190SJeff Kirsher 	}
9415a2cc190SJeff Kirsher 
9425a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET);
9435a2cc190SJeff Kirsher 	dev_cap->max_sq_sg = field;
9445a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET);
9455a2cc190SJeff Kirsher 	dev_cap->max_sq_desc_sz = size;
9465a2cc190SJeff Kirsher 
9477c3d21c8SMoshe Shemesh 	MLX4_GET(field, outbox, QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET);
9487c3d21c8SMoshe Shemesh 	if (field & 0x1)
9497c3d21c8SMoshe Shemesh 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SVLAN_BY_QP;
9505a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET);
9515a2cc190SJeff Kirsher 	dev_cap->max_qp_per_mcg = 1 << field;
9525a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET);
9535a2cc190SJeff Kirsher 	dev_cap->reserved_mgms = field & 0xf;
9545a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET);
9555a2cc190SJeff Kirsher 	dev_cap->max_mcgs = 1 << field;
9565a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET);
9575a2cc190SJeff Kirsher 	dev_cap->reserved_pds = field >> 4;
9585a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
9595a2cc190SJeff Kirsher 	dev_cap->max_pds = 1 << (field & 0x3f);
960f470f8d4SLinus Torvalds 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
961f470f8d4SLinus Torvalds 	dev_cap->reserved_xrcds = field >> 4;
962426dd00dSDotan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET);
963f470f8d4SLinus Torvalds 	dev_cap->max_xrcds = 1 << (field & 0x1f);
9645a2cc190SJeff Kirsher 
9655a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
9665a2cc190SJeff Kirsher 	dev_cap->rdmarc_entry_sz = size;
9675a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET);
9685a2cc190SJeff Kirsher 	dev_cap->qpc_entry_sz = size;
9695a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET);
9705a2cc190SJeff Kirsher 	dev_cap->aux_entry_sz = size;
9715a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET);
9725a2cc190SJeff Kirsher 	dev_cap->altc_entry_sz = size;
9735a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET);
9745a2cc190SJeff Kirsher 	dev_cap->eqc_entry_sz = size;
9755a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET);
9765a2cc190SJeff Kirsher 	dev_cap->cqc_entry_sz = size;
9775a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET);
9785a2cc190SJeff Kirsher 	dev_cap->srq_entry_sz = size;
9795a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET);
9805a2cc190SJeff Kirsher 	dev_cap->cmpt_entry_sz = size;
9815a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET);
9825a2cc190SJeff Kirsher 	dev_cap->mtt_entry_sz = size;
9835a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET);
9845a2cc190SJeff Kirsher 	dev_cap->dmpt_entry_sz = size;
9855a2cc190SJeff Kirsher 
9865a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET);
9875a2cc190SJeff Kirsher 	dev_cap->max_srq_sz = 1 << field;
9885a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET);
9895a2cc190SJeff Kirsher 	dev_cap->max_qp_sz = 1 << field;
9905a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET);
9915a2cc190SJeff Kirsher 	dev_cap->resize_srq = field & 1;
9925a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET);
9935a2cc190SJeff Kirsher 	dev_cap->max_rq_sg = field;
9945a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET);
9955a2cc190SJeff Kirsher 	dev_cap->max_rq_desc_sz = size;
99677507aa2SIdo Shamay 	MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE);
997d019fcb2SIdo Shamay 	if (field & (1 << 4))
998d019fcb2SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QOS_VPP;
999adbc7ac5SSaeed Mahameed 	if (field & (1 << 5))
1000adbc7ac5SSaeed Mahameed 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL;
100177507aa2SIdo Shamay 	if (field & (1 << 6))
100277507aa2SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CQE_STRIDE;
100377507aa2SIdo Shamay 	if (field & (1 << 7))
100477507aa2SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE;
10055a2cc190SJeff Kirsher 	MLX4_GET(dev_cap->bmme_flags, outbox,
10065a2cc190SJeff Kirsher 		 QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1007d8ae9141SMoni Shoua 	if (dev_cap->bmme_flags & MLX4_FLAG_ROCE_V1_V2)
1008d8ae9141SMoni Shoua 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ROCE_V1_V2;
100959e14e32SMoni Shoua 	if (dev_cap->bmme_flags & MLX4_FLAG_PORT_REMAP)
101059e14e32SMoni Shoua 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_PORT_REMAP;
1011d475c95bSMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
1012d475c95bSMatan Barak 	if (field & 0x20)
1013d475c95bSMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CONFIG_DEV;
101478500b8cSMuhammad Mahajna 	if (field & (1 << 2))
101578500b8cSMuhammad Mahajna 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_IGNORE_FCS;
101677fc29c4SHadar Hen Zion 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PHV_EN_OFFSET);
101777fc29c4SHadar Hen Zion 	if (field & 0x80)
101877fc29c4SHadar Hen Zion 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_PHV_EN;
101977fc29c4SHadar Hen Zion 	if (field & 0x40)
102077fc29c4SHadar Hen Zion 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN;
102177fc29c4SHadar Hen Zion 
10225a2cc190SJeff Kirsher 	MLX4_GET(dev_cap->reserved_lkey, outbox,
10235a2cc190SJeff Kirsher 		 QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
1024a53e3e8cSSaeed Mahameed 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETH_BACKPL_OFFSET);
1025a53e3e8cSSaeed Mahameed 	if (field32 & (1 << 0))
1026a53e3e8cSSaeed Mahameed 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP;
1027be6a6b43SJack Morgenstein 	if (field32 & (1 << 7))
1028be6a6b43SJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT;
1029c7c122edSMark Bloch 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_DIAG_RPRT_PER_PORT);
1030c7c122edSMark Bloch 	if (field32 & (1 << 17))
1031c7c122edSMark Bloch 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT;
1032955154faSMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
1033955154faSMatan Barak 	if (field & 1<<6)
10345930e8d0SOr Gerlitz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN;
10357ffdf726SOr Gerlitz 	MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
10367ffdf726SOr Gerlitz 	if (field & 1<<3)
10377ffdf726SOr Gerlitz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS;
10383742cc65SIdo Shamay 	if (field & (1 << 5))
10393742cc65SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETS_CFG;
10405a2cc190SJeff Kirsher 	MLX4_GET(dev_cap->max_icm_sz, outbox,
10415a2cc190SJeff Kirsher 		 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
10425a2cc190SJeff Kirsher 	if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
10435a2cc190SJeff Kirsher 		MLX4_GET(dev_cap->max_counters, outbox,
10445a2cc190SJeff Kirsher 			 QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
10455a2cc190SJeff Kirsher 
1046114840c3SJack Morgenstein 	MLX4_GET(field32, outbox,
1047114840c3SJack Morgenstein 		 QUERY_DEV_CAP_MAD_DEMUX_OFFSET);
1048114840c3SJack Morgenstein 	if (field32 & (1 << 0))
1049114840c3SJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX;
1050114840c3SJack Morgenstein 
10517d077cd3SMatan Barak 	MLX4_GET(dev_cap->dmfs_high_rate_qpn_base, outbox,
10527d077cd3SMatan Barak 		 QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET);
10537d077cd3SMatan Barak 	dev_cap->dmfs_high_rate_qpn_base &= MGM_QPN_MASK;
10547d077cd3SMatan Barak 	MLX4_GET(dev_cap->dmfs_high_rate_qpn_range, outbox,
10557d077cd3SMatan Barak 		 QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET);
10567d077cd3SMatan Barak 	dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK;
10577d077cd3SMatan Barak 
1058fc31e256SOr Gerlitz 	MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET);
1059fc31e256SOr Gerlitz 	dev_cap->rl_caps.num_rates = size;
1060fc31e256SOr Gerlitz 	if (dev_cap->rl_caps.num_rates) {
1061fc31e256SOr Gerlitz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT;
1062fc31e256SOr Gerlitz 		MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET);
1063fc31e256SOr Gerlitz 		dev_cap->rl_caps.max_val  = size & 0xfff;
1064fc31e256SOr Gerlitz 		dev_cap->rl_caps.max_unit = size >> 14;
1065fc31e256SOr Gerlitz 		MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET);
1066fc31e256SOr Gerlitz 		dev_cap->rl_caps.min_val  = size & 0xfff;
1067fc31e256SOr Gerlitz 		dev_cap->rl_caps.min_unit = size >> 14;
1068fc31e256SOr Gerlitz 	}
1069fc31e256SOr Gerlitz 
10703f7fb021SRony Efraim 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1071b01978caSJack Morgenstein 	if (field32 & (1 << 16))
1072b01978caSJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
10739a892835SMaor Gottlieb 	if (field32 & (1 << 18))
10749a892835SMaor Gottlieb 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB;
10759a892835SMaor Gottlieb 	if (field32 & (1 << 19))
10769a892835SMaor Gottlieb 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_LB_SRC_CHK;
10773f7fb021SRony Efraim 	if (field32 & (1 << 26))
10783f7fb021SRony Efraim 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
1079e6b6a231SRony Efraim 	if (field32 & (1 << 20))
1080e6b6a231SRony Efraim 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;
1081de966c59SMatan Barak 	if (field32 & (1 << 21))
1082de966c59SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS;
10833f7fb021SRony Efraim 
1084431df8c7SMatan Barak 	for (i = 1; i <= dev_cap->num_ports; i++) {
1085431df8c7SMatan Barak 		err = mlx4_QUERY_PORT(dev, i, dev_cap->port_cap + i);
10865a2cc190SJeff Kirsher 		if (err)
10875a2cc190SJeff Kirsher 			goto out;
10885a2cc190SJeff Kirsher 	}
10895a2cc190SJeff Kirsher 
10905a2cc190SJeff Kirsher 	/*
10915a2cc190SJeff Kirsher 	 * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then
10925a2cc190SJeff Kirsher 	 * we can't use any EQs whose doorbell falls on that page,
10935a2cc190SJeff Kirsher 	 * even if the EQ itself isn't reserved.
10945a2cc190SJeff Kirsher 	 */
10957ae0e400SMatan Barak 	if (dev_cap->num_sys_eqs == 0)
10965a2cc190SJeff Kirsher 		dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4,
10975a2cc190SJeff Kirsher 					    dev_cap->reserved_eqs);
10987ae0e400SMatan Barak 	else
10997ae0e400SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SYS_EQS;
11005a2cc190SJeff Kirsher 
1101c78e25edSOr Gerlitz out:
1102c78e25edSOr Gerlitz 	mlx4_free_cmd_mailbox(dev, mailbox);
1103c78e25edSOr Gerlitz 	return err;
1104c78e25edSOr Gerlitz }
1105c78e25edSOr Gerlitz 
1106c78e25edSOr Gerlitz void mlx4_dev_cap_dump(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
1107c78e25edSOr Gerlitz {
1108c78e25edSOr Gerlitz 	if (dev_cap->bf_reg_size > 0)
1109c78e25edSOr Gerlitz 		mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n",
1110c78e25edSOr Gerlitz 			 dev_cap->bf_reg_size, dev_cap->bf_regs_per_page);
1111c78e25edSOr Gerlitz 	else
1112c78e25edSOr Gerlitz 		mlx4_dbg(dev, "BlueFlame not available\n");
1113c78e25edSOr Gerlitz 
1114c78e25edSOr Gerlitz 	mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n",
1115c78e25edSOr Gerlitz 		 dev_cap->bmme_flags, dev_cap->reserved_lkey);
11165a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max ICM size %lld MB\n",
11175a2cc190SJeff Kirsher 		 (unsigned long long) dev_cap->max_icm_sz >> 20);
11185a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
11195a2cc190SJeff Kirsher 		 dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz);
11205a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
11215a2cc190SJeff Kirsher 		 dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz);
11225a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
11235a2cc190SJeff Kirsher 		 dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz);
11247ae0e400SMatan Barak 	mlx4_dbg(dev, "Num sys EQs: %d, max EQs: %d, reserved EQs: %d, entry size: %d\n",
11257ae0e400SMatan Barak 		 dev_cap->num_sys_eqs, dev_cap->max_eqs, dev_cap->reserved_eqs,
11267ae0e400SMatan Barak 		 dev_cap->eqc_entry_sz);
11275a2cc190SJeff Kirsher 	mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
11285a2cc190SJeff Kirsher 		 dev_cap->reserved_mrws, dev_cap->reserved_mtts);
11295a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
11305a2cc190SJeff Kirsher 		 dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars);
11315a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
11325a2cc190SJeff Kirsher 		 dev_cap->max_pds, dev_cap->reserved_mgms);
11335a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
11345a2cc190SJeff Kirsher 		 dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
11355a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
1136431df8c7SMatan Barak 		 dev_cap->local_ca_ack_delay, 128 << dev_cap->port_cap[1].ib_mtu,
1137431df8c7SMatan Barak 		 dev_cap->port_cap[1].max_port_width);
11385a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
11395a2cc190SJeff Kirsher 		 dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
11405a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
11415a2cc190SJeff Kirsher 		 dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
11425a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
11435a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters);
1144b3416f44SShlomo Pongratz 	mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz);
11457d077cd3SMatan Barak 	mlx4_dbg(dev, "DMFS high rate steer QPn base: %d\n",
11467d077cd3SMatan Barak 		 dev_cap->dmfs_high_rate_qpn_base);
11477d077cd3SMatan Barak 	mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n",
11487d077cd3SMatan Barak 		 dev_cap->dmfs_high_rate_qpn_range);
1149fc31e256SOr Gerlitz 
1150fc31e256SOr Gerlitz 	if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT) {
1151fc31e256SOr Gerlitz 		struct mlx4_rate_limit_caps *rl_caps = &dev_cap->rl_caps;
1152fc31e256SOr Gerlitz 
1153fc31e256SOr Gerlitz 		mlx4_dbg(dev, "QP Rate-Limit: #rates %d, unit/val max %d/%d, min %d/%d\n",
1154fc31e256SOr Gerlitz 			 rl_caps->num_rates, rl_caps->max_unit, rl_caps->max_val,
1155fc31e256SOr Gerlitz 			 rl_caps->min_unit, rl_caps->min_val);
1156fc31e256SOr Gerlitz 	}
1157fc31e256SOr Gerlitz 
11585a2cc190SJeff Kirsher 	dump_dev_cap_flags(dev, dev_cap->flags);
1159b3416f44SShlomo Pongratz 	dump_dev_cap_flags2(dev, dev_cap->flags2);
11605a2cc190SJeff Kirsher }
11615a2cc190SJeff Kirsher 
1162431df8c7SMatan Barak int mlx4_QUERY_PORT(struct mlx4_dev *dev, int port, struct mlx4_port_cap *port_cap)
1163431df8c7SMatan Barak {
1164431df8c7SMatan Barak 	struct mlx4_cmd_mailbox *mailbox;
1165431df8c7SMatan Barak 	u32 *outbox;
1166431df8c7SMatan Barak 	u8 field;
1167431df8c7SMatan Barak 	u32 field32;
1168431df8c7SMatan Barak 	int err;
1169431df8c7SMatan Barak 
1170431df8c7SMatan Barak 	mailbox = mlx4_alloc_cmd_mailbox(dev);
1171431df8c7SMatan Barak 	if (IS_ERR(mailbox))
1172431df8c7SMatan Barak 		return PTR_ERR(mailbox);
1173431df8c7SMatan Barak 	outbox = mailbox->buf;
1174431df8c7SMatan Barak 
1175431df8c7SMatan Barak 	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
1176431df8c7SMatan Barak 		err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
1177431df8c7SMatan Barak 				   MLX4_CMD_TIME_CLASS_A,
1178431df8c7SMatan Barak 				   MLX4_CMD_NATIVE);
1179431df8c7SMatan Barak 
1180431df8c7SMatan Barak 		if (err)
1181431df8c7SMatan Barak 			goto out;
1182431df8c7SMatan Barak 
1183431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
1184431df8c7SMatan Barak 		port_cap->max_vl	   = field >> 4;
1185431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
1186431df8c7SMatan Barak 		port_cap->ib_mtu	   = field >> 4;
1187431df8c7SMatan Barak 		port_cap->max_port_width = field & 0xf;
1188431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
1189431df8c7SMatan Barak 		port_cap->max_gids	   = 1 << (field & 0xf);
1190431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
1191431df8c7SMatan Barak 		port_cap->max_pkeys	   = 1 << (field & 0xf);
1192431df8c7SMatan Barak 	} else {
1193431df8c7SMatan Barak #define QUERY_PORT_SUPPORTED_TYPE_OFFSET	0x00
1194431df8c7SMatan Barak #define QUERY_PORT_MTU_OFFSET			0x01
1195431df8c7SMatan Barak #define QUERY_PORT_ETH_MTU_OFFSET		0x02
1196431df8c7SMatan Barak #define QUERY_PORT_WIDTH_OFFSET			0x06
1197431df8c7SMatan Barak #define QUERY_PORT_MAX_GID_PKEY_OFFSET		0x07
1198431df8c7SMatan Barak #define QUERY_PORT_MAX_MACVLAN_OFFSET		0x0a
1199431df8c7SMatan Barak #define QUERY_PORT_MAX_VL_OFFSET		0x0b
1200431df8c7SMatan Barak #define QUERY_PORT_MAC_OFFSET			0x10
1201431df8c7SMatan Barak #define QUERY_PORT_TRANS_VENDOR_OFFSET		0x18
1202431df8c7SMatan Barak #define QUERY_PORT_WAVELENGTH_OFFSET		0x1c
1203431df8c7SMatan Barak #define QUERY_PORT_TRANS_CODE_OFFSET		0x20
1204431df8c7SMatan Barak 
1205431df8c7SMatan Barak 		err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, MLX4_CMD_QUERY_PORT,
1206431df8c7SMatan Barak 				   MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
1207431df8c7SMatan Barak 		if (err)
1208431df8c7SMatan Barak 			goto out;
1209431df8c7SMatan Barak 
1210431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET);
1211e34305c8SOr Gerlitz 		port_cap->link_state = (field & 0x80) >> 7;
1212431df8c7SMatan Barak 		port_cap->supported_port_types = field & 3;
1213431df8c7SMatan Barak 		port_cap->suggested_type = (field >> 3) & 1;
1214431df8c7SMatan Barak 		port_cap->default_sense = (field >> 4) & 1;
12157d077cd3SMatan Barak 		port_cap->dmfs_optimized_state = (field >> 5) & 1;
1216431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
1217431df8c7SMatan Barak 		port_cap->ib_mtu	   = field & 0xf;
1218431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
1219431df8c7SMatan Barak 		port_cap->max_port_width = field & 0xf;
1220431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
1221431df8c7SMatan Barak 		port_cap->max_gids	   = 1 << (field >> 4);
1222431df8c7SMatan Barak 		port_cap->max_pkeys	   = 1 << (field & 0xf);
1223431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
1224431df8c7SMatan Barak 		port_cap->max_vl	   = field & 0xf;
1225af7d5185SRana Shahout 		port_cap->max_tc_eth	   = field >> 4;
1226431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET);
1227431df8c7SMatan Barak 		port_cap->log_max_macs  = field & 0xf;
1228431df8c7SMatan Barak 		port_cap->log_max_vlans = field >> 4;
1229431df8c7SMatan Barak 		MLX4_GET(port_cap->eth_mtu, outbox, QUERY_PORT_ETH_MTU_OFFSET);
1230431df8c7SMatan Barak 		MLX4_GET(port_cap->def_mac, outbox, QUERY_PORT_MAC_OFFSET);
1231431df8c7SMatan Barak 		MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET);
1232431df8c7SMatan Barak 		port_cap->trans_type = field32 >> 24;
1233431df8c7SMatan Barak 		port_cap->vendor_oui = field32 & 0xffffff;
1234431df8c7SMatan Barak 		MLX4_GET(port_cap->wavelength, outbox, QUERY_PORT_WAVELENGTH_OFFSET);
1235431df8c7SMatan Barak 		MLX4_GET(port_cap->trans_code, outbox, QUERY_PORT_TRANS_CODE_OFFSET);
1236431df8c7SMatan Barak 	}
1237431df8c7SMatan Barak 
1238431df8c7SMatan Barak out:
1239431df8c7SMatan Barak 	mlx4_free_cmd_mailbox(dev, mailbox);
1240431df8c7SMatan Barak 	return err;
1241431df8c7SMatan Barak }
1242431df8c7SMatan Barak 
12430b131561SMatan Barak #define DEV_CAP_EXT_2_FLAG_PFC_COUNTERS	(1 << 28)
1244383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_VLAN_CONTROL (1 << 26)
1245383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_80_VFS	(1 << 21)
1246383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_FSM		(1 << 20)
1247383677daSOr Gerlitz 
1248b91cb3ebSJack Morgenstein int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
1249b91cb3ebSJack Morgenstein 			       struct mlx4_vhcr *vhcr,
1250b91cb3ebSJack Morgenstein 			       struct mlx4_cmd_mailbox *inbox,
1251b91cb3ebSJack Morgenstein 			       struct mlx4_cmd_mailbox *outbox,
1252b91cb3ebSJack Morgenstein 			       struct mlx4_cmd_info *cmd)
1253b91cb3ebSJack Morgenstein {
12542a4fae14SJack Morgenstein 	u64	flags;
1255b91cb3ebSJack Morgenstein 	int	err = 0;
1256b91cb3ebSJack Morgenstein 	u8	field;
1257fc31e256SOr Gerlitz 	u16	field16;
1258383677daSOr Gerlitz 	u32	bmme_flags, field32;
1259449fc488SMatan Barak 	int	real_port;
1260449fc488SMatan Barak 	int	slave_port;
1261449fc488SMatan Barak 	int	first_port;
1262449fc488SMatan Barak 	struct mlx4_active_ports actv_ports;
1263b91cb3ebSJack Morgenstein 
1264b91cb3ebSJack Morgenstein 	err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
1265b91cb3ebSJack Morgenstein 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1266b91cb3ebSJack Morgenstein 	if (err)
1267b91cb3ebSJack Morgenstein 		return err;
1268b91cb3ebSJack Morgenstein 
1269d8ae9141SMoni Shoua 	disable_unsupported_roce_caps(outbox->buf);
1270cc1ade94SShani Michaeli 	/* add port mng change event capability and disable mw type 1
1271cc1ade94SShani Michaeli 	 * unconditionally to slaves
1272cc1ade94SShani Michaeli 	 */
12732a4fae14SJack Morgenstein 	MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
12742a4fae14SJack Morgenstein 	flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV;
1275cc1ade94SShani Michaeli 	flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
1276449fc488SMatan Barak 	actv_ports = mlx4_get_active_ports(dev, slave);
1277449fc488SMatan Barak 	first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports);
1278449fc488SMatan Barak 	for (slave_port = 0, real_port = first_port;
1279449fc488SMatan Barak 	     real_port < first_port +
1280449fc488SMatan Barak 	     bitmap_weight(actv_ports.ports, dev->caps.num_ports);
1281449fc488SMatan Barak 	     ++real_port, ++slave_port) {
1282449fc488SMatan Barak 		if (flags & (MLX4_DEV_CAP_FLAG_WOL_PORT1 << real_port))
1283449fc488SMatan Barak 			flags |= MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port;
1284449fc488SMatan Barak 		else
1285449fc488SMatan Barak 			flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port);
1286449fc488SMatan Barak 	}
1287449fc488SMatan Barak 	for (; slave_port < dev->caps.num_ports; ++slave_port)
1288449fc488SMatan Barak 		flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port);
1289802f42a8SIdo Shamay 
1290802f42a8SIdo Shamay 	/* Not exposing RSS IP fragments to guests */
1291802f42a8SIdo Shamay 	flags &= ~MLX4_DEV_CAP_FLAG_RSS_IP_FRAG;
12922a4fae14SJack Morgenstein 	MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
12932a4fae14SJack Morgenstein 
1294449fc488SMatan Barak 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VL_PORT_OFFSET);
1295449fc488SMatan Barak 	field &= ~0x0F;
1296449fc488SMatan Barak 	field |= bitmap_weight(actv_ports.ports, dev->caps.num_ports) & 0x0F;
1297449fc488SMatan Barak 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VL_PORT_OFFSET);
1298449fc488SMatan Barak 
129930b40c31SAmir Vadai 	/* For guests, disable timestamp */
130030b40c31SAmir Vadai 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
130130b40c31SAmir Vadai 	field &= 0x7f;
130230b40c31SAmir Vadai 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
130330b40c31SAmir Vadai 
13043742cc65SIdo Shamay 	/* For guests, disable vxlan tunneling and QoS support */
130557352ef4SAmir Vadai 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VXLAN);
13063742cc65SIdo Shamay 	field &= 0xd7;
13077ffdf726SOr Gerlitz 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN);
13087ffdf726SOr Gerlitz 
130951af33cfSIdo Shamay 	/* For guests, disable port BEACON */
131051af33cfSIdo Shamay 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_PORT_BEACON_OFFSET);
131151af33cfSIdo Shamay 	field &= 0x7f;
131251af33cfSIdo Shamay 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_PORT_BEACON_OFFSET);
131351af33cfSIdo Shamay 
1314b91cb3ebSJack Morgenstein 	/* For guests, report Blueflame disabled */
1315b91cb3ebSJack Morgenstein 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
1316b91cb3ebSJack Morgenstein 	field &= 0x7f;
1317b91cb3ebSJack Morgenstein 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
1318b91cb3ebSJack Morgenstein 
131959e14e32SMoni Shoua 	/* For guests, disable mw type 2 and port remap*/
132057352ef4SAmir Vadai 	MLX4_GET(bmme_flags, outbox->buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1321cc1ade94SShani Michaeli 	bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
132259e14e32SMoni Shoua 	bmme_flags &= ~MLX4_FLAG_PORT_REMAP;
1323cc1ade94SShani Michaeli 	MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1324cc1ade94SShani Michaeli 
13250081c8f3SJack Morgenstein 	/* turn off device-managed steering capability if not enabled */
13260081c8f3SJack Morgenstein 	if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
13270081c8f3SJack Morgenstein 		MLX4_GET(field, outbox->buf,
13280081c8f3SJack Morgenstein 			 QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
13290081c8f3SJack Morgenstein 		field &= 0x7f;
13300081c8f3SJack Morgenstein 		MLX4_PUT(outbox->buf, field,
13310081c8f3SJack Morgenstein 			 QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
13320081c8f3SJack Morgenstein 	}
13334de65803SMatan Barak 
13344de65803SMatan Barak 	/* turn off ipoib managed steering for guests */
133557352ef4SAmir Vadai 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
13364de65803SMatan Barak 	field &= ~0x80;
13374de65803SMatan Barak 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
13384de65803SMatan Barak 
1339383677daSOr Gerlitz 	/* turn off host side virt features (VST, FSM, etc) for guests */
1340383677daSOr Gerlitz 	MLX4_GET(field32, outbox->buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1341383677daSOr Gerlitz 	field32 &= ~(DEV_CAP_EXT_2_FLAG_VLAN_CONTROL | DEV_CAP_EXT_2_FLAG_80_VFS |
13420b131561SMatan Barak 		     DEV_CAP_EXT_2_FLAG_FSM | DEV_CAP_EXT_2_FLAG_PFC_COUNTERS);
1343383677daSOr Gerlitz 	MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1344383677daSOr Gerlitz 
1345d237baa1SShani Michaeli 	/* turn off QCN for guests */
1346d237baa1SShani Michaeli 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
1347d237baa1SShani Michaeli 	field &= 0xfe;
1348d237baa1SShani Michaeli 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
1349d237baa1SShani Michaeli 
1350fc31e256SOr Gerlitz 	/* turn off QP max-rate limiting for guests */
1351fc31e256SOr Gerlitz 	field16 = 0;
1352fc31e256SOr Gerlitz 	MLX4_PUT(outbox->buf, field16, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET);
1353fc31e256SOr Gerlitz 
1354d019fcb2SIdo Shamay 	/* turn off QoS per VF support for guests */
1355d019fcb2SIdo Shamay 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE);
1356d019fcb2SIdo Shamay 	field &= 0xef;
1357d019fcb2SIdo Shamay 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE);
1358d019fcb2SIdo Shamay 
135978500b8cSMuhammad Mahajna 	/* turn off ignore FCS feature for guests */
136078500b8cSMuhammad Mahajna 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
136178500b8cSMuhammad Mahajna 	field &= 0xfb;
136278500b8cSMuhammad Mahajna 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
136378500b8cSMuhammad Mahajna 
1364b91cb3ebSJack Morgenstein 	return 0;
1365b91cb3ebSJack Morgenstein }
1366b91cb3ebSJack Morgenstein 
1367d8ae9141SMoni Shoua static void disable_unsupported_roce_caps(void *buf)
1368d8ae9141SMoni Shoua {
1369d8ae9141SMoni Shoua 	u32 flags;
1370d8ae9141SMoni Shoua 
1371d8ae9141SMoni Shoua 	MLX4_GET(flags, buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
1372d8ae9141SMoni Shoua 	flags &= ~(1UL << 31);
1373d8ae9141SMoni Shoua 	MLX4_PUT(buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
1374d8ae9141SMoni Shoua 	MLX4_GET(flags, buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1375d8ae9141SMoni Shoua 	flags &= ~(1UL << 24);
1376d8ae9141SMoni Shoua 	MLX4_PUT(buf, flags, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1377d8ae9141SMoni Shoua 	MLX4_GET(flags, buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1378d8ae9141SMoni Shoua 	flags &= ~(MLX4_FLAG_ROCE_V1_V2);
1379d8ae9141SMoni Shoua 	MLX4_PUT(buf, flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1380d8ae9141SMoni Shoua }
1381d8ae9141SMoni Shoua 
13825cc914f1SMarcel Apfelbaum int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
13835cc914f1SMarcel Apfelbaum 			    struct mlx4_vhcr *vhcr,
13845cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *inbox,
13855cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *outbox,
13865cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_info *cmd)
13875cc914f1SMarcel Apfelbaum {
13880eb62b93SRony Efraim 	struct mlx4_priv *priv = mlx4_priv(dev);
13895cc914f1SMarcel Apfelbaum 	u64 def_mac;
13905cc914f1SMarcel Apfelbaum 	u8 port_type;
13916634961cSJack Morgenstein 	u16 short_field;
13925cc914f1SMarcel Apfelbaum 	int err;
1393948e306dSRony Efraim 	int admin_link_state;
1394449fc488SMatan Barak 	int port = mlx4_slave_convert_port(dev, slave,
1395449fc488SMatan Barak 					   vhcr->in_modifier & 0xFF);
13965cc914f1SMarcel Apfelbaum 
1397105c320fSJack Morgenstein #define MLX4_VF_PORT_NO_LINK_SENSE_MASK	0xE0
1398948e306dSRony Efraim #define MLX4_PORT_LINK_UP_MASK		0x80
13996634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_PKEY_OFFSET	0x0c
14006634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_GID_OFFSET	0x0e
140195f56e7aSYevgeny Petrilin 
1402449fc488SMatan Barak 	if (port < 0)
1403449fc488SMatan Barak 		return -EINVAL;
1404449fc488SMatan Barak 
1405a7401b9cSJack Morgenstein 	/* Protect against untrusted guests: enforce that this is the
1406a7401b9cSJack Morgenstein 	 * QUERY_PORT general query.
1407a7401b9cSJack Morgenstein 	 */
1408a7401b9cSJack Morgenstein 	if (vhcr->op_modifier || vhcr->in_modifier & ~0xFF)
1409a7401b9cSJack Morgenstein 		return -EINVAL;
1410a7401b9cSJack Morgenstein 
1411a7401b9cSJack Morgenstein 	vhcr->in_modifier = port;
1412449fc488SMatan Barak 
14135cc914f1SMarcel Apfelbaum 	err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0,
14145cc914f1SMarcel Apfelbaum 			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
14155cc914f1SMarcel Apfelbaum 			   MLX4_CMD_NATIVE);
14165cc914f1SMarcel Apfelbaum 
14175cc914f1SMarcel Apfelbaum 	if (!err && dev->caps.function != slave) {
14180eb62b93SRony Efraim 		def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
14195cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
14205cc914f1SMarcel Apfelbaum 
14215cc914f1SMarcel Apfelbaum 		/* get port type - currently only eth is enabled */
14225cc914f1SMarcel Apfelbaum 		MLX4_GET(port_type, outbox->buf,
14235cc914f1SMarcel Apfelbaum 			 QUERY_PORT_SUPPORTED_TYPE_OFFSET);
14245cc914f1SMarcel Apfelbaum 
1425105c320fSJack Morgenstein 		/* No link sensing allowed */
1426105c320fSJack Morgenstein 		port_type &= MLX4_VF_PORT_NO_LINK_SENSE_MASK;
1427105c320fSJack Morgenstein 		/* set port type to currently operating port type */
1428105c320fSJack Morgenstein 		port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3);
14295cc914f1SMarcel Apfelbaum 
1430948e306dSRony Efraim 		admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state;
1431948e306dSRony Efraim 		if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state)
1432948e306dSRony Efraim 			port_type |= MLX4_PORT_LINK_UP_MASK;
1433948e306dSRony Efraim 		else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state)
1434948e306dSRony Efraim 			port_type &= ~MLX4_PORT_LINK_UP_MASK;
1435e34305c8SOr Gerlitz 		else if (IFLA_VF_LINK_STATE_AUTO == admin_link_state && mlx4_is_bonded(dev)) {
1436e34305c8SOr Gerlitz 			int other_port = (port == 1) ? 2 : 1;
1437e34305c8SOr Gerlitz 			struct mlx4_port_cap port_cap;
1438e34305c8SOr Gerlitz 
1439e34305c8SOr Gerlitz 			err = mlx4_QUERY_PORT(dev, other_port, &port_cap);
1440e34305c8SOr Gerlitz 			if (err)
1441e34305c8SOr Gerlitz 				goto out;
1442e34305c8SOr Gerlitz 			port_type |= (port_cap.link_state << 7);
1443e34305c8SOr Gerlitz 		}
1444948e306dSRony Efraim 
14455cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, port_type,
14465cc914f1SMarcel Apfelbaum 			 QUERY_PORT_SUPPORTED_TYPE_OFFSET);
14476634961cSJack Morgenstein 
1448b6ffaeffSJack Morgenstein 		if (dev->caps.port_type[vhcr->in_modifier] == MLX4_PORT_TYPE_ETH)
1449449fc488SMatan Barak 			short_field = mlx4_get_slave_num_gids(dev, slave, port);
1450b6ffaeffSJack Morgenstein 		else
14516634961cSJack Morgenstein 			short_field = 1; /* slave max gids */
14526634961cSJack Morgenstein 		MLX4_PUT(outbox->buf, short_field,
14536634961cSJack Morgenstein 			 QUERY_PORT_CUR_MAX_GID_OFFSET);
14546634961cSJack Morgenstein 
14556634961cSJack Morgenstein 		short_field = dev->caps.pkey_table_len[vhcr->in_modifier];
14566634961cSJack Morgenstein 		MLX4_PUT(outbox->buf, short_field,
14576634961cSJack Morgenstein 			 QUERY_PORT_CUR_MAX_PKEY_OFFSET);
14585cc914f1SMarcel Apfelbaum 	}
1459e34305c8SOr Gerlitz out:
14605cc914f1SMarcel Apfelbaum 	return err;
14615cc914f1SMarcel Apfelbaum }
14625cc914f1SMarcel Apfelbaum 
14636634961cSJack Morgenstein int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port,
14646634961cSJack Morgenstein 				    int *gid_tbl_len, int *pkey_tbl_len)
14656634961cSJack Morgenstein {
14666634961cSJack Morgenstein 	struct mlx4_cmd_mailbox *mailbox;
14676634961cSJack Morgenstein 	u32			*outbox;
14686634961cSJack Morgenstein 	u16			field;
14696634961cSJack Morgenstein 	int			err;
14706634961cSJack Morgenstein 
14716634961cSJack Morgenstein 	mailbox = mlx4_alloc_cmd_mailbox(dev);
14726634961cSJack Morgenstein 	if (IS_ERR(mailbox))
14736634961cSJack Morgenstein 		return PTR_ERR(mailbox);
14746634961cSJack Morgenstein 
14756634961cSJack Morgenstein 	err =  mlx4_cmd_box(dev, 0, mailbox->dma, port, 0,
14766634961cSJack Morgenstein 			    MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
14776634961cSJack Morgenstein 			    MLX4_CMD_WRAPPED);
14786634961cSJack Morgenstein 	if (err)
14796634961cSJack Morgenstein 		goto out;
14806634961cSJack Morgenstein 
14816634961cSJack Morgenstein 	outbox = mailbox->buf;
14826634961cSJack Morgenstein 
14836634961cSJack Morgenstein 	MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_GID_OFFSET);
14846634961cSJack Morgenstein 	*gid_tbl_len = field;
14856634961cSJack Morgenstein 
14866634961cSJack Morgenstein 	MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_PKEY_OFFSET);
14876634961cSJack Morgenstein 	*pkey_tbl_len = field;
14886634961cSJack Morgenstein 
14896634961cSJack Morgenstein out:
14906634961cSJack Morgenstein 	mlx4_free_cmd_mailbox(dev, mailbox);
14916634961cSJack Morgenstein 	return err;
14926634961cSJack Morgenstein }
14936634961cSJack Morgenstein EXPORT_SYMBOL(mlx4_get_slave_pkey_gid_tbl_len);
14946634961cSJack Morgenstein 
14955a2cc190SJeff Kirsher int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt)
14965a2cc190SJeff Kirsher {
14975a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
14985a2cc190SJeff Kirsher 	struct mlx4_icm_iter iter;
14995a2cc190SJeff Kirsher 	__be64 *pages;
15005a2cc190SJeff Kirsher 	int lg;
15015a2cc190SJeff Kirsher 	int nent = 0;
15025a2cc190SJeff Kirsher 	int i;
15035a2cc190SJeff Kirsher 	int err = 0;
15045a2cc190SJeff Kirsher 	int ts = 0, tc = 0;
15055a2cc190SJeff Kirsher 
15065a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
15075a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
15085a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
15095a2cc190SJeff Kirsher 	pages = mailbox->buf;
15105a2cc190SJeff Kirsher 
15115a2cc190SJeff Kirsher 	for (mlx4_icm_first(icm, &iter);
15125a2cc190SJeff Kirsher 	     !mlx4_icm_last(&iter);
15135a2cc190SJeff Kirsher 	     mlx4_icm_next(&iter)) {
15145a2cc190SJeff Kirsher 		/*
15155a2cc190SJeff Kirsher 		 * We have to pass pages that are aligned to their
15165a2cc190SJeff Kirsher 		 * size, so find the least significant 1 in the
15175a2cc190SJeff Kirsher 		 * address or size and use that as our log2 size.
15185a2cc190SJeff Kirsher 		 */
15195a2cc190SJeff Kirsher 		lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1;
15205a2cc190SJeff Kirsher 		if (lg < MLX4_ICM_PAGE_SHIFT) {
15211a91de28SJoe Perches 			mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx)\n",
15225a2cc190SJeff Kirsher 				  MLX4_ICM_PAGE_SIZE,
15235a2cc190SJeff Kirsher 				  (unsigned long long) mlx4_icm_addr(&iter),
15245a2cc190SJeff Kirsher 				  mlx4_icm_size(&iter));
15255a2cc190SJeff Kirsher 			err = -EINVAL;
15265a2cc190SJeff Kirsher 			goto out;
15275a2cc190SJeff Kirsher 		}
15285a2cc190SJeff Kirsher 
15295a2cc190SJeff Kirsher 		for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) {
15305a2cc190SJeff Kirsher 			if (virt != -1) {
15315a2cc190SJeff Kirsher 				pages[nent * 2] = cpu_to_be64(virt);
15325a2cc190SJeff Kirsher 				virt += 1 << lg;
15335a2cc190SJeff Kirsher 			}
15345a2cc190SJeff Kirsher 
15355a2cc190SJeff Kirsher 			pages[nent * 2 + 1] =
15365a2cc190SJeff Kirsher 				cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) |
15375a2cc190SJeff Kirsher 					    (lg - MLX4_ICM_PAGE_SHIFT));
15385a2cc190SJeff Kirsher 			ts += 1 << (lg - 10);
15395a2cc190SJeff Kirsher 			++tc;
15405a2cc190SJeff Kirsher 
15415a2cc190SJeff Kirsher 			if (++nent == MLX4_MAILBOX_SIZE / 16) {
15425a2cc190SJeff Kirsher 				err = mlx4_cmd(dev, mailbox->dma, nent, 0, op,
1543f9baff50SJack Morgenstein 						MLX4_CMD_TIME_CLASS_B,
1544f9baff50SJack Morgenstein 						MLX4_CMD_NATIVE);
15455a2cc190SJeff Kirsher 				if (err)
15465a2cc190SJeff Kirsher 					goto out;
15475a2cc190SJeff Kirsher 				nent = 0;
15485a2cc190SJeff Kirsher 			}
15495a2cc190SJeff Kirsher 		}
15505a2cc190SJeff Kirsher 	}
15515a2cc190SJeff Kirsher 
15525a2cc190SJeff Kirsher 	if (nent)
1553f9baff50SJack Morgenstein 		err = mlx4_cmd(dev, mailbox->dma, nent, 0, op,
1554f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
15555a2cc190SJeff Kirsher 	if (err)
15565a2cc190SJeff Kirsher 		goto out;
15575a2cc190SJeff Kirsher 
15585a2cc190SJeff Kirsher 	switch (op) {
15595a2cc190SJeff Kirsher 	case MLX4_CMD_MAP_FA:
15601a91de28SJoe Perches 		mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW\n", tc, ts);
15615a2cc190SJeff Kirsher 		break;
15625a2cc190SJeff Kirsher 	case MLX4_CMD_MAP_ICM_AUX:
15631a91de28SJoe Perches 		mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux\n", tc, ts);
15645a2cc190SJeff Kirsher 		break;
15655a2cc190SJeff Kirsher 	case MLX4_CMD_MAP_ICM:
15661a91de28SJoe Perches 		mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM\n",
15675a2cc190SJeff Kirsher 			 tc, ts, (unsigned long long) virt - (ts << 10));
15685a2cc190SJeff Kirsher 		break;
15695a2cc190SJeff Kirsher 	}
15705a2cc190SJeff Kirsher 
15715a2cc190SJeff Kirsher out:
15725a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
15735a2cc190SJeff Kirsher 	return err;
15745a2cc190SJeff Kirsher }
15755a2cc190SJeff Kirsher 
15765a2cc190SJeff Kirsher int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm)
15775a2cc190SJeff Kirsher {
15785a2cc190SJeff Kirsher 	return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1);
15795a2cc190SJeff Kirsher }
15805a2cc190SJeff Kirsher 
15815a2cc190SJeff Kirsher int mlx4_UNMAP_FA(struct mlx4_dev *dev)
15825a2cc190SJeff Kirsher {
1583f9baff50SJack Morgenstein 	return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA,
1584f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
15855a2cc190SJeff Kirsher }
15865a2cc190SJeff Kirsher 
15875a2cc190SJeff Kirsher 
15885a2cc190SJeff Kirsher int mlx4_RUN_FW(struct mlx4_dev *dev)
15895a2cc190SJeff Kirsher {
1590f9baff50SJack Morgenstein 	return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW,
1591f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
15925a2cc190SJeff Kirsher }
15935a2cc190SJeff Kirsher 
15945a2cc190SJeff Kirsher int mlx4_QUERY_FW(struct mlx4_dev *dev)
15955a2cc190SJeff Kirsher {
15965a2cc190SJeff Kirsher 	struct mlx4_fw  *fw  = &mlx4_priv(dev)->fw;
15975a2cc190SJeff Kirsher 	struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
15985a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
15995a2cc190SJeff Kirsher 	u32 *outbox;
16005a2cc190SJeff Kirsher 	int err = 0;
16015a2cc190SJeff Kirsher 	u64 fw_ver;
16025a2cc190SJeff Kirsher 	u16 cmd_if_rev;
16035a2cc190SJeff Kirsher 	u8 lg;
16045a2cc190SJeff Kirsher 
16055a2cc190SJeff Kirsher #define QUERY_FW_OUT_SIZE             0x100
16065a2cc190SJeff Kirsher #define QUERY_FW_VER_OFFSET            0x00
16075cc914f1SMarcel Apfelbaum #define QUERY_FW_PPF_ID		       0x09
16085a2cc190SJeff Kirsher #define QUERY_FW_CMD_IF_REV_OFFSET     0x0a
16095a2cc190SJeff Kirsher #define QUERY_FW_MAX_CMD_OFFSET        0x0f
16105a2cc190SJeff Kirsher #define QUERY_FW_ERR_START_OFFSET      0x30
16115a2cc190SJeff Kirsher #define QUERY_FW_ERR_SIZE_OFFSET       0x38
16125a2cc190SJeff Kirsher #define QUERY_FW_ERR_BAR_OFFSET        0x3c
16135a2cc190SJeff Kirsher 
16145a2cc190SJeff Kirsher #define QUERY_FW_SIZE_OFFSET           0x00
16155a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BASE_OFFSET   0x20
16165a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BAR_OFFSET    0x28
16175a2cc190SJeff Kirsher 
16185cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BASE_OFFSET      0x40
16195cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BAR_OFFSET       0x48
16205cc914f1SMarcel Apfelbaum 
1621ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_OFFSET	       0x50
1622ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_BAR	       0x58
1623ddd8a6c1SEugenia Emantayev 
16245a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
16255a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
16265a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
16275a2cc190SJeff Kirsher 	outbox = mailbox->buf;
16285a2cc190SJeff Kirsher 
16295a2cc190SJeff Kirsher 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW,
1630f9baff50SJack Morgenstein 			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
16315a2cc190SJeff Kirsher 	if (err)
16325a2cc190SJeff Kirsher 		goto out;
16335a2cc190SJeff Kirsher 
16345a2cc190SJeff Kirsher 	MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET);
16355a2cc190SJeff Kirsher 	/*
16365a2cc190SJeff Kirsher 	 * FW subminor version is at more significant bits than minor
16375a2cc190SJeff Kirsher 	 * version, so swap here.
16385a2cc190SJeff Kirsher 	 */
16395a2cc190SJeff Kirsher 	dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) |
16405a2cc190SJeff Kirsher 		((fw_ver & 0xffff0000ull) >> 16) |
16415a2cc190SJeff Kirsher 		((fw_ver & 0x0000ffffull) << 16);
16425a2cc190SJeff Kirsher 
1643752a50caSJack Morgenstein 	MLX4_GET(lg, outbox, QUERY_FW_PPF_ID);
1644752a50caSJack Morgenstein 	dev->caps.function = lg;
1645752a50caSJack Morgenstein 
1646b91cb3ebSJack Morgenstein 	if (mlx4_is_slave(dev))
1647b91cb3ebSJack Morgenstein 		goto out;
1648b91cb3ebSJack Morgenstein 
16495cc914f1SMarcel Apfelbaum 
16505a2cc190SJeff Kirsher 	MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
16515a2cc190SJeff Kirsher 	if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
16525a2cc190SJeff Kirsher 	    cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
16531a91de28SJoe Perches 		mlx4_err(dev, "Installed FW has unsupported command interface revision %d\n",
16545a2cc190SJeff Kirsher 			 cmd_if_rev);
16555a2cc190SJeff Kirsher 		mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n",
16565a2cc190SJeff Kirsher 			 (int) (dev->caps.fw_ver >> 32),
16575a2cc190SJeff Kirsher 			 (int) (dev->caps.fw_ver >> 16) & 0xffff,
16585a2cc190SJeff Kirsher 			 (int) dev->caps.fw_ver & 0xffff);
16591a91de28SJoe Perches 		mlx4_err(dev, "This driver version supports only revisions %d to %d\n",
16605a2cc190SJeff Kirsher 			 MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV);
16615a2cc190SJeff Kirsher 		err = -ENODEV;
16625a2cc190SJeff Kirsher 		goto out;
16635a2cc190SJeff Kirsher 	}
16645a2cc190SJeff Kirsher 
16655a2cc190SJeff Kirsher 	if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS)
16665a2cc190SJeff Kirsher 		dev->flags |= MLX4_FLAG_OLD_PORT_CMDS;
16675a2cc190SJeff Kirsher 
16685a2cc190SJeff Kirsher 	MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
16695a2cc190SJeff Kirsher 	cmd->max_cmds = 1 << lg;
16705a2cc190SJeff Kirsher 
16715a2cc190SJeff Kirsher 	mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n",
16725a2cc190SJeff Kirsher 		 (int) (dev->caps.fw_ver >> 32),
16735a2cc190SJeff Kirsher 		 (int) (dev->caps.fw_ver >> 16) & 0xffff,
16745a2cc190SJeff Kirsher 		 (int) dev->caps.fw_ver & 0xffff,
16755a2cc190SJeff Kirsher 		 cmd_if_rev, cmd->max_cmds);
16765a2cc190SJeff Kirsher 
16775a2cc190SJeff Kirsher 	MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET);
16785a2cc190SJeff Kirsher 	MLX4_GET(fw->catas_size,   outbox, QUERY_FW_ERR_SIZE_OFFSET);
16795a2cc190SJeff Kirsher 	MLX4_GET(fw->catas_bar,    outbox, QUERY_FW_ERR_BAR_OFFSET);
16805a2cc190SJeff Kirsher 	fw->catas_bar = (fw->catas_bar >> 6) * 2;
16815a2cc190SJeff Kirsher 
16825a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n",
16835a2cc190SJeff Kirsher 		 (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar);
16845a2cc190SJeff Kirsher 
16855a2cc190SJeff Kirsher 	MLX4_GET(fw->fw_pages,     outbox, QUERY_FW_SIZE_OFFSET);
16865a2cc190SJeff Kirsher 	MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET);
16875a2cc190SJeff Kirsher 	MLX4_GET(fw->clr_int_bar,  outbox, QUERY_FW_CLR_INT_BAR_OFFSET);
16885a2cc190SJeff Kirsher 	fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2;
16895a2cc190SJeff Kirsher 
16905cc914f1SMarcel Apfelbaum 	MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET);
16915cc914f1SMarcel Apfelbaum 	MLX4_GET(fw->comm_bar,  outbox, QUERY_FW_COMM_BAR_OFFSET);
16925cc914f1SMarcel Apfelbaum 	fw->comm_bar = (fw->comm_bar >> 6) * 2;
16935cc914f1SMarcel Apfelbaum 	mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n",
16945cc914f1SMarcel Apfelbaum 		 fw->comm_bar, fw->comm_base);
16955a2cc190SJeff Kirsher 	mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
16965a2cc190SJeff Kirsher 
1697ddd8a6c1SEugenia Emantayev 	MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET);
1698ddd8a6c1SEugenia Emantayev 	MLX4_GET(fw->clock_bar,    outbox, QUERY_FW_CLOCK_BAR);
1699ddd8a6c1SEugenia Emantayev 	fw->clock_bar = (fw->clock_bar >> 6) * 2;
1700ddd8a6c1SEugenia Emantayev 	mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n",
1701ddd8a6c1SEugenia Emantayev 		 fw->clock_bar, fw->clock_offset);
1702ddd8a6c1SEugenia Emantayev 
17035a2cc190SJeff Kirsher 	/*
17045a2cc190SJeff Kirsher 	 * Round up number of system pages needed in case
17055a2cc190SJeff Kirsher 	 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
17065a2cc190SJeff Kirsher 	 */
17075a2cc190SJeff Kirsher 	fw->fw_pages =
17085a2cc190SJeff Kirsher 		ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >>
17095a2cc190SJeff Kirsher 		(PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT);
17105a2cc190SJeff Kirsher 
17115a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n",
17125a2cc190SJeff Kirsher 		 (unsigned long long) fw->clr_int_base, fw->clr_int_bar);
17135a2cc190SJeff Kirsher 
17145a2cc190SJeff Kirsher out:
17155a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
17165a2cc190SJeff Kirsher 	return err;
17175a2cc190SJeff Kirsher }
17185a2cc190SJeff Kirsher 
1719b91cb3ebSJack Morgenstein int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave,
1720b91cb3ebSJack Morgenstein 			  struct mlx4_vhcr *vhcr,
1721b91cb3ebSJack Morgenstein 			  struct mlx4_cmd_mailbox *inbox,
1722b91cb3ebSJack Morgenstein 			  struct mlx4_cmd_mailbox *outbox,
1723b91cb3ebSJack Morgenstein 			  struct mlx4_cmd_info *cmd)
1724b91cb3ebSJack Morgenstein {
1725b91cb3ebSJack Morgenstein 	u8 *outbuf;
1726b91cb3ebSJack Morgenstein 	int err;
1727b91cb3ebSJack Morgenstein 
1728b91cb3ebSJack Morgenstein 	outbuf = outbox->buf;
1729b91cb3ebSJack Morgenstein 	err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_FW,
1730b91cb3ebSJack Morgenstein 			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1731b91cb3ebSJack Morgenstein 	if (err)
1732b91cb3ebSJack Morgenstein 		return err;
1733b91cb3ebSJack Morgenstein 
1734752a50caSJack Morgenstein 	/* for slaves, set pci PPF ID to invalid and zero out everything
1735752a50caSJack Morgenstein 	 * else except FW version */
1736b91cb3ebSJack Morgenstein 	outbuf[0] = outbuf[1] = 0;
1737b91cb3ebSJack Morgenstein 	memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8);
1738752a50caSJack Morgenstein 	outbuf[QUERY_FW_PPF_ID] = MLX4_INVALID_SLAVE_ID;
1739752a50caSJack Morgenstein 
1740b91cb3ebSJack Morgenstein 	return 0;
1741b91cb3ebSJack Morgenstein }
1742b91cb3ebSJack Morgenstein 
17435a2cc190SJeff Kirsher static void get_board_id(void *vsd, char *board_id)
17445a2cc190SJeff Kirsher {
17455a2cc190SJeff Kirsher 	int i;
17465a2cc190SJeff Kirsher 
17475a2cc190SJeff Kirsher #define VSD_OFFSET_SIG1		0x00
17485a2cc190SJeff Kirsher #define VSD_OFFSET_SIG2		0xde
17495a2cc190SJeff Kirsher #define VSD_OFFSET_MLX_BOARD_ID	0xd0
17505a2cc190SJeff Kirsher #define VSD_OFFSET_TS_BOARD_ID	0x20
17515a2cc190SJeff Kirsher 
17525a2cc190SJeff Kirsher #define VSD_SIGNATURE_TOPSPIN	0x5ad
17535a2cc190SJeff Kirsher 
17545a2cc190SJeff Kirsher 	memset(board_id, 0, MLX4_BOARD_ID_LEN);
17555a2cc190SJeff Kirsher 
17565a2cc190SJeff Kirsher 	if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
17575a2cc190SJeff Kirsher 	    be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
17585a2cc190SJeff Kirsher 		strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN);
17595a2cc190SJeff Kirsher 	} else {
17605a2cc190SJeff Kirsher 		/*
17615a2cc190SJeff Kirsher 		 * The board ID is a string but the firmware byte
17625a2cc190SJeff Kirsher 		 * swaps each 4-byte word before passing it back to
17635a2cc190SJeff Kirsher 		 * us.  Therefore we need to swab it before printing.
17645a2cc190SJeff Kirsher 		 */
176517d5ceb6SDavid Ahern 		u32 *bid_u32 = (u32 *)board_id;
176617d5ceb6SDavid Ahern 
176717d5ceb6SDavid Ahern 		for (i = 0; i < 4; ++i) {
176817d5ceb6SDavid Ahern 			u32 *addr;
176917d5ceb6SDavid Ahern 			u32 val;
177017d5ceb6SDavid Ahern 
177117d5ceb6SDavid Ahern 			addr = (u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4);
177217d5ceb6SDavid Ahern 			val = get_unaligned(addr);
177317d5ceb6SDavid Ahern 			val = swab32(val);
177417d5ceb6SDavid Ahern 			put_unaligned(val, &bid_u32[i]);
177517d5ceb6SDavid Ahern 		}
17765a2cc190SJeff Kirsher 	}
17775a2cc190SJeff Kirsher }
17785a2cc190SJeff Kirsher 
17795a2cc190SJeff Kirsher int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
17805a2cc190SJeff Kirsher {
17815a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
17825a2cc190SJeff Kirsher 	u32 *outbox;
17835a2cc190SJeff Kirsher 	int err;
17845a2cc190SJeff Kirsher 
17855a2cc190SJeff Kirsher #define QUERY_ADAPTER_OUT_SIZE             0x100
17865a2cc190SJeff Kirsher #define QUERY_ADAPTER_INTA_PIN_OFFSET      0x10
17875a2cc190SJeff Kirsher #define QUERY_ADAPTER_VSD_OFFSET           0x20
17885a2cc190SJeff Kirsher 
17895a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
17905a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
17915a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
17925a2cc190SJeff Kirsher 	outbox = mailbox->buf;
17935a2cc190SJeff Kirsher 
17945a2cc190SJeff Kirsher 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER,
1795f9baff50SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
17965a2cc190SJeff Kirsher 	if (err)
17975a2cc190SJeff Kirsher 		goto out;
17985a2cc190SJeff Kirsher 
17995a2cc190SJeff Kirsher 	MLX4_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
18005a2cc190SJeff Kirsher 
18015a2cc190SJeff Kirsher 	get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
18025a2cc190SJeff Kirsher 		     adapter->board_id);
18035a2cc190SJeff Kirsher 
18045a2cc190SJeff Kirsher out:
18055a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
18065a2cc190SJeff Kirsher 	return err;
18075a2cc190SJeff Kirsher }
18085a2cc190SJeff Kirsher 
18095a2cc190SJeff Kirsher int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
18105a2cc190SJeff Kirsher {
18115a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
18125a2cc190SJeff Kirsher 	__be32 *inbox;
18135a2cc190SJeff Kirsher 	int err;
18147d077cd3SMatan Barak 	static const u8 a0_dmfs_hw_steering[] =  {
18157d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_DEFAULT]		= 0,
18167d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_DYNAMIC]		= 1,
18177d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_STATIC]		= 2,
18187d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_DISABLE]		= 3
18197d077cd3SMatan Barak 	};
18205a2cc190SJeff Kirsher 
18215a2cc190SJeff Kirsher #define INIT_HCA_IN_SIZE		 0x200
18225a2cc190SJeff Kirsher #define INIT_HCA_VERSION_OFFSET		 0x000
18235a2cc190SJeff Kirsher #define	 INIT_HCA_VERSION		 2
18247ffdf726SOr Gerlitz #define INIT_HCA_VXLAN_OFFSET		 0x0c
18255a2cc190SJeff Kirsher #define INIT_HCA_CACHELINE_SZ_OFFSET	 0x0e
18265a2cc190SJeff Kirsher #define INIT_HCA_FLAGS_OFFSET		 0x014
1827be6a6b43SJack Morgenstein #define INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET 0x018
18285a2cc190SJeff Kirsher #define INIT_HCA_QPC_OFFSET		 0x020
18295a2cc190SJeff Kirsher #define	 INIT_HCA_QPC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x10)
18305a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_QP_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x17)
18315a2cc190SJeff Kirsher #define	 INIT_HCA_SRQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x28)
18325a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_SRQ_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x2f)
18335a2cc190SJeff Kirsher #define	 INIT_HCA_CQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x30)
18345a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_CQ_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x37)
18355cc914f1SMarcel Apfelbaum #define	 INIT_HCA_EQE_CQE_OFFSETS	 (INIT_HCA_QPC_OFFSET + 0x38)
183677507aa2SIdo Shamay #define	 INIT_HCA_EQE_CQE_STRIDE_OFFSET  (INIT_HCA_QPC_OFFSET + 0x3b)
18375a2cc190SJeff Kirsher #define	 INIT_HCA_ALTC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x40)
18385a2cc190SJeff Kirsher #define	 INIT_HCA_AUXC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x50)
18395a2cc190SJeff Kirsher #define	 INIT_HCA_EQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x60)
18405a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_EQ_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x67)
18417ae0e400SMatan Barak #define	INIT_HCA_NUM_SYS_EQS_OFFSET	(INIT_HCA_QPC_OFFSET + 0x6a)
18425a2cc190SJeff Kirsher #define	 INIT_HCA_RDMARC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x70)
18435a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_RD_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x77)
18445a2cc190SJeff Kirsher #define INIT_HCA_MCAST_OFFSET		 0x0c0
18455a2cc190SJeff Kirsher #define	 INIT_HCA_MC_BASE_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x00)
18465a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
18475a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_MC_HASH_SZ_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x16)
18485a2cc190SJeff Kirsher #define  INIT_HCA_UC_STEERING_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x18)
18495a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
18500ff1fb65SHadar Hen Zion #define  INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN	0x6
18510ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_PARAM_OFFSET         0x1d0
18520ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_BASE_OFFSET          (INIT_HCA_FS_PARAM_OFFSET + 0x00)
18530ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x12)
18547d077cd3SMatan Barak #define  INIT_HCA_FS_A0_OFFSET		  (INIT_HCA_FS_PARAM_OFFSET + 0x18)
18550ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_LOG_TABLE_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
18560ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_ETH_BITS_OFFSET      (INIT_HCA_FS_PARAM_OFFSET + 0x21)
18570ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22)
18580ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_IB_BITS_OFFSET       (INIT_HCA_FS_PARAM_OFFSET + 0x25)
18590ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_IB_NUM_ADDRS_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x26)
18605a2cc190SJeff Kirsher #define INIT_HCA_TPT_OFFSET		 0x0f0
18615a2cc190SJeff Kirsher #define	 INIT_HCA_DMPT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x00)
1862e448834eSShani Michaeli #define  INIT_HCA_TPT_MW_OFFSET		 (INIT_HCA_TPT_OFFSET + 0x08)
18635a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_MPT_SZ_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x0b)
18645a2cc190SJeff Kirsher #define	 INIT_HCA_MTT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x10)
18655a2cc190SJeff Kirsher #define	 INIT_HCA_CMPT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x18)
18665a2cc190SJeff Kirsher #define INIT_HCA_UAR_OFFSET		 0x120
18675a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_UAR_SZ_OFFSET	 (INIT_HCA_UAR_OFFSET + 0x0a)
18685a2cc190SJeff Kirsher #define  INIT_HCA_UAR_PAGE_SZ_OFFSET     (INIT_HCA_UAR_OFFSET + 0x0b)
18695a2cc190SJeff Kirsher 
18705a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
18715a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
18725a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
18735a2cc190SJeff Kirsher 	inbox = mailbox->buf;
18745a2cc190SJeff Kirsher 
18755a2cc190SJeff Kirsher 	*((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION;
18765a2cc190SJeff Kirsher 
18775a2cc190SJeff Kirsher 	*((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) =
187838353364SYishai Hadas 		((ilog2(cache_line_size()) - 4) << 5) | (1 << 4);
18795a2cc190SJeff Kirsher 
18805a2cc190SJeff Kirsher #if defined(__LITTLE_ENDIAN)
18815a2cc190SJeff Kirsher 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
18825a2cc190SJeff Kirsher #elif defined(__BIG_ENDIAN)
18835a2cc190SJeff Kirsher 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1);
18845a2cc190SJeff Kirsher #else
18855a2cc190SJeff Kirsher #error Host endianness not defined
18865a2cc190SJeff Kirsher #endif
18875a2cc190SJeff Kirsher 	/* Check port for UD address vector: */
18885a2cc190SJeff Kirsher 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1);
18895a2cc190SJeff Kirsher 
18905a2cc190SJeff Kirsher 	/* Enable IPoIB checksumming if we can: */
18915a2cc190SJeff Kirsher 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
18925a2cc190SJeff Kirsher 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
18935a2cc190SJeff Kirsher 
18945a2cc190SJeff Kirsher 	/* Enable QoS support if module parameter set */
189538438f7cSIdo Shamay 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETS_CFG && enable_qos)
18965a2cc190SJeff Kirsher 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
18975a2cc190SJeff Kirsher 
18985a2cc190SJeff Kirsher 	/* enable counters */
18995a2cc190SJeff Kirsher 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
19005a2cc190SJeff Kirsher 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
19015a2cc190SJeff Kirsher 
1902802f42a8SIdo Shamay 	/* Enable RSS spread to fragmented IP packets when supported */
1903802f42a8SIdo Shamay 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_RSS_IP_FRAG)
1904802f42a8SIdo Shamay 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 13);
1905802f42a8SIdo Shamay 
190608ff3235SOr Gerlitz 	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
190708ff3235SOr Gerlitz 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) {
190808ff3235SOr Gerlitz 		*(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29);
190908ff3235SOr Gerlitz 		dev->caps.eqe_size   = 64;
191008ff3235SOr Gerlitz 		dev->caps.eqe_factor = 1;
191108ff3235SOr Gerlitz 	} else {
191208ff3235SOr Gerlitz 		dev->caps.eqe_size   = 32;
191308ff3235SOr Gerlitz 		dev->caps.eqe_factor = 0;
191408ff3235SOr Gerlitz 	}
191508ff3235SOr Gerlitz 
191608ff3235SOr Gerlitz 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) {
191708ff3235SOr Gerlitz 		*(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30);
191808ff3235SOr Gerlitz 		dev->caps.cqe_size   = 64;
191977507aa2SIdo Shamay 		dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;
192008ff3235SOr Gerlitz 	} else {
192108ff3235SOr Gerlitz 		dev->caps.cqe_size   = 32;
192208ff3235SOr Gerlitz 	}
192308ff3235SOr Gerlitz 
192477507aa2SIdo Shamay 	/* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */
192577507aa2SIdo Shamay 	if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) &&
192677507aa2SIdo Shamay 	    (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) {
192777507aa2SIdo Shamay 		dev->caps.eqe_size = cache_line_size();
192877507aa2SIdo Shamay 		dev->caps.cqe_size = cache_line_size();
192977507aa2SIdo Shamay 		dev->caps.eqe_factor = 0;
193077507aa2SIdo Shamay 		MLX4_PUT(inbox, (u8)((ilog2(dev->caps.eqe_size) - 5) << 4 |
193177507aa2SIdo Shamay 				      (ilog2(dev->caps.eqe_size) - 5)),
193277507aa2SIdo Shamay 			 INIT_HCA_EQE_CQE_STRIDE_OFFSET);
193377507aa2SIdo Shamay 
193477507aa2SIdo Shamay 		/* User still need to know to support CQE > 32B */
193577507aa2SIdo Shamay 		dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;
193677507aa2SIdo Shamay 	}
193777507aa2SIdo Shamay 
1938be6a6b43SJack Morgenstein 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT)
1939be6a6b43SJack Morgenstein 		*(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31);
1940be6a6b43SJack Morgenstein 
19415a2cc190SJeff Kirsher 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
19425a2cc190SJeff Kirsher 
19435a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
19445a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_qps,   INIT_HCA_LOG_QP_OFFSET);
19455a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->srqc_base,     INIT_HCA_SRQC_BASE_OFFSET);
19465a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_srqs,  INIT_HCA_LOG_SRQ_OFFSET);
19475a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->cqc_base,      INIT_HCA_CQC_BASE_OFFSET);
19485a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_cqs,   INIT_HCA_LOG_CQ_OFFSET);
19495a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->altc_base,     INIT_HCA_ALTC_BASE_OFFSET);
19505a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->auxc_base,     INIT_HCA_AUXC_BASE_OFFSET);
19515a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->eqc_base,      INIT_HCA_EQC_BASE_OFFSET);
19525a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_eqs,   INIT_HCA_LOG_EQ_OFFSET);
19537ae0e400SMatan Barak 	MLX4_PUT(inbox, param->num_sys_eqs,   INIT_HCA_NUM_SYS_EQS_OFFSET);
19545a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->rdmarc_base,   INIT_HCA_RDMARC_BASE_OFFSET);
19555a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET);
19565a2cc190SJeff Kirsher 
19570ff1fb65SHadar Hen Zion 	/* steering attributes */
19580ff1fb65SHadar Hen Zion 	if (dev->caps.steering_mode ==
19590ff1fb65SHadar Hen Zion 	    MLX4_STEERING_MODE_DEVICE_MANAGED) {
19600ff1fb65SHadar Hen Zion 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |=
19610ff1fb65SHadar Hen Zion 			cpu_to_be32(1 <<
19620ff1fb65SHadar Hen Zion 				    INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN);
19635a2cc190SJeff Kirsher 
19640ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET);
19650ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_entry_sz,
19660ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
19670ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_table_sz,
19680ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
19690ff1fb65SHadar Hen Zion 		/* Enable Ethernet flow steering
19700ff1fb65SHadar Hen Zion 		 * with udp unicast and tcp unicast
19710ff1fb65SHadar Hen Zion 		 */
19727d077cd3SMatan Barak 		if (dev->caps.dmfs_high_steer_mode !=
19737d077cd3SMatan Barak 		    MLX4_STEERING_DMFS_A0_STATIC)
19747d077cd3SMatan Barak 			MLX4_PUT(inbox,
19757d077cd3SMatan Barak 				 (u8)(MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN),
19760ff1fb65SHadar Hen Zion 				 INIT_HCA_FS_ETH_BITS_OFFSET);
19770ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
19780ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET);
19790ff1fb65SHadar Hen Zion 		/* Enable IPoIB flow steering
19800ff1fb65SHadar Hen Zion 		 * with udp unicast and tcp unicast
19810ff1fb65SHadar Hen Zion 		 */
198223537b73SHadar Hen Zion 		MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN),
19830ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_IB_BITS_OFFSET);
19840ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
19850ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_IB_NUM_ADDRS_OFFSET);
19867d077cd3SMatan Barak 
19877d077cd3SMatan Barak 		if (dev->caps.dmfs_high_steer_mode !=
19887d077cd3SMatan Barak 		    MLX4_STEERING_DMFS_A0_NOT_SUPPORTED)
19897d077cd3SMatan Barak 			MLX4_PUT(inbox,
19907d077cd3SMatan Barak 				 ((u8)(a0_dmfs_hw_steering[dev->caps.dmfs_high_steer_mode]
19917d077cd3SMatan Barak 				       << 6)),
19927d077cd3SMatan Barak 				 INIT_HCA_FS_A0_OFFSET);
19930ff1fb65SHadar Hen Zion 	} else {
19945a2cc190SJeff Kirsher 		MLX4_PUT(inbox, param->mc_base,	INIT_HCA_MC_BASE_OFFSET);
19950ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_entry_sz,
19960ff1fb65SHadar Hen Zion 			 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
19970ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_hash_sz,
19980ff1fb65SHadar Hen Zion 			 INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
19990ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_table_sz,
20000ff1fb65SHadar Hen Zion 			 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
2001c96d97f4SHadar Hen Zion 		if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
20020ff1fb65SHadar Hen Zion 			MLX4_PUT(inbox, (u8) (1 << 3),
20030ff1fb65SHadar Hen Zion 				 INIT_HCA_UC_STEERING_OFFSET);
20040ff1fb65SHadar Hen Zion 	}
20055a2cc190SJeff Kirsher 
20065a2cc190SJeff Kirsher 	/* TPT attributes */
20075a2cc190SJeff Kirsher 
20085a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->dmpt_base,  INIT_HCA_DMPT_BASE_OFFSET);
2009e448834eSShani Michaeli 	MLX4_PUT(inbox, param->mw_enabled, INIT_HCA_TPT_MW_OFFSET);
20105a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET);
20115a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->mtt_base,   INIT_HCA_MTT_BASE_OFFSET);
20125a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->cmpt_base,  INIT_HCA_CMPT_BASE_OFFSET);
20135a2cc190SJeff Kirsher 
20145a2cc190SJeff Kirsher 	/* UAR attributes */
20155a2cc190SJeff Kirsher 
2016ab9c17a0SJack Morgenstein 	MLX4_PUT(inbox, param->uar_page_sz,	INIT_HCA_UAR_PAGE_SZ_OFFSET);
20175a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_uar_sz,      INIT_HCA_LOG_UAR_SZ_OFFSET);
20185a2cc190SJeff Kirsher 
20197ffdf726SOr Gerlitz 	/* set parser VXLAN attributes */
20207ffdf726SOr Gerlitz 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) {
20217ffdf726SOr Gerlitz 		u8 parser_params = 0;
20227ffdf726SOr Gerlitz 		MLX4_PUT(inbox, parser_params,	INIT_HCA_VXLAN_OFFSET);
20237ffdf726SOr Gerlitz 	}
20247ffdf726SOr Gerlitz 
20255a031086SJack Morgenstein 	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA,
20265a031086SJack Morgenstein 		       MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
20275a2cc190SJeff Kirsher 
20285a2cc190SJeff Kirsher 	if (err)
20295a2cc190SJeff Kirsher 		mlx4_err(dev, "INIT_HCA returns %d\n", err);
20305a2cc190SJeff Kirsher 
20315a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
20325a2cc190SJeff Kirsher 	return err;
20335a2cc190SJeff Kirsher }
20345a2cc190SJeff Kirsher 
2035ab9c17a0SJack Morgenstein int mlx4_QUERY_HCA(struct mlx4_dev *dev,
2036ab9c17a0SJack Morgenstein 		   struct mlx4_init_hca_param *param)
2037ab9c17a0SJack Morgenstein {
2038ab9c17a0SJack Morgenstein 	struct mlx4_cmd_mailbox *mailbox;
2039ab9c17a0SJack Morgenstein 	__be32 *outbox;
20407b8157beSJack Morgenstein 	u32 dword_field;
2041ab9c17a0SJack Morgenstein 	int err;
204208ff3235SOr Gerlitz 	u8 byte_field;
20437d077cd3SMatan Barak 	static const u8 a0_dmfs_query_hw_steering[] =  {
20447d077cd3SMatan Barak 		[0] = MLX4_STEERING_DMFS_A0_DEFAULT,
20457d077cd3SMatan Barak 		[1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
20467d077cd3SMatan Barak 		[2] = MLX4_STEERING_DMFS_A0_STATIC,
20477d077cd3SMatan Barak 		[3] = MLX4_STEERING_DMFS_A0_DISABLE
20487d077cd3SMatan Barak 	};
2049ab9c17a0SJack Morgenstein 
2050ab9c17a0SJack Morgenstein #define QUERY_HCA_GLOBAL_CAPS_OFFSET	0x04
2051ddd8a6c1SEugenia Emantayev #define QUERY_HCA_CORE_CLOCK_OFFSET	0x0c
2052ab9c17a0SJack Morgenstein 
2053ab9c17a0SJack Morgenstein 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2054ab9c17a0SJack Morgenstein 	if (IS_ERR(mailbox))
2055ab9c17a0SJack Morgenstein 		return PTR_ERR(mailbox);
2056ab9c17a0SJack Morgenstein 	outbox = mailbox->buf;
2057ab9c17a0SJack Morgenstein 
2058ab9c17a0SJack Morgenstein 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
2059ab9c17a0SJack Morgenstein 			   MLX4_CMD_QUERY_HCA,
2060ab9c17a0SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_B,
2061ab9c17a0SJack Morgenstein 			   !mlx4_is_slave(dev));
2062ab9c17a0SJack Morgenstein 	if (err)
2063ab9c17a0SJack Morgenstein 		goto out;
2064ab9c17a0SJack Morgenstein 
2065ab9c17a0SJack Morgenstein 	MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET);
2066ddd8a6c1SEugenia Emantayev 	MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
2067ab9c17a0SJack Morgenstein 
2068ab9c17a0SJack Morgenstein 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
2069ab9c17a0SJack Morgenstein 
2070ab9c17a0SJack Morgenstein 	MLX4_GET(param->qpc_base,      outbox, INIT_HCA_QPC_BASE_OFFSET);
2071ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_num_qps,   outbox, INIT_HCA_LOG_QP_OFFSET);
2072ab9c17a0SJack Morgenstein 	MLX4_GET(param->srqc_base,     outbox, INIT_HCA_SRQC_BASE_OFFSET);
2073ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_num_srqs,  outbox, INIT_HCA_LOG_SRQ_OFFSET);
2074ab9c17a0SJack Morgenstein 	MLX4_GET(param->cqc_base,      outbox, INIT_HCA_CQC_BASE_OFFSET);
2075ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_num_cqs,   outbox, INIT_HCA_LOG_CQ_OFFSET);
2076ab9c17a0SJack Morgenstein 	MLX4_GET(param->altc_base,     outbox, INIT_HCA_ALTC_BASE_OFFSET);
2077ab9c17a0SJack Morgenstein 	MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
2078ab9c17a0SJack Morgenstein 	MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
2079ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
20807ae0e400SMatan Barak 	MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
2081ab9c17a0SJack Morgenstein 	MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
2082ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
2083ab9c17a0SJack Morgenstein 
20847b8157beSJack Morgenstein 	MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
20857b8157beSJack Morgenstein 	if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
20867b8157beSJack Morgenstein 		param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
20877b8157beSJack Morgenstein 	} else {
20887b8157beSJack Morgenstein 		MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET);
20897b8157beSJack Morgenstein 		if (byte_field & 0x8)
20907b8157beSJack Morgenstein 			param->steering_mode = MLX4_STEERING_MODE_B0;
20917b8157beSJack Morgenstein 		else
20927b8157beSJack Morgenstein 			param->steering_mode = MLX4_STEERING_MODE_A0;
20937b8157beSJack Morgenstein 	}
2094802f42a8SIdo Shamay 
2095802f42a8SIdo Shamay 	if (dword_field & (1 << 13))
2096802f42a8SIdo Shamay 		param->rss_ip_frags = 1;
2097802f42a8SIdo Shamay 
20980ff1fb65SHadar Hen Zion 	/* steering attributes */
20997b8157beSJack Morgenstein 	if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
21000ff1fb65SHadar Hen Zion 		MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
21010ff1fb65SHadar Hen Zion 		MLX4_GET(param->log_mc_entry_sz, outbox,
21020ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
21030ff1fb65SHadar Hen Zion 		MLX4_GET(param->log_mc_table_sz, outbox,
21040ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
21057d077cd3SMatan Barak 		MLX4_GET(byte_field, outbox,
21067d077cd3SMatan Barak 			 INIT_HCA_FS_A0_OFFSET);
21077d077cd3SMatan Barak 		param->dmfs_high_steer_mode =
21087d077cd3SMatan Barak 			a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
21090ff1fb65SHadar Hen Zion 	} else {
2110ab9c17a0SJack Morgenstein 		MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
2111ab9c17a0SJack Morgenstein 		MLX4_GET(param->log_mc_entry_sz, outbox,
2112ab9c17a0SJack Morgenstein 			 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
2113ab9c17a0SJack Morgenstein 		MLX4_GET(param->log_mc_hash_sz,  outbox,
2114ab9c17a0SJack Morgenstein 			 INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
2115ab9c17a0SJack Morgenstein 		MLX4_GET(param->log_mc_table_sz, outbox,
2116ab9c17a0SJack Morgenstein 			 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
21170ff1fb65SHadar Hen Zion 	}
2118ab9c17a0SJack Morgenstein 
211908ff3235SOr Gerlitz 	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
212008ff3235SOr Gerlitz 	MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS);
212108ff3235SOr Gerlitz 	if (byte_field & 0x20) /* 64-bytes eqe enabled */
212208ff3235SOr Gerlitz 		param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED;
212308ff3235SOr Gerlitz 	if (byte_field & 0x40) /* 64-bytes cqe enabled */
212408ff3235SOr Gerlitz 		param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED;
212508ff3235SOr Gerlitz 
212677507aa2SIdo Shamay 	/* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */
212777507aa2SIdo Shamay 	MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_STRIDE_OFFSET);
212877507aa2SIdo Shamay 	if (byte_field) {
2129c3f2511fSIdo Shamay 		param->dev_cap_enabled |= MLX4_DEV_CAP_EQE_STRIDE_ENABLED;
2130c3f2511fSIdo Shamay 		param->dev_cap_enabled |= MLX4_DEV_CAP_CQE_STRIDE_ENABLED;
213177507aa2SIdo Shamay 		param->cqe_size = 1 << ((byte_field &
213277507aa2SIdo Shamay 					 MLX4_CQE_SIZE_MASK_STRIDE) + 5);
213377507aa2SIdo Shamay 		param->eqe_size = 1 << (((byte_field &
213477507aa2SIdo Shamay 					  MLX4_EQE_SIZE_MASK_STRIDE) >> 4) + 5);
213577507aa2SIdo Shamay 	}
213677507aa2SIdo Shamay 
2137ab9c17a0SJack Morgenstein 	/* TPT attributes */
2138ab9c17a0SJack Morgenstein 
2139ab9c17a0SJack Morgenstein 	MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
2140e448834eSShani Michaeli 	MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
2141ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
2142ab9c17a0SJack Morgenstein 	MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
2143ab9c17a0SJack Morgenstein 	MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
2144ab9c17a0SJack Morgenstein 
2145ab9c17a0SJack Morgenstein 	/* UAR attributes */
2146ab9c17a0SJack Morgenstein 
2147ab9c17a0SJack Morgenstein 	MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
2148ab9c17a0SJack Morgenstein 	MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
2149ab9c17a0SJack Morgenstein 
215077fc29c4SHadar Hen Zion 	/* phv_check enable */
215177fc29c4SHadar Hen Zion 	MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
215277fc29c4SHadar Hen Zion 	if (byte_field & 0x2)
215377fc29c4SHadar Hen Zion 		param->phv_check_en = 1;
2154ab9c17a0SJack Morgenstein out:
2155ab9c17a0SJack Morgenstein 	mlx4_free_cmd_mailbox(dev, mailbox);
2156ab9c17a0SJack Morgenstein 
2157ab9c17a0SJack Morgenstein 	return err;
2158ab9c17a0SJack Morgenstein }
2159ab9c17a0SJack Morgenstein 
21606d6e996cSMajd Dibbiny static int mlx4_hca_core_clock_update(struct mlx4_dev *dev)
21616d6e996cSMajd Dibbiny {
21626d6e996cSMajd Dibbiny 	struct mlx4_cmd_mailbox *mailbox;
21636d6e996cSMajd Dibbiny 	__be32 *outbox;
21646d6e996cSMajd Dibbiny 	int err;
21656d6e996cSMajd Dibbiny 
21666d6e996cSMajd Dibbiny 	mailbox = mlx4_alloc_cmd_mailbox(dev);
21676d6e996cSMajd Dibbiny 	if (IS_ERR(mailbox)) {
21686d6e996cSMajd Dibbiny 		mlx4_warn(dev, "hca_core_clock mailbox allocation failed\n");
21696d6e996cSMajd Dibbiny 		return PTR_ERR(mailbox);
21706d6e996cSMajd Dibbiny 	}
21716d6e996cSMajd Dibbiny 	outbox = mailbox->buf;
21726d6e996cSMajd Dibbiny 
21736d6e996cSMajd Dibbiny 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
21746d6e996cSMajd Dibbiny 			   MLX4_CMD_QUERY_HCA,
21756d6e996cSMajd Dibbiny 			   MLX4_CMD_TIME_CLASS_B,
21766d6e996cSMajd Dibbiny 			   !mlx4_is_slave(dev));
21776d6e996cSMajd Dibbiny 	if (err) {
21786d6e996cSMajd Dibbiny 		mlx4_warn(dev, "hca_core_clock update failed\n");
21796d6e996cSMajd Dibbiny 		goto out;
21806d6e996cSMajd Dibbiny 	}
21816d6e996cSMajd Dibbiny 
21826d6e996cSMajd Dibbiny 	MLX4_GET(dev->caps.hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
21836d6e996cSMajd Dibbiny 
21846d6e996cSMajd Dibbiny out:
21856d6e996cSMajd Dibbiny 	mlx4_free_cmd_mailbox(dev, mailbox);
21866d6e996cSMajd Dibbiny 
21876d6e996cSMajd Dibbiny 	return err;
21886d6e996cSMajd Dibbiny }
21896d6e996cSMajd Dibbiny 
2190980e9001SJack Morgenstein /* for IB-type ports only in SRIOV mode. Checks that both proxy QP0
2191980e9001SJack Morgenstein  * and real QP0 are active, so that the paravirtualized QP0 is ready
2192980e9001SJack Morgenstein  * to operate */
2193980e9001SJack Morgenstein static int check_qp0_state(struct mlx4_dev *dev, int function, int port)
2194980e9001SJack Morgenstein {
2195980e9001SJack Morgenstein 	struct mlx4_priv *priv = mlx4_priv(dev);
2196980e9001SJack Morgenstein 	/* irrelevant if not infiniband */
2197980e9001SJack Morgenstein 	if (priv->mfunc.master.qp0_state[port].proxy_qp0_active &&
2198980e9001SJack Morgenstein 	    priv->mfunc.master.qp0_state[port].qp0_active)
2199980e9001SJack Morgenstein 		return 1;
2200980e9001SJack Morgenstein 	return 0;
2201980e9001SJack Morgenstein }
2202980e9001SJack Morgenstein 
22035cc914f1SMarcel Apfelbaum int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
22045cc914f1SMarcel Apfelbaum 			   struct mlx4_vhcr *vhcr,
22055cc914f1SMarcel Apfelbaum 			   struct mlx4_cmd_mailbox *inbox,
22065cc914f1SMarcel Apfelbaum 			   struct mlx4_cmd_mailbox *outbox,
22075cc914f1SMarcel Apfelbaum 			   struct mlx4_cmd_info *cmd)
22085cc914f1SMarcel Apfelbaum {
22095cc914f1SMarcel Apfelbaum 	struct mlx4_priv *priv = mlx4_priv(dev);
2210449fc488SMatan Barak 	int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier);
22115cc914f1SMarcel Apfelbaum 	int err;
22125cc914f1SMarcel Apfelbaum 
2213449fc488SMatan Barak 	if (port < 0)
2214449fc488SMatan Barak 		return -EINVAL;
2215449fc488SMatan Barak 
22165cc914f1SMarcel Apfelbaum 	if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port))
22175cc914f1SMarcel Apfelbaum 		return 0;
22185cc914f1SMarcel Apfelbaum 
2219980e9001SJack Morgenstein 	if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
22205cc914f1SMarcel Apfelbaum 		/* Enable port only if it was previously disabled */
22215cc914f1SMarcel Apfelbaum 		if (!priv->mfunc.master.init_port_ref[port]) {
22225cc914f1SMarcel Apfelbaum 			err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
22235cc914f1SMarcel Apfelbaum 				       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
22245cc914f1SMarcel Apfelbaum 			if (err)
22255cc914f1SMarcel Apfelbaum 				return err;
22265cc914f1SMarcel Apfelbaum 		}
22278bac9edeSJack Morgenstein 		priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
2228980e9001SJack Morgenstein 	} else {
2229980e9001SJack Morgenstein 		if (slave == mlx4_master_func_num(dev)) {
2230980e9001SJack Morgenstein 			if (check_qp0_state(dev, slave, port) &&
2231980e9001SJack Morgenstein 			    !priv->mfunc.master.qp0_state[port].port_active) {
2232980e9001SJack Morgenstein 				err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
2233980e9001SJack Morgenstein 					       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
2234980e9001SJack Morgenstein 				if (err)
2235980e9001SJack Morgenstein 					return err;
2236980e9001SJack Morgenstein 				priv->mfunc.master.qp0_state[port].port_active = 1;
2237980e9001SJack Morgenstein 				priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
2238980e9001SJack Morgenstein 			}
2239980e9001SJack Morgenstein 		} else
2240980e9001SJack Morgenstein 			priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
2241980e9001SJack Morgenstein 	}
22425cc914f1SMarcel Apfelbaum 	++priv->mfunc.master.init_port_ref[port];
22435cc914f1SMarcel Apfelbaum 	return 0;
22445cc914f1SMarcel Apfelbaum }
22455cc914f1SMarcel Apfelbaum 
22465a2cc190SJeff Kirsher int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
22475a2cc190SJeff Kirsher {
22485a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
22495a2cc190SJeff Kirsher 	u32 *inbox;
22505a2cc190SJeff Kirsher 	int err;
22515a2cc190SJeff Kirsher 	u32 flags;
22525a2cc190SJeff Kirsher 	u16 field;
22535a2cc190SJeff Kirsher 
22545a2cc190SJeff Kirsher 	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
22555a2cc190SJeff Kirsher #define INIT_PORT_IN_SIZE          256
22565a2cc190SJeff Kirsher #define INIT_PORT_FLAGS_OFFSET     0x00
22575a2cc190SJeff Kirsher #define INIT_PORT_FLAG_SIG         (1 << 18)
22585a2cc190SJeff Kirsher #define INIT_PORT_FLAG_NG          (1 << 17)
22595a2cc190SJeff Kirsher #define INIT_PORT_FLAG_G0          (1 << 16)
22605a2cc190SJeff Kirsher #define INIT_PORT_VL_SHIFT         4
22615a2cc190SJeff Kirsher #define INIT_PORT_PORT_WIDTH_SHIFT 8
22625a2cc190SJeff Kirsher #define INIT_PORT_MTU_OFFSET       0x04
22635a2cc190SJeff Kirsher #define INIT_PORT_MAX_GID_OFFSET   0x06
22645a2cc190SJeff Kirsher #define INIT_PORT_MAX_PKEY_OFFSET  0x0a
22655a2cc190SJeff Kirsher #define INIT_PORT_GUID0_OFFSET     0x10
22665a2cc190SJeff Kirsher #define INIT_PORT_NODE_GUID_OFFSET 0x18
22675a2cc190SJeff Kirsher #define INIT_PORT_SI_GUID_OFFSET   0x20
22685a2cc190SJeff Kirsher 
22695a2cc190SJeff Kirsher 		mailbox = mlx4_alloc_cmd_mailbox(dev);
22705a2cc190SJeff Kirsher 		if (IS_ERR(mailbox))
22715a2cc190SJeff Kirsher 			return PTR_ERR(mailbox);
22725a2cc190SJeff Kirsher 		inbox = mailbox->buf;
22735a2cc190SJeff Kirsher 
22745a2cc190SJeff Kirsher 		flags = 0;
22755a2cc190SJeff Kirsher 		flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT;
22765a2cc190SJeff Kirsher 		flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
22775a2cc190SJeff Kirsher 		MLX4_PUT(inbox, flags,		  INIT_PORT_FLAGS_OFFSET);
22785a2cc190SJeff Kirsher 
22795a2cc190SJeff Kirsher 		field = 128 << dev->caps.ib_mtu_cap[port];
22805a2cc190SJeff Kirsher 		MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
22815a2cc190SJeff Kirsher 		field = dev->caps.gid_table_len[port];
22825a2cc190SJeff Kirsher 		MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
22835a2cc190SJeff Kirsher 		field = dev->caps.pkey_table_len[port];
22845a2cc190SJeff Kirsher 		MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET);
22855a2cc190SJeff Kirsher 
22865a2cc190SJeff Kirsher 		err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
2287f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
22885a2cc190SJeff Kirsher 
22895a2cc190SJeff Kirsher 		mlx4_free_cmd_mailbox(dev, mailbox);
22905a2cc190SJeff Kirsher 	} else
22915a2cc190SJeff Kirsher 		err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
2292f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
22935a2cc190SJeff Kirsher 
22946d6e996cSMajd Dibbiny 	if (!err)
22956d6e996cSMajd Dibbiny 		mlx4_hca_core_clock_update(dev);
22966d6e996cSMajd Dibbiny 
22975a2cc190SJeff Kirsher 	return err;
22985a2cc190SJeff Kirsher }
22995a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_INIT_PORT);
23005a2cc190SJeff Kirsher 
23015cc914f1SMarcel Apfelbaum int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave,
23025cc914f1SMarcel Apfelbaum 			    struct mlx4_vhcr *vhcr,
23035cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *inbox,
23045cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *outbox,
23055cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_info *cmd)
23065cc914f1SMarcel Apfelbaum {
23075cc914f1SMarcel Apfelbaum 	struct mlx4_priv *priv = mlx4_priv(dev);
2308449fc488SMatan Barak 	int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier);
23095cc914f1SMarcel Apfelbaum 	int err;
23105cc914f1SMarcel Apfelbaum 
2311449fc488SMatan Barak 	if (port < 0)
2312449fc488SMatan Barak 		return -EINVAL;
2313449fc488SMatan Barak 
23145cc914f1SMarcel Apfelbaum 	if (!(priv->mfunc.master.slave_state[slave].init_port_mask &
23155cc914f1SMarcel Apfelbaum 	    (1 << port)))
23165cc914f1SMarcel Apfelbaum 		return 0;
23175cc914f1SMarcel Apfelbaum 
2318980e9001SJack Morgenstein 	if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
23195cc914f1SMarcel Apfelbaum 		if (priv->mfunc.master.init_port_ref[port] == 1) {
2320980e9001SJack Morgenstein 			err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
23215a031086SJack Morgenstein 				       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
23225cc914f1SMarcel Apfelbaum 			if (err)
23235cc914f1SMarcel Apfelbaum 				return err;
23245cc914f1SMarcel Apfelbaum 		}
23255cc914f1SMarcel Apfelbaum 		priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
2326980e9001SJack Morgenstein 	} else {
2327980e9001SJack Morgenstein 		/* infiniband port */
2328980e9001SJack Morgenstein 		if (slave == mlx4_master_func_num(dev)) {
2329980e9001SJack Morgenstein 			if (!priv->mfunc.master.qp0_state[port].qp0_active &&
2330980e9001SJack Morgenstein 			    priv->mfunc.master.qp0_state[port].port_active) {
2331980e9001SJack Morgenstein 				err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
23325a031086SJack Morgenstein 					       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
2333980e9001SJack Morgenstein 				if (err)
2334980e9001SJack Morgenstein 					return err;
2335980e9001SJack Morgenstein 				priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
2336980e9001SJack Morgenstein 				priv->mfunc.master.qp0_state[port].port_active = 0;
2337980e9001SJack Morgenstein 			}
2338980e9001SJack Morgenstein 		} else
2339980e9001SJack Morgenstein 			priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
2340980e9001SJack Morgenstein 	}
23415cc914f1SMarcel Apfelbaum 	--priv->mfunc.master.init_port_ref[port];
23425cc914f1SMarcel Apfelbaum 	return 0;
23435cc914f1SMarcel Apfelbaum }
23445cc914f1SMarcel Apfelbaum 
23455a2cc190SJeff Kirsher int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port)
23465a2cc190SJeff Kirsher {
23475a031086SJack Morgenstein 	return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
23485a031086SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
23495a2cc190SJeff Kirsher }
23505a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT);
23515a2cc190SJeff Kirsher 
23525a2cc190SJeff Kirsher int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic)
23535a2cc190SJeff Kirsher {
23545a031086SJack Morgenstein 	return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA,
23555a031086SJack Morgenstein 			MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
23565a2cc190SJeff Kirsher }
23575a2cc190SJeff Kirsher 
2358d18f141aSOr Gerlitz struct mlx4_config_dev {
2359d18f141aSOr Gerlitz 	__be32	update_flags;
2360d475c95bSMatan Barak 	__be32	rsvd1[3];
2361d18f141aSOr Gerlitz 	__be16	vxlan_udp_dport;
2362d18f141aSOr Gerlitz 	__be16	rsvd2;
2363fca83006SMoni Shoua 	__be16  roce_v2_entropy;
2364fca83006SMoni Shoua 	__be16  roce_v2_udp_dport;
236559e14e32SMoni Shoua 	__be32	roce_flags;
236659e14e32SMoni Shoua 	__be32	rsvd4[25];
236759e14e32SMoni Shoua 	__be16	rsvd5;
236859e14e32SMoni Shoua 	u8	rsvd6;
2369d475c95bSMatan Barak 	u8	rx_checksum_val;
2370d18f141aSOr Gerlitz };
2371d18f141aSOr Gerlitz 
2372d18f141aSOr Gerlitz #define MLX4_VXLAN_UDP_DPORT (1 << 0)
2373fca83006SMoni Shoua #define MLX4_ROCE_V2_UDP_DPORT BIT(3)
237459e14e32SMoni Shoua #define MLX4_DISABLE_RX_PORT BIT(18)
2375d18f141aSOr Gerlitz 
2376d475c95bSMatan Barak static int mlx4_CONFIG_DEV_set(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
2377d18f141aSOr Gerlitz {
2378d18f141aSOr Gerlitz 	int err;
2379d18f141aSOr Gerlitz 	struct mlx4_cmd_mailbox *mailbox;
2380d18f141aSOr Gerlitz 
2381d18f141aSOr Gerlitz 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2382d18f141aSOr Gerlitz 	if (IS_ERR(mailbox))
2383d18f141aSOr Gerlitz 		return PTR_ERR(mailbox);
2384d18f141aSOr Gerlitz 
2385d18f141aSOr Gerlitz 	memcpy(mailbox->buf, config_dev, sizeof(*config_dev));
2386d18f141aSOr Gerlitz 
2387d18f141aSOr Gerlitz 	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_CONFIG_DEV,
2388d18f141aSOr Gerlitz 		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
2389d18f141aSOr Gerlitz 
2390d18f141aSOr Gerlitz 	mlx4_free_cmd_mailbox(dev, mailbox);
2391d18f141aSOr Gerlitz 	return err;
2392d18f141aSOr Gerlitz }
2393d18f141aSOr Gerlitz 
2394d475c95bSMatan Barak static int mlx4_CONFIG_DEV_get(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
2395d475c95bSMatan Barak {
2396d475c95bSMatan Barak 	int err;
2397d475c95bSMatan Barak 	struct mlx4_cmd_mailbox *mailbox;
2398d475c95bSMatan Barak 
2399d475c95bSMatan Barak 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2400d475c95bSMatan Barak 	if (IS_ERR(mailbox))
2401d475c95bSMatan Barak 		return PTR_ERR(mailbox);
2402d475c95bSMatan Barak 
2403d475c95bSMatan Barak 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 1, MLX4_CMD_CONFIG_DEV,
2404d475c95bSMatan Barak 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
2405d475c95bSMatan Barak 
2406d475c95bSMatan Barak 	if (!err)
2407d475c95bSMatan Barak 		memcpy(config_dev, mailbox->buf, sizeof(*config_dev));
2408d475c95bSMatan Barak 
2409d475c95bSMatan Barak 	mlx4_free_cmd_mailbox(dev, mailbox);
2410d475c95bSMatan Barak 	return err;
2411d475c95bSMatan Barak }
2412d475c95bSMatan Barak 
2413d475c95bSMatan Barak /* Conversion between the HW values and the actual functionality.
2414d475c95bSMatan Barak  * The value represented by the array index,
2415d475c95bSMatan Barak  * and the functionality determined by the flags.
2416d475c95bSMatan Barak  */
2417d475c95bSMatan Barak static const u8 config_dev_csum_flags[] = {
2418d475c95bSMatan Barak 	[0] =	0,
2419d475c95bSMatan Barak 	[1] =	MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP,
2420d475c95bSMatan Barak 	[2] =	MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP	|
2421d475c95bSMatan Barak 		MLX4_RX_CSUM_MODE_L4,
2422d475c95bSMatan Barak 	[3] =	MLX4_RX_CSUM_MODE_L4			|
2423d475c95bSMatan Barak 		MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP	|
2424d475c95bSMatan Barak 		MLX4_RX_CSUM_MODE_MULTI_VLAN
2425d475c95bSMatan Barak };
2426d475c95bSMatan Barak 
2427d475c95bSMatan Barak int mlx4_config_dev_retrieval(struct mlx4_dev *dev,
2428d475c95bSMatan Barak 			      struct mlx4_config_dev_params *params)
2429d475c95bSMatan Barak {
24306af0a52fSMaor Gottlieb 	struct mlx4_config_dev config_dev = {0};
2431d475c95bSMatan Barak 	int err;
2432d475c95bSMatan Barak 	u8 csum_mask;
2433d475c95bSMatan Barak 
2434d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_MASK			0x7
2435d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET	0
2436d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET	4
2437d475c95bSMatan Barak 
2438d475c95bSMatan Barak 	if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV))
2439d475c95bSMatan Barak 		return -ENOTSUPP;
2440d475c95bSMatan Barak 
2441d475c95bSMatan Barak 	err = mlx4_CONFIG_DEV_get(dev, &config_dev);
2442d475c95bSMatan Barak 	if (err)
2443d475c95bSMatan Barak 		return err;
2444d475c95bSMatan Barak 
2445d475c95bSMatan Barak 	csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET) &
2446d475c95bSMatan Barak 			CONFIG_DEV_RX_CSUM_MODE_MASK;
2447d475c95bSMatan Barak 
2448d475c95bSMatan Barak 	if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0]))
2449d475c95bSMatan Barak 		return -EINVAL;
2450d475c95bSMatan Barak 	params->rx_csum_flags_port_1 = config_dev_csum_flags[csum_mask];
2451d475c95bSMatan Barak 
2452d475c95bSMatan Barak 	csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET) &
2453d475c95bSMatan Barak 			CONFIG_DEV_RX_CSUM_MODE_MASK;
2454d475c95bSMatan Barak 
2455d475c95bSMatan Barak 	if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0]))
2456d475c95bSMatan Barak 		return -EINVAL;
2457d475c95bSMatan Barak 	params->rx_csum_flags_port_2 = config_dev_csum_flags[csum_mask];
2458d475c95bSMatan Barak 
2459d475c95bSMatan Barak 	params->vxlan_udp_dport = be16_to_cpu(config_dev.vxlan_udp_dport);
2460d475c95bSMatan Barak 
2461d475c95bSMatan Barak 	return 0;
2462d475c95bSMatan Barak }
2463d475c95bSMatan Barak EXPORT_SYMBOL_GPL(mlx4_config_dev_retrieval);
2464d475c95bSMatan Barak 
2465d18f141aSOr Gerlitz int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port)
2466d18f141aSOr Gerlitz {
2467d18f141aSOr Gerlitz 	struct mlx4_config_dev config_dev;
2468d18f141aSOr Gerlitz 
2469d18f141aSOr Gerlitz 	memset(&config_dev, 0, sizeof(config_dev));
2470d18f141aSOr Gerlitz 	config_dev.update_flags    = cpu_to_be32(MLX4_VXLAN_UDP_DPORT);
2471d18f141aSOr Gerlitz 	config_dev.vxlan_udp_dport = udp_port;
2472d18f141aSOr Gerlitz 
2473d475c95bSMatan Barak 	return mlx4_CONFIG_DEV_set(dev, &config_dev);
2474d18f141aSOr Gerlitz }
2475d18f141aSOr Gerlitz EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port);
2476d18f141aSOr Gerlitz 
247759e14e32SMoni Shoua #define CONFIG_DISABLE_RX_PORT BIT(15)
247859e14e32SMoni Shoua int mlx4_disable_rx_port_check(struct mlx4_dev *dev, bool dis)
247959e14e32SMoni Shoua {
248059e14e32SMoni Shoua 	struct mlx4_config_dev config_dev;
248159e14e32SMoni Shoua 
248259e14e32SMoni Shoua 	memset(&config_dev, 0, sizeof(config_dev));
248359e14e32SMoni Shoua 	config_dev.update_flags = cpu_to_be32(MLX4_DISABLE_RX_PORT);
248459e14e32SMoni Shoua 	if (dis)
248559e14e32SMoni Shoua 		config_dev.roce_flags =
248659e14e32SMoni Shoua 			cpu_to_be32(CONFIG_DISABLE_RX_PORT);
248759e14e32SMoni Shoua 
248859e14e32SMoni Shoua 	return mlx4_CONFIG_DEV_set(dev, &config_dev);
248959e14e32SMoni Shoua }
249059e14e32SMoni Shoua 
2491fca83006SMoni Shoua int mlx4_config_roce_v2_port(struct mlx4_dev *dev, u16 udp_port)
2492fca83006SMoni Shoua {
2493fca83006SMoni Shoua 	struct mlx4_config_dev config_dev;
2494fca83006SMoni Shoua 
2495fca83006SMoni Shoua 	memset(&config_dev, 0, sizeof(config_dev));
2496fca83006SMoni Shoua 	config_dev.update_flags    = cpu_to_be32(MLX4_ROCE_V2_UDP_DPORT);
2497fca83006SMoni Shoua 	config_dev.roce_v2_udp_dport = cpu_to_be16(udp_port);
2498fca83006SMoni Shoua 
2499fca83006SMoni Shoua 	return mlx4_CONFIG_DEV_set(dev, &config_dev);
2500fca83006SMoni Shoua }
2501fca83006SMoni Shoua EXPORT_SYMBOL_GPL(mlx4_config_roce_v2_port);
2502fca83006SMoni Shoua 
250359e14e32SMoni Shoua int mlx4_virt2phy_port_map(struct mlx4_dev *dev, u32 port1, u32 port2)
250459e14e32SMoni Shoua {
250559e14e32SMoni Shoua 	struct mlx4_cmd_mailbox *mailbox;
250659e14e32SMoni Shoua 	struct {
250759e14e32SMoni Shoua 		__be32 v_port1;
250859e14e32SMoni Shoua 		__be32 v_port2;
250959e14e32SMoni Shoua 	} *v2p;
251059e14e32SMoni Shoua 	int err;
251159e14e32SMoni Shoua 
251259e14e32SMoni Shoua 	mailbox = mlx4_alloc_cmd_mailbox(dev);
251359e14e32SMoni Shoua 	if (IS_ERR(mailbox))
251459e14e32SMoni Shoua 		return -ENOMEM;
251559e14e32SMoni Shoua 
251659e14e32SMoni Shoua 	v2p = mailbox->buf;
251759e14e32SMoni Shoua 	v2p->v_port1 = cpu_to_be32(port1);
251859e14e32SMoni Shoua 	v2p->v_port2 = cpu_to_be32(port2);
251959e14e32SMoni Shoua 
252059e14e32SMoni Shoua 	err = mlx4_cmd(dev, mailbox->dma, 0,
252159e14e32SMoni Shoua 		       MLX4_SET_PORT_VIRT2PHY, MLX4_CMD_VIRT_PORT_MAP,
252259e14e32SMoni Shoua 		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
252359e14e32SMoni Shoua 
252459e14e32SMoni Shoua 	mlx4_free_cmd_mailbox(dev, mailbox);
252559e14e32SMoni Shoua 	return err;
252659e14e32SMoni Shoua }
252759e14e32SMoni Shoua 
2528d18f141aSOr Gerlitz 
25295a2cc190SJeff Kirsher int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages)
25305a2cc190SJeff Kirsher {
25315a2cc190SJeff Kirsher 	int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0,
25325a2cc190SJeff Kirsher 			       MLX4_CMD_SET_ICM_SIZE,
2533f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
25345a2cc190SJeff Kirsher 	if (ret)
25355a2cc190SJeff Kirsher 		return ret;
25365a2cc190SJeff Kirsher 
25375a2cc190SJeff Kirsher 	/*
25385a2cc190SJeff Kirsher 	 * Round up number of system pages needed in case
25395a2cc190SJeff Kirsher 	 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
25405a2cc190SJeff Kirsher 	 */
25415a2cc190SJeff Kirsher 	*aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >>
25425a2cc190SJeff Kirsher 		(PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT);
25435a2cc190SJeff Kirsher 
25445a2cc190SJeff Kirsher 	return 0;
25455a2cc190SJeff Kirsher }
25465a2cc190SJeff Kirsher 
25475a2cc190SJeff Kirsher int mlx4_NOP(struct mlx4_dev *dev)
25485a2cc190SJeff Kirsher {
25495a2cc190SJeff Kirsher 	/* Input modifier of 0x1f means "finish as soon as possible." */
25505a031086SJack Morgenstein 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, MLX4_CMD_TIME_CLASS_A,
25515a031086SJack Morgenstein 			MLX4_CMD_NATIVE);
25525a2cc190SJeff Kirsher }
25535a2cc190SJeff Kirsher 
2554bfaf3168SMark Bloch int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
2555bfaf3168SMark Bloch 			     const u32 offset[],
2556bfaf3168SMark Bloch 			     u32 value[], size_t array_len, u8 port)
2557bfaf3168SMark Bloch {
2558bfaf3168SMark Bloch 	struct mlx4_cmd_mailbox *mailbox;
2559bfaf3168SMark Bloch 	u32 *outbox;
2560bfaf3168SMark Bloch 	size_t i;
2561bfaf3168SMark Bloch 	int ret;
2562bfaf3168SMark Bloch 
2563bfaf3168SMark Bloch 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2564bfaf3168SMark Bloch 	if (IS_ERR(mailbox))
2565bfaf3168SMark Bloch 		return PTR_ERR(mailbox);
2566bfaf3168SMark Bloch 
2567bfaf3168SMark Bloch 	outbox = mailbox->buf;
2568bfaf3168SMark Bloch 
2569bfaf3168SMark Bloch 	ret = mlx4_cmd_box(dev, 0, mailbox->dma, port, op_modifier,
2570bfaf3168SMark Bloch 			   MLX4_CMD_DIAG_RPRT, MLX4_CMD_TIME_CLASS_A,
2571bfaf3168SMark Bloch 			   MLX4_CMD_NATIVE);
2572bfaf3168SMark Bloch 	if (ret)
2573bfaf3168SMark Bloch 		goto out;
2574bfaf3168SMark Bloch 
2575bfaf3168SMark Bloch 	for (i = 0; i < array_len; i++) {
2576bfaf3168SMark Bloch 		if (offset[i] > MLX4_MAILBOX_SIZE) {
2577bfaf3168SMark Bloch 			ret = -EINVAL;
2578bfaf3168SMark Bloch 			goto out;
2579bfaf3168SMark Bloch 		}
2580bfaf3168SMark Bloch 
2581bfaf3168SMark Bloch 		MLX4_GET(value[i], outbox, offset[i]);
2582bfaf3168SMark Bloch 	}
2583bfaf3168SMark Bloch 
2584bfaf3168SMark Bloch out:
2585bfaf3168SMark Bloch 	mlx4_free_cmd_mailbox(dev, mailbox);
2586bfaf3168SMark Bloch 	return ret;
2587bfaf3168SMark Bloch }
2588bfaf3168SMark Bloch EXPORT_SYMBOL(mlx4_query_diag_counters);
2589bfaf3168SMark Bloch 
25908e1a28e8SHadar Hen Zion int mlx4_get_phys_port_id(struct mlx4_dev *dev)
25918e1a28e8SHadar Hen Zion {
25928e1a28e8SHadar Hen Zion 	u8 port;
25938e1a28e8SHadar Hen Zion 	u32 *outbox;
25948e1a28e8SHadar Hen Zion 	struct mlx4_cmd_mailbox *mailbox;
25958e1a28e8SHadar Hen Zion 	u32 in_mod;
25968e1a28e8SHadar Hen Zion 	u32 guid_hi, guid_lo;
25978e1a28e8SHadar Hen Zion 	int err, ret = 0;
25988e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_PORT_OFFSET 8
25998e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_H	 0X14
26008e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_L	 0X1c
26018e1a28e8SHadar Hen Zion 
26028e1a28e8SHadar Hen Zion 	mailbox = mlx4_alloc_cmd_mailbox(dev);
26038e1a28e8SHadar Hen Zion 	if (IS_ERR(mailbox))
26048e1a28e8SHadar Hen Zion 		return PTR_ERR(mailbox);
26058e1a28e8SHadar Hen Zion 	outbox = mailbox->buf;
26068e1a28e8SHadar Hen Zion 
26078e1a28e8SHadar Hen Zion 	for (port = 1; port <= dev->caps.num_ports; port++) {
26088e1a28e8SHadar Hen Zion 		in_mod = port << MOD_STAT_CFG_PORT_OFFSET;
26098e1a28e8SHadar Hen Zion 		err = mlx4_cmd_box(dev, 0, mailbox->dma, in_mod, 0x2,
26108e1a28e8SHadar Hen Zion 				   MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A,
26118e1a28e8SHadar Hen Zion 				   MLX4_CMD_NATIVE);
26128e1a28e8SHadar Hen Zion 		if (err) {
26138e1a28e8SHadar Hen Zion 			mlx4_err(dev, "Fail to get port %d uplink guid\n",
26148e1a28e8SHadar Hen Zion 				 port);
26158e1a28e8SHadar Hen Zion 			ret = err;
26168e1a28e8SHadar Hen Zion 		} else {
26178e1a28e8SHadar Hen Zion 			MLX4_GET(guid_hi, outbox, MOD_STAT_CFG_GUID_H);
26188e1a28e8SHadar Hen Zion 			MLX4_GET(guid_lo, outbox, MOD_STAT_CFG_GUID_L);
26198e1a28e8SHadar Hen Zion 			dev->caps.phys_port_id[port] = (u64)guid_lo |
26208e1a28e8SHadar Hen Zion 						       (u64)guid_hi << 32;
26218e1a28e8SHadar Hen Zion 		}
26228e1a28e8SHadar Hen Zion 	}
26238e1a28e8SHadar Hen Zion 	mlx4_free_cmd_mailbox(dev, mailbox);
26248e1a28e8SHadar Hen Zion 	return ret;
26258e1a28e8SHadar Hen Zion }
26268e1a28e8SHadar Hen Zion 
26275a2cc190SJeff Kirsher #define MLX4_WOL_SETUP_MODE (5 << 28)
26285a2cc190SJeff Kirsher int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
26295a2cc190SJeff Kirsher {
26305a2cc190SJeff Kirsher 	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
26315a2cc190SJeff Kirsher 
26325a2cc190SJeff Kirsher 	return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
2633f9baff50SJack Morgenstein 			    MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A,
2634f9baff50SJack Morgenstein 			    MLX4_CMD_NATIVE);
26355a2cc190SJeff Kirsher }
26365a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_read);
26375a2cc190SJeff Kirsher 
26385a2cc190SJeff Kirsher int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
26395a2cc190SJeff Kirsher {
26405a2cc190SJeff Kirsher 	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
26415a2cc190SJeff Kirsher 
26425a2cc190SJeff Kirsher 	return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
2643f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
26445a2cc190SJeff Kirsher }
26455a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_write);
2646fe6f700dSYevgeny Petrilin 
2647fe6f700dSYevgeny Petrilin enum {
2648fe6f700dSYevgeny Petrilin 	ADD_TO_MCG = 0x26,
2649fe6f700dSYevgeny Petrilin };
2650fe6f700dSYevgeny Petrilin 
2651fe6f700dSYevgeny Petrilin 
2652fe6f700dSYevgeny Petrilin void mlx4_opreq_action(struct work_struct *work)
2653fe6f700dSYevgeny Petrilin {
2654fe6f700dSYevgeny Petrilin 	struct mlx4_priv *priv = container_of(work, struct mlx4_priv,
2655fe6f700dSYevgeny Petrilin 					      opreq_task);
2656fe6f700dSYevgeny Petrilin 	struct mlx4_dev *dev = &priv->dev;
2657fe6f700dSYevgeny Petrilin 	int num_tasks = atomic_read(&priv->opreq_count);
2658fe6f700dSYevgeny Petrilin 	struct mlx4_cmd_mailbox *mailbox;
2659fe6f700dSYevgeny Petrilin 	struct mlx4_mgm *mgm;
2660fe6f700dSYevgeny Petrilin 	u32 *outbox;
2661fe6f700dSYevgeny Petrilin 	u32 modifier;
2662fe6f700dSYevgeny Petrilin 	u16 token;
2663fe6f700dSYevgeny Petrilin 	u16 type;
2664fe6f700dSYevgeny Petrilin 	int err;
2665fe6f700dSYevgeny Petrilin 	u32 num_qps;
2666fe6f700dSYevgeny Petrilin 	struct mlx4_qp qp;
2667fe6f700dSYevgeny Petrilin 	int i;
2668fe6f700dSYevgeny Petrilin 	u8 rem_mcg;
2669fe6f700dSYevgeny Petrilin 	u8 prot;
2670fe6f700dSYevgeny Petrilin 
2671fe6f700dSYevgeny Petrilin #define GET_OP_REQ_MODIFIER_OFFSET	0x08
2672fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TOKEN_OFFSET		0x14
2673fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TYPE_OFFSET		0x1a
2674fe6f700dSYevgeny Petrilin #define GET_OP_REQ_DATA_OFFSET		0x20
2675fe6f700dSYevgeny Petrilin 
2676fe6f700dSYevgeny Petrilin 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2677fe6f700dSYevgeny Petrilin 	if (IS_ERR(mailbox)) {
2678fe6f700dSYevgeny Petrilin 		mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n");
2679fe6f700dSYevgeny Petrilin 		return;
2680fe6f700dSYevgeny Petrilin 	}
2681fe6f700dSYevgeny Petrilin 	outbox = mailbox->buf;
2682fe6f700dSYevgeny Petrilin 
2683fe6f700dSYevgeny Petrilin 	while (num_tasks) {
2684fe6f700dSYevgeny Petrilin 		err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
2685fe6f700dSYevgeny Petrilin 				   MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
2686fe6f700dSYevgeny Petrilin 				   MLX4_CMD_NATIVE);
2687fe6f700dSYevgeny Petrilin 		if (err) {
26886d3be300SMasanari Iida 			mlx4_err(dev, "Failed to retrieve required operation: %d\n",
2689fe6f700dSYevgeny Petrilin 				 err);
2690fe6f700dSYevgeny Petrilin 			return;
2691fe6f700dSYevgeny Petrilin 		}
2692fe6f700dSYevgeny Petrilin 		MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
2693fe6f700dSYevgeny Petrilin 		MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);
2694fe6f700dSYevgeny Petrilin 		MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET);
2695fe6f700dSYevgeny Petrilin 		type &= 0xfff;
2696fe6f700dSYevgeny Petrilin 
2697fe6f700dSYevgeny Petrilin 		switch (type) {
2698fe6f700dSYevgeny Petrilin 		case ADD_TO_MCG:
2699fe6f700dSYevgeny Petrilin 			if (dev->caps.steering_mode ==
2700fe6f700dSYevgeny Petrilin 			    MLX4_STEERING_MODE_DEVICE_MANAGED) {
2701fe6f700dSYevgeny Petrilin 				mlx4_warn(dev, "ADD MCG operation is not supported in DEVICE_MANAGED steering mode\n");
2702fe6f700dSYevgeny Petrilin 				err = EPERM;
2703fe6f700dSYevgeny Petrilin 				break;
2704fe6f700dSYevgeny Petrilin 			}
2705fe6f700dSYevgeny Petrilin 			mgm = (struct mlx4_mgm *)((u8 *)(outbox) +
2706fe6f700dSYevgeny Petrilin 						  GET_OP_REQ_DATA_OFFSET);
2707fe6f700dSYevgeny Petrilin 			num_qps = be32_to_cpu(mgm->members_count) &
2708fe6f700dSYevgeny Petrilin 				  MGM_QPN_MASK;
2709fe6f700dSYevgeny Petrilin 			rem_mcg = ((u8 *)(&mgm->members_count))[0] & 1;
2710fe6f700dSYevgeny Petrilin 			prot = ((u8 *)(&mgm->members_count))[0] >> 6;
2711fe6f700dSYevgeny Petrilin 
2712fe6f700dSYevgeny Petrilin 			for (i = 0; i < num_qps; i++) {
2713fe6f700dSYevgeny Petrilin 				qp.qpn = be32_to_cpu(mgm->qp[i]);
2714fe6f700dSYevgeny Petrilin 				if (rem_mcg)
2715fe6f700dSYevgeny Petrilin 					err = mlx4_multicast_detach(dev, &qp,
2716fe6f700dSYevgeny Petrilin 								    mgm->gid,
2717fe6f700dSYevgeny Petrilin 								    prot, 0);
2718fe6f700dSYevgeny Petrilin 				else
2719fe6f700dSYevgeny Petrilin 					err = mlx4_multicast_attach(dev, &qp,
2720fe6f700dSYevgeny Petrilin 								    mgm->gid,
2721fe6f700dSYevgeny Petrilin 								    mgm->gid[5]
2722fe6f700dSYevgeny Petrilin 								    , 0, prot,
2723fe6f700dSYevgeny Petrilin 								    NULL);
2724fe6f700dSYevgeny Petrilin 				if (err)
2725fe6f700dSYevgeny Petrilin 					break;
2726fe6f700dSYevgeny Petrilin 			}
2727fe6f700dSYevgeny Petrilin 			break;
2728fe6f700dSYevgeny Petrilin 		default:
2729fe6f700dSYevgeny Petrilin 			mlx4_warn(dev, "Bad type for required operation\n");
2730fe6f700dSYevgeny Petrilin 			err = EINVAL;
2731fe6f700dSYevgeny Petrilin 			break;
2732fe6f700dSYevgeny Petrilin 		}
273328d222bbSEyal Perry 		err = mlx4_cmd(dev, 0, ((u32) err |
273428d222bbSEyal Perry 					(__force u32)cpu_to_be32(token) << 16),
2735fe6f700dSYevgeny Petrilin 			       1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
2736fe6f700dSYevgeny Petrilin 			       MLX4_CMD_NATIVE);
2737fe6f700dSYevgeny Petrilin 		if (err) {
2738fe6f700dSYevgeny Petrilin 			mlx4_err(dev, "Failed to acknowledge required request: %d\n",
2739fe6f700dSYevgeny Petrilin 				 err);
2740fe6f700dSYevgeny Petrilin 			goto out;
2741fe6f700dSYevgeny Petrilin 		}
2742fe6f700dSYevgeny Petrilin 		memset(outbox, 0, 0xffc);
2743fe6f700dSYevgeny Petrilin 		num_tasks = atomic_dec_return(&priv->opreq_count);
2744fe6f700dSYevgeny Petrilin 	}
2745fe6f700dSYevgeny Petrilin 
2746fe6f700dSYevgeny Petrilin out:
2747fe6f700dSYevgeny Petrilin 	mlx4_free_cmd_mailbox(dev, mailbox);
2748fe6f700dSYevgeny Petrilin }
2749114840c3SJack Morgenstein 
2750114840c3SJack Morgenstein static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev,
2751114840c3SJack Morgenstein 					  struct mlx4_cmd_mailbox *mailbox)
2752114840c3SJack Morgenstein {
2753114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET		0x10
2754114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET		0x20
2755114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET		0x40
2756114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET	0x70
2757114840c3SJack Morgenstein 
2758114840c3SJack Morgenstein 	u32 set_attr_mask, getresp_attr_mask;
2759114840c3SJack Morgenstein 	u32 trap_attr_mask, traprepress_attr_mask;
2760114840c3SJack Morgenstein 
2761114840c3SJack Morgenstein 	MLX4_GET(set_attr_mask, mailbox->buf,
2762114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET);
2763114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n",
2764114840c3SJack Morgenstein 		 set_attr_mask);
2765114840c3SJack Morgenstein 
2766114840c3SJack Morgenstein 	MLX4_GET(getresp_attr_mask, mailbox->buf,
2767114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET);
2768114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n",
2769114840c3SJack Morgenstein 		 getresp_attr_mask);
2770114840c3SJack Morgenstein 
2771114840c3SJack Morgenstein 	MLX4_GET(trap_attr_mask, mailbox->buf,
2772114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET);
2773114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n",
2774114840c3SJack Morgenstein 		 trap_attr_mask);
2775114840c3SJack Morgenstein 
2776114840c3SJack Morgenstein 	MLX4_GET(traprepress_attr_mask, mailbox->buf,
2777114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET);
2778114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n",
2779114840c3SJack Morgenstein 		 traprepress_attr_mask);
2780114840c3SJack Morgenstein 
2781114840c3SJack Morgenstein 	if (set_attr_mask && getresp_attr_mask && trap_attr_mask &&
2782114840c3SJack Morgenstein 	    traprepress_attr_mask)
2783114840c3SJack Morgenstein 		return 1;
2784114840c3SJack Morgenstein 
2785114840c3SJack Morgenstein 	return 0;
2786114840c3SJack Morgenstein }
2787114840c3SJack Morgenstein 
2788114840c3SJack Morgenstein int mlx4_config_mad_demux(struct mlx4_dev *dev)
2789114840c3SJack Morgenstein {
2790114840c3SJack Morgenstein 	struct mlx4_cmd_mailbox *mailbox;
2791114840c3SJack Morgenstein 	int err;
2792114840c3SJack Morgenstein 
2793114840c3SJack Morgenstein 	/* Check if mad_demux is supported */
2794114840c3SJack Morgenstein 	if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX))
2795114840c3SJack Morgenstein 		return 0;
2796114840c3SJack Morgenstein 
2797114840c3SJack Morgenstein 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2798114840c3SJack Morgenstein 	if (IS_ERR(mailbox)) {
2799114840c3SJack Morgenstein 		mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX");
2800114840c3SJack Morgenstein 		return -ENOMEM;
2801114840c3SJack Morgenstein 	}
2802114840c3SJack Morgenstein 
2803114840c3SJack Morgenstein 	/* Query mad_demux to find out which MADs are handled by internal sma */
2804114840c3SJack Morgenstein 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */,
2805114840c3SJack Morgenstein 			   MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX,
2806114840c3SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
2807114840c3SJack Morgenstein 	if (err) {
2808114840c3SJack Morgenstein 		mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n",
2809114840c3SJack Morgenstein 			  err);
2810114840c3SJack Morgenstein 		goto out;
2811114840c3SJack Morgenstein 	}
2812114840c3SJack Morgenstein 
2813fd10ed8eSJack Morgenstein 	if (mlx4_check_smp_firewall_active(dev, mailbox))
2814fd10ed8eSJack Morgenstein 		dev->flags |= MLX4_FLAG_SECURE_HOST;
2815114840c3SJack Morgenstein 
2816114840c3SJack Morgenstein 	/* Config mad_demux to handle all MADs returned by the query above */
2817114840c3SJack Morgenstein 	err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */,
2818114840c3SJack Morgenstein 		       MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX,
2819114840c3SJack Morgenstein 		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
2820114840c3SJack Morgenstein 	if (err) {
2821114840c3SJack Morgenstein 		mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err);
2822114840c3SJack Morgenstein 		goto out;
2823114840c3SJack Morgenstein 	}
2824114840c3SJack Morgenstein 
2825fd10ed8eSJack Morgenstein 	if (dev->flags & MLX4_FLAG_SECURE_HOST)
2826114840c3SJack Morgenstein 		mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n");
2827114840c3SJack Morgenstein out:
2828114840c3SJack Morgenstein 	mlx4_free_cmd_mailbox(dev, mailbox);
2829114840c3SJack Morgenstein 	return err;
2830114840c3SJack Morgenstein }
2831adbc7ac5SSaeed Mahameed 
2832adbc7ac5SSaeed Mahameed /* Access Reg commands */
2833adbc7ac5SSaeed Mahameed enum mlx4_access_reg_masks {
2834adbc7ac5SSaeed Mahameed 	MLX4_ACCESS_REG_STATUS_MASK = 0x7f,
2835adbc7ac5SSaeed Mahameed 	MLX4_ACCESS_REG_METHOD_MASK = 0x7f,
2836adbc7ac5SSaeed Mahameed 	MLX4_ACCESS_REG_LEN_MASK = 0x7ff
2837adbc7ac5SSaeed Mahameed };
2838adbc7ac5SSaeed Mahameed 
2839adbc7ac5SSaeed Mahameed struct mlx4_access_reg {
2840adbc7ac5SSaeed Mahameed 	__be16 constant1;
2841adbc7ac5SSaeed Mahameed 	u8 status;
2842adbc7ac5SSaeed Mahameed 	u8 resrvd1;
2843adbc7ac5SSaeed Mahameed 	__be16 reg_id;
2844adbc7ac5SSaeed Mahameed 	u8 method;
2845adbc7ac5SSaeed Mahameed 	u8 constant2;
2846adbc7ac5SSaeed Mahameed 	__be32 resrvd2[2];
2847adbc7ac5SSaeed Mahameed 	__be16 len_const;
2848adbc7ac5SSaeed Mahameed 	__be16 resrvd3;
2849adbc7ac5SSaeed Mahameed #define MLX4_ACCESS_REG_HEADER_SIZE (20)
2850adbc7ac5SSaeed Mahameed 	u8 reg_data[MLX4_MAILBOX_SIZE-MLX4_ACCESS_REG_HEADER_SIZE];
2851adbc7ac5SSaeed Mahameed } __attribute__((__packed__));
2852adbc7ac5SSaeed Mahameed 
2853adbc7ac5SSaeed Mahameed /**
2854adbc7ac5SSaeed Mahameed  * mlx4_ACCESS_REG - Generic access reg command.
2855adbc7ac5SSaeed Mahameed  * @dev: mlx4_dev.
2856adbc7ac5SSaeed Mahameed  * @reg_id: register ID to access.
2857adbc7ac5SSaeed Mahameed  * @method: Access method Read/Write.
2858adbc7ac5SSaeed Mahameed  * @reg_len: register length to Read/Write in bytes.
2859adbc7ac5SSaeed Mahameed  * @reg_data: reg_data pointer to Read/Write From/To.
2860adbc7ac5SSaeed Mahameed  *
2861adbc7ac5SSaeed Mahameed  * Access ConnectX registers FW command.
2862adbc7ac5SSaeed Mahameed  * Returns 0 on success and copies outbox mlx4_access_reg data
2863adbc7ac5SSaeed Mahameed  * field into reg_data or a negative error code.
2864adbc7ac5SSaeed Mahameed  */
2865adbc7ac5SSaeed Mahameed static int mlx4_ACCESS_REG(struct mlx4_dev *dev, u16 reg_id,
2866adbc7ac5SSaeed Mahameed 			   enum mlx4_access_reg_method method,
2867adbc7ac5SSaeed Mahameed 			   u16 reg_len, void *reg_data)
2868adbc7ac5SSaeed Mahameed {
2869adbc7ac5SSaeed Mahameed 	struct mlx4_cmd_mailbox *inbox, *outbox;
2870adbc7ac5SSaeed Mahameed 	struct mlx4_access_reg *inbuf, *outbuf;
2871adbc7ac5SSaeed Mahameed 	int err;
2872adbc7ac5SSaeed Mahameed 
2873adbc7ac5SSaeed Mahameed 	inbox = mlx4_alloc_cmd_mailbox(dev);
2874adbc7ac5SSaeed Mahameed 	if (IS_ERR(inbox))
2875adbc7ac5SSaeed Mahameed 		return PTR_ERR(inbox);
2876adbc7ac5SSaeed Mahameed 
2877adbc7ac5SSaeed Mahameed 	outbox = mlx4_alloc_cmd_mailbox(dev);
2878adbc7ac5SSaeed Mahameed 	if (IS_ERR(outbox)) {
2879adbc7ac5SSaeed Mahameed 		mlx4_free_cmd_mailbox(dev, inbox);
2880adbc7ac5SSaeed Mahameed 		return PTR_ERR(outbox);
2881adbc7ac5SSaeed Mahameed 	}
2882adbc7ac5SSaeed Mahameed 
2883adbc7ac5SSaeed Mahameed 	inbuf = inbox->buf;
2884adbc7ac5SSaeed Mahameed 	outbuf = outbox->buf;
2885adbc7ac5SSaeed Mahameed 
2886adbc7ac5SSaeed Mahameed 	inbuf->constant1 = cpu_to_be16(0x1<<11 | 0x4);
2887adbc7ac5SSaeed Mahameed 	inbuf->constant2 = 0x1;
2888adbc7ac5SSaeed Mahameed 	inbuf->reg_id = cpu_to_be16(reg_id);
2889adbc7ac5SSaeed Mahameed 	inbuf->method = method & MLX4_ACCESS_REG_METHOD_MASK;
2890adbc7ac5SSaeed Mahameed 
2891adbc7ac5SSaeed Mahameed 	reg_len = min(reg_len, (u16)(sizeof(inbuf->reg_data)));
2892adbc7ac5SSaeed Mahameed 	inbuf->len_const =
2893adbc7ac5SSaeed Mahameed 		cpu_to_be16(((reg_len/4 + 1) & MLX4_ACCESS_REG_LEN_MASK) |
2894adbc7ac5SSaeed Mahameed 			    ((0x3) << 12));
2895adbc7ac5SSaeed Mahameed 
2896adbc7ac5SSaeed Mahameed 	memcpy(inbuf->reg_data, reg_data, reg_len);
2897adbc7ac5SSaeed Mahameed 	err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 0, 0,
2898adbc7ac5SSaeed Mahameed 			   MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C,
28996e806699SSaeed Mahameed 			   MLX4_CMD_WRAPPED);
2900adbc7ac5SSaeed Mahameed 	if (err)
2901adbc7ac5SSaeed Mahameed 		goto out;
2902adbc7ac5SSaeed Mahameed 
2903adbc7ac5SSaeed Mahameed 	if (outbuf->status & MLX4_ACCESS_REG_STATUS_MASK) {
2904adbc7ac5SSaeed Mahameed 		err = outbuf->status & MLX4_ACCESS_REG_STATUS_MASK;
2905adbc7ac5SSaeed Mahameed 		mlx4_err(dev,
2906adbc7ac5SSaeed Mahameed 			 "MLX4_CMD_ACCESS_REG(%x) returned REG status (%x)\n",
2907adbc7ac5SSaeed Mahameed 			 reg_id, err);
2908adbc7ac5SSaeed Mahameed 		goto out;
2909adbc7ac5SSaeed Mahameed 	}
2910adbc7ac5SSaeed Mahameed 
2911adbc7ac5SSaeed Mahameed 	memcpy(reg_data, outbuf->reg_data, reg_len);
2912adbc7ac5SSaeed Mahameed out:
2913adbc7ac5SSaeed Mahameed 	mlx4_free_cmd_mailbox(dev, inbox);
2914adbc7ac5SSaeed Mahameed 	mlx4_free_cmd_mailbox(dev, outbox);
2915adbc7ac5SSaeed Mahameed 	return err;
2916adbc7ac5SSaeed Mahameed }
2917adbc7ac5SSaeed Mahameed 
2918adbc7ac5SSaeed Mahameed /* ConnectX registers IDs */
2919adbc7ac5SSaeed Mahameed enum mlx4_reg_id {
2920adbc7ac5SSaeed Mahameed 	MLX4_REG_ID_PTYS = 0x5004,
2921adbc7ac5SSaeed Mahameed };
2922adbc7ac5SSaeed Mahameed 
2923adbc7ac5SSaeed Mahameed /**
2924adbc7ac5SSaeed Mahameed  * mlx4_ACCESS_PTYS_REG - Access PTYs (Port Type and Speed)
2925adbc7ac5SSaeed Mahameed  * register
2926adbc7ac5SSaeed Mahameed  * @dev: mlx4_dev.
2927adbc7ac5SSaeed Mahameed  * @method: Access method Read/Write.
2928adbc7ac5SSaeed Mahameed  * @ptys_reg: PTYS register data pointer.
2929adbc7ac5SSaeed Mahameed  *
2930adbc7ac5SSaeed Mahameed  * Access ConnectX PTYS register, to Read/Write Port Type/Speed
2931adbc7ac5SSaeed Mahameed  * configuration
2932adbc7ac5SSaeed Mahameed  * Returns 0 on success or a negative error code.
2933adbc7ac5SSaeed Mahameed  */
2934adbc7ac5SSaeed Mahameed int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev,
2935adbc7ac5SSaeed Mahameed 			 enum mlx4_access_reg_method method,
2936adbc7ac5SSaeed Mahameed 			 struct mlx4_ptys_reg *ptys_reg)
2937adbc7ac5SSaeed Mahameed {
2938adbc7ac5SSaeed Mahameed 	return mlx4_ACCESS_REG(dev, MLX4_REG_ID_PTYS,
2939adbc7ac5SSaeed Mahameed 			       method, sizeof(*ptys_reg), ptys_reg);
2940adbc7ac5SSaeed Mahameed }
2941adbc7ac5SSaeed Mahameed EXPORT_SYMBOL_GPL(mlx4_ACCESS_PTYS_REG);
29426e806699SSaeed Mahameed 
29436e806699SSaeed Mahameed int mlx4_ACCESS_REG_wrapper(struct mlx4_dev *dev, int slave,
29446e806699SSaeed Mahameed 			    struct mlx4_vhcr *vhcr,
29456e806699SSaeed Mahameed 			    struct mlx4_cmd_mailbox *inbox,
29466e806699SSaeed Mahameed 			    struct mlx4_cmd_mailbox *outbox,
29476e806699SSaeed Mahameed 			    struct mlx4_cmd_info *cmd)
29486e806699SSaeed Mahameed {
29496e806699SSaeed Mahameed 	struct mlx4_access_reg *inbuf = inbox->buf;
29506e806699SSaeed Mahameed 	u8 method = inbuf->method & MLX4_ACCESS_REG_METHOD_MASK;
29516e806699SSaeed Mahameed 	u16 reg_id = be16_to_cpu(inbuf->reg_id);
29526e806699SSaeed Mahameed 
29536e806699SSaeed Mahameed 	if (slave != mlx4_master_func_num(dev) &&
29546e806699SSaeed Mahameed 	    method == MLX4_ACCESS_REG_WRITE)
29556e806699SSaeed Mahameed 		return -EPERM;
29566e806699SSaeed Mahameed 
29576e806699SSaeed Mahameed 	if (reg_id == MLX4_REG_ID_PTYS) {
29586e806699SSaeed Mahameed 		struct mlx4_ptys_reg *ptys_reg =
29596e806699SSaeed Mahameed 			(struct mlx4_ptys_reg *)inbuf->reg_data;
29606e806699SSaeed Mahameed 
29616e806699SSaeed Mahameed 		ptys_reg->local_port =
29626e806699SSaeed Mahameed 			mlx4_slave_convert_port(dev, slave,
29636e806699SSaeed Mahameed 						ptys_reg->local_port);
29646e806699SSaeed Mahameed 	}
29656e806699SSaeed Mahameed 
29666e806699SSaeed Mahameed 	return mlx4_cmd_box(dev, inbox->dma, outbox->dma, vhcr->in_modifier,
29676e806699SSaeed Mahameed 			    0, MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C,
29686e806699SSaeed Mahameed 			    MLX4_CMD_NATIVE);
29696e806699SSaeed Mahameed }
297077fc29c4SHadar Hen Zion 
297177fc29c4SHadar Hen Zion static int mlx4_SET_PORT_phv_bit(struct mlx4_dev *dev, u8 port, u8 phv_bit)
297277fc29c4SHadar Hen Zion {
297377fc29c4SHadar Hen Zion #define SET_PORT_GEN_PHV_VALID	0x10
297477fc29c4SHadar Hen Zion #define SET_PORT_GEN_PHV_EN	0x80
297577fc29c4SHadar Hen Zion 
297677fc29c4SHadar Hen Zion 	struct mlx4_cmd_mailbox *mailbox;
297777fc29c4SHadar Hen Zion 	struct mlx4_set_port_general_context *context;
297877fc29c4SHadar Hen Zion 	u32 in_mod;
297977fc29c4SHadar Hen Zion 	int err;
298077fc29c4SHadar Hen Zion 
298177fc29c4SHadar Hen Zion 	mailbox = mlx4_alloc_cmd_mailbox(dev);
298277fc29c4SHadar Hen Zion 	if (IS_ERR(mailbox))
298377fc29c4SHadar Hen Zion 		return PTR_ERR(mailbox);
298477fc29c4SHadar Hen Zion 	context = mailbox->buf;
298577fc29c4SHadar Hen Zion 
2986*40fb4fc1SShaker Daibes 	context->flags2 |=  SET_PORT_GEN_PHV_VALID;
298777fc29c4SHadar Hen Zion 	if (phv_bit)
298877fc29c4SHadar Hen Zion 		context->phv_en |=  SET_PORT_GEN_PHV_EN;
298977fc29c4SHadar Hen Zion 
299077fc29c4SHadar Hen Zion 	in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
299177fc29c4SHadar Hen Zion 	err = mlx4_cmd(dev, mailbox->dma, in_mod, MLX4_SET_PORT_ETH_OPCODE,
299277fc29c4SHadar Hen Zion 		       MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
299377fc29c4SHadar Hen Zion 		       MLX4_CMD_NATIVE);
299477fc29c4SHadar Hen Zion 
299577fc29c4SHadar Hen Zion 	mlx4_free_cmd_mailbox(dev, mailbox);
299677fc29c4SHadar Hen Zion 	return err;
299777fc29c4SHadar Hen Zion }
299877fc29c4SHadar Hen Zion 
299977fc29c4SHadar Hen Zion int get_phv_bit(struct mlx4_dev *dev, u8 port, int *phv)
300077fc29c4SHadar Hen Zion {
300177fc29c4SHadar Hen Zion 	int err;
300277fc29c4SHadar Hen Zion 	struct mlx4_func_cap func_cap;
300377fc29c4SHadar Hen Zion 
300477fc29c4SHadar Hen Zion 	memset(&func_cap, 0, sizeof(func_cap));
300535e455f4SAmir Vadai 	err = mlx4_QUERY_FUNC_CAP(dev, port, &func_cap);
300677fc29c4SHadar Hen Zion 	if (!err)
3007c9cc599aSMoshe Shemesh 		*phv = func_cap.flags0 & QUERY_FUNC_CAP_PHV_BIT;
300877fc29c4SHadar Hen Zion 	return err;
300977fc29c4SHadar Hen Zion }
301077fc29c4SHadar Hen Zion EXPORT_SYMBOL(get_phv_bit);
301177fc29c4SHadar Hen Zion 
301277fc29c4SHadar Hen Zion int set_phv_bit(struct mlx4_dev *dev, u8 port, int new_val)
301377fc29c4SHadar Hen Zion {
301477fc29c4SHadar Hen Zion 	int ret;
301577fc29c4SHadar Hen Zion 
301677fc29c4SHadar Hen Zion 	if (mlx4_is_slave(dev))
301777fc29c4SHadar Hen Zion 		return -EPERM;
301877fc29c4SHadar Hen Zion 
301977fc29c4SHadar Hen Zion 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
302077fc29c4SHadar Hen Zion 	    !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
302177fc29c4SHadar Hen Zion 		ret = mlx4_SET_PORT_phv_bit(dev, port, new_val);
302277fc29c4SHadar Hen Zion 		if (!ret)
302377fc29c4SHadar Hen Zion 			dev->caps.phv_bit[port] = new_val;
302477fc29c4SHadar Hen Zion 		return ret;
302577fc29c4SHadar Hen Zion 	}
302677fc29c4SHadar Hen Zion 
302777fc29c4SHadar Hen Zion 	return -EOPNOTSUPP;
302877fc29c4SHadar Hen Zion }
302977fc29c4SHadar Hen Zion EXPORT_SYMBOL(set_phv_bit);
30302b3ddf27SJack Morgenstein 
30317c3d21c8SMoshe Shemesh int mlx4_get_is_vlan_offload_disabled(struct mlx4_dev *dev, u8 port,
30327c3d21c8SMoshe Shemesh 				      bool *vlan_offload_disabled)
30337c3d21c8SMoshe Shemesh {
30347c3d21c8SMoshe Shemesh 	struct mlx4_func_cap func_cap;
30357c3d21c8SMoshe Shemesh 	int err;
30367c3d21c8SMoshe Shemesh 
30377c3d21c8SMoshe Shemesh 	memset(&func_cap, 0, sizeof(func_cap));
30387c3d21c8SMoshe Shemesh 	err = mlx4_QUERY_FUNC_CAP(dev, port, &func_cap);
30397c3d21c8SMoshe Shemesh 	if (!err)
30407c3d21c8SMoshe Shemesh 		*vlan_offload_disabled =
30417c3d21c8SMoshe Shemesh 			!!(func_cap.flags0 &
30427c3d21c8SMoshe Shemesh 			   QUERY_FUNC_CAP_VLAN_OFFLOAD_DISABLE);
30437c3d21c8SMoshe Shemesh 	return err;
30447c3d21c8SMoshe Shemesh }
30457c3d21c8SMoshe Shemesh EXPORT_SYMBOL(mlx4_get_is_vlan_offload_disabled);
30467c3d21c8SMoshe Shemesh 
30472b3ddf27SJack Morgenstein void mlx4_replace_zero_macs(struct mlx4_dev *dev)
30482b3ddf27SJack Morgenstein {
30492b3ddf27SJack Morgenstein 	int i;
30502b3ddf27SJack Morgenstein 	u8 mac_addr[ETH_ALEN];
30512b3ddf27SJack Morgenstein 
30522b3ddf27SJack Morgenstein 	dev->port_random_macs = 0;
30532b3ddf27SJack Morgenstein 	for (i = 1; i <= dev->caps.num_ports; ++i)
30542b3ddf27SJack Morgenstein 		if (!dev->caps.def_mac[i] &&
30552b3ddf27SJack Morgenstein 		    dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH) {
30562b3ddf27SJack Morgenstein 			eth_random_addr(mac_addr);
30572b3ddf27SJack Morgenstein 			dev->port_random_macs |= 1 << i;
30582b3ddf27SJack Morgenstein 			dev->caps.def_mac[i] = mlx4_mac_to_u64(mac_addr);
30592b3ddf27SJack Morgenstein 		}
30602b3ddf27SJack Morgenstein }
30612b3ddf27SJack Morgenstein EXPORT_SYMBOL_GPL(mlx4_replace_zero_macs);
3062