xref: /linux/drivers/net/ethernet/mellanox/mlx4/fw.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
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>
39691223ecSThomas Meyer #include <linux/kernel.h>
4048962f5cSJason Gunthorpe #include <uapi/rdma/mlx4-abi.h>
415a2cc190SJeff Kirsher 
425a2cc190SJeff Kirsher #include "fw.h"
435a2cc190SJeff Kirsher #include "icm.h"
445a2cc190SJeff Kirsher 
455a2cc190SJeff Kirsher enum {
465a2cc190SJeff Kirsher 	MLX4_COMMAND_INTERFACE_MIN_REV		= 2,
475a2cc190SJeff Kirsher 	MLX4_COMMAND_INTERFACE_MAX_REV		= 3,
485a2cc190SJeff Kirsher 	MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS	= 3,
495a2cc190SJeff Kirsher };
505a2cc190SJeff Kirsher 
515a2cc190SJeff Kirsher extern void __buggy_use_of_MLX4_GET(void);
525a2cc190SJeff Kirsher extern void __buggy_use_of_MLX4_PUT(void);
535a2cc190SJeff Kirsher 
5472da2e91SMoshe Lazer static bool enable_qos;
555a2cc190SJeff Kirsher module_param(enable_qos, bool, 0444);
5672da2e91SMoshe Lazer MODULE_PARM_DESC(enable_qos, "Enable Enhanced QoS support (default: off)");
575a2cc190SJeff Kirsher 
585a2cc190SJeff Kirsher #define MLX4_GET(dest, source, offset)				      \
595a2cc190SJeff Kirsher 	do {							      \
605a2cc190SJeff Kirsher 		void *__p = (char *) (source) + (offset);	      \
61b71322d9STariq Toukan 		__be64 val;                                           \
625a2cc190SJeff Kirsher 		switch (sizeof(dest)) {				      \
635a2cc190SJeff Kirsher 		case 1: (dest) = *(u8 *) __p;	    break;	      \
645a2cc190SJeff Kirsher 		case 2: (dest) = be16_to_cpup(__p); break;	      \
655a2cc190SJeff Kirsher 		case 4: (dest) = be32_to_cpup(__p); break;	      \
66b71322d9STariq Toukan 		case 8: val = get_unaligned((__be64 *)__p);           \
6717d5ceb6SDavid Ahern 			(dest) = be64_to_cpu(val);  break;            \
685a2cc190SJeff Kirsher 		default: __buggy_use_of_MLX4_GET();		      \
695a2cc190SJeff Kirsher 		}						      \
705a2cc190SJeff Kirsher 	} while (0)
715a2cc190SJeff Kirsher 
725a2cc190SJeff Kirsher #define MLX4_PUT(dest, source, offset)				      \
735a2cc190SJeff Kirsher 	do {							      \
745a2cc190SJeff Kirsher 		void *__d = ((char *) (dest) + (offset));	      \
755a2cc190SJeff Kirsher 		switch (sizeof(source)) {			      \
765a2cc190SJeff Kirsher 		case 1: *(u8 *) __d = (source);		       break; \
775a2cc190SJeff Kirsher 		case 2:	*(__be16 *) __d = cpu_to_be16(source); break; \
785a2cc190SJeff Kirsher 		case 4:	*(__be32 *) __d = cpu_to_be32(source); break; \
795a2cc190SJeff Kirsher 		case 8:	*(__be64 *) __d = cpu_to_be64(source); break; \
805a2cc190SJeff Kirsher 		default: __buggy_use_of_MLX4_PUT();		      \
815a2cc190SJeff Kirsher 		}						      \
825a2cc190SJeff Kirsher 	} while (0)
835a2cc190SJeff Kirsher 
dump_dev_cap_flags(struct mlx4_dev * dev,u64 flags)845a2cc190SJeff Kirsher static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
855a2cc190SJeff Kirsher {
865a2cc190SJeff Kirsher 	static const char *fname[] = {
875a2cc190SJeff Kirsher 		[ 0] = "RC transport",
885a2cc190SJeff Kirsher 		[ 1] = "UC transport",
895a2cc190SJeff Kirsher 		[ 2] = "UD transport",
905a2cc190SJeff Kirsher 		[ 3] = "XRC transport",
915a2cc190SJeff Kirsher 		[ 6] = "SRQ support",
925a2cc190SJeff Kirsher 		[ 7] = "IPoIB checksum offload",
935a2cc190SJeff Kirsher 		[ 8] = "P_Key violation counter",
945a2cc190SJeff Kirsher 		[ 9] = "Q_Key violation counter",
954d531aa8SOr Gerlitz 		[12] = "Dual Port Different Protocol (DPDP) support",
965a2cc190SJeff Kirsher 		[15] = "Big LSO headers",
975a2cc190SJeff Kirsher 		[16] = "MW support",
985a2cc190SJeff Kirsher 		[17] = "APM support",
995a2cc190SJeff Kirsher 		[18] = "Atomic ops support",
1005a2cc190SJeff Kirsher 		[19] = "Raw multicast support",
1015a2cc190SJeff Kirsher 		[20] = "Address vector port checking support",
1025a2cc190SJeff Kirsher 		[21] = "UD multicast support",
1035a2cc190SJeff Kirsher 		[30] = "IBoE support",
1045a2cc190SJeff Kirsher 		[32] = "Unicast loopback support",
105f3a9d1f2SYevgeny Petrilin 		[34] = "FCS header control",
106cb2147a9SOr Gerlitz 		[37] = "Wake On LAN (port1) support",
107cb2147a9SOr Gerlitz 		[38] = "Wake On LAN (port2) support",
1085a2cc190SJeff Kirsher 		[40] = "UDP RSS support",
1095a2cc190SJeff Kirsher 		[41] = "Unicast VEP steering support",
1105a2cc190SJeff Kirsher 		[42] = "Multicast VEP steering support",
1115a2cc190SJeff Kirsher 		[48] = "Counters support",
112802f42a8SIdo Shamay 		[52] = "RSS IP fragments support",
113540b3a39SOr Gerlitz 		[53] = "Port ETS Scheduler support",
1144d531aa8SOr Gerlitz 		[55] = "Port link type sensing support",
11500f5ce99SJack Morgenstein 		[59] = "Port management change event support",
11608ff3235SOr Gerlitz 		[61] = "64 byte EQE support",
11708ff3235SOr Gerlitz 		[62] = "64 byte CQE support",
1185a2cc190SJeff Kirsher 	};
1195a2cc190SJeff Kirsher 	int i;
1205a2cc190SJeff Kirsher 
1215a2cc190SJeff Kirsher 	mlx4_dbg(dev, "DEV_CAP flags:\n");
1225a2cc190SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(fname); ++i)
1235a2cc190SJeff Kirsher 		if (fname[i] && (flags & (1LL << i)))
1245a2cc190SJeff Kirsher 			mlx4_dbg(dev, "    %s\n", fname[i]);
1255a2cc190SJeff Kirsher }
1265a2cc190SJeff Kirsher 
dump_dev_cap_flags2(struct mlx4_dev * dev,u64 flags)127b3416f44SShlomo Pongratz static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
128b3416f44SShlomo Pongratz {
129b3416f44SShlomo Pongratz 	static const char * const fname[] = {
130b3416f44SShlomo Pongratz 		[0] = "RSS support",
131b3416f44SShlomo Pongratz 		[1] = "RSS Toeplitz Hash Function support",
1320ff1fb65SHadar Hen Zion 		[2] = "RSS XOR Hash Function support",
13356cb4567SOr Gerlitz 		[3] = "Device managed flow steering support",
134d998735fSEugenia Emantayev 		[4] = "Automatic MAC reassignment support",
1354e8cf5b8SOr Gerlitz 		[5] = "Time stamping support",
1364e8cf5b8SOr Gerlitz 		[6] = "VST (control vlan insertion/stripping) support",
137b01978caSJack Morgenstein 		[7] = "FSM (MAC anti-spoofing) support",
1387ffdf726SOr Gerlitz 		[8] = "Dynamic QP updates support",
13956cb4567SOr Gerlitz 		[9] = "Device managed flow steering IPoIB support",
140114840c3SJack Morgenstein 		[10] = "TCP/IP offloads/flow-steering for VXLAN support",
14177507aa2SIdo Shamay 		[11] = "MAD DEMUX (Secure-Host) support",
14277507aa2SIdo Shamay 		[12] = "Large cache line (>64B) CQE stride support",
143adbc7ac5SSaeed Mahameed 		[13] = "Large cache line (>64B) EQE stride support",
144a53e3e8cSSaeed Mahameed 		[14] = "Ethernet protocol control support",
145d475c95bSMatan Barak 		[15] = "Ethernet Backplane autoneg support",
1467ae0e400SMatan Barak 		[16] = "CONFIG DEV support",
147de966c59SMatan Barak 		[17] = "Asymmetric EQs support",
1487d077cd3SMatan Barak 		[18] = "More than 80 VFs support",
149be6a6b43SJack Morgenstein 		[19] = "Performance optimized for limited rule configuration flow steering support",
15059e14e32SMoni Shoua 		[20] = "Recoverable error events support",
151d237baa1SShani Michaeli 		[21] = "Port Remap support",
152fc31e256SOr Gerlitz 		[22] = "QCN support",
1530b131561SMatan Barak 		[23] = "QP rate limiting support",
154d019fcb2SIdo Shamay 		[24] = "Ethernet Flow control statistics support",
155d019fcb2SIdo Shamay 		[25] = "Granular QoS per VF support",
1563742cc65SIdo Shamay 		[26] = "Port ETS Scheduler support",
15751af33cfSIdo Shamay 		[27] = "Port beacon support",
15878500b8cSMuhammad Mahajna 		[28] = "RX-ALL support",
15977fc29c4SHadar Hen Zion 		[29] = "802.1ad offload support",
1609a892835SMaor Gottlieb 		[31] = "Modifying loopback source checks using UPDATE_QP support",
1619a892835SMaor Gottlieb 		[32] = "Loopback source checks support",
1620e451e88SMarina Varshaver 		[33] = "RoCEv2 support",
1637c3d21c8SMoshe Shemesh 		[34] = "DMFS Sniffer support (UC & MC)",
164bff0c684SJack Morgenstein 		[35] = "Diag counters per port",
165f9fb9d0bSJack Morgenstein 		[36] = "QinQ VST mode support",
1665886259cSJack Morgenstein 		[37] = "sl to vl mapping table change event support",
167be599603SMoshe Shemesh 		[38] = "user MAC support",
168e5c9a705SEran Ben Elisha 		[39] = "Report driver version to FW support",
169e4567897SDaniel Jurgens 		[40] = "SW CQ initialization support",
170b3416f44SShlomo Pongratz 	};
171b3416f44SShlomo Pongratz 	int i;
172b3416f44SShlomo Pongratz 
173b3416f44SShlomo Pongratz 	for (i = 0; i < ARRAY_SIZE(fname); ++i)
174b3416f44SShlomo Pongratz 		if (fname[i] && (flags & (1LL << i)))
175b3416f44SShlomo Pongratz 			mlx4_dbg(dev, "    %s\n", fname[i]);
176b3416f44SShlomo Pongratz }
177b3416f44SShlomo Pongratz 
mlx4_MOD_STAT_CFG(struct mlx4_dev * dev,struct mlx4_mod_stat_cfg * cfg)1785a2cc190SJeff Kirsher int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
1795a2cc190SJeff Kirsher {
1805a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
1815a2cc190SJeff Kirsher 	u32 *inbox;
1825a2cc190SJeff Kirsher 	int err = 0;
1835a2cc190SJeff Kirsher 
1845a2cc190SJeff Kirsher #define MOD_STAT_CFG_IN_SIZE		0x100
1855a2cc190SJeff Kirsher 
1865a2cc190SJeff Kirsher #define MOD_STAT_CFG_PG_SZ_M_OFFSET	0x002
1875a2cc190SJeff Kirsher #define MOD_STAT_CFG_PG_SZ_OFFSET	0x003
1885a2cc190SJeff Kirsher 
1895a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
1905a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
1915a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
1925a2cc190SJeff Kirsher 	inbox = mailbox->buf;
1935a2cc190SJeff Kirsher 
1945a2cc190SJeff Kirsher 	MLX4_PUT(inbox, cfg->log_pg_sz, MOD_STAT_CFG_PG_SZ_OFFSET);
1955a2cc190SJeff Kirsher 	MLX4_PUT(inbox, cfg->log_pg_sz_m, MOD_STAT_CFG_PG_SZ_M_OFFSET);
1965a2cc190SJeff Kirsher 
1975a2cc190SJeff Kirsher 	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_MOD_STAT_CFG,
198f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1995a2cc190SJeff Kirsher 
2005a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
2015a2cc190SJeff Kirsher 	return err;
2025a2cc190SJeff Kirsher }
2035a2cc190SJeff Kirsher 
mlx4_QUERY_FUNC(struct mlx4_dev * dev,struct mlx4_func * func,int slave)204e8c4265bSMatan Barak int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave)
205e8c4265bSMatan Barak {
206e8c4265bSMatan Barak 	struct mlx4_cmd_mailbox *mailbox;
207e8c4265bSMatan Barak 	u32 *outbox;
208e8c4265bSMatan Barak 	u8 in_modifier;
209e8c4265bSMatan Barak 	u8 field;
210e8c4265bSMatan Barak 	u16 field16;
211e8c4265bSMatan Barak 	int err;
212e8c4265bSMatan Barak 
213e8c4265bSMatan Barak #define QUERY_FUNC_BUS_OFFSET			0x00
214e8c4265bSMatan Barak #define QUERY_FUNC_DEVICE_OFFSET		0x01
215e8c4265bSMatan Barak #define QUERY_FUNC_FUNCTION_OFFSET		0x01
216e8c4265bSMatan Barak #define QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET	0x03
217e8c4265bSMatan Barak #define QUERY_FUNC_RSVD_EQS_OFFSET		0x04
218e8c4265bSMatan Barak #define QUERY_FUNC_MAX_EQ_OFFSET		0x06
219e8c4265bSMatan Barak #define QUERY_FUNC_RSVD_UARS_OFFSET		0x0b
220e8c4265bSMatan Barak 
221e8c4265bSMatan Barak 	mailbox = mlx4_alloc_cmd_mailbox(dev);
222e8c4265bSMatan Barak 	if (IS_ERR(mailbox))
223e8c4265bSMatan Barak 		return PTR_ERR(mailbox);
224e8c4265bSMatan Barak 	outbox = mailbox->buf;
225e8c4265bSMatan Barak 
226e8c4265bSMatan Barak 	in_modifier = slave;
227e8c4265bSMatan Barak 
228e8c4265bSMatan Barak 	err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, 0,
229e8c4265bSMatan Barak 			   MLX4_CMD_QUERY_FUNC,
230e8c4265bSMatan Barak 			   MLX4_CMD_TIME_CLASS_A,
231e8c4265bSMatan Barak 			   MLX4_CMD_NATIVE);
232e8c4265bSMatan Barak 	if (err)
233e8c4265bSMatan Barak 		goto out;
234e8c4265bSMatan Barak 
235e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_BUS_OFFSET);
236e8c4265bSMatan Barak 	func->bus = field & 0xf;
237e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_DEVICE_OFFSET);
238e8c4265bSMatan Barak 	func->device = field & 0xf1;
239e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_FUNCTION_OFFSET);
240e8c4265bSMatan Barak 	func->function = field & 0x7;
241e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET);
242e8c4265bSMatan Barak 	func->physical_function = field & 0xf;
243e8c4265bSMatan Barak 	MLX4_GET(field16, outbox, QUERY_FUNC_RSVD_EQS_OFFSET);
244e8c4265bSMatan Barak 	func->rsvd_eqs = field16 & 0xffff;
245e8c4265bSMatan Barak 	MLX4_GET(field16, outbox, QUERY_FUNC_MAX_EQ_OFFSET);
246e8c4265bSMatan Barak 	func->max_eq = field16 & 0xffff;
247e8c4265bSMatan Barak 	MLX4_GET(field, outbox, QUERY_FUNC_RSVD_UARS_OFFSET);
248e8c4265bSMatan Barak 	func->rsvd_uars = field & 0x0f;
249e8c4265bSMatan Barak 
250e8c4265bSMatan Barak 	mlx4_dbg(dev, "Bus: %d, Device: %d, Function: %d, Physical function: %d, Max EQs: %d, Reserved EQs: %d, Reserved UARs: %d\n",
251e8c4265bSMatan Barak 		 func->bus, func->device, func->function, func->physical_function,
252e8c4265bSMatan Barak 		 func->max_eq, func->rsvd_eqs, func->rsvd_uars);
253e8c4265bSMatan Barak 
254e8c4265bSMatan Barak out:
255e8c4265bSMatan Barak 	mlx4_free_cmd_mailbox(dev, mailbox);
256e8c4265bSMatan Barak 	return err;
257e8c4265bSMatan Barak }
258e8c4265bSMatan Barak 
mlx4_activate_vst_qinq(struct mlx4_priv * priv,int slave,int port)259b42959dcSMoshe Shemesh static int mlx4_activate_vst_qinq(struct mlx4_priv *priv, int slave, int port)
260b42959dcSMoshe Shemesh {
261b42959dcSMoshe Shemesh 	struct mlx4_vport_oper_state *vp_oper;
262b42959dcSMoshe Shemesh 	struct mlx4_vport_state *vp_admin;
263b42959dcSMoshe Shemesh 	int err;
264b42959dcSMoshe Shemesh 
265b42959dcSMoshe Shemesh 	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
266b42959dcSMoshe Shemesh 	vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
267b42959dcSMoshe Shemesh 
268b42959dcSMoshe Shemesh 	if (vp_admin->default_vlan != vp_oper->state.default_vlan) {
269b42959dcSMoshe Shemesh 		err = __mlx4_register_vlan(&priv->dev, port,
270b42959dcSMoshe Shemesh 					   vp_admin->default_vlan,
271b42959dcSMoshe Shemesh 					   &vp_oper->vlan_idx);
272b42959dcSMoshe Shemesh 		if (err) {
273b42959dcSMoshe Shemesh 			vp_oper->vlan_idx = NO_INDX;
274b42959dcSMoshe Shemesh 			mlx4_warn(&priv->dev,
275b42959dcSMoshe Shemesh 				  "No vlan resources slave %d, port %d\n",
276b42959dcSMoshe Shemesh 				  slave, port);
277b42959dcSMoshe Shemesh 			return err;
278b42959dcSMoshe Shemesh 		}
279b42959dcSMoshe Shemesh 		mlx4_dbg(&priv->dev, "alloc vlan %d idx  %d slave %d port %d\n",
280b42959dcSMoshe Shemesh 			 (int)(vp_oper->state.default_vlan),
281b42959dcSMoshe Shemesh 			 vp_oper->vlan_idx, slave, port);
282b42959dcSMoshe Shemesh 	}
283b42959dcSMoshe Shemesh 	vp_oper->state.vlan_proto   = vp_admin->vlan_proto;
284b42959dcSMoshe Shemesh 	vp_oper->state.default_vlan = vp_admin->default_vlan;
285b42959dcSMoshe Shemesh 	vp_oper->state.default_qos  = vp_admin->default_qos;
286b42959dcSMoshe Shemesh 
287b42959dcSMoshe Shemesh 	return 0;
288b42959dcSMoshe Shemesh }
289b42959dcSMoshe Shemesh 
mlx4_handle_vst_qinq(struct mlx4_priv * priv,int slave,int port)290b42959dcSMoshe Shemesh static int mlx4_handle_vst_qinq(struct mlx4_priv *priv, int slave, int port)
291b42959dcSMoshe Shemesh {
292b42959dcSMoshe Shemesh 	struct mlx4_vport_oper_state *vp_oper;
293b42959dcSMoshe Shemesh 	struct mlx4_slave_state *slave_state;
294b42959dcSMoshe Shemesh 	struct mlx4_vport_state *vp_admin;
295b42959dcSMoshe Shemesh 	int err;
296b42959dcSMoshe Shemesh 
297b42959dcSMoshe Shemesh 	vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
298b42959dcSMoshe Shemesh 	vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
299b42959dcSMoshe Shemesh 	slave_state = &priv->mfunc.master.slave_state[slave];
300b42959dcSMoshe Shemesh 
301b42959dcSMoshe Shemesh 	if ((vp_admin->vlan_proto != htons(ETH_P_8021AD)) ||
302b42959dcSMoshe Shemesh 	    (!slave_state->active))
303b42959dcSMoshe Shemesh 		return 0;
304b42959dcSMoshe Shemesh 
305b42959dcSMoshe Shemesh 	if (vp_oper->state.vlan_proto == vp_admin->vlan_proto &&
306b42959dcSMoshe Shemesh 	    vp_oper->state.default_vlan == vp_admin->default_vlan &&
307b42959dcSMoshe Shemesh 	    vp_oper->state.default_qos == vp_admin->default_qos)
308b42959dcSMoshe Shemesh 		return 0;
309b42959dcSMoshe Shemesh 
310b42959dcSMoshe Shemesh 	if (!slave_state->vst_qinq_supported) {
311b42959dcSMoshe Shemesh 		/* Warn and revert the request to set vst QinQ mode */
312b42959dcSMoshe Shemesh 		vp_admin->vlan_proto   = vp_oper->state.vlan_proto;
313b42959dcSMoshe Shemesh 		vp_admin->default_vlan = vp_oper->state.default_vlan;
314b42959dcSMoshe Shemesh 		vp_admin->default_qos  = vp_oper->state.default_qos;
315b42959dcSMoshe Shemesh 
316b42959dcSMoshe Shemesh 		mlx4_warn(&priv->dev,
317b42959dcSMoshe Shemesh 			  "Slave %d does not support VST QinQ mode\n", slave);
318b42959dcSMoshe Shemesh 		return 0;
319b42959dcSMoshe Shemesh 	}
320b42959dcSMoshe Shemesh 
321b42959dcSMoshe Shemesh 	err = mlx4_activate_vst_qinq(priv, slave, port);
322b42959dcSMoshe Shemesh 	return err;
323b42959dcSMoshe Shemesh }
324b42959dcSMoshe Shemesh 
mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)3255cc914f1SMarcel Apfelbaum int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
3265cc914f1SMarcel Apfelbaum 				struct mlx4_vhcr *vhcr,
3275cc914f1SMarcel Apfelbaum 				struct mlx4_cmd_mailbox *inbox,
3285cc914f1SMarcel Apfelbaum 				struct mlx4_cmd_mailbox *outbox,
3295cc914f1SMarcel Apfelbaum 				struct mlx4_cmd_info *cmd)
3305cc914f1SMarcel Apfelbaum {
3315a0d0a61SJack Morgenstein 	struct mlx4_priv *priv = mlx4_priv(dev);
33299ec41d0SJack Morgenstein 	u8	field, port;
33399ec41d0SJack Morgenstein 	u32	size, proxy_qp, qkey;
3345cc914f1SMarcel Apfelbaum 	int	err = 0;
3357ae0e400SMatan Barak 	struct mlx4_func func;
3365cc914f1SMarcel Apfelbaum 
3375cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_FLAGS_OFFSET		0x0
3385cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET		0x1
3395cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PF_BHVR_OFFSET		0x4
340105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_OFFSET		0x8
341eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP	0x10
342eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP	0x14
343eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP	0x18
344eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP	0x20
345eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP	0x24
346eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP	0x28
3475cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_MAX_EQ_OFFSET		0x2c
34869612b9fSRoland Dreier #define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET	0x30
349f0ce0615SJack Morgenstein #define QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET	0x48
3505cc914f1SMarcel Apfelbaum 
351eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET		0x50
352eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET		0x54
353eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET		0x58
354eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET		0x60
355eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET		0x64
356eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET		0x68
357eb456a68SJack Morgenstein 
358ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET	0x6c
359ddae0349SEugenia Emantayev 
360105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FMR_FLAG			0x80
361105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RDMA		0x40
362105c320fSJack Morgenstein #define QUERY_FUNC_CAP_FLAG_ETH			0x80
363eb456a68SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_QUOTAS		0x10
364f0ce0615SJack Morgenstein #define QUERY_FUNC_CAP_FLAG_RESD_LKEY		0x08
365ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX	0x04
366ddae0349SEugenia Emantayev 
367ddae0349SEugenia Emantayev #define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG	(1UL << 31)
368d57febe1SMatan Barak #define QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG	(1UL << 30)
369105c320fSJack Morgenstein 
370105c320fSJack Morgenstein /* when opcode modifier = 1 */
3715cc914f1SMarcel Apfelbaum #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET		0x3
37299ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET	0x4
37373e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_OFFSET		0x8
37473e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_OFFSET		0xc
3755cc914f1SMarcel Apfelbaum 
37647605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_TUNNEL		0x10
37747605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP0_PROXY		0x14
37847605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_TUNNEL		0x18
37947605df9SJack Morgenstein #define QUERY_FUNC_CAP_QP1_PROXY		0x1c
3808e1a28e8SHadar Hen Zion #define QUERY_FUNC_CAP_PHYS_PORT_ID		0x28
38147605df9SJack Morgenstein 
38273e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_MAC		0x40
38373e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN	0x80
384eb17711bSHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS1_NIC_INFO			0x10
38599ec41d0SJack Morgenstein #define QUERY_FUNC_CAP_VF_ENABLE_QP0		0x08
386105c320fSJack Morgenstein 
38773e74ab4SHadar Hen Zion #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80
38877fc29c4SHadar Hen Zion #define QUERY_FUNC_CAP_PHV_BIT			0x40
3897c3d21c8SMoshe Shemesh #define QUERY_FUNC_CAP_VLAN_OFFLOAD_DISABLE	0x20
390105c320fSJack Morgenstein 
391b42959dcSMoshe Shemesh #define QUERY_FUNC_CAP_SUPPORTS_VST_QINQ	BIT(30)
392b42959dcSMoshe Shemesh #define QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS BIT(31)
393b42959dcSMoshe Shemesh 
3945cc914f1SMarcel Apfelbaum 	if (vhcr->op_modifier == 1) {
395449fc488SMatan Barak 		struct mlx4_active_ports actv_ports =
396449fc488SMatan Barak 			mlx4_get_active_ports(dev, slave);
397449fc488SMatan Barak 		int converted_port = mlx4_slave_convert_port(
398449fc488SMatan Barak 				dev, slave, vhcr->in_modifier);
399b42959dcSMoshe Shemesh 		struct mlx4_vport_oper_state *vp_oper;
400449fc488SMatan Barak 
401449fc488SMatan Barak 		if (converted_port < 0)
402449fc488SMatan Barak 			return -EINVAL;
403449fc488SMatan Barak 
404449fc488SMatan Barak 		vhcr->in_modifier = converted_port;
405449fc488SMatan Barak 		/* phys-port = logical-port */
406449fc488SMatan Barak 		field = vhcr->in_modifier -
407449fc488SMatan Barak 			find_first_bit(actv_ports.ports, dev->caps.num_ports);
40847605df9SJack Morgenstein 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
40947605df9SJack Morgenstein 
41099ec41d0SJack Morgenstein 		port = vhcr->in_modifier;
41199ec41d0SJack Morgenstein 		proxy_qp = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1;
41299ec41d0SJack Morgenstein 
41399ec41d0SJack Morgenstein 		/* Set nic_info bit to mark new fields support */
41499ec41d0SJack Morgenstein 		field  = QUERY_FUNC_CAP_FLAGS1_NIC_INFO;
41599ec41d0SJack Morgenstein 
41699ec41d0SJack Morgenstein 		if (mlx4_vf_smi_enabled(dev, slave, port) &&
41799ec41d0SJack Morgenstein 		    !mlx4_get_parav_qkey(dev, proxy_qp, &qkey)) {
41899ec41d0SJack Morgenstein 			field |= QUERY_FUNC_CAP_VF_ENABLE_QP0;
41999ec41d0SJack Morgenstein 			MLX4_PUT(outbox->buf, qkey,
42099ec41d0SJack Morgenstein 				 QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);
42199ec41d0SJack Morgenstein 		}
42299ec41d0SJack Morgenstein 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET);
42399ec41d0SJack Morgenstein 
42447605df9SJack Morgenstein 		/* size is now the QP number */
42599ec41d0SJack Morgenstein 		size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1;
42647605df9SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL);
42747605df9SJack Morgenstein 
42847605df9SJack Morgenstein 		size += 2;
42947605df9SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL);
43047605df9SJack Morgenstein 
43199ec41d0SJack Morgenstein 		MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP0_PROXY);
43299ec41d0SJack Morgenstein 		proxy_qp += 2;
43399ec41d0SJack Morgenstein 		MLX4_PUT(outbox->buf, proxy_qp, QUERY_FUNC_CAP_QP1_PROXY);
43447605df9SJack Morgenstein 
4358e1a28e8SHadar Hen Zion 		MLX4_PUT(outbox->buf, dev->caps.phys_port_id[vhcr->in_modifier],
4368e1a28e8SHadar Hen Zion 			 QUERY_FUNC_CAP_PHYS_PORT_ID);
4378e1a28e8SHadar Hen Zion 
438b42959dcSMoshe Shemesh 		vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
439b42959dcSMoshe Shemesh 		err = mlx4_handle_vst_qinq(priv, slave, port);
440b42959dcSMoshe Shemesh 		if (err)
441b42959dcSMoshe Shemesh 			return err;
442b42959dcSMoshe Shemesh 
4437c3d21c8SMoshe Shemesh 		field = 0;
4447c3d21c8SMoshe Shemesh 		if (dev->caps.phv_bit[port])
4457c3d21c8SMoshe Shemesh 			field |= QUERY_FUNC_CAP_PHV_BIT;
4467c3d21c8SMoshe Shemesh 		if (vp_oper->state.vlan_proto == htons(ETH_P_8021AD))
4477c3d21c8SMoshe Shemesh 			field |= QUERY_FUNC_CAP_VLAN_OFFLOAD_DISABLE;
4487c3d21c8SMoshe Shemesh 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS0_OFFSET);
44977fc29c4SHadar Hen Zion 
4505cc914f1SMarcel Apfelbaum 	} else if (vhcr->op_modifier == 0) {
451449fc488SMatan Barak 		struct mlx4_active_ports actv_ports =
452449fc488SMatan Barak 			mlx4_get_active_ports(dev, slave);
453b42959dcSMoshe Shemesh 		struct mlx4_slave_state *slave_state =
454b42959dcSMoshe Shemesh 			&priv->mfunc.master.slave_state[slave];
455b42959dcSMoshe Shemesh 
456f0ce0615SJack Morgenstein 		/* enable rdma and ethernet interfaces, new quota locations,
457f0ce0615SJack Morgenstein 		 * and reserved lkey
458f0ce0615SJack Morgenstein 		 */
459eb456a68SJack Morgenstein 		field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA |
460f0ce0615SJack Morgenstein 			 QUERY_FUNC_CAP_FLAG_QUOTAS | QUERY_FUNC_CAP_FLAG_VALID_MAILBOX |
461f0ce0615SJack Morgenstein 			 QUERY_FUNC_CAP_FLAG_RESD_LKEY);
4625cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
4635cc914f1SMarcel Apfelbaum 
464449fc488SMatan Barak 		field = min(
465449fc488SMatan Barak 			bitmap_weight(actv_ports.ports, dev->caps.num_ports),
4664e23eeebSLinus Torvalds 			(unsigned int) dev->caps.num_ports);
4675cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
4685cc914f1SMarcel Apfelbaum 
46908ff3235SOr Gerlitz 		size = dev->caps.function_caps; /* set PF behaviours */
4705cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
4715cc914f1SMarcel Apfelbaum 
472105c320fSJack Morgenstein 		field = 0; /* protected FMR support not available as yet */
473105c320fSJack Morgenstein 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET);
474105c320fSJack Morgenstein 
4755a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave];
4765cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
477eb456a68SJack Morgenstein 		size = dev->caps.num_qps;
478eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
4795cc914f1SMarcel Apfelbaum 
4805a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave];
4815cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
482eb456a68SJack Morgenstein 		size = dev->caps.num_srqs;
483eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
4845cc914f1SMarcel Apfelbaum 
4855a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave];
4865cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
487eb456a68SJack Morgenstein 		size = dev->caps.num_cqs;
488eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
4895cc914f1SMarcel Apfelbaum 
4907ae0e400SMatan Barak 		if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) ||
4917ae0e400SMatan Barak 		    mlx4_QUERY_FUNC(dev, &func, slave)) {
4927ae0e400SMatan Barak 			size = vhcr->in_modifier &
4937ae0e400SMatan Barak 				QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ?
4947ae0e400SMatan Barak 				dev->caps.num_eqs :
4957ae0e400SMatan Barak 				rounddown_pow_of_two(dev->caps.num_eqs);
4965cc914f1SMarcel Apfelbaum 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
4975cc914f1SMarcel Apfelbaum 			size = dev->caps.reserved_eqs;
4985cc914f1SMarcel Apfelbaum 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
4997ae0e400SMatan Barak 		} else {
5007ae0e400SMatan Barak 			size = vhcr->in_modifier &
5017ae0e400SMatan Barak 				QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ?
5027ae0e400SMatan Barak 				func.max_eq :
5037ae0e400SMatan Barak 				rounddown_pow_of_two(func.max_eq);
5047ae0e400SMatan Barak 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
5057ae0e400SMatan Barak 			size = func.rsvd_eqs;
5067ae0e400SMatan Barak 			MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
5077ae0e400SMatan Barak 		}
5085cc914f1SMarcel Apfelbaum 
5095a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave];
5105cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
511eb456a68SJack Morgenstein 		size = dev->caps.num_mpts;
512eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
5135cc914f1SMarcel Apfelbaum 
5145a0d0a61SJack Morgenstein 		size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave];
5155cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
516eb456a68SJack Morgenstein 		size = dev->caps.num_mtts;
517eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
5185cc914f1SMarcel Apfelbaum 
5195cc914f1SMarcel Apfelbaum 		size = dev->caps.num_mgms + dev->caps.num_amgms;
5205cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
521eb456a68SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
5225cc914f1SMarcel Apfelbaum 
523d57febe1SMatan Barak 		size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG |
524d57febe1SMatan Barak 			QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG;
525ddae0349SEugenia Emantayev 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET);
526f0ce0615SJack Morgenstein 
527f0ce0615SJack Morgenstein 		size = dev->caps.reserved_lkey + ((slave << 8) & 0xFF00);
528f0ce0615SJack Morgenstein 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET);
529b42959dcSMoshe Shemesh 
530b42959dcSMoshe Shemesh 		if (vhcr->in_modifier & QUERY_FUNC_CAP_SUPPORTS_VST_QINQ)
531b42959dcSMoshe Shemesh 			slave_state->vst_qinq_supported = true;
532b42959dcSMoshe Shemesh 
5335cc914f1SMarcel Apfelbaum 	} else
5345cc914f1SMarcel Apfelbaum 		err = -EINVAL;
5355cc914f1SMarcel Apfelbaum 
5365cc914f1SMarcel Apfelbaum 	return err;
5375cc914f1SMarcel Apfelbaum }
5385cc914f1SMarcel Apfelbaum 
mlx4_QUERY_FUNC_CAP(struct mlx4_dev * dev,u8 gen_or_port,struct mlx4_func_cap * func_cap)539225c6c8cSMatan Barak int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,
54047605df9SJack Morgenstein 			struct mlx4_func_cap *func_cap)
5415cc914f1SMarcel Apfelbaum {
5425cc914f1SMarcel Apfelbaum 	struct mlx4_cmd_mailbox *mailbox;
5435cc914f1SMarcel Apfelbaum 	u32			*outbox;
54447605df9SJack Morgenstein 	u8			field, op_modifier;
54599ec41d0SJack Morgenstein 	u32			size, qkey;
546eb456a68SJack Morgenstein 	int			err = 0, quotas = 0;
5477ae0e400SMatan Barak 	u32                     in_modifier;
548b42959dcSMoshe Shemesh 	u32			slave_caps;
5495cc914f1SMarcel Apfelbaum 
55047605df9SJack Morgenstein 	op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
551b42959dcSMoshe Shemesh 	slave_caps = QUERY_FUNC_CAP_SUPPORTS_VST_QINQ |
5527ae0e400SMatan Barak 		QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS;
553b42959dcSMoshe Shemesh 	in_modifier = op_modifier ? gen_or_port : slave_caps;
5545cc914f1SMarcel Apfelbaum 
5555cc914f1SMarcel Apfelbaum 	mailbox = mlx4_alloc_cmd_mailbox(dev);
5565cc914f1SMarcel Apfelbaum 	if (IS_ERR(mailbox))
5575cc914f1SMarcel Apfelbaum 		return PTR_ERR(mailbox);
5585cc914f1SMarcel Apfelbaum 
5597ae0e400SMatan Barak 	err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, op_modifier,
56047605df9SJack Morgenstein 			   MLX4_CMD_QUERY_FUNC_CAP,
5615cc914f1SMarcel Apfelbaum 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
5625cc914f1SMarcel Apfelbaum 	if (err)
5635cc914f1SMarcel Apfelbaum 		goto out;
5645cc914f1SMarcel Apfelbaum 
5655cc914f1SMarcel Apfelbaum 	outbox = mailbox->buf;
5665cc914f1SMarcel Apfelbaum 
56747605df9SJack Morgenstein 	if (!op_modifier) {
5685cc914f1SMarcel Apfelbaum 		MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET);
569105c320fSJack Morgenstein 		if (!(field & (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA))) {
570105c320fSJack Morgenstein 			mlx4_err(dev, "The host supports neither eth nor rdma interfaces\n");
5715cc914f1SMarcel Apfelbaum 			err = -EPROTONOSUPPORT;
5725cc914f1SMarcel Apfelbaum 			goto out;
5735cc914f1SMarcel Apfelbaum 		}
574105c320fSJack Morgenstein 		func_cap->flags = field;
575eb456a68SJack Morgenstein 		quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS);
5765cc914f1SMarcel Apfelbaum 
5775cc914f1SMarcel Apfelbaum 		MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
5785cc914f1SMarcel Apfelbaum 		func_cap->num_ports = field;
5795cc914f1SMarcel Apfelbaum 
5805cc914f1SMarcel Apfelbaum 		MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
5815cc914f1SMarcel Apfelbaum 		func_cap->pf_context_behaviour = size;
5825cc914f1SMarcel Apfelbaum 
583eb456a68SJack Morgenstein 		if (quotas) {
5845cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
5855cc914f1SMarcel Apfelbaum 			func_cap->qp_quota = size & 0xFFFFFF;
5865cc914f1SMarcel Apfelbaum 
5875cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
5885cc914f1SMarcel Apfelbaum 			func_cap->srq_quota = size & 0xFFFFFF;
5895cc914f1SMarcel Apfelbaum 
5905cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
5915cc914f1SMarcel Apfelbaum 			func_cap->cq_quota = size & 0xFFFFFF;
5925cc914f1SMarcel Apfelbaum 
5935cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
5945cc914f1SMarcel Apfelbaum 			func_cap->mpt_quota = size & 0xFFFFFF;
5955cc914f1SMarcel Apfelbaum 
5965cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
5975cc914f1SMarcel Apfelbaum 			func_cap->mtt_quota = size & 0xFFFFFF;
5985cc914f1SMarcel Apfelbaum 
5995cc914f1SMarcel Apfelbaum 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
6005cc914f1SMarcel Apfelbaum 			func_cap->mcg_quota = size & 0xFFFFFF;
601eb456a68SJack Morgenstein 
602eb456a68SJack Morgenstein 		} else {
603eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
604eb456a68SJack Morgenstein 			func_cap->qp_quota = size & 0xFFFFFF;
605eb456a68SJack Morgenstein 
606eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
607eb456a68SJack Morgenstein 			func_cap->srq_quota = size & 0xFFFFFF;
608eb456a68SJack Morgenstein 
609eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
610eb456a68SJack Morgenstein 			func_cap->cq_quota = size & 0xFFFFFF;
611eb456a68SJack Morgenstein 
612eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
613eb456a68SJack Morgenstein 			func_cap->mpt_quota = size & 0xFFFFFF;
614eb456a68SJack Morgenstein 
615eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
616eb456a68SJack Morgenstein 			func_cap->mtt_quota = size & 0xFFFFFF;
617eb456a68SJack Morgenstein 
618eb456a68SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
619eb456a68SJack Morgenstein 			func_cap->mcg_quota = size & 0xFFFFFF;
620eb456a68SJack Morgenstein 		}
621eb456a68SJack Morgenstein 		MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
622eb456a68SJack Morgenstein 		func_cap->max_eq = size & 0xFFFFFF;
623eb456a68SJack Morgenstein 
624eb456a68SJack Morgenstein 		MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
625eb456a68SJack Morgenstein 		func_cap->reserved_eq = size & 0xFFFFFF;
626eb456a68SJack Morgenstein 
627f0ce0615SJack Morgenstein 		if (func_cap->flags & QUERY_FUNC_CAP_FLAG_RESD_LKEY) {
628f0ce0615SJack Morgenstein 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_RESD_LKEY_OFFSET);
629f0ce0615SJack Morgenstein 			func_cap->reserved_lkey = size;
630f0ce0615SJack Morgenstein 		} else {
631f0ce0615SJack Morgenstein 			func_cap->reserved_lkey = 0;
632f0ce0615SJack Morgenstein 		}
633f0ce0615SJack Morgenstein 
634ddae0349SEugenia Emantayev 		func_cap->extra_flags = 0;
635ddae0349SEugenia Emantayev 
636ddae0349SEugenia Emantayev 		/* Mailbox data from 0x6c and onward should only be treated if
637ddae0349SEugenia Emantayev 		 * QUERY_FUNC_CAP_FLAG_VALID_MAILBOX is set in func_cap->flags
638ddae0349SEugenia Emantayev 		 */
639ddae0349SEugenia Emantayev 		if (func_cap->flags & QUERY_FUNC_CAP_FLAG_VALID_MAILBOX) {
640ddae0349SEugenia Emantayev 			MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET);
641ddae0349SEugenia Emantayev 			if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG)
642ddae0349SEugenia Emantayev 				func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP;
643d57febe1SMatan Barak 			if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG)
644d57febe1SMatan Barak 				func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_A0_RES_QP;
645ddae0349SEugenia Emantayev 		}
646ddae0349SEugenia Emantayev 
6475cc914f1SMarcel Apfelbaum 		goto out;
64847605df9SJack Morgenstein 	}
6495cc914f1SMarcel Apfelbaum 
65047605df9SJack Morgenstein 	/* logical port query */
65147605df9SJack Morgenstein 	if (gen_or_port > dev->caps.num_ports) {
65247605df9SJack Morgenstein 		err = -EINVAL;
65347605df9SJack Morgenstein 		goto out;
65447605df9SJack Morgenstein 	}
65547605df9SJack Morgenstein 
656eb17711bSHadar Hen Zion 	MLX4_GET(func_cap->flags1, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET);
65747605df9SJack Morgenstein 	if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_ETH) {
658bc82878bSJack Morgenstein 		if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_VLAN) {
6595cc914f1SMarcel Apfelbaum 			mlx4_err(dev, "VLAN is enforced on this port\n");
6605cc914f1SMarcel Apfelbaum 			err = -EPROTONOSUPPORT;
6615cc914f1SMarcel Apfelbaum 			goto out;
6625cc914f1SMarcel Apfelbaum 		}
6635cc914f1SMarcel Apfelbaum 
664eb17711bSHadar Hen Zion 		if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_FORCE_MAC) {
6655cc914f1SMarcel Apfelbaum 			mlx4_err(dev, "Force mac is enabled on this port\n");
6665cc914f1SMarcel Apfelbaum 			err = -EPROTONOSUPPORT;
6675cc914f1SMarcel Apfelbaum 			goto out;
6685cc914f1SMarcel Apfelbaum 		}
66947605df9SJack Morgenstein 	} else if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_IB) {
67073e74ab4SHadar Hen Zion 		MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET);
67173e74ab4SHadar Hen Zion 		if (field & QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID) {
6721a91de28SJoe Perches 			mlx4_err(dev, "phy_wqe_gid is enforced on this ib port\n");
673105c320fSJack Morgenstein 			err = -EPROTONOSUPPORT;
674105c320fSJack Morgenstein 			goto out;
675105c320fSJack Morgenstein 		}
676105c320fSJack Morgenstein 	}
6775cc914f1SMarcel Apfelbaum 
6785cc914f1SMarcel Apfelbaum 	MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
67947605df9SJack Morgenstein 	func_cap->physical_port = field;
68047605df9SJack Morgenstein 	if (func_cap->physical_port != gen_or_port) {
68172b8eaabSTariq Toukan 		err = -EINVAL;
68247605df9SJack Morgenstein 		goto out;
6835cc914f1SMarcel Apfelbaum 	}
6845cc914f1SMarcel Apfelbaum 
68599ec41d0SJack Morgenstein 	if (func_cap->flags1 & QUERY_FUNC_CAP_VF_ENABLE_QP0) {
68699ec41d0SJack Morgenstein 		MLX4_GET(qkey, outbox, QUERY_FUNC_CAP_PRIV_VF_QKEY_OFFSET);
687c73c8b1eSEran Ben Elisha 		func_cap->spec_qps.qp0_qkey = qkey;
68899ec41d0SJack Morgenstein 	} else {
689c73c8b1eSEran Ben Elisha 		func_cap->spec_qps.qp0_qkey = 0;
69099ec41d0SJack Morgenstein 	}
69199ec41d0SJack Morgenstein 
69247605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL);
693c73c8b1eSEran Ben Elisha 	func_cap->spec_qps.qp0_tunnel = size & 0xFFFFFF;
69447605df9SJack Morgenstein 
69547605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_PROXY);
696c73c8b1eSEran Ben Elisha 	func_cap->spec_qps.qp0_proxy = size & 0xFFFFFF;
69747605df9SJack Morgenstein 
69847605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_TUNNEL);
699c73c8b1eSEran Ben Elisha 	func_cap->spec_qps.qp1_tunnel = size & 0xFFFFFF;
70047605df9SJack Morgenstein 
70147605df9SJack Morgenstein 	MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_PROXY);
702c73c8b1eSEran Ben Elisha 	func_cap->spec_qps.qp1_proxy = size & 0xFFFFFF;
70347605df9SJack Morgenstein 
7048e1a28e8SHadar Hen Zion 	if (func_cap->flags1 & QUERY_FUNC_CAP_FLAGS1_NIC_INFO)
7058e1a28e8SHadar Hen Zion 		MLX4_GET(func_cap->phys_port_id, outbox,
7068e1a28e8SHadar Hen Zion 			 QUERY_FUNC_CAP_PHYS_PORT_ID);
7078e1a28e8SHadar Hen Zion 
708c9cc599aSMoshe Shemesh 	MLX4_GET(func_cap->flags0, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET);
70977fc29c4SHadar Hen Zion 
7105cc914f1SMarcel Apfelbaum 	/* All other resources are allocated by the master, but we still report
7115cc914f1SMarcel Apfelbaum 	 * 'num' and 'reserved' capabilities as follows:
7125cc914f1SMarcel Apfelbaum 	 * - num remains the maximum resource index
7135cc914f1SMarcel Apfelbaum 	 * - 'num - reserved' is the total available objects of a resource, but
7145cc914f1SMarcel Apfelbaum 	 *   resource indices may be less than 'reserved'
7155cc914f1SMarcel Apfelbaum 	 * TODO: set per-resource quotas */
7165cc914f1SMarcel Apfelbaum 
7175cc914f1SMarcel Apfelbaum out:
7185cc914f1SMarcel Apfelbaum 	mlx4_free_cmd_mailbox(dev, mailbox);
7195cc914f1SMarcel Apfelbaum 
7205cc914f1SMarcel Apfelbaum 	return err;
7215cc914f1SMarcel Apfelbaum }
7225cc914f1SMarcel Apfelbaum 
723d8ae9141SMoni Shoua static void disable_unsupported_roce_caps(void *buf);
724d8ae9141SMoni Shoua 
mlx4_QUERY_DEV_CAP(struct mlx4_dev * dev,struct mlx4_dev_cap * dev_cap)7255a2cc190SJeff Kirsher int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
7265a2cc190SJeff Kirsher {
7275a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
7285a2cc190SJeff Kirsher 	u32 *outbox;
7295a2cc190SJeff Kirsher 	u8 field;
7305a2cc190SJeff Kirsher 	u32 field32, flags, ext_flags;
7315a2cc190SJeff Kirsher 	u16 size;
7325a2cc190SJeff Kirsher 	u16 stat_rate;
7335a2cc190SJeff Kirsher 	int err;
7345a2cc190SJeff Kirsher 	int i;
7355a2cc190SJeff Kirsher 
7365a2cc190SJeff Kirsher #define QUERY_DEV_CAP_OUT_SIZE		       0x100
7375a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET		0x10
7385a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET		0x11
7395a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_QP_OFFSET		0x12
7405a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_OFFSET		0x13
7415a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_SRQ_OFFSET		0x14
7425a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SRQ_OFFSET		0x15
7435a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EEC_OFFSET		0x16
7445a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EEC_OFFSET		0x17
7455a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET		0x19
7465a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_CQ_OFFSET		0x1a
7475a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_CQ_OFFSET		0x1b
7485a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MPT_OFFSET		0x1d
7495a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_EQ_OFFSET		0x1e
7505a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_EQ_OFFSET		0x1f
7515a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MTT_OFFSET		0x20
7525a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET		0x21
7535a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MRW_OFFSET		0x22
7545a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET	0x23
7557ae0e400SMatan Barak #define QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET		0x26
7565a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_AV_OFFSET		0x27
7575a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET		0x29
7585a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET		0x2b
7595a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GSO_OFFSET		0x2d
760b3416f44SShlomo Pongratz #define QUERY_DEV_CAP_RSS_OFFSET		0x2e
7615a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_RDMA_OFFSET		0x2f
7625a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET		0x33
76351af33cfSIdo Shamay #define QUERY_DEV_CAP_PORT_BEACON_OFFSET	0x34
7645a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ACK_DELAY_OFFSET		0x35
7655a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET		0x36
7665a2cc190SJeff Kirsher #define QUERY_DEV_CAP_VL_PORT_OFFSET		0x37
7675a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET		0x38
7685a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_GID_OFFSET		0x3b
7695a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET	0x3c
770d998735fSEugenia Emantayev #define QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET	0x3e
7715a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PKEY_OFFSET		0x3f
7725a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EXT_FLAGS_OFFSET		0x40
773c994f778SInbar Karmy #define QUERY_DEV_CAP_WOL_OFFSET		0x43
7745a2cc190SJeff Kirsher #define QUERY_DEV_CAP_FLAGS_OFFSET		0x44
7755a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_UAR_OFFSET		0x48
7765a2cc190SJeff Kirsher #define QUERY_DEV_CAP_UAR_SZ_OFFSET		0x49
7775a2cc190SJeff Kirsher #define QUERY_DEV_CAP_PAGE_SZ_OFFSET		0x4b
7785a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BF_OFFSET			0x4c
7795a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET	0x4d
7805a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET	0x4e
7815a2cc190SJeff Kirsher #define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET	0x4f
7825a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET		0x51
7835a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET	0x52
7845a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET		0x55
7855a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET	0x56
786be599603SMoshe Shemesh #define QUERY_DEV_CAP_USER_MAC_EN_OFFSET	0x5C
7877c3d21c8SMoshe Shemesh #define QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET	0x5D
7885a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET		0x61
7895a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_MCG_OFFSET		0x62
7905a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_MCG_OFFSET		0x63
7915a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_PD_OFFSET		0x64
7925a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_PD_OFFSET		0x65
793f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_RSVD_XRC_OFFSET		0x66
794f470f8d4SLinus Torvalds #define QUERY_DEV_CAP_MAX_XRC_OFFSET		0x67
7955a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET	0x68
7960b131561SMatan Barak #define QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET	0x70
7973f7fb021SRony Efraim #define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET	0x70
7984de65803SMatan Barak #define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET	0x74
7990ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET	0x76
8000ff1fb65SHadar Hen Zion #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET	0x77
801fd10ed8eSJack Morgenstein #define QUERY_DEV_CAP_SL2VL_EVENT_OFFSET	0x78
80277507aa2SIdo Shamay #define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE	0x7a
803d237baa1SShani Michaeli #define QUERY_DEV_CAP_ECN_QCN_VER_OFFSET	0x7b
8045a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
8055a2cc190SJeff Kirsher #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET	0x82
8065a2cc190SJeff Kirsher #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET	0x84
8075a2cc190SJeff Kirsher #define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET	0x86
8085a2cc190SJeff Kirsher #define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET	0x88
8095a2cc190SJeff Kirsher #define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET	0x8a
8105a2cc190SJeff Kirsher #define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET	0x8c
8115a2cc190SJeff Kirsher #define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET	0x8e
8125a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET	0x90
8135a2cc190SJeff Kirsher #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET	0x92
8145a2cc190SJeff Kirsher #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET		0x94
815d475c95bSMatan Barak #define QUERY_DEV_CAP_CONFIG_DEV_OFFSET		0x94
81677fc29c4SHadar Hen Zion #define QUERY_DEV_CAP_PHV_EN_OFFSET		0x96
8175a2cc190SJeff Kirsher #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET		0x98
8185a2cc190SJeff Kirsher #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET		0xa0
819a53e3e8cSSaeed Mahameed #define QUERY_DEV_CAP_ETH_BACKPL_OFFSET		0x9c
820c7c122edSMark Bloch #define QUERY_DEV_CAP_DIAG_RPRT_PER_PORT	0x9c
821955154faSMatan Barak #define QUERY_DEV_CAP_FW_REASSIGN_MAC		0x9d
8227ffdf726SOr Gerlitz #define QUERY_DEV_CAP_VXLAN			0x9e
823114840c3SJack Morgenstein #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET		0xb0
8247d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET	0xa8
8257d077cd3SMatan Barak #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET	0xac
826404e5a12SShay Drory #define QUERY_DEV_CAP_MAP_CLOCK_TO_USER 0xc1
827fc31e256SOr Gerlitz #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET	0xcc
828fc31e256SOr Gerlitz #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET	0xd0
829fc31e256SOr Gerlitz #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET	0xd2
830523f9eb1SAlex Vesker #define QUERY_DEV_CAP_HEALTH_BUFFER_ADDRESS_OFFSET	0xe4
8315a2cc190SJeff Kirsher 
832b3416f44SShlomo Pongratz 	dev_cap->flags2 = 0;
8335a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
8345a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
8355a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
8365a2cc190SJeff Kirsher 	outbox = mailbox->buf;
8375a2cc190SJeff Kirsher 
8385a2cc190SJeff Kirsher 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
839401453a3SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
8405a2cc190SJeff Kirsher 	if (err)
8415a2cc190SJeff Kirsher 		goto out;
8425a2cc190SJeff Kirsher 
843d8ae9141SMoni Shoua 	if (mlx4_is_mfunc(dev))
844d8ae9141SMoni Shoua 		disable_unsupported_roce_caps(outbox);
845404e5a12SShay Drory 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAP_CLOCK_TO_USER);
846404e5a12SShay Drory 	dev_cap->map_clock_to_user = field & 0x80;
8475a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET);
8485a2cc190SJeff Kirsher 	dev_cap->reserved_qps = 1 << (field & 0xf);
8495a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET);
8505a2cc190SJeff Kirsher 	dev_cap->max_qps = 1 << (field & 0x1f);
8515a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET);
8525a2cc190SJeff Kirsher 	dev_cap->reserved_srqs = 1 << (field >> 4);
8535a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET);
8545a2cc190SJeff Kirsher 	dev_cap->max_srqs = 1 << (field & 0x1f);
8555a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET);
8565a2cc190SJeff Kirsher 	dev_cap->max_cq_sz = 1 << field;
8575a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET);
8585a2cc190SJeff Kirsher 	dev_cap->reserved_cqs = 1 << (field & 0xf);
8595a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET);
8605a2cc190SJeff Kirsher 	dev_cap->max_cqs = 1 << (field & 0x1f);
8615a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET);
8625a2cc190SJeff Kirsher 	dev_cap->max_mpts = 1 << (field & 0x3f);
8635a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET);
8647c68dd43SMatan Barak 	dev_cap->reserved_eqs = 1 << (field & 0xf);
8655a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET);
8665a2cc190SJeff Kirsher 	dev_cap->max_eqs = 1 << (field & 0xf);
8675a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
8685a2cc190SJeff Kirsher 	dev_cap->reserved_mtts = 1 << (field >> 4);
8695a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET);
8705a2cc190SJeff Kirsher 	dev_cap->reserved_mrws = 1 << (field & 0xf);
8717ae0e400SMatan Barak 	MLX4_GET(size, outbox, QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET);
8727ae0e400SMatan Barak 	dev_cap->num_sys_eqs = size & 0xfff;
8735a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET);
8745a2cc190SJeff Kirsher 	dev_cap->max_requester_per_qp = 1 << (field & 0x3f);
8755a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET);
8765a2cc190SJeff Kirsher 	dev_cap->max_responder_per_qp = 1 << (field & 0x3f);
8775a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET);
8785a2cc190SJeff Kirsher 	field &= 0x1f;
8795a2cc190SJeff Kirsher 	if (!field)
8805a2cc190SJeff Kirsher 		dev_cap->max_gso_sz = 0;
8815a2cc190SJeff Kirsher 	else
8825a2cc190SJeff Kirsher 		dev_cap->max_gso_sz = 1 << field;
8835a2cc190SJeff Kirsher 
884b3416f44SShlomo Pongratz 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET);
885b3416f44SShlomo Pongratz 	if (field & 0x20)
886b3416f44SShlomo Pongratz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR;
887b3416f44SShlomo Pongratz 	if (field & 0x10)
888b3416f44SShlomo Pongratz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP;
889b3416f44SShlomo Pongratz 	field &= 0xf;
890b3416f44SShlomo Pongratz 	if (field) {
891b3416f44SShlomo Pongratz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS;
892b3416f44SShlomo Pongratz 		dev_cap->max_rss_tbl_sz = 1 << field;
893b3416f44SShlomo Pongratz 	} else
894b3416f44SShlomo Pongratz 		dev_cap->max_rss_tbl_sz = 0;
8955a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
8965a2cc190SJeff Kirsher 	dev_cap->max_rdma_global = 1 << (field & 0x3f);
8975a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
8985a2cc190SJeff Kirsher 	dev_cap->local_ca_ack_delay = field & 0x1f;
8995a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
9005a2cc190SJeff Kirsher 	dev_cap->num_ports = field & 0xf;
9015a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
902fab9adfbSEran Ben Elisha 	dev_cap->max_msg_sz = 1 << (field & 0x1f);
9030b131561SMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET);
9040b131561SMatan Barak 	if (field & 0x10)
9050b131561SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN;
9060ff1fb65SHadar Hen Zion 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
9070ff1fb65SHadar Hen Zion 	if (field & 0x80)
9080ff1fb65SHadar Hen Zion 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
9090ff1fb65SHadar Hen Zion 	dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f;
9100e451e88SMarina Varshaver 	if (field & 0x20)
9110e451e88SMarina Varshaver 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_UC_MC_SNIFFER;
91251af33cfSIdo Shamay 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_BEACON_OFFSET);
91351af33cfSIdo Shamay 	if (field & 0x80)
91451af33cfSIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_PORT_BEACON;
9154de65803SMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
9164de65803SMatan Barak 	if (field & 0x80)
9174de65803SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB;
9180ff1fb65SHadar Hen Zion 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
9190ff1fb65SHadar Hen Zion 	dev_cap->fs_max_num_qp_per_entry = field;
920fd10ed8eSJack Morgenstein 	MLX4_GET(field, outbox, QUERY_DEV_CAP_SL2VL_EVENT_OFFSET);
921fd10ed8eSJack Morgenstein 	if (field & (1 << 5))
922fd10ed8eSJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SL_TO_VL_CHANGE_EVENT;
923d237baa1SShani Michaeli 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
924d237baa1SShani Michaeli 	if (field & 0x1)
925d237baa1SShani Michaeli 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QCN;
9265a2cc190SJeff Kirsher 	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
9275a2cc190SJeff Kirsher 	dev_cap->stat_rate_support = stat_rate;
928d998735fSEugenia Emantayev 	MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
929d998735fSEugenia Emantayev 	if (field & 0x80)
930d998735fSEugenia Emantayev 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS;
9315a2cc190SJeff Kirsher 	MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
9325a2cc190SJeff Kirsher 	MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
9335a2cc190SJeff Kirsher 	dev_cap->flags = flags | (u64)ext_flags << 32;
934c994f778SInbar Karmy 	MLX4_GET(field, outbox, QUERY_DEV_CAP_WOL_OFFSET);
935c994f778SInbar Karmy 	dev_cap->wol_port[1] = !!(field & 0x20);
936c994f778SInbar Karmy 	dev_cap->wol_port[2] = !!(field & 0x40);
9375a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
9385a2cc190SJeff Kirsher 	dev_cap->reserved_uars = field >> 4;
9395a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET);
9405a2cc190SJeff Kirsher 	dev_cap->uar_size = 1 << ((field & 0x3f) + 20);
9415a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET);
9425a2cc190SJeff Kirsher 	dev_cap->min_page_sz = 1 << field;
9435a2cc190SJeff Kirsher 
9445a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET);
9455a2cc190SJeff Kirsher 	if (field & 0x80) {
9465a2cc190SJeff Kirsher 		MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET);
9475a2cc190SJeff Kirsher 		dev_cap->bf_reg_size = 1 << (field & 0x1f);
9485a2cc190SJeff Kirsher 		MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET);
9495a2cc190SJeff Kirsher 		if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size))
9505a2cc190SJeff Kirsher 			field = 3;
9515a2cc190SJeff Kirsher 		dev_cap->bf_regs_per_page = 1 << (field & 0x3f);
9525a2cc190SJeff Kirsher 	} else {
9535a2cc190SJeff Kirsher 		dev_cap->bf_reg_size = 0;
9545a2cc190SJeff Kirsher 	}
9555a2cc190SJeff Kirsher 
9565a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET);
9575a2cc190SJeff Kirsher 	dev_cap->max_sq_sg = field;
9585a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET);
9595a2cc190SJeff Kirsher 	dev_cap->max_sq_desc_sz = size;
9605a2cc190SJeff Kirsher 
961be599603SMoshe Shemesh 	MLX4_GET(field, outbox, QUERY_DEV_CAP_USER_MAC_EN_OFFSET);
962be599603SMoshe Shemesh 	if (field & (1 << 2))
963be599603SMoshe Shemesh 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_USER_MAC_EN;
9647c3d21c8SMoshe Shemesh 	MLX4_GET(field, outbox, QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET);
9657c3d21c8SMoshe Shemesh 	if (field & 0x1)
9667c3d21c8SMoshe Shemesh 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SVLAN_BY_QP;
9675a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET);
9685a2cc190SJeff Kirsher 	dev_cap->max_qp_per_mcg = 1 << field;
9695a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET);
9705a2cc190SJeff Kirsher 	dev_cap->reserved_mgms = field & 0xf;
9715a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET);
9725a2cc190SJeff Kirsher 	dev_cap->max_mcgs = 1 << field;
9735a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET);
9745a2cc190SJeff Kirsher 	dev_cap->reserved_pds = field >> 4;
9755a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
9765a2cc190SJeff Kirsher 	dev_cap->max_pds = 1 << (field & 0x3f);
977f470f8d4SLinus Torvalds 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
978f470f8d4SLinus Torvalds 	dev_cap->reserved_xrcds = field >> 4;
979426dd00dSDotan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET);
980f470f8d4SLinus Torvalds 	dev_cap->max_xrcds = 1 << (field & 0x1f);
9815a2cc190SJeff Kirsher 
9825a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
9835a2cc190SJeff Kirsher 	dev_cap->rdmarc_entry_sz = size;
9845a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET);
9855a2cc190SJeff Kirsher 	dev_cap->qpc_entry_sz = size;
9865a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET);
9875a2cc190SJeff Kirsher 	dev_cap->aux_entry_sz = size;
9885a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET);
9895a2cc190SJeff Kirsher 	dev_cap->altc_entry_sz = size;
9905a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET);
9915a2cc190SJeff Kirsher 	dev_cap->eqc_entry_sz = size;
9925a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET);
9935a2cc190SJeff Kirsher 	dev_cap->cqc_entry_sz = size;
9945a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET);
9955a2cc190SJeff Kirsher 	dev_cap->srq_entry_sz = size;
9965a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET);
9975a2cc190SJeff Kirsher 	dev_cap->cmpt_entry_sz = size;
9985a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET);
9995a2cc190SJeff Kirsher 	dev_cap->mtt_entry_sz = size;
10005a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET);
10015a2cc190SJeff Kirsher 	dev_cap->dmpt_entry_sz = size;
10025a2cc190SJeff Kirsher 
10035a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET);
10045a2cc190SJeff Kirsher 	dev_cap->max_srq_sz = 1 << field;
10055a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET);
10065a2cc190SJeff Kirsher 	dev_cap->max_qp_sz = 1 << field;
10075a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET);
10085a2cc190SJeff Kirsher 	dev_cap->resize_srq = field & 1;
10095a2cc190SJeff Kirsher 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET);
10105a2cc190SJeff Kirsher 	dev_cap->max_rq_sg = field;
10115a2cc190SJeff Kirsher 	MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET);
10125a2cc190SJeff Kirsher 	dev_cap->max_rq_desc_sz = size;
101377507aa2SIdo Shamay 	MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE);
1014d019fcb2SIdo Shamay 	if (field & (1 << 4))
1015d019fcb2SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QOS_VPP;
1016adbc7ac5SSaeed Mahameed 	if (field & (1 << 5))
1017adbc7ac5SSaeed Mahameed 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL;
101877507aa2SIdo Shamay 	if (field & (1 << 6))
101977507aa2SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CQE_STRIDE;
102077507aa2SIdo Shamay 	if (field & (1 << 7))
102177507aa2SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE;
10225a2cc190SJeff Kirsher 	MLX4_GET(dev_cap->bmme_flags, outbox,
10235a2cc190SJeff Kirsher 		 QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1024d8ae9141SMoni Shoua 	if (dev_cap->bmme_flags & MLX4_FLAG_ROCE_V1_V2)
1025d8ae9141SMoni Shoua 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ROCE_V1_V2;
102659e14e32SMoni Shoua 	if (dev_cap->bmme_flags & MLX4_FLAG_PORT_REMAP)
102759e14e32SMoni Shoua 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_PORT_REMAP;
1028d475c95bSMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
1029d475c95bSMatan Barak 	if (field & 0x20)
1030d475c95bSMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CONFIG_DEV;
103178500b8cSMuhammad Mahajna 	if (field & (1 << 2))
103278500b8cSMuhammad Mahajna 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_IGNORE_FCS;
103377fc29c4SHadar Hen Zion 	MLX4_GET(field, outbox, QUERY_DEV_CAP_PHV_EN_OFFSET);
103477fc29c4SHadar Hen Zion 	if (field & 0x80)
103577fc29c4SHadar Hen Zion 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_PHV_EN;
103677fc29c4SHadar Hen Zion 	if (field & 0x40)
103777fc29c4SHadar Hen Zion 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN;
103877fc29c4SHadar Hen Zion 
10395a2cc190SJeff Kirsher 	MLX4_GET(dev_cap->reserved_lkey, outbox,
10405a2cc190SJeff Kirsher 		 QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
1041a53e3e8cSSaeed Mahameed 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETH_BACKPL_OFFSET);
1042a53e3e8cSSaeed Mahameed 	if (field32 & (1 << 0))
1043a53e3e8cSSaeed Mahameed 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP;
1044be6a6b43SJack Morgenstein 	if (field32 & (1 << 7))
1045be6a6b43SJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT;
1046e5c9a705SEran Ben Elisha 	if (field32 & (1 << 8))
1047e5c9a705SEran Ben Elisha 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW;
1048c7c122edSMark Bloch 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_DIAG_RPRT_PER_PORT);
1049c7c122edSMark Bloch 	if (field32 & (1 << 17))
1050c7c122edSMark Bloch 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT;
1051955154faSMatan Barak 	MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
1052955154faSMatan Barak 	if (field & 1<<6)
10535930e8d0SOr Gerlitz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN;
10547ffdf726SOr Gerlitz 	MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
10557ffdf726SOr Gerlitz 	if (field & 1<<3)
10567ffdf726SOr Gerlitz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS;
10573742cc65SIdo Shamay 	if (field & (1 << 5))
10583742cc65SIdo Shamay 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETS_CFG;
10595a2cc190SJeff Kirsher 	MLX4_GET(dev_cap->max_icm_sz, outbox,
10605a2cc190SJeff Kirsher 		 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
10615a2cc190SJeff Kirsher 	if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
10625a2cc190SJeff Kirsher 		MLX4_GET(dev_cap->max_counters, outbox,
10635a2cc190SJeff Kirsher 			 QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
10645a2cc190SJeff Kirsher 
1065114840c3SJack Morgenstein 	MLX4_GET(field32, outbox,
1066114840c3SJack Morgenstein 		 QUERY_DEV_CAP_MAD_DEMUX_OFFSET);
1067114840c3SJack Morgenstein 	if (field32 & (1 << 0))
1068114840c3SJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX;
1069114840c3SJack Morgenstein 
10707d077cd3SMatan Barak 	MLX4_GET(dev_cap->dmfs_high_rate_qpn_base, outbox,
10717d077cd3SMatan Barak 		 QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET);
10727d077cd3SMatan Barak 	dev_cap->dmfs_high_rate_qpn_base &= MGM_QPN_MASK;
10737d077cd3SMatan Barak 	MLX4_GET(dev_cap->dmfs_high_rate_qpn_range, outbox,
10747d077cd3SMatan Barak 		 QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET);
10757d077cd3SMatan Barak 	dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK;
10767d077cd3SMatan Barak 
1077fc31e256SOr Gerlitz 	MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET);
1078fc31e256SOr Gerlitz 	dev_cap->rl_caps.num_rates = size;
1079fc31e256SOr Gerlitz 	if (dev_cap->rl_caps.num_rates) {
1080fc31e256SOr Gerlitz 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT;
1081fc31e256SOr Gerlitz 		MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET);
1082fc31e256SOr Gerlitz 		dev_cap->rl_caps.max_val  = size & 0xfff;
1083fc31e256SOr Gerlitz 		dev_cap->rl_caps.max_unit = size >> 14;
1084fc31e256SOr Gerlitz 		MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET);
1085fc31e256SOr Gerlitz 		dev_cap->rl_caps.min_val  = size & 0xfff;
1086fc31e256SOr Gerlitz 		dev_cap->rl_caps.min_unit = size >> 14;
1087fc31e256SOr Gerlitz 	}
1088fc31e256SOr Gerlitz 
1089523f9eb1SAlex Vesker 	MLX4_GET(dev_cap->health_buffer_addrs, outbox,
1090523f9eb1SAlex Vesker 		 QUERY_DEV_CAP_HEALTH_BUFFER_ADDRESS_OFFSET);
1091523f9eb1SAlex Vesker 
10923f7fb021SRony Efraim 	MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1093b01978caSJack Morgenstein 	if (field32 & (1 << 16))
1094b01978caSJack Morgenstein 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
10959a892835SMaor Gottlieb 	if (field32 & (1 << 18))
10969a892835SMaor Gottlieb 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB;
10979a892835SMaor Gottlieb 	if (field32 & (1 << 19))
10989a892835SMaor Gottlieb 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_LB_SRC_CHK;
10993f7fb021SRony Efraim 	if (field32 & (1 << 26))
11003f7fb021SRony Efraim 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
1101e6b6a231SRony Efraim 	if (field32 & (1 << 20))
1102e6b6a231SRony Efraim 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;
1103de966c59SMatan Barak 	if (field32 & (1 << 21))
1104de966c59SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS;
1105e4567897SDaniel Jurgens 	if (field32 & (1 << 23))
1106e4567897SDaniel Jurgens 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SW_CQ_INIT;
11073f7fb021SRony Efraim 
1108431df8c7SMatan Barak 	for (i = 1; i <= dev_cap->num_ports; i++) {
1109431df8c7SMatan Barak 		err = mlx4_QUERY_PORT(dev, i, dev_cap->port_cap + i);
11105a2cc190SJeff Kirsher 		if (err)
11115a2cc190SJeff Kirsher 			goto out;
11125a2cc190SJeff Kirsher 	}
11135a2cc190SJeff Kirsher 
11145a2cc190SJeff Kirsher 	/*
11155a2cc190SJeff Kirsher 	 * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then
11165a2cc190SJeff Kirsher 	 * we can't use any EQs whose doorbell falls on that page,
11175a2cc190SJeff Kirsher 	 * even if the EQ itself isn't reserved.
11185a2cc190SJeff Kirsher 	 */
11197ae0e400SMatan Barak 	if (dev_cap->num_sys_eqs == 0)
11205a2cc190SJeff Kirsher 		dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4,
11215a2cc190SJeff Kirsher 					    dev_cap->reserved_eqs);
11227ae0e400SMatan Barak 	else
11237ae0e400SMatan Barak 		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SYS_EQS;
11245a2cc190SJeff Kirsher 
1125c78e25edSOr Gerlitz out:
1126c78e25edSOr Gerlitz 	mlx4_free_cmd_mailbox(dev, mailbox);
1127c78e25edSOr Gerlitz 	return err;
1128c78e25edSOr Gerlitz }
1129c78e25edSOr Gerlitz 
mlx4_dev_cap_dump(struct mlx4_dev * dev,struct mlx4_dev_cap * dev_cap)1130c78e25edSOr Gerlitz void mlx4_dev_cap_dump(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
1131c78e25edSOr Gerlitz {
1132c78e25edSOr Gerlitz 	if (dev_cap->bf_reg_size > 0)
1133c78e25edSOr Gerlitz 		mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n",
1134c78e25edSOr Gerlitz 			 dev_cap->bf_reg_size, dev_cap->bf_regs_per_page);
1135c78e25edSOr Gerlitz 	else
1136c78e25edSOr Gerlitz 		mlx4_dbg(dev, "BlueFlame not available\n");
1137c78e25edSOr Gerlitz 
1138c78e25edSOr Gerlitz 	mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n",
1139c78e25edSOr Gerlitz 		 dev_cap->bmme_flags, dev_cap->reserved_lkey);
11405a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max ICM size %lld MB\n",
11415a2cc190SJeff Kirsher 		 (unsigned long long) dev_cap->max_icm_sz >> 20);
11425a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
11435a2cc190SJeff Kirsher 		 dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz);
11445a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
11455a2cc190SJeff Kirsher 		 dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz);
11465a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
11475a2cc190SJeff Kirsher 		 dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz);
11487ae0e400SMatan Barak 	mlx4_dbg(dev, "Num sys EQs: %d, max EQs: %d, reserved EQs: %d, entry size: %d\n",
11497ae0e400SMatan Barak 		 dev_cap->num_sys_eqs, dev_cap->max_eqs, dev_cap->reserved_eqs,
11507ae0e400SMatan Barak 		 dev_cap->eqc_entry_sz);
11515a2cc190SJeff Kirsher 	mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
11525a2cc190SJeff Kirsher 		 dev_cap->reserved_mrws, dev_cap->reserved_mtts);
11535a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
11545a2cc190SJeff Kirsher 		 dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars);
11555a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
11565a2cc190SJeff Kirsher 		 dev_cap->max_pds, dev_cap->reserved_mgms);
11575a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
11585a2cc190SJeff Kirsher 		 dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
11595a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
1160431df8c7SMatan Barak 		 dev_cap->local_ca_ack_delay, 128 << dev_cap->port_cap[1].ib_mtu,
1161431df8c7SMatan Barak 		 dev_cap->port_cap[1].max_port_width);
11625a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
11635a2cc190SJeff Kirsher 		 dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
11645a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
11655a2cc190SJeff Kirsher 		 dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
11665a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
11675a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters);
1168b3416f44SShlomo Pongratz 	mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz);
11697d077cd3SMatan Barak 	mlx4_dbg(dev, "DMFS high rate steer QPn base: %d\n",
11707d077cd3SMatan Barak 		 dev_cap->dmfs_high_rate_qpn_base);
11717d077cd3SMatan Barak 	mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n",
11727d077cd3SMatan Barak 		 dev_cap->dmfs_high_rate_qpn_range);
1173fc31e256SOr Gerlitz 
1174fc31e256SOr Gerlitz 	if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT) {
1175fc31e256SOr Gerlitz 		struct mlx4_rate_limit_caps *rl_caps = &dev_cap->rl_caps;
1176fc31e256SOr Gerlitz 
1177fc31e256SOr Gerlitz 		mlx4_dbg(dev, "QP Rate-Limit: #rates %d, unit/val max %d/%d, min %d/%d\n",
1178fc31e256SOr Gerlitz 			 rl_caps->num_rates, rl_caps->max_unit, rl_caps->max_val,
1179fc31e256SOr Gerlitz 			 rl_caps->min_unit, rl_caps->min_val);
1180fc31e256SOr Gerlitz 	}
1181fc31e256SOr Gerlitz 
11825a2cc190SJeff Kirsher 	dump_dev_cap_flags(dev, dev_cap->flags);
1183b3416f44SShlomo Pongratz 	dump_dev_cap_flags2(dev, dev_cap->flags2);
11845a2cc190SJeff Kirsher }
11855a2cc190SJeff Kirsher 
mlx4_QUERY_PORT(struct mlx4_dev * dev,int port,struct mlx4_port_cap * port_cap)1186431df8c7SMatan Barak int mlx4_QUERY_PORT(struct mlx4_dev *dev, int port, struct mlx4_port_cap *port_cap)
1187431df8c7SMatan Barak {
1188431df8c7SMatan Barak 	struct mlx4_cmd_mailbox *mailbox;
1189431df8c7SMatan Barak 	u32 *outbox;
1190431df8c7SMatan Barak 	u8 field;
1191431df8c7SMatan Barak 	u32 field32;
1192431df8c7SMatan Barak 	int err;
1193431df8c7SMatan Barak 
1194431df8c7SMatan Barak 	mailbox = mlx4_alloc_cmd_mailbox(dev);
1195431df8c7SMatan Barak 	if (IS_ERR(mailbox))
1196431df8c7SMatan Barak 		return PTR_ERR(mailbox);
1197431df8c7SMatan Barak 	outbox = mailbox->buf;
1198431df8c7SMatan Barak 
1199431df8c7SMatan Barak 	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
1200431df8c7SMatan Barak 		err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
1201431df8c7SMatan Barak 				   MLX4_CMD_TIME_CLASS_A,
1202431df8c7SMatan Barak 				   MLX4_CMD_NATIVE);
1203431df8c7SMatan Barak 
1204431df8c7SMatan Barak 		if (err)
1205431df8c7SMatan Barak 			goto out;
1206431df8c7SMatan Barak 
1207431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
1208431df8c7SMatan Barak 		port_cap->max_vl	   = field >> 4;
1209431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
1210431df8c7SMatan Barak 		port_cap->ib_mtu	   = field >> 4;
1211431df8c7SMatan Barak 		port_cap->max_port_width = field & 0xf;
1212431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
1213431df8c7SMatan Barak 		port_cap->max_gids	   = 1 << (field & 0xf);
1214431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
1215431df8c7SMatan Barak 		port_cap->max_pkeys	   = 1 << (field & 0xf);
1216431df8c7SMatan Barak 	} else {
1217431df8c7SMatan Barak #define QUERY_PORT_SUPPORTED_TYPE_OFFSET	0x00
1218431df8c7SMatan Barak #define QUERY_PORT_MTU_OFFSET			0x01
1219431df8c7SMatan Barak #define QUERY_PORT_ETH_MTU_OFFSET		0x02
1220431df8c7SMatan Barak #define QUERY_PORT_WIDTH_OFFSET			0x06
1221431df8c7SMatan Barak #define QUERY_PORT_MAX_GID_PKEY_OFFSET		0x07
1222431df8c7SMatan Barak #define QUERY_PORT_MAX_MACVLAN_OFFSET		0x0a
1223431df8c7SMatan Barak #define QUERY_PORT_MAX_VL_OFFSET		0x0b
1224431df8c7SMatan Barak #define QUERY_PORT_MAC_OFFSET			0x10
1225431df8c7SMatan Barak #define QUERY_PORT_TRANS_VENDOR_OFFSET		0x18
1226431df8c7SMatan Barak #define QUERY_PORT_WAVELENGTH_OFFSET		0x1c
1227431df8c7SMatan Barak #define QUERY_PORT_TRANS_CODE_OFFSET		0x20
1228431df8c7SMatan Barak 
1229431df8c7SMatan Barak 		err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, MLX4_CMD_QUERY_PORT,
1230431df8c7SMatan Barak 				   MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
1231431df8c7SMatan Barak 		if (err)
1232431df8c7SMatan Barak 			goto out;
1233431df8c7SMatan Barak 
1234431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET);
1235e34305c8SOr Gerlitz 		port_cap->link_state = (field & 0x80) >> 7;
1236431df8c7SMatan Barak 		port_cap->supported_port_types = field & 3;
1237431df8c7SMatan Barak 		port_cap->suggested_type = (field >> 3) & 1;
1238431df8c7SMatan Barak 		port_cap->default_sense = (field >> 4) & 1;
12397d077cd3SMatan Barak 		port_cap->dmfs_optimized_state = (field >> 5) & 1;
1240431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
1241431df8c7SMatan Barak 		port_cap->ib_mtu	   = field & 0xf;
1242431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
1243431df8c7SMatan Barak 		port_cap->max_port_width = field & 0xf;
1244431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
1245431df8c7SMatan Barak 		port_cap->max_gids	   = 1 << (field >> 4);
1246431df8c7SMatan Barak 		port_cap->max_pkeys	   = 1 << (field & 0xf);
1247431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
1248431df8c7SMatan Barak 		port_cap->max_vl	   = field & 0xf;
1249af7d5185SRana Shahout 		port_cap->max_tc_eth	   = field >> 4;
1250431df8c7SMatan Barak 		MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET);
1251431df8c7SMatan Barak 		port_cap->log_max_macs  = field & 0xf;
1252431df8c7SMatan Barak 		port_cap->log_max_vlans = field >> 4;
1253431df8c7SMatan Barak 		MLX4_GET(port_cap->eth_mtu, outbox, QUERY_PORT_ETH_MTU_OFFSET);
1254431df8c7SMatan Barak 		MLX4_GET(port_cap->def_mac, outbox, QUERY_PORT_MAC_OFFSET);
1255431df8c7SMatan Barak 		MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET);
1256431df8c7SMatan Barak 		port_cap->trans_type = field32 >> 24;
1257431df8c7SMatan Barak 		port_cap->vendor_oui = field32 & 0xffffff;
1258431df8c7SMatan Barak 		MLX4_GET(port_cap->wavelength, outbox, QUERY_PORT_WAVELENGTH_OFFSET);
1259431df8c7SMatan Barak 		MLX4_GET(port_cap->trans_code, outbox, QUERY_PORT_TRANS_CODE_OFFSET);
1260431df8c7SMatan Barak 	}
1261431df8c7SMatan Barak 
1262431df8c7SMatan Barak out:
1263431df8c7SMatan Barak 	mlx4_free_cmd_mailbox(dev, mailbox);
1264431df8c7SMatan Barak 	return err;
1265431df8c7SMatan Barak }
1266431df8c7SMatan Barak 
12670b131561SMatan Barak #define DEV_CAP_EXT_2_FLAG_PFC_COUNTERS	(1 << 28)
1268383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_VLAN_CONTROL (1 << 26)
1269383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_80_VFS	(1 << 21)
1270383677daSOr Gerlitz #define DEV_CAP_EXT_2_FLAG_FSM		(1 << 20)
1271383677daSOr Gerlitz 
mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)1272b91cb3ebSJack Morgenstein int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
1273b91cb3ebSJack Morgenstein 			       struct mlx4_vhcr *vhcr,
1274b91cb3ebSJack Morgenstein 			       struct mlx4_cmd_mailbox *inbox,
1275b91cb3ebSJack Morgenstein 			       struct mlx4_cmd_mailbox *outbox,
1276b91cb3ebSJack Morgenstein 			       struct mlx4_cmd_info *cmd)
1277b91cb3ebSJack Morgenstein {
12782a4fae14SJack Morgenstein 	u64	flags;
1279b91cb3ebSJack Morgenstein 	int	err = 0;
1280b91cb3ebSJack Morgenstein 	u8	field;
1281fc31e256SOr Gerlitz 	u16	field16;
1282383677daSOr Gerlitz 	u32	bmme_flags, field32;
1283449fc488SMatan Barak 	int	real_port;
1284449fc488SMatan Barak 	int	slave_port;
1285449fc488SMatan Barak 	int	first_port;
1286449fc488SMatan Barak 	struct mlx4_active_ports actv_ports;
1287b91cb3ebSJack Morgenstein 
1288b91cb3ebSJack Morgenstein 	err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
1289b91cb3ebSJack Morgenstein 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1290b91cb3ebSJack Morgenstein 	if (err)
1291b91cb3ebSJack Morgenstein 		return err;
1292b91cb3ebSJack Morgenstein 
1293d8ae9141SMoni Shoua 	disable_unsupported_roce_caps(outbox->buf);
1294cc1ade94SShani Michaeli 	/* add port mng change event capability and disable mw type 1
1295cc1ade94SShani Michaeli 	 * unconditionally to slaves
1296cc1ade94SShani Michaeli 	 */
12972a4fae14SJack Morgenstein 	MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
12982a4fae14SJack Morgenstein 	flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV;
1299cc1ade94SShani Michaeli 	flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
1300449fc488SMatan Barak 	actv_ports = mlx4_get_active_ports(dev, slave);
1301449fc488SMatan Barak 	first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports);
1302449fc488SMatan Barak 	for (slave_port = 0, real_port = first_port;
1303449fc488SMatan Barak 	     real_port < first_port +
1304449fc488SMatan Barak 	     bitmap_weight(actv_ports.ports, dev->caps.num_ports);
1305449fc488SMatan Barak 	     ++real_port, ++slave_port) {
1306449fc488SMatan Barak 		if (flags & (MLX4_DEV_CAP_FLAG_WOL_PORT1 << real_port))
1307449fc488SMatan Barak 			flags |= MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port;
1308449fc488SMatan Barak 		else
1309449fc488SMatan Barak 			flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port);
1310449fc488SMatan Barak 	}
1311449fc488SMatan Barak 	for (; slave_port < dev->caps.num_ports; ++slave_port)
1312449fc488SMatan Barak 		flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port);
1313802f42a8SIdo Shamay 
1314802f42a8SIdo Shamay 	/* Not exposing RSS IP fragments to guests */
1315802f42a8SIdo Shamay 	flags &= ~MLX4_DEV_CAP_FLAG_RSS_IP_FRAG;
13162a4fae14SJack Morgenstein 	MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
13172a4fae14SJack Morgenstein 
1318449fc488SMatan Barak 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VL_PORT_OFFSET);
1319449fc488SMatan Barak 	field &= ~0x0F;
1320449fc488SMatan Barak 	field |= bitmap_weight(actv_ports.ports, dev->caps.num_ports) & 0x0F;
1321449fc488SMatan Barak 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VL_PORT_OFFSET);
1322449fc488SMatan Barak 
132330b40c31SAmir Vadai 	/* For guests, disable timestamp */
132430b40c31SAmir Vadai 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
132530b40c31SAmir Vadai 	field &= 0x7f;
132630b40c31SAmir Vadai 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
132730b40c31SAmir Vadai 
13283742cc65SIdo Shamay 	/* For guests, disable vxlan tunneling and QoS support */
132957352ef4SAmir Vadai 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VXLAN);
13303742cc65SIdo Shamay 	field &= 0xd7;
13317ffdf726SOr Gerlitz 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN);
13327ffdf726SOr Gerlitz 
133351af33cfSIdo Shamay 	/* For guests, disable port BEACON */
133451af33cfSIdo Shamay 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_PORT_BEACON_OFFSET);
133551af33cfSIdo Shamay 	field &= 0x7f;
133651af33cfSIdo Shamay 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_PORT_BEACON_OFFSET);
133751af33cfSIdo Shamay 
1338b91cb3ebSJack Morgenstein 	/* For guests, report Blueflame disabled */
1339b91cb3ebSJack Morgenstein 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
1340b91cb3ebSJack Morgenstein 	field &= 0x7f;
1341b91cb3ebSJack Morgenstein 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
1342b91cb3ebSJack Morgenstein 
134359e14e32SMoni Shoua 	/* For guests, disable mw type 2 and port remap*/
134457352ef4SAmir Vadai 	MLX4_GET(bmme_flags, outbox->buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1345cc1ade94SShani Michaeli 	bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
134659e14e32SMoni Shoua 	bmme_flags &= ~MLX4_FLAG_PORT_REMAP;
1347cc1ade94SShani Michaeli 	MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1348cc1ade94SShani Michaeli 
13490081c8f3SJack Morgenstein 	/* turn off device-managed steering capability if not enabled */
13500081c8f3SJack Morgenstein 	if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
13510081c8f3SJack Morgenstein 		MLX4_GET(field, outbox->buf,
13520081c8f3SJack Morgenstein 			 QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
13530081c8f3SJack Morgenstein 		field &= 0x7f;
13540081c8f3SJack Morgenstein 		MLX4_PUT(outbox->buf, field,
13550081c8f3SJack Morgenstein 			 QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
13560081c8f3SJack Morgenstein 	}
13574de65803SMatan Barak 
13584de65803SMatan Barak 	/* turn off ipoib managed steering for guests */
135957352ef4SAmir Vadai 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
13604de65803SMatan Barak 	field &= ~0x80;
13614de65803SMatan Barak 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
13624de65803SMatan Barak 
1363383677daSOr Gerlitz 	/* turn off host side virt features (VST, FSM, etc) for guests */
1364383677daSOr Gerlitz 	MLX4_GET(field32, outbox->buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1365383677daSOr Gerlitz 	field32 &= ~(DEV_CAP_EXT_2_FLAG_VLAN_CONTROL | DEV_CAP_EXT_2_FLAG_80_VFS |
13660b131561SMatan Barak 		     DEV_CAP_EXT_2_FLAG_FSM | DEV_CAP_EXT_2_FLAG_PFC_COUNTERS);
1367383677daSOr Gerlitz 	MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1368383677daSOr Gerlitz 
1369d237baa1SShani Michaeli 	/* turn off QCN for guests */
1370d237baa1SShani Michaeli 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
1371d237baa1SShani Michaeli 	field &= 0xfe;
1372d237baa1SShani Michaeli 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
1373d237baa1SShani Michaeli 
1374fc31e256SOr Gerlitz 	/* turn off QP max-rate limiting for guests */
1375fc31e256SOr Gerlitz 	field16 = 0;
1376fc31e256SOr Gerlitz 	MLX4_PUT(outbox->buf, field16, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET);
1377fc31e256SOr Gerlitz 
1378d019fcb2SIdo Shamay 	/* turn off QoS per VF support for guests */
1379d019fcb2SIdo Shamay 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE);
1380d019fcb2SIdo Shamay 	field &= 0xef;
1381d019fcb2SIdo Shamay 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE);
1382d019fcb2SIdo Shamay 
138378500b8cSMuhammad Mahajna 	/* turn off ignore FCS feature for guests */
138478500b8cSMuhammad Mahajna 	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
138578500b8cSMuhammad Mahajna 	field &= 0xfb;
138678500b8cSMuhammad Mahajna 	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
138778500b8cSMuhammad Mahajna 
1388b91cb3ebSJack Morgenstein 	return 0;
1389b91cb3ebSJack Morgenstein }
1390b91cb3ebSJack Morgenstein 
disable_unsupported_roce_caps(void * buf)1391d8ae9141SMoni Shoua static void disable_unsupported_roce_caps(void *buf)
1392d8ae9141SMoni Shoua {
1393d8ae9141SMoni Shoua 	u32 flags;
1394d8ae9141SMoni Shoua 
1395d8ae9141SMoni Shoua 	MLX4_GET(flags, buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
1396d8ae9141SMoni Shoua 	flags &= ~(1UL << 31);
1397d8ae9141SMoni Shoua 	MLX4_PUT(buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
1398d8ae9141SMoni Shoua 	MLX4_GET(flags, buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1399d8ae9141SMoni Shoua 	flags &= ~(1UL << 24);
1400d8ae9141SMoni Shoua 	MLX4_PUT(buf, flags, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
1401d8ae9141SMoni Shoua 	MLX4_GET(flags, buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1402d8ae9141SMoni Shoua 	flags &= ~(MLX4_FLAG_ROCE_V1_V2);
1403d8ae9141SMoni Shoua 	MLX4_PUT(buf, flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
1404d8ae9141SMoni Shoua }
1405d8ae9141SMoni Shoua 
mlx4_QUERY_PORT_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)14065cc914f1SMarcel Apfelbaum int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
14075cc914f1SMarcel Apfelbaum 			    struct mlx4_vhcr *vhcr,
14085cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *inbox,
14095cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *outbox,
14105cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_info *cmd)
14115cc914f1SMarcel Apfelbaum {
14120eb62b93SRony Efraim 	struct mlx4_priv *priv = mlx4_priv(dev);
14135cc914f1SMarcel Apfelbaum 	u64 def_mac;
14145cc914f1SMarcel Apfelbaum 	u8 port_type;
14156634961cSJack Morgenstein 	u16 short_field;
14165cc914f1SMarcel Apfelbaum 	int err;
1417948e306dSRony Efraim 	int admin_link_state;
1418449fc488SMatan Barak 	int port = mlx4_slave_convert_port(dev, slave,
1419449fc488SMatan Barak 					   vhcr->in_modifier & 0xFF);
14205cc914f1SMarcel Apfelbaum 
1421105c320fSJack Morgenstein #define MLX4_VF_PORT_NO_LINK_SENSE_MASK	0xE0
1422948e306dSRony Efraim #define MLX4_PORT_LINK_UP_MASK		0x80
14236634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_PKEY_OFFSET	0x0c
14246634961cSJack Morgenstein #define QUERY_PORT_CUR_MAX_GID_OFFSET	0x0e
142595f56e7aSYevgeny Petrilin 
1426449fc488SMatan Barak 	if (port < 0)
1427449fc488SMatan Barak 		return -EINVAL;
1428449fc488SMatan Barak 
1429a7401b9cSJack Morgenstein 	/* Protect against untrusted guests: enforce that this is the
1430a7401b9cSJack Morgenstein 	 * QUERY_PORT general query.
1431a7401b9cSJack Morgenstein 	 */
1432a7401b9cSJack Morgenstein 	if (vhcr->op_modifier || vhcr->in_modifier & ~0xFF)
1433a7401b9cSJack Morgenstein 		return -EINVAL;
1434a7401b9cSJack Morgenstein 
1435a7401b9cSJack Morgenstein 	vhcr->in_modifier = port;
1436449fc488SMatan Barak 
14375cc914f1SMarcel Apfelbaum 	err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0,
14385cc914f1SMarcel Apfelbaum 			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
14395cc914f1SMarcel Apfelbaum 			   MLX4_CMD_NATIVE);
14405cc914f1SMarcel Apfelbaum 
14415cc914f1SMarcel Apfelbaum 	if (!err && dev->caps.function != slave) {
14420eb62b93SRony Efraim 		def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
14435cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
14445cc914f1SMarcel Apfelbaum 
14455cc914f1SMarcel Apfelbaum 		/* get port type - currently only eth is enabled */
14465cc914f1SMarcel Apfelbaum 		MLX4_GET(port_type, outbox->buf,
14475cc914f1SMarcel Apfelbaum 			 QUERY_PORT_SUPPORTED_TYPE_OFFSET);
14485cc914f1SMarcel Apfelbaum 
1449105c320fSJack Morgenstein 		/* No link sensing allowed */
1450105c320fSJack Morgenstein 		port_type &= MLX4_VF_PORT_NO_LINK_SENSE_MASK;
1451105c320fSJack Morgenstein 		/* set port type to currently operating port type */
1452105c320fSJack Morgenstein 		port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3);
14535cc914f1SMarcel Apfelbaum 
1454948e306dSRony Efraim 		admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state;
1455948e306dSRony Efraim 		if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state)
1456948e306dSRony Efraim 			port_type |= MLX4_PORT_LINK_UP_MASK;
1457948e306dSRony Efraim 		else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state)
1458948e306dSRony Efraim 			port_type &= ~MLX4_PORT_LINK_UP_MASK;
1459e34305c8SOr Gerlitz 		else if (IFLA_VF_LINK_STATE_AUTO == admin_link_state && mlx4_is_bonded(dev)) {
1460e34305c8SOr Gerlitz 			int other_port = (port == 1) ? 2 : 1;
1461e34305c8SOr Gerlitz 			struct mlx4_port_cap port_cap;
1462e34305c8SOr Gerlitz 
1463e34305c8SOr Gerlitz 			err = mlx4_QUERY_PORT(dev, other_port, &port_cap);
1464e34305c8SOr Gerlitz 			if (err)
1465e34305c8SOr Gerlitz 				goto out;
1466e34305c8SOr Gerlitz 			port_type |= (port_cap.link_state << 7);
1467e34305c8SOr Gerlitz 		}
1468948e306dSRony Efraim 
14695cc914f1SMarcel Apfelbaum 		MLX4_PUT(outbox->buf, port_type,
14705cc914f1SMarcel Apfelbaum 			 QUERY_PORT_SUPPORTED_TYPE_OFFSET);
14716634961cSJack Morgenstein 
1472b6ffaeffSJack Morgenstein 		if (dev->caps.port_type[vhcr->in_modifier] == MLX4_PORT_TYPE_ETH)
1473449fc488SMatan Barak 			short_field = mlx4_get_slave_num_gids(dev, slave, port);
1474b6ffaeffSJack Morgenstein 		else
14756634961cSJack Morgenstein 			short_field = 1; /* slave max gids */
14766634961cSJack Morgenstein 		MLX4_PUT(outbox->buf, short_field,
14776634961cSJack Morgenstein 			 QUERY_PORT_CUR_MAX_GID_OFFSET);
14786634961cSJack Morgenstein 
14796634961cSJack Morgenstein 		short_field = dev->caps.pkey_table_len[vhcr->in_modifier];
14806634961cSJack Morgenstein 		MLX4_PUT(outbox->buf, short_field,
14816634961cSJack Morgenstein 			 QUERY_PORT_CUR_MAX_PKEY_OFFSET);
14825cc914f1SMarcel Apfelbaum 	}
1483e34305c8SOr Gerlitz out:
14845cc914f1SMarcel Apfelbaum 	return err;
14855cc914f1SMarcel Apfelbaum }
14865cc914f1SMarcel Apfelbaum 
mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev * dev,u8 port,int * gid_tbl_len,int * pkey_tbl_len)14876634961cSJack Morgenstein int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port,
14886634961cSJack Morgenstein 				    int *gid_tbl_len, int *pkey_tbl_len)
14896634961cSJack Morgenstein {
14906634961cSJack Morgenstein 	struct mlx4_cmd_mailbox *mailbox;
14916634961cSJack Morgenstein 	u32			*outbox;
14926634961cSJack Morgenstein 	u16			field;
14936634961cSJack Morgenstein 	int			err;
14946634961cSJack Morgenstein 
14956634961cSJack Morgenstein 	mailbox = mlx4_alloc_cmd_mailbox(dev);
14966634961cSJack Morgenstein 	if (IS_ERR(mailbox))
14976634961cSJack Morgenstein 		return PTR_ERR(mailbox);
14986634961cSJack Morgenstein 
14996634961cSJack Morgenstein 	err =  mlx4_cmd_box(dev, 0, mailbox->dma, port, 0,
15006634961cSJack Morgenstein 			    MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
15016634961cSJack Morgenstein 			    MLX4_CMD_WRAPPED);
15026634961cSJack Morgenstein 	if (err)
15036634961cSJack Morgenstein 		goto out;
15046634961cSJack Morgenstein 
15056634961cSJack Morgenstein 	outbox = mailbox->buf;
15066634961cSJack Morgenstein 
15076634961cSJack Morgenstein 	MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_GID_OFFSET);
15086634961cSJack Morgenstein 	*gid_tbl_len = field;
15096634961cSJack Morgenstein 
15106634961cSJack Morgenstein 	MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_PKEY_OFFSET);
15116634961cSJack Morgenstein 	*pkey_tbl_len = field;
15126634961cSJack Morgenstein 
15136634961cSJack Morgenstein out:
15146634961cSJack Morgenstein 	mlx4_free_cmd_mailbox(dev, mailbox);
15156634961cSJack Morgenstein 	return err;
15166634961cSJack Morgenstein }
15176634961cSJack Morgenstein EXPORT_SYMBOL(mlx4_get_slave_pkey_gid_tbl_len);
15186634961cSJack Morgenstein 
mlx4_map_cmd(struct mlx4_dev * dev,u16 op,struct mlx4_icm * icm,u64 virt)15195a2cc190SJeff Kirsher int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt)
15205a2cc190SJeff Kirsher {
15215a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
15225a2cc190SJeff Kirsher 	struct mlx4_icm_iter iter;
15235a2cc190SJeff Kirsher 	__be64 *pages;
15245a2cc190SJeff Kirsher 	int lg;
15255a2cc190SJeff Kirsher 	int nent = 0;
15265a2cc190SJeff Kirsher 	int i;
15275a2cc190SJeff Kirsher 	int err = 0;
15285a2cc190SJeff Kirsher 	int ts = 0, tc = 0;
15295a2cc190SJeff Kirsher 
15305a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
15315a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
15325a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
15335a2cc190SJeff Kirsher 	pages = mailbox->buf;
15345a2cc190SJeff Kirsher 
15355a2cc190SJeff Kirsher 	for (mlx4_icm_first(icm, &iter);
15365a2cc190SJeff Kirsher 	     !mlx4_icm_last(&iter);
15375a2cc190SJeff Kirsher 	     mlx4_icm_next(&iter)) {
15385a2cc190SJeff Kirsher 		/*
15395a2cc190SJeff Kirsher 		 * We have to pass pages that are aligned to their
15405a2cc190SJeff Kirsher 		 * size, so find the least significant 1 in the
15415a2cc190SJeff Kirsher 		 * address or size and use that as our log2 size.
15425a2cc190SJeff Kirsher 		 */
15435a2cc190SJeff Kirsher 		lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1;
15445a2cc190SJeff Kirsher 		if (lg < MLX4_ICM_PAGE_SHIFT) {
15451a91de28SJoe Perches 			mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx)\n",
15465a2cc190SJeff Kirsher 				  MLX4_ICM_PAGE_SIZE,
15475a2cc190SJeff Kirsher 				  (unsigned long long) mlx4_icm_addr(&iter),
15485a2cc190SJeff Kirsher 				  mlx4_icm_size(&iter));
15495a2cc190SJeff Kirsher 			err = -EINVAL;
15505a2cc190SJeff Kirsher 			goto out;
15515a2cc190SJeff Kirsher 		}
15525a2cc190SJeff Kirsher 
15535a2cc190SJeff Kirsher 		for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) {
15545a2cc190SJeff Kirsher 			if (virt != -1) {
15555a2cc190SJeff Kirsher 				pages[nent * 2] = cpu_to_be64(virt);
1556187782ebSLeon Romanovsky 				virt += 1ULL << lg;
15575a2cc190SJeff Kirsher 			}
15585a2cc190SJeff Kirsher 
15595a2cc190SJeff Kirsher 			pages[nent * 2 + 1] =
15605a2cc190SJeff Kirsher 				cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) |
15615a2cc190SJeff Kirsher 					    (lg - MLX4_ICM_PAGE_SHIFT));
15625a2cc190SJeff Kirsher 			ts += 1 << (lg - 10);
15635a2cc190SJeff Kirsher 			++tc;
15645a2cc190SJeff Kirsher 
15655a2cc190SJeff Kirsher 			if (++nent == MLX4_MAILBOX_SIZE / 16) {
15665a2cc190SJeff Kirsher 				err = mlx4_cmd(dev, mailbox->dma, nent, 0, op,
1567f9baff50SJack Morgenstein 						MLX4_CMD_TIME_CLASS_B,
1568f9baff50SJack Morgenstein 						MLX4_CMD_NATIVE);
15695a2cc190SJeff Kirsher 				if (err)
15705a2cc190SJeff Kirsher 					goto out;
15715a2cc190SJeff Kirsher 				nent = 0;
15725a2cc190SJeff Kirsher 			}
15735a2cc190SJeff Kirsher 		}
15745a2cc190SJeff Kirsher 	}
15755a2cc190SJeff Kirsher 
15765a2cc190SJeff Kirsher 	if (nent)
1577f9baff50SJack Morgenstein 		err = mlx4_cmd(dev, mailbox->dma, nent, 0, op,
1578f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
15795a2cc190SJeff Kirsher 	if (err)
15805a2cc190SJeff Kirsher 		goto out;
15815a2cc190SJeff Kirsher 
15825a2cc190SJeff Kirsher 	switch (op) {
15835a2cc190SJeff Kirsher 	case MLX4_CMD_MAP_FA:
15841a91de28SJoe Perches 		mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW\n", tc, ts);
15855a2cc190SJeff Kirsher 		break;
15865a2cc190SJeff Kirsher 	case MLX4_CMD_MAP_ICM_AUX:
15871a91de28SJoe Perches 		mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux\n", tc, ts);
15885a2cc190SJeff Kirsher 		break;
15895a2cc190SJeff Kirsher 	case MLX4_CMD_MAP_ICM:
15901a91de28SJoe Perches 		mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM\n",
15915a2cc190SJeff Kirsher 			 tc, ts, (unsigned long long) virt - (ts << 10));
15925a2cc190SJeff Kirsher 		break;
15935a2cc190SJeff Kirsher 	}
15945a2cc190SJeff Kirsher 
15955a2cc190SJeff Kirsher out:
15965a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
15975a2cc190SJeff Kirsher 	return err;
15985a2cc190SJeff Kirsher }
15995a2cc190SJeff Kirsher 
mlx4_MAP_FA(struct mlx4_dev * dev,struct mlx4_icm * icm)16005a2cc190SJeff Kirsher int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm)
16015a2cc190SJeff Kirsher {
16025a2cc190SJeff Kirsher 	return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1);
16035a2cc190SJeff Kirsher }
16045a2cc190SJeff Kirsher 
mlx4_UNMAP_FA(struct mlx4_dev * dev)16055a2cc190SJeff Kirsher int mlx4_UNMAP_FA(struct mlx4_dev *dev)
16065a2cc190SJeff Kirsher {
1607f9baff50SJack Morgenstein 	return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA,
1608f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
16095a2cc190SJeff Kirsher }
16105a2cc190SJeff Kirsher 
16115a2cc190SJeff Kirsher 
mlx4_RUN_FW(struct mlx4_dev * dev)16125a2cc190SJeff Kirsher int mlx4_RUN_FW(struct mlx4_dev *dev)
16135a2cc190SJeff Kirsher {
1614f9baff50SJack Morgenstein 	return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW,
1615f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
16165a2cc190SJeff Kirsher }
16175a2cc190SJeff Kirsher 
mlx4_QUERY_FW(struct mlx4_dev * dev)16185a2cc190SJeff Kirsher int mlx4_QUERY_FW(struct mlx4_dev *dev)
16195a2cc190SJeff Kirsher {
16205a2cc190SJeff Kirsher 	struct mlx4_fw  *fw  = &mlx4_priv(dev)->fw;
16215a2cc190SJeff Kirsher 	struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
16225a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
16235a2cc190SJeff Kirsher 	u32 *outbox;
16245a2cc190SJeff Kirsher 	int err = 0;
16255a2cc190SJeff Kirsher 	u64 fw_ver;
16265a2cc190SJeff Kirsher 	u16 cmd_if_rev;
16275a2cc190SJeff Kirsher 	u8 lg;
16285a2cc190SJeff Kirsher 
16295a2cc190SJeff Kirsher #define QUERY_FW_OUT_SIZE             0x100
16305a2cc190SJeff Kirsher #define QUERY_FW_VER_OFFSET            0x00
16315cc914f1SMarcel Apfelbaum #define QUERY_FW_PPF_ID		       0x09
16325a2cc190SJeff Kirsher #define QUERY_FW_CMD_IF_REV_OFFSET     0x0a
16335a2cc190SJeff Kirsher #define QUERY_FW_MAX_CMD_OFFSET        0x0f
16345a2cc190SJeff Kirsher #define QUERY_FW_ERR_START_OFFSET      0x30
16355a2cc190SJeff Kirsher #define QUERY_FW_ERR_SIZE_OFFSET       0x38
16365a2cc190SJeff Kirsher #define QUERY_FW_ERR_BAR_OFFSET        0x3c
16375a2cc190SJeff Kirsher 
16385a2cc190SJeff Kirsher #define QUERY_FW_SIZE_OFFSET           0x00
16395a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BASE_OFFSET   0x20
16405a2cc190SJeff Kirsher #define QUERY_FW_CLR_INT_BAR_OFFSET    0x28
16415a2cc190SJeff Kirsher 
16425cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BASE_OFFSET      0x40
16435cc914f1SMarcel Apfelbaum #define QUERY_FW_COMM_BAR_OFFSET       0x48
16445cc914f1SMarcel Apfelbaum 
1645ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_OFFSET	       0x50
1646ddd8a6c1SEugenia Emantayev #define QUERY_FW_CLOCK_BAR	       0x58
1647ddd8a6c1SEugenia Emantayev 
16485a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
16495a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
16505a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
16515a2cc190SJeff Kirsher 	outbox = mailbox->buf;
16525a2cc190SJeff Kirsher 
16535a2cc190SJeff Kirsher 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW,
1654f9baff50SJack Morgenstein 			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
16555a2cc190SJeff Kirsher 	if (err)
16565a2cc190SJeff Kirsher 		goto out;
16575a2cc190SJeff Kirsher 
16585a2cc190SJeff Kirsher 	MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET);
16595a2cc190SJeff Kirsher 	/*
16605a2cc190SJeff Kirsher 	 * FW subminor version is at more significant bits than minor
16615a2cc190SJeff Kirsher 	 * version, so swap here.
16625a2cc190SJeff Kirsher 	 */
16635a2cc190SJeff Kirsher 	dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) |
16645a2cc190SJeff Kirsher 		((fw_ver & 0xffff0000ull) >> 16) |
16655a2cc190SJeff Kirsher 		((fw_ver & 0x0000ffffull) << 16);
16665a2cc190SJeff Kirsher 
1667752a50caSJack Morgenstein 	MLX4_GET(lg, outbox, QUERY_FW_PPF_ID);
1668752a50caSJack Morgenstein 	dev->caps.function = lg;
1669752a50caSJack Morgenstein 
1670b91cb3ebSJack Morgenstein 	if (mlx4_is_slave(dev))
1671b91cb3ebSJack Morgenstein 		goto out;
1672b91cb3ebSJack Morgenstein 
16735cc914f1SMarcel Apfelbaum 
16745a2cc190SJeff Kirsher 	MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
16755a2cc190SJeff Kirsher 	if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
16765a2cc190SJeff Kirsher 	    cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
16771a91de28SJoe Perches 		mlx4_err(dev, "Installed FW has unsupported command interface revision %d\n",
16785a2cc190SJeff Kirsher 			 cmd_if_rev);
16795a2cc190SJeff Kirsher 		mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n",
16805a2cc190SJeff Kirsher 			 (int) (dev->caps.fw_ver >> 32),
16815a2cc190SJeff Kirsher 			 (int) (dev->caps.fw_ver >> 16) & 0xffff,
16825a2cc190SJeff Kirsher 			 (int) dev->caps.fw_ver & 0xffff);
16831a91de28SJoe Perches 		mlx4_err(dev, "This driver version supports only revisions %d to %d\n",
16845a2cc190SJeff Kirsher 			 MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV);
16855a2cc190SJeff Kirsher 		err = -ENODEV;
16865a2cc190SJeff Kirsher 		goto out;
16875a2cc190SJeff Kirsher 	}
16885a2cc190SJeff Kirsher 
16895a2cc190SJeff Kirsher 	if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS)
16905a2cc190SJeff Kirsher 		dev->flags |= MLX4_FLAG_OLD_PORT_CMDS;
16915a2cc190SJeff Kirsher 
16925a2cc190SJeff Kirsher 	MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
16935a2cc190SJeff Kirsher 	cmd->max_cmds = 1 << lg;
16945a2cc190SJeff Kirsher 
16955a2cc190SJeff Kirsher 	mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n",
16965a2cc190SJeff Kirsher 		 (int) (dev->caps.fw_ver >> 32),
16975a2cc190SJeff Kirsher 		 (int) (dev->caps.fw_ver >> 16) & 0xffff,
16985a2cc190SJeff Kirsher 		 (int) dev->caps.fw_ver & 0xffff,
16995a2cc190SJeff Kirsher 		 cmd_if_rev, cmd->max_cmds);
17005a2cc190SJeff Kirsher 
17015a2cc190SJeff Kirsher 	MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET);
17025a2cc190SJeff Kirsher 	MLX4_GET(fw->catas_size,   outbox, QUERY_FW_ERR_SIZE_OFFSET);
17035a2cc190SJeff Kirsher 	MLX4_GET(fw->catas_bar,    outbox, QUERY_FW_ERR_BAR_OFFSET);
17045a2cc190SJeff Kirsher 	fw->catas_bar = (fw->catas_bar >> 6) * 2;
17055a2cc190SJeff Kirsher 
17065a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n",
17075a2cc190SJeff Kirsher 		 (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar);
17085a2cc190SJeff Kirsher 
17095a2cc190SJeff Kirsher 	MLX4_GET(fw->fw_pages,     outbox, QUERY_FW_SIZE_OFFSET);
17105a2cc190SJeff Kirsher 	MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET);
17115a2cc190SJeff Kirsher 	MLX4_GET(fw->clr_int_bar,  outbox, QUERY_FW_CLR_INT_BAR_OFFSET);
17125a2cc190SJeff Kirsher 	fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2;
17135a2cc190SJeff Kirsher 
17145cc914f1SMarcel Apfelbaum 	MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET);
17155cc914f1SMarcel Apfelbaum 	MLX4_GET(fw->comm_bar,  outbox, QUERY_FW_COMM_BAR_OFFSET);
17165cc914f1SMarcel Apfelbaum 	fw->comm_bar = (fw->comm_bar >> 6) * 2;
17175cc914f1SMarcel Apfelbaum 	mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n",
17185cc914f1SMarcel Apfelbaum 		 fw->comm_bar, fw->comm_base);
17195a2cc190SJeff Kirsher 	mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
17205a2cc190SJeff Kirsher 
1721ddd8a6c1SEugenia Emantayev 	MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET);
1722ddd8a6c1SEugenia Emantayev 	MLX4_GET(fw->clock_bar,    outbox, QUERY_FW_CLOCK_BAR);
1723ddd8a6c1SEugenia Emantayev 	fw->clock_bar = (fw->clock_bar >> 6) * 2;
1724ddd8a6c1SEugenia Emantayev 	mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n",
1725ddd8a6c1SEugenia Emantayev 		 fw->clock_bar, fw->clock_offset);
1726ddd8a6c1SEugenia Emantayev 
17275a2cc190SJeff Kirsher 	/*
17285a2cc190SJeff Kirsher 	 * Round up number of system pages needed in case
17295a2cc190SJeff Kirsher 	 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
17305a2cc190SJeff Kirsher 	 */
17315a2cc190SJeff Kirsher 	fw->fw_pages =
17325a2cc190SJeff Kirsher 		ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >>
17335a2cc190SJeff Kirsher 		(PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT);
17345a2cc190SJeff Kirsher 
17355a2cc190SJeff Kirsher 	mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n",
17365a2cc190SJeff Kirsher 		 (unsigned long long) fw->clr_int_base, fw->clr_int_bar);
17375a2cc190SJeff Kirsher 
17385a2cc190SJeff Kirsher out:
17395a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
17405a2cc190SJeff Kirsher 	return err;
17415a2cc190SJeff Kirsher }
17425a2cc190SJeff Kirsher 
mlx4_QUERY_FW_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)1743b91cb3ebSJack Morgenstein int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave,
1744b91cb3ebSJack Morgenstein 			  struct mlx4_vhcr *vhcr,
1745b91cb3ebSJack Morgenstein 			  struct mlx4_cmd_mailbox *inbox,
1746b91cb3ebSJack Morgenstein 			  struct mlx4_cmd_mailbox *outbox,
1747b91cb3ebSJack Morgenstein 			  struct mlx4_cmd_info *cmd)
1748b91cb3ebSJack Morgenstein {
1749b91cb3ebSJack Morgenstein 	u8 *outbuf;
1750b91cb3ebSJack Morgenstein 	int err;
1751b91cb3ebSJack Morgenstein 
1752b91cb3ebSJack Morgenstein 	outbuf = outbox->buf;
1753b91cb3ebSJack Morgenstein 	err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_FW,
1754b91cb3ebSJack Morgenstein 			    MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1755b91cb3ebSJack Morgenstein 	if (err)
1756b91cb3ebSJack Morgenstein 		return err;
1757b91cb3ebSJack Morgenstein 
1758752a50caSJack Morgenstein 	/* for slaves, set pci PPF ID to invalid and zero out everything
1759752a50caSJack Morgenstein 	 * else except FW version */
1760b91cb3ebSJack Morgenstein 	outbuf[0] = outbuf[1] = 0;
1761b91cb3ebSJack Morgenstein 	memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8);
1762752a50caSJack Morgenstein 	outbuf[QUERY_FW_PPF_ID] = MLX4_INVALID_SLAVE_ID;
1763752a50caSJack Morgenstein 
1764b91cb3ebSJack Morgenstein 	return 0;
1765b91cb3ebSJack Morgenstein }
1766b91cb3ebSJack Morgenstein 
get_board_id(void * vsd,char * board_id)17675a2cc190SJeff Kirsher static void get_board_id(void *vsd, char *board_id)
17685a2cc190SJeff Kirsher {
17695a2cc190SJeff Kirsher 	int i;
17705a2cc190SJeff Kirsher 
17715a2cc190SJeff Kirsher #define VSD_OFFSET_SIG1		0x00
17725a2cc190SJeff Kirsher #define VSD_OFFSET_SIG2		0xde
17735a2cc190SJeff Kirsher #define VSD_OFFSET_MLX_BOARD_ID	0xd0
17745a2cc190SJeff Kirsher #define VSD_OFFSET_TS_BOARD_ID	0x20
17755a2cc190SJeff Kirsher 
17765a2cc190SJeff Kirsher #define VSD_SIGNATURE_TOPSPIN	0x5ad
17775a2cc190SJeff Kirsher 
17785a2cc190SJeff Kirsher 	memset(board_id, 0, MLX4_BOARD_ID_LEN);
17795a2cc190SJeff Kirsher 
17805a2cc190SJeff Kirsher 	if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
17815a2cc190SJeff Kirsher 	    be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
1782f029c781SWolfram Sang 		strscpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN);
17835a2cc190SJeff Kirsher 	} else {
17845a2cc190SJeff Kirsher 		/*
17855a2cc190SJeff Kirsher 		 * The board ID is a string but the firmware byte
17865a2cc190SJeff Kirsher 		 * swaps each 4-byte word before passing it back to
17875a2cc190SJeff Kirsher 		 * us.  Therefore we need to swab it before printing.
17885a2cc190SJeff Kirsher 		 */
178917d5ceb6SDavid Ahern 		u32 *bid_u32 = (u32 *)board_id;
179017d5ceb6SDavid Ahern 
179117d5ceb6SDavid Ahern 		for (i = 0; i < 4; ++i) {
179217d5ceb6SDavid Ahern 			u32 *addr;
179317d5ceb6SDavid Ahern 			u32 val;
179417d5ceb6SDavid Ahern 
179517d5ceb6SDavid Ahern 			addr = (u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4);
179617d5ceb6SDavid Ahern 			val = get_unaligned(addr);
179717d5ceb6SDavid Ahern 			val = swab32(val);
179817d5ceb6SDavid Ahern 			put_unaligned(val, &bid_u32[i]);
179917d5ceb6SDavid Ahern 		}
18005a2cc190SJeff Kirsher 	}
18015a2cc190SJeff Kirsher }
18025a2cc190SJeff Kirsher 
mlx4_QUERY_ADAPTER(struct mlx4_dev * dev,struct mlx4_adapter * adapter)18035a2cc190SJeff Kirsher int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
18045a2cc190SJeff Kirsher {
18055a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
18065a2cc190SJeff Kirsher 	u32 *outbox;
18075a2cc190SJeff Kirsher 	int err;
18085a2cc190SJeff Kirsher 
18095a2cc190SJeff Kirsher #define QUERY_ADAPTER_OUT_SIZE             0x100
18105a2cc190SJeff Kirsher #define QUERY_ADAPTER_INTA_PIN_OFFSET      0x10
18115a2cc190SJeff Kirsher #define QUERY_ADAPTER_VSD_OFFSET           0x20
18125a2cc190SJeff Kirsher 
18135a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
18145a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
18155a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
18165a2cc190SJeff Kirsher 	outbox = mailbox->buf;
18175a2cc190SJeff Kirsher 
18185a2cc190SJeff Kirsher 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER,
1819f9baff50SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
18205a2cc190SJeff Kirsher 	if (err)
18215a2cc190SJeff Kirsher 		goto out;
18225a2cc190SJeff Kirsher 
18235a2cc190SJeff Kirsher 	MLX4_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
18245a2cc190SJeff Kirsher 
18255a2cc190SJeff Kirsher 	get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
18265a2cc190SJeff Kirsher 		     adapter->board_id);
18275a2cc190SJeff Kirsher 
18285a2cc190SJeff Kirsher out:
18295a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
18305a2cc190SJeff Kirsher 	return err;
18315a2cc190SJeff Kirsher }
18325a2cc190SJeff Kirsher 
mlx4_INIT_HCA(struct mlx4_dev * dev,struct mlx4_init_hca_param * param)18335a2cc190SJeff Kirsher int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
18345a2cc190SJeff Kirsher {
18355a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
18365a2cc190SJeff Kirsher 	__be32 *inbox;
18375a2cc190SJeff Kirsher 	int err;
18387d077cd3SMatan Barak 	static const u8 a0_dmfs_hw_steering[] =  {
18397d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_DEFAULT]		= 0,
18407d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_DYNAMIC]		= 1,
18417d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_STATIC]		= 2,
18427d077cd3SMatan Barak 		[MLX4_STEERING_DMFS_A0_DISABLE]		= 3
18437d077cd3SMatan Barak 	};
18445a2cc190SJeff Kirsher 
18455a2cc190SJeff Kirsher #define INIT_HCA_IN_SIZE		 0x200
18465a2cc190SJeff Kirsher #define INIT_HCA_VERSION_OFFSET		 0x000
18475a2cc190SJeff Kirsher #define	 INIT_HCA_VERSION		 2
18487ffdf726SOr Gerlitz #define INIT_HCA_VXLAN_OFFSET		 0x0c
18495a2cc190SJeff Kirsher #define INIT_HCA_CACHELINE_SZ_OFFSET	 0x0e
18505a2cc190SJeff Kirsher #define INIT_HCA_FLAGS_OFFSET		 0x014
1851be6a6b43SJack Morgenstein #define INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET 0x018
18525a2cc190SJeff Kirsher #define INIT_HCA_QPC_OFFSET		 0x020
18535a2cc190SJeff Kirsher #define	 INIT_HCA_QPC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x10)
18545a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_QP_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x17)
18555a2cc190SJeff Kirsher #define	 INIT_HCA_SRQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x28)
18565a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_SRQ_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x2f)
18575a2cc190SJeff Kirsher #define	 INIT_HCA_CQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x30)
18585a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_CQ_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x37)
18595cc914f1SMarcel Apfelbaum #define	 INIT_HCA_EQE_CQE_OFFSETS	 (INIT_HCA_QPC_OFFSET + 0x38)
186077507aa2SIdo Shamay #define	 INIT_HCA_EQE_CQE_STRIDE_OFFSET  (INIT_HCA_QPC_OFFSET + 0x3b)
18615a2cc190SJeff Kirsher #define	 INIT_HCA_ALTC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x40)
18625a2cc190SJeff Kirsher #define	 INIT_HCA_AUXC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x50)
18635a2cc190SJeff Kirsher #define	 INIT_HCA_EQC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x60)
18645a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_EQ_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x67)
18657ae0e400SMatan Barak #define	INIT_HCA_NUM_SYS_EQS_OFFSET	(INIT_HCA_QPC_OFFSET + 0x6a)
18665a2cc190SJeff Kirsher #define	 INIT_HCA_RDMARC_BASE_OFFSET	 (INIT_HCA_QPC_OFFSET + 0x70)
18675a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_RD_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x77)
18685a2cc190SJeff Kirsher #define INIT_HCA_MCAST_OFFSET		 0x0c0
18695a2cc190SJeff Kirsher #define	 INIT_HCA_MC_BASE_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x00)
18706d9c8d15SAya Levin #define	 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x13)
18716d9c8d15SAya Levin #define	 INIT_HCA_LOG_MC_HASH_SZ_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x17)
18725a2cc190SJeff Kirsher #define  INIT_HCA_UC_STEERING_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x18)
18735a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
18740ff1fb65SHadar Hen Zion #define  INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN	0x6
1875e5c9a705SEran Ben Elisha #define  INIT_HCA_DRIVER_VERSION_OFFSET   0x140
1876e5c9a705SEran Ben Elisha #define  INIT_HCA_DRIVER_VERSION_SZ       0x40
18770ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_PARAM_OFFSET         0x1d0
18780ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_BASE_OFFSET          (INIT_HCA_FS_PARAM_OFFSET + 0x00)
18796d9c8d15SAya Levin #define  INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x13)
18807d077cd3SMatan Barak #define  INIT_HCA_FS_A0_OFFSET		  (INIT_HCA_FS_PARAM_OFFSET + 0x18)
18810ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_LOG_TABLE_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
18820ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_ETH_BITS_OFFSET      (INIT_HCA_FS_PARAM_OFFSET + 0x21)
18830ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22)
18840ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_IB_BITS_OFFSET       (INIT_HCA_FS_PARAM_OFFSET + 0x25)
18850ff1fb65SHadar Hen Zion #define  INIT_HCA_FS_IB_NUM_ADDRS_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x26)
18865a2cc190SJeff Kirsher #define INIT_HCA_TPT_OFFSET		 0x0f0
18875a2cc190SJeff Kirsher #define	 INIT_HCA_DMPT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x00)
1888e448834eSShani Michaeli #define  INIT_HCA_TPT_MW_OFFSET		 (INIT_HCA_TPT_OFFSET + 0x08)
18895a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_MPT_SZ_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x0b)
18905a2cc190SJeff Kirsher #define	 INIT_HCA_MTT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x10)
18915a2cc190SJeff Kirsher #define	 INIT_HCA_CMPT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x18)
18925a2cc190SJeff Kirsher #define INIT_HCA_UAR_OFFSET		 0x120
18935a2cc190SJeff Kirsher #define	 INIT_HCA_LOG_UAR_SZ_OFFSET	 (INIT_HCA_UAR_OFFSET + 0x0a)
18945a2cc190SJeff Kirsher #define  INIT_HCA_UAR_PAGE_SZ_OFFSET     (INIT_HCA_UAR_OFFSET + 0x0b)
18955a2cc190SJeff Kirsher 
18965a2cc190SJeff Kirsher 	mailbox = mlx4_alloc_cmd_mailbox(dev);
18975a2cc190SJeff Kirsher 	if (IS_ERR(mailbox))
18985a2cc190SJeff Kirsher 		return PTR_ERR(mailbox);
18995a2cc190SJeff Kirsher 	inbox = mailbox->buf;
19005a2cc190SJeff Kirsher 
19015a2cc190SJeff Kirsher 	*((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION;
19025a2cc190SJeff Kirsher 
19035a2cc190SJeff Kirsher 	*((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) =
190438353364SYishai Hadas 		((ilog2(cache_line_size()) - 4) << 5) | (1 << 4);
19055a2cc190SJeff Kirsher 
19065a2cc190SJeff Kirsher #if defined(__LITTLE_ENDIAN)
19075a2cc190SJeff Kirsher 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
19085a2cc190SJeff Kirsher #elif defined(__BIG_ENDIAN)
19095a2cc190SJeff Kirsher 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1);
19105a2cc190SJeff Kirsher #else
19115a2cc190SJeff Kirsher #error Host endianness not defined
19125a2cc190SJeff Kirsher #endif
19135a2cc190SJeff Kirsher 	/* Check port for UD address vector: */
19145a2cc190SJeff Kirsher 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1);
19155a2cc190SJeff Kirsher 
19165a2cc190SJeff Kirsher 	/* Enable IPoIB checksumming if we can: */
19175a2cc190SJeff Kirsher 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
19185a2cc190SJeff Kirsher 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
19195a2cc190SJeff Kirsher 
19205a2cc190SJeff Kirsher 	/* Enable QoS support if module parameter set */
192138438f7cSIdo Shamay 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETS_CFG && enable_qos)
19225a2cc190SJeff Kirsher 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
19235a2cc190SJeff Kirsher 
19245a2cc190SJeff Kirsher 	/* enable counters */
19255a2cc190SJeff Kirsher 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
19265a2cc190SJeff Kirsher 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
19275a2cc190SJeff Kirsher 
1928802f42a8SIdo Shamay 	/* Enable RSS spread to fragmented IP packets when supported */
1929802f42a8SIdo Shamay 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_RSS_IP_FRAG)
1930802f42a8SIdo Shamay 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 13);
1931802f42a8SIdo Shamay 
193208ff3235SOr Gerlitz 	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
193308ff3235SOr Gerlitz 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) {
193408ff3235SOr Gerlitz 		*(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29);
193508ff3235SOr Gerlitz 		dev->caps.eqe_size   = 64;
193608ff3235SOr Gerlitz 		dev->caps.eqe_factor = 1;
193708ff3235SOr Gerlitz 	} else {
193808ff3235SOr Gerlitz 		dev->caps.eqe_size   = 32;
193908ff3235SOr Gerlitz 		dev->caps.eqe_factor = 0;
194008ff3235SOr Gerlitz 	}
194108ff3235SOr Gerlitz 
194208ff3235SOr Gerlitz 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) {
194308ff3235SOr Gerlitz 		*(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30);
194408ff3235SOr Gerlitz 		dev->caps.cqe_size   = 64;
194577507aa2SIdo Shamay 		dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;
194608ff3235SOr Gerlitz 	} else {
194708ff3235SOr Gerlitz 		dev->caps.cqe_size   = 32;
194808ff3235SOr Gerlitz 	}
194908ff3235SOr Gerlitz 
195077507aa2SIdo Shamay 	/* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */
195177507aa2SIdo Shamay 	if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) &&
195277507aa2SIdo Shamay 	    (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) {
195377507aa2SIdo Shamay 		dev->caps.eqe_size = cache_line_size();
195477507aa2SIdo Shamay 		dev->caps.cqe_size = cache_line_size();
195577507aa2SIdo Shamay 		dev->caps.eqe_factor = 0;
195677507aa2SIdo Shamay 		MLX4_PUT(inbox, (u8)((ilog2(dev->caps.eqe_size) - 5) << 4 |
195777507aa2SIdo Shamay 				      (ilog2(dev->caps.eqe_size) - 5)),
195877507aa2SIdo Shamay 			 INIT_HCA_EQE_CQE_STRIDE_OFFSET);
195977507aa2SIdo Shamay 
196077507aa2SIdo Shamay 		/* User still need to know to support CQE > 32B */
196177507aa2SIdo Shamay 		dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE;
196277507aa2SIdo Shamay 	}
196377507aa2SIdo Shamay 
1964be6a6b43SJack Morgenstein 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT)
1965be6a6b43SJack Morgenstein 		*(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31);
1966be6a6b43SJack Morgenstein 
1967e5c9a705SEran Ben Elisha 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW) {
1968e5c9a705SEran Ben Elisha 		u8 *dst = (u8 *)(inbox + INIT_HCA_DRIVER_VERSION_OFFSET / 4);
1969e5c9a705SEran Ben Elisha 
1970*88fca39bSJustin Stitt 		strscpy(dst, DRV_NAME_FOR_FW, INIT_HCA_DRIVER_VERSION_SZ);
1971e5c9a705SEran Ben Elisha 		mlx4_dbg(dev, "Reporting Driver Version to FW: %s\n", dst);
1972e5c9a705SEran Ben Elisha 	}
1973e5c9a705SEran Ben Elisha 
19745a2cc190SJeff Kirsher 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
19755a2cc190SJeff Kirsher 
19765a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
19775a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_qps,   INIT_HCA_LOG_QP_OFFSET);
19785a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->srqc_base,     INIT_HCA_SRQC_BASE_OFFSET);
19795a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_srqs,  INIT_HCA_LOG_SRQ_OFFSET);
19805a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->cqc_base,      INIT_HCA_CQC_BASE_OFFSET);
19815a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_cqs,   INIT_HCA_LOG_CQ_OFFSET);
19825a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->altc_base,     INIT_HCA_ALTC_BASE_OFFSET);
19835a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->auxc_base,     INIT_HCA_AUXC_BASE_OFFSET);
19845a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->eqc_base,      INIT_HCA_EQC_BASE_OFFSET);
19855a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_num_eqs,   INIT_HCA_LOG_EQ_OFFSET);
19867ae0e400SMatan Barak 	MLX4_PUT(inbox, param->num_sys_eqs,   INIT_HCA_NUM_SYS_EQS_OFFSET);
19875a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->rdmarc_base,   INIT_HCA_RDMARC_BASE_OFFSET);
19885a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET);
19895a2cc190SJeff Kirsher 
19900ff1fb65SHadar Hen Zion 	/* steering attributes */
19910ff1fb65SHadar Hen Zion 	if (dev->caps.steering_mode ==
19920ff1fb65SHadar Hen Zion 	    MLX4_STEERING_MODE_DEVICE_MANAGED) {
19930ff1fb65SHadar Hen Zion 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |=
19940ff1fb65SHadar Hen Zion 			cpu_to_be32(1 <<
19950ff1fb65SHadar Hen Zion 				    INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN);
19965a2cc190SJeff Kirsher 
19970ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET);
19980ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_entry_sz,
19990ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
20000ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_table_sz,
20010ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
20020ff1fb65SHadar Hen Zion 		/* Enable Ethernet flow steering
20030ff1fb65SHadar Hen Zion 		 * with udp unicast and tcp unicast
20040ff1fb65SHadar Hen Zion 		 */
20057d077cd3SMatan Barak 		if (dev->caps.dmfs_high_steer_mode !=
20067d077cd3SMatan Barak 		    MLX4_STEERING_DMFS_A0_STATIC)
20077d077cd3SMatan Barak 			MLX4_PUT(inbox,
20087d077cd3SMatan Barak 				 (u8)(MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN),
20090ff1fb65SHadar Hen Zion 				 INIT_HCA_FS_ETH_BITS_OFFSET);
20100ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
20110ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET);
20120ff1fb65SHadar Hen Zion 		/* Enable IPoIB flow steering
20130ff1fb65SHadar Hen Zion 		 * with udp unicast and tcp unicast
20140ff1fb65SHadar Hen Zion 		 */
201523537b73SHadar Hen Zion 		MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN),
20160ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_IB_BITS_OFFSET);
20170ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
20180ff1fb65SHadar Hen Zion 			 INIT_HCA_FS_IB_NUM_ADDRS_OFFSET);
20197d077cd3SMatan Barak 
20207d077cd3SMatan Barak 		if (dev->caps.dmfs_high_steer_mode !=
20217d077cd3SMatan Barak 		    MLX4_STEERING_DMFS_A0_NOT_SUPPORTED)
20227d077cd3SMatan Barak 			MLX4_PUT(inbox,
20237d077cd3SMatan Barak 				 ((u8)(a0_dmfs_hw_steering[dev->caps.dmfs_high_steer_mode]
20247d077cd3SMatan Barak 				       << 6)),
20257d077cd3SMatan Barak 				 INIT_HCA_FS_A0_OFFSET);
20260ff1fb65SHadar Hen Zion 	} else {
20275a2cc190SJeff Kirsher 		MLX4_PUT(inbox, param->mc_base,	INIT_HCA_MC_BASE_OFFSET);
20280ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_entry_sz,
20290ff1fb65SHadar Hen Zion 			 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
20300ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_hash_sz,
20310ff1fb65SHadar Hen Zion 			 INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
20320ff1fb65SHadar Hen Zion 		MLX4_PUT(inbox, param->log_mc_table_sz,
20330ff1fb65SHadar Hen Zion 			 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
2034c96d97f4SHadar Hen Zion 		if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
20350ff1fb65SHadar Hen Zion 			MLX4_PUT(inbox, (u8) (1 << 3),
20360ff1fb65SHadar Hen Zion 				 INIT_HCA_UC_STEERING_OFFSET);
20370ff1fb65SHadar Hen Zion 	}
20385a2cc190SJeff Kirsher 
20395a2cc190SJeff Kirsher 	/* TPT attributes */
20405a2cc190SJeff Kirsher 
20415a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->dmpt_base,  INIT_HCA_DMPT_BASE_OFFSET);
2042e448834eSShani Michaeli 	MLX4_PUT(inbox, param->mw_enabled, INIT_HCA_TPT_MW_OFFSET);
20435a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET);
20445a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->mtt_base,   INIT_HCA_MTT_BASE_OFFSET);
20455a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->cmpt_base,  INIT_HCA_CMPT_BASE_OFFSET);
20465a2cc190SJeff Kirsher 
20475a2cc190SJeff Kirsher 	/* UAR attributes */
20485a2cc190SJeff Kirsher 
2049ab9c17a0SJack Morgenstein 	MLX4_PUT(inbox, param->uar_page_sz,	INIT_HCA_UAR_PAGE_SZ_OFFSET);
20505a2cc190SJeff Kirsher 	MLX4_PUT(inbox, param->log_uar_sz,      INIT_HCA_LOG_UAR_SZ_OFFSET);
20515a2cc190SJeff Kirsher 
20527ffdf726SOr Gerlitz 	/* set parser VXLAN attributes */
20537ffdf726SOr Gerlitz 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) {
20547ffdf726SOr Gerlitz 		u8 parser_params = 0;
20557ffdf726SOr Gerlitz 		MLX4_PUT(inbox, parser_params,	INIT_HCA_VXLAN_OFFSET);
20567ffdf726SOr Gerlitz 	}
20577ffdf726SOr Gerlitz 
20585a031086SJack Morgenstein 	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA,
20595a031086SJack Morgenstein 		       MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
20605a2cc190SJeff Kirsher 
20615a2cc190SJeff Kirsher 	if (err)
20625a2cc190SJeff Kirsher 		mlx4_err(dev, "INIT_HCA returns %d\n", err);
20635a2cc190SJeff Kirsher 
20645a2cc190SJeff Kirsher 	mlx4_free_cmd_mailbox(dev, mailbox);
20655a2cc190SJeff Kirsher 	return err;
20665a2cc190SJeff Kirsher }
20675a2cc190SJeff Kirsher 
mlx4_QUERY_HCA(struct mlx4_dev * dev,struct mlx4_init_hca_param * param)2068ab9c17a0SJack Morgenstein int mlx4_QUERY_HCA(struct mlx4_dev *dev,
2069ab9c17a0SJack Morgenstein 		   struct mlx4_init_hca_param *param)
2070ab9c17a0SJack Morgenstein {
2071ab9c17a0SJack Morgenstein 	struct mlx4_cmd_mailbox *mailbox;
2072ab9c17a0SJack Morgenstein 	__be32 *outbox;
2073a40ded60SAya Levin 	u64 qword_field;
20747b8157beSJack Morgenstein 	u32 dword_field;
2075a40ded60SAya Levin 	u16 word_field;
207608ff3235SOr Gerlitz 	u8 byte_field;
2077a40ded60SAya Levin 	int err;
20787d077cd3SMatan Barak 	static const u8 a0_dmfs_query_hw_steering[] =  {
20797d077cd3SMatan Barak 		[0] = MLX4_STEERING_DMFS_A0_DEFAULT,
20807d077cd3SMatan Barak 		[1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
20817d077cd3SMatan Barak 		[2] = MLX4_STEERING_DMFS_A0_STATIC,
20827d077cd3SMatan Barak 		[3] = MLX4_STEERING_DMFS_A0_DISABLE
20837d077cd3SMatan Barak 	};
2084ab9c17a0SJack Morgenstein 
2085ab9c17a0SJack Morgenstein #define QUERY_HCA_GLOBAL_CAPS_OFFSET	0x04
2086ddd8a6c1SEugenia Emantayev #define QUERY_HCA_CORE_CLOCK_OFFSET	0x0c
2087ab9c17a0SJack Morgenstein 
2088ab9c17a0SJack Morgenstein 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2089ab9c17a0SJack Morgenstein 	if (IS_ERR(mailbox))
2090ab9c17a0SJack Morgenstein 		return PTR_ERR(mailbox);
2091ab9c17a0SJack Morgenstein 	outbox = mailbox->buf;
2092ab9c17a0SJack Morgenstein 
2093ab9c17a0SJack Morgenstein 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
2094ab9c17a0SJack Morgenstein 			   MLX4_CMD_QUERY_HCA,
2095ab9c17a0SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_B,
2096ab9c17a0SJack Morgenstein 			   !mlx4_is_slave(dev));
2097ab9c17a0SJack Morgenstein 	if (err)
2098ab9c17a0SJack Morgenstein 		goto out;
2099ab9c17a0SJack Morgenstein 
2100ab9c17a0SJack Morgenstein 	MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET);
2101ddd8a6c1SEugenia Emantayev 	MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
2102ab9c17a0SJack Morgenstein 
2103ab9c17a0SJack Morgenstein 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
2104ab9c17a0SJack Morgenstein 
2105a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
2106a40ded60SAya Levin 	param->qpc_base = qword_field & ~((u64)0x1f);
2107a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
2108a40ded60SAya Levin 	param->log_num_qps = byte_field & 0x1f;
2109a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
2110a40ded60SAya Levin 	param->srqc_base = qword_field & ~((u64)0x1f);
2111a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
2112a40ded60SAya Levin 	param->log_num_srqs = byte_field & 0x1f;
2113a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
2114a40ded60SAya Levin 	param->cqc_base = qword_field & ~((u64)0x1f);
2115a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
2116a40ded60SAya Levin 	param->log_num_cqs = byte_field & 0x1f;
2117a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
2118a40ded60SAya Levin 	param->altc_base = qword_field;
2119a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
2120a40ded60SAya Levin 	param->auxc_base = qword_field;
2121a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
2122a40ded60SAya Levin 	param->eqc_base = qword_field & ~((u64)0x1f);
2123a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
2124a40ded60SAya Levin 	param->log_num_eqs = byte_field & 0x1f;
2125a40ded60SAya Levin 	MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
2126a40ded60SAya Levin 	param->num_sys_eqs = word_field & 0xfff;
2127a40ded60SAya Levin 	MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
2128a40ded60SAya Levin 	param->rdmarc_base = qword_field & ~((u64)0x1f);
2129a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
2130a40ded60SAya Levin 	param->log_rd_per_qp = byte_field & 0x7;
2131ab9c17a0SJack Morgenstein 
21327b8157beSJack Morgenstein 	MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
21337b8157beSJack Morgenstein 	if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
21347b8157beSJack Morgenstein 		param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
21357b8157beSJack Morgenstein 	} else {
21367b8157beSJack Morgenstein 		MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET);
21377b8157beSJack Morgenstein 		if (byte_field & 0x8)
21387b8157beSJack Morgenstein 			param->steering_mode = MLX4_STEERING_MODE_B0;
21397b8157beSJack Morgenstein 		else
21407b8157beSJack Morgenstein 			param->steering_mode = MLX4_STEERING_MODE_A0;
21417b8157beSJack Morgenstein 	}
2142802f42a8SIdo Shamay 
2143802f42a8SIdo Shamay 	if (dword_field & (1 << 13))
2144802f42a8SIdo Shamay 		param->rss_ip_frags = 1;
2145802f42a8SIdo Shamay 
21460ff1fb65SHadar Hen Zion 	/* steering attributes */
21477b8157beSJack Morgenstein 	if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
21480ff1fb65SHadar Hen Zion 		MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
2149a40ded60SAya Levin 		MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
2150a40ded60SAya Levin 		param->log_mc_entry_sz = byte_field & 0x1f;
2151a40ded60SAya Levin 		MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
2152a40ded60SAya Levin 		param->log_mc_table_sz = byte_field & 0x1f;
2153a40ded60SAya Levin 		MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
21547d077cd3SMatan Barak 		param->dmfs_high_steer_mode =
21557d077cd3SMatan Barak 			a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
21560ff1fb65SHadar Hen Zion 	} else {
2157ab9c17a0SJack Morgenstein 		MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
2158a40ded60SAya Levin 		MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
2159a40ded60SAya Levin 		param->log_mc_entry_sz = byte_field & 0x1f;
2160a40ded60SAya Levin 		MLX4_GET(byte_field,  outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
2161a40ded60SAya Levin 		param->log_mc_hash_sz = byte_field & 0x1f;
2162a40ded60SAya Levin 		MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
2163a40ded60SAya Levin 		param->log_mc_table_sz = byte_field & 0x1f;
21640ff1fb65SHadar Hen Zion 	}
2165ab9c17a0SJack Morgenstein 
216608ff3235SOr Gerlitz 	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
216708ff3235SOr Gerlitz 	MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS);
216808ff3235SOr Gerlitz 	if (byte_field & 0x20) /* 64-bytes eqe enabled */
216908ff3235SOr Gerlitz 		param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED;
217008ff3235SOr Gerlitz 	if (byte_field & 0x40) /* 64-bytes cqe enabled */
217108ff3235SOr Gerlitz 		param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED;
217208ff3235SOr Gerlitz 
217377507aa2SIdo Shamay 	/* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */
217477507aa2SIdo Shamay 	MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_STRIDE_OFFSET);
217577507aa2SIdo Shamay 	if (byte_field) {
2176c3f2511fSIdo Shamay 		param->dev_cap_enabled |= MLX4_DEV_CAP_EQE_STRIDE_ENABLED;
2177c3f2511fSIdo Shamay 		param->dev_cap_enabled |= MLX4_DEV_CAP_CQE_STRIDE_ENABLED;
217877507aa2SIdo Shamay 		param->cqe_size = 1 << ((byte_field &
217977507aa2SIdo Shamay 					 MLX4_CQE_SIZE_MASK_STRIDE) + 5);
218077507aa2SIdo Shamay 		param->eqe_size = 1 << (((byte_field &
218177507aa2SIdo Shamay 					  MLX4_EQE_SIZE_MASK_STRIDE) >> 4) + 5);
218277507aa2SIdo Shamay 	}
218377507aa2SIdo Shamay 
2184ab9c17a0SJack Morgenstein 	/* TPT attributes */
2185ab9c17a0SJack Morgenstein 
2186ab9c17a0SJack Morgenstein 	MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
2187a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
2188a40ded60SAya Levin 	param->mw_enabled = byte_field >> 7;
2189a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
2190a40ded60SAya Levin 	param->log_mpt_sz = byte_field & 0x3f;
2191ab9c17a0SJack Morgenstein 	MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
2192ab9c17a0SJack Morgenstein 	MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
2193ab9c17a0SJack Morgenstein 
2194ab9c17a0SJack Morgenstein 	/* UAR attributes */
2195ab9c17a0SJack Morgenstein 
2196ab9c17a0SJack Morgenstein 	MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
2197a40ded60SAya Levin 	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
2198a40ded60SAya Levin 	param->log_uar_sz = byte_field & 0xf;
2199ab9c17a0SJack Morgenstein 
220077fc29c4SHadar Hen Zion 	/* phv_check enable */
220177fc29c4SHadar Hen Zion 	MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
220277fc29c4SHadar Hen Zion 	if (byte_field & 0x2)
220377fc29c4SHadar Hen Zion 		param->phv_check_en = 1;
2204ab9c17a0SJack Morgenstein out:
2205ab9c17a0SJack Morgenstein 	mlx4_free_cmd_mailbox(dev, mailbox);
2206ab9c17a0SJack Morgenstein 
2207ab9c17a0SJack Morgenstein 	return err;
2208ab9c17a0SJack Morgenstein }
2209ab9c17a0SJack Morgenstein 
mlx4_hca_core_clock_update(struct mlx4_dev * dev)22106d6e996cSMajd Dibbiny static int mlx4_hca_core_clock_update(struct mlx4_dev *dev)
22116d6e996cSMajd Dibbiny {
22126d6e996cSMajd Dibbiny 	struct mlx4_cmd_mailbox *mailbox;
22136d6e996cSMajd Dibbiny 	__be32 *outbox;
22146d6e996cSMajd Dibbiny 	int err;
22156d6e996cSMajd Dibbiny 
22166d6e996cSMajd Dibbiny 	mailbox = mlx4_alloc_cmd_mailbox(dev);
22176d6e996cSMajd Dibbiny 	if (IS_ERR(mailbox)) {
22186d6e996cSMajd Dibbiny 		mlx4_warn(dev, "hca_core_clock mailbox allocation failed\n");
22196d6e996cSMajd Dibbiny 		return PTR_ERR(mailbox);
22206d6e996cSMajd Dibbiny 	}
22216d6e996cSMajd Dibbiny 	outbox = mailbox->buf;
22226d6e996cSMajd Dibbiny 
22236d6e996cSMajd Dibbiny 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
22246d6e996cSMajd Dibbiny 			   MLX4_CMD_QUERY_HCA,
22256d6e996cSMajd Dibbiny 			   MLX4_CMD_TIME_CLASS_B,
22266d6e996cSMajd Dibbiny 			   !mlx4_is_slave(dev));
22276d6e996cSMajd Dibbiny 	if (err) {
22286d6e996cSMajd Dibbiny 		mlx4_warn(dev, "hca_core_clock update failed\n");
22296d6e996cSMajd Dibbiny 		goto out;
22306d6e996cSMajd Dibbiny 	}
22316d6e996cSMajd Dibbiny 
22326d6e996cSMajd Dibbiny 	MLX4_GET(dev->caps.hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
22336d6e996cSMajd Dibbiny 
22346d6e996cSMajd Dibbiny out:
22356d6e996cSMajd Dibbiny 	mlx4_free_cmd_mailbox(dev, mailbox);
22366d6e996cSMajd Dibbiny 
22376d6e996cSMajd Dibbiny 	return err;
22386d6e996cSMajd Dibbiny }
22396d6e996cSMajd Dibbiny 
2240980e9001SJack Morgenstein /* for IB-type ports only in SRIOV mode. Checks that both proxy QP0
2241980e9001SJack Morgenstein  * and real QP0 are active, so that the paravirtualized QP0 is ready
2242980e9001SJack Morgenstein  * to operate */
check_qp0_state(struct mlx4_dev * dev,int function,int port)2243980e9001SJack Morgenstein static int check_qp0_state(struct mlx4_dev *dev, int function, int port)
2244980e9001SJack Morgenstein {
2245980e9001SJack Morgenstein 	struct mlx4_priv *priv = mlx4_priv(dev);
2246980e9001SJack Morgenstein 	/* irrelevant if not infiniband */
2247980e9001SJack Morgenstein 	if (priv->mfunc.master.qp0_state[port].proxy_qp0_active &&
2248980e9001SJack Morgenstein 	    priv->mfunc.master.qp0_state[port].qp0_active)
2249980e9001SJack Morgenstein 		return 1;
2250980e9001SJack Morgenstein 	return 0;
2251980e9001SJack Morgenstein }
2252980e9001SJack Morgenstein 
mlx4_INIT_PORT_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)22535cc914f1SMarcel Apfelbaum int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
22545cc914f1SMarcel Apfelbaum 			   struct mlx4_vhcr *vhcr,
22555cc914f1SMarcel Apfelbaum 			   struct mlx4_cmd_mailbox *inbox,
22565cc914f1SMarcel Apfelbaum 			   struct mlx4_cmd_mailbox *outbox,
22575cc914f1SMarcel Apfelbaum 			   struct mlx4_cmd_info *cmd)
22585cc914f1SMarcel Apfelbaum {
22595cc914f1SMarcel Apfelbaum 	struct mlx4_priv *priv = mlx4_priv(dev);
2260449fc488SMatan Barak 	int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier);
22615cc914f1SMarcel Apfelbaum 	int err;
22625cc914f1SMarcel Apfelbaum 
2263449fc488SMatan Barak 	if (port < 0)
2264449fc488SMatan Barak 		return -EINVAL;
2265449fc488SMatan Barak 
22665cc914f1SMarcel Apfelbaum 	if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port))
22675cc914f1SMarcel Apfelbaum 		return 0;
22685cc914f1SMarcel Apfelbaum 
2269980e9001SJack Morgenstein 	if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
22705cc914f1SMarcel Apfelbaum 		/* Enable port only if it was previously disabled */
22715cc914f1SMarcel Apfelbaum 		if (!priv->mfunc.master.init_port_ref[port]) {
22725cc914f1SMarcel Apfelbaum 			err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
22735cc914f1SMarcel Apfelbaum 				       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
22745cc914f1SMarcel Apfelbaum 			if (err)
22755cc914f1SMarcel Apfelbaum 				return err;
22765cc914f1SMarcel Apfelbaum 		}
22778bac9edeSJack Morgenstein 		priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
2278980e9001SJack Morgenstein 	} else {
2279980e9001SJack Morgenstein 		if (slave == mlx4_master_func_num(dev)) {
2280980e9001SJack Morgenstein 			if (check_qp0_state(dev, slave, port) &&
2281980e9001SJack Morgenstein 			    !priv->mfunc.master.qp0_state[port].port_active) {
2282980e9001SJack Morgenstein 				err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
2283980e9001SJack Morgenstein 					       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
2284980e9001SJack Morgenstein 				if (err)
2285980e9001SJack Morgenstein 					return err;
2286980e9001SJack Morgenstein 				priv->mfunc.master.qp0_state[port].port_active = 1;
2287980e9001SJack Morgenstein 				priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
2288980e9001SJack Morgenstein 			}
2289980e9001SJack Morgenstein 		} else
2290980e9001SJack Morgenstein 			priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
2291980e9001SJack Morgenstein 	}
22925cc914f1SMarcel Apfelbaum 	++priv->mfunc.master.init_port_ref[port];
22935cc914f1SMarcel Apfelbaum 	return 0;
22945cc914f1SMarcel Apfelbaum }
22955cc914f1SMarcel Apfelbaum 
mlx4_INIT_PORT(struct mlx4_dev * dev,int port)22965a2cc190SJeff Kirsher int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
22975a2cc190SJeff Kirsher {
22985a2cc190SJeff Kirsher 	struct mlx4_cmd_mailbox *mailbox;
22995a2cc190SJeff Kirsher 	u32 *inbox;
23005a2cc190SJeff Kirsher 	int err;
23015a2cc190SJeff Kirsher 	u32 flags;
23025a2cc190SJeff Kirsher 	u16 field;
23035a2cc190SJeff Kirsher 
23045a2cc190SJeff Kirsher 	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
23055a2cc190SJeff Kirsher #define INIT_PORT_IN_SIZE          256
23065a2cc190SJeff Kirsher #define INIT_PORT_FLAGS_OFFSET     0x00
23075a2cc190SJeff Kirsher #define INIT_PORT_FLAG_SIG         (1 << 18)
23085a2cc190SJeff Kirsher #define INIT_PORT_FLAG_NG          (1 << 17)
23095a2cc190SJeff Kirsher #define INIT_PORT_FLAG_G0          (1 << 16)
23105a2cc190SJeff Kirsher #define INIT_PORT_VL_SHIFT         4
23115a2cc190SJeff Kirsher #define INIT_PORT_PORT_WIDTH_SHIFT 8
23125a2cc190SJeff Kirsher #define INIT_PORT_MTU_OFFSET       0x04
23135a2cc190SJeff Kirsher #define INIT_PORT_MAX_GID_OFFSET   0x06
23145a2cc190SJeff Kirsher #define INIT_PORT_MAX_PKEY_OFFSET  0x0a
23155a2cc190SJeff Kirsher #define INIT_PORT_GUID0_OFFSET     0x10
23165a2cc190SJeff Kirsher #define INIT_PORT_NODE_GUID_OFFSET 0x18
23175a2cc190SJeff Kirsher #define INIT_PORT_SI_GUID_OFFSET   0x20
23185a2cc190SJeff Kirsher 
23195a2cc190SJeff Kirsher 		mailbox = mlx4_alloc_cmd_mailbox(dev);
23205a2cc190SJeff Kirsher 		if (IS_ERR(mailbox))
23215a2cc190SJeff Kirsher 			return PTR_ERR(mailbox);
23225a2cc190SJeff Kirsher 		inbox = mailbox->buf;
23235a2cc190SJeff Kirsher 
23245a2cc190SJeff Kirsher 		flags = 0;
23255a2cc190SJeff Kirsher 		flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT;
23265a2cc190SJeff Kirsher 		flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
23275a2cc190SJeff Kirsher 		MLX4_PUT(inbox, flags,		  INIT_PORT_FLAGS_OFFSET);
23285a2cc190SJeff Kirsher 
23295a2cc190SJeff Kirsher 		field = 128 << dev->caps.ib_mtu_cap[port];
23305a2cc190SJeff Kirsher 		MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
23315a2cc190SJeff Kirsher 		field = dev->caps.gid_table_len[port];
23325a2cc190SJeff Kirsher 		MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
23335a2cc190SJeff Kirsher 		field = dev->caps.pkey_table_len[port];
23345a2cc190SJeff Kirsher 		MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET);
23355a2cc190SJeff Kirsher 
23365a2cc190SJeff Kirsher 		err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
2337f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
23385a2cc190SJeff Kirsher 
23395a2cc190SJeff Kirsher 		mlx4_free_cmd_mailbox(dev, mailbox);
23405a2cc190SJeff Kirsher 	} else
23415a2cc190SJeff Kirsher 		err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
2342f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
23435a2cc190SJeff Kirsher 
23446d6e996cSMajd Dibbiny 	if (!err)
23456d6e996cSMajd Dibbiny 		mlx4_hca_core_clock_update(dev);
23466d6e996cSMajd Dibbiny 
23475a2cc190SJeff Kirsher 	return err;
23485a2cc190SJeff Kirsher }
23495a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_INIT_PORT);
23505a2cc190SJeff Kirsher 
mlx4_CLOSE_PORT_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)23515cc914f1SMarcel Apfelbaum int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave,
23525cc914f1SMarcel Apfelbaum 			    struct mlx4_vhcr *vhcr,
23535cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *inbox,
23545cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_mailbox *outbox,
23555cc914f1SMarcel Apfelbaum 			    struct mlx4_cmd_info *cmd)
23565cc914f1SMarcel Apfelbaum {
23575cc914f1SMarcel Apfelbaum 	struct mlx4_priv *priv = mlx4_priv(dev);
2358449fc488SMatan Barak 	int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier);
23595cc914f1SMarcel Apfelbaum 	int err;
23605cc914f1SMarcel Apfelbaum 
2361449fc488SMatan Barak 	if (port < 0)
2362449fc488SMatan Barak 		return -EINVAL;
2363449fc488SMatan Barak 
23645cc914f1SMarcel Apfelbaum 	if (!(priv->mfunc.master.slave_state[slave].init_port_mask &
23655cc914f1SMarcel Apfelbaum 	    (1 << port)))
23665cc914f1SMarcel Apfelbaum 		return 0;
23675cc914f1SMarcel Apfelbaum 
2368980e9001SJack Morgenstein 	if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
23695cc914f1SMarcel Apfelbaum 		if (priv->mfunc.master.init_port_ref[port] == 1) {
2370980e9001SJack Morgenstein 			err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
23715a031086SJack Morgenstein 				       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
23725cc914f1SMarcel Apfelbaum 			if (err)
23735cc914f1SMarcel Apfelbaum 				return err;
23745cc914f1SMarcel Apfelbaum 		}
23755cc914f1SMarcel Apfelbaum 		priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
2376980e9001SJack Morgenstein 	} else {
2377980e9001SJack Morgenstein 		/* infiniband port */
2378980e9001SJack Morgenstein 		if (slave == mlx4_master_func_num(dev)) {
2379980e9001SJack Morgenstein 			if (!priv->mfunc.master.qp0_state[port].qp0_active &&
2380980e9001SJack Morgenstein 			    priv->mfunc.master.qp0_state[port].port_active) {
2381980e9001SJack Morgenstein 				err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
23825a031086SJack Morgenstein 					       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
2383980e9001SJack Morgenstein 				if (err)
2384980e9001SJack Morgenstein 					return err;
2385980e9001SJack Morgenstein 				priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
2386980e9001SJack Morgenstein 				priv->mfunc.master.qp0_state[port].port_active = 0;
2387980e9001SJack Morgenstein 			}
2388980e9001SJack Morgenstein 		} else
2389980e9001SJack Morgenstein 			priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
2390980e9001SJack Morgenstein 	}
23915cc914f1SMarcel Apfelbaum 	--priv->mfunc.master.init_port_ref[port];
23925cc914f1SMarcel Apfelbaum 	return 0;
23935cc914f1SMarcel Apfelbaum }
23945cc914f1SMarcel Apfelbaum 
mlx4_CLOSE_PORT(struct mlx4_dev * dev,int port)23955a2cc190SJeff Kirsher int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port)
23965a2cc190SJeff Kirsher {
23975a031086SJack Morgenstein 	return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
23985a031086SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
23995a2cc190SJeff Kirsher }
24005a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT);
24015a2cc190SJeff Kirsher 
mlx4_CLOSE_HCA(struct mlx4_dev * dev,int panic)24025a2cc190SJeff Kirsher int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic)
24035a2cc190SJeff Kirsher {
24045a031086SJack Morgenstein 	return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA,
24055a031086SJack Morgenstein 			MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
24065a2cc190SJeff Kirsher }
24075a2cc190SJeff Kirsher 
2408d18f141aSOr Gerlitz struct mlx4_config_dev {
2409d18f141aSOr Gerlitz 	__be32	update_flags;
2410d475c95bSMatan Barak 	__be32	rsvd1[3];
2411d18f141aSOr Gerlitz 	__be16	vxlan_udp_dport;
2412d18f141aSOr Gerlitz 	__be16	rsvd2;
2413fca83006SMoni Shoua 	__be16  roce_v2_entropy;
2414fca83006SMoni Shoua 	__be16  roce_v2_udp_dport;
241559e14e32SMoni Shoua 	__be32	roce_flags;
241659e14e32SMoni Shoua 	__be32	rsvd4[25];
241759e14e32SMoni Shoua 	__be16	rsvd5;
241859e14e32SMoni Shoua 	u8	rsvd6;
2419d475c95bSMatan Barak 	u8	rx_checksum_val;
2420d18f141aSOr Gerlitz };
2421d18f141aSOr Gerlitz 
2422d18f141aSOr Gerlitz #define MLX4_VXLAN_UDP_DPORT (1 << 0)
2423fca83006SMoni Shoua #define MLX4_ROCE_V2_UDP_DPORT BIT(3)
242459e14e32SMoni Shoua #define MLX4_DISABLE_RX_PORT BIT(18)
2425d18f141aSOr Gerlitz 
mlx4_CONFIG_DEV_set(struct mlx4_dev * dev,struct mlx4_config_dev * config_dev)2426d475c95bSMatan Barak static int mlx4_CONFIG_DEV_set(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
2427d18f141aSOr Gerlitz {
2428d18f141aSOr Gerlitz 	int err;
2429d18f141aSOr Gerlitz 	struct mlx4_cmd_mailbox *mailbox;
2430d18f141aSOr Gerlitz 
2431d18f141aSOr Gerlitz 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2432d18f141aSOr Gerlitz 	if (IS_ERR(mailbox))
2433d18f141aSOr Gerlitz 		return PTR_ERR(mailbox);
2434d18f141aSOr Gerlitz 
2435d18f141aSOr Gerlitz 	memcpy(mailbox->buf, config_dev, sizeof(*config_dev));
2436d18f141aSOr Gerlitz 
2437d18f141aSOr Gerlitz 	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_CONFIG_DEV,
2438d18f141aSOr Gerlitz 		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
2439d18f141aSOr Gerlitz 
2440d18f141aSOr Gerlitz 	mlx4_free_cmd_mailbox(dev, mailbox);
2441d18f141aSOr Gerlitz 	return err;
2442d18f141aSOr Gerlitz }
2443d18f141aSOr Gerlitz 
mlx4_CONFIG_DEV_get(struct mlx4_dev * dev,struct mlx4_config_dev * config_dev)2444d475c95bSMatan Barak static int mlx4_CONFIG_DEV_get(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
2445d475c95bSMatan Barak {
2446d475c95bSMatan Barak 	int err;
2447d475c95bSMatan Barak 	struct mlx4_cmd_mailbox *mailbox;
2448d475c95bSMatan Barak 
2449d475c95bSMatan Barak 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2450d475c95bSMatan Barak 	if (IS_ERR(mailbox))
2451d475c95bSMatan Barak 		return PTR_ERR(mailbox);
2452d475c95bSMatan Barak 
2453d475c95bSMatan Barak 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 1, MLX4_CMD_CONFIG_DEV,
2454d475c95bSMatan Barak 			   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
2455d475c95bSMatan Barak 
2456d475c95bSMatan Barak 	if (!err)
2457d475c95bSMatan Barak 		memcpy(config_dev, mailbox->buf, sizeof(*config_dev));
2458d475c95bSMatan Barak 
2459d475c95bSMatan Barak 	mlx4_free_cmd_mailbox(dev, mailbox);
2460d475c95bSMatan Barak 	return err;
2461d475c95bSMatan Barak }
2462d475c95bSMatan Barak 
2463d475c95bSMatan Barak /* Conversion between the HW values and the actual functionality.
2464d475c95bSMatan Barak  * The value represented by the array index,
2465d475c95bSMatan Barak  * and the functionality determined by the flags.
2466d475c95bSMatan Barak  */
2467d475c95bSMatan Barak static const u8 config_dev_csum_flags[] = {
2468d475c95bSMatan Barak 	[0] =	0,
2469d475c95bSMatan Barak 	[1] =	MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP,
2470d475c95bSMatan Barak 	[2] =	MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP	|
2471d475c95bSMatan Barak 		MLX4_RX_CSUM_MODE_L4,
2472d475c95bSMatan Barak 	[3] =	MLX4_RX_CSUM_MODE_L4			|
2473d475c95bSMatan Barak 		MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP	|
2474d475c95bSMatan Barak 		MLX4_RX_CSUM_MODE_MULTI_VLAN
2475d475c95bSMatan Barak };
2476d475c95bSMatan Barak 
mlx4_config_dev_retrieval(struct mlx4_dev * dev,struct mlx4_config_dev_params * params)2477d475c95bSMatan Barak int mlx4_config_dev_retrieval(struct mlx4_dev *dev,
2478d475c95bSMatan Barak 			      struct mlx4_config_dev_params *params)
2479d475c95bSMatan Barak {
24806af0a52fSMaor Gottlieb 	struct mlx4_config_dev config_dev = {0};
2481d475c95bSMatan Barak 	int err;
2482d475c95bSMatan Barak 	u8 csum_mask;
2483d475c95bSMatan Barak 
2484d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_MASK			0x7
2485d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET	0
2486d475c95bSMatan Barak #define CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET	4
2487d475c95bSMatan Barak 
2488d475c95bSMatan Barak 	if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV))
2489423b3aecSOr Gerlitz 		return -EOPNOTSUPP;
2490d475c95bSMatan Barak 
2491d475c95bSMatan Barak 	err = mlx4_CONFIG_DEV_get(dev, &config_dev);
2492d475c95bSMatan Barak 	if (err)
2493d475c95bSMatan Barak 		return err;
2494d475c95bSMatan Barak 
2495d475c95bSMatan Barak 	csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET) &
2496d475c95bSMatan Barak 			CONFIG_DEV_RX_CSUM_MODE_MASK;
2497d475c95bSMatan Barak 
2498691223ecSThomas Meyer 	if (csum_mask >= ARRAY_SIZE(config_dev_csum_flags))
2499d475c95bSMatan Barak 		return -EINVAL;
2500d475c95bSMatan Barak 	params->rx_csum_flags_port_1 = config_dev_csum_flags[csum_mask];
2501d475c95bSMatan Barak 
2502d475c95bSMatan Barak 	csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET) &
2503d475c95bSMatan Barak 			CONFIG_DEV_RX_CSUM_MODE_MASK;
2504d475c95bSMatan Barak 
2505691223ecSThomas Meyer 	if (csum_mask >= ARRAY_SIZE(config_dev_csum_flags))
2506d475c95bSMatan Barak 		return -EINVAL;
2507d475c95bSMatan Barak 	params->rx_csum_flags_port_2 = config_dev_csum_flags[csum_mask];
2508d475c95bSMatan Barak 
2509d475c95bSMatan Barak 	params->vxlan_udp_dport = be16_to_cpu(config_dev.vxlan_udp_dport);
2510d475c95bSMatan Barak 
2511d475c95bSMatan Barak 	return 0;
2512d475c95bSMatan Barak }
2513d475c95bSMatan Barak EXPORT_SYMBOL_GPL(mlx4_config_dev_retrieval);
2514d475c95bSMatan Barak 
mlx4_config_vxlan_port(struct mlx4_dev * dev,__be16 udp_port)2515d18f141aSOr Gerlitz int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port)
2516d18f141aSOr Gerlitz {
2517d18f141aSOr Gerlitz 	struct mlx4_config_dev config_dev;
2518d18f141aSOr Gerlitz 
2519d18f141aSOr Gerlitz 	memset(&config_dev, 0, sizeof(config_dev));
2520d18f141aSOr Gerlitz 	config_dev.update_flags    = cpu_to_be32(MLX4_VXLAN_UDP_DPORT);
2521d18f141aSOr Gerlitz 	config_dev.vxlan_udp_dport = udp_port;
2522d18f141aSOr Gerlitz 
2523d475c95bSMatan Barak 	return mlx4_CONFIG_DEV_set(dev, &config_dev);
2524d18f141aSOr Gerlitz }
2525d18f141aSOr Gerlitz EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port);
2526d18f141aSOr Gerlitz 
252759e14e32SMoni Shoua #define CONFIG_DISABLE_RX_PORT BIT(15)
mlx4_disable_rx_port_check(struct mlx4_dev * dev,bool dis)252859e14e32SMoni Shoua int mlx4_disable_rx_port_check(struct mlx4_dev *dev, bool dis)
252959e14e32SMoni Shoua {
253059e14e32SMoni Shoua 	struct mlx4_config_dev config_dev;
253159e14e32SMoni Shoua 
253259e14e32SMoni Shoua 	memset(&config_dev, 0, sizeof(config_dev));
253359e14e32SMoni Shoua 	config_dev.update_flags = cpu_to_be32(MLX4_DISABLE_RX_PORT);
253459e14e32SMoni Shoua 	if (dis)
253559e14e32SMoni Shoua 		config_dev.roce_flags =
253659e14e32SMoni Shoua 			cpu_to_be32(CONFIG_DISABLE_RX_PORT);
253759e14e32SMoni Shoua 
253859e14e32SMoni Shoua 	return mlx4_CONFIG_DEV_set(dev, &config_dev);
253959e14e32SMoni Shoua }
254059e14e32SMoni Shoua 
mlx4_config_roce_v2_port(struct mlx4_dev * dev,u16 udp_port)2541fca83006SMoni Shoua int mlx4_config_roce_v2_port(struct mlx4_dev *dev, u16 udp_port)
2542fca83006SMoni Shoua {
2543fca83006SMoni Shoua 	struct mlx4_config_dev config_dev;
2544fca83006SMoni Shoua 
2545fca83006SMoni Shoua 	memset(&config_dev, 0, sizeof(config_dev));
2546fca83006SMoni Shoua 	config_dev.update_flags    = cpu_to_be32(MLX4_ROCE_V2_UDP_DPORT);
2547fca83006SMoni Shoua 	config_dev.roce_v2_udp_dport = cpu_to_be16(udp_port);
2548fca83006SMoni Shoua 
2549fca83006SMoni Shoua 	return mlx4_CONFIG_DEV_set(dev, &config_dev);
2550fca83006SMoni Shoua }
2551fca83006SMoni Shoua EXPORT_SYMBOL_GPL(mlx4_config_roce_v2_port);
2552fca83006SMoni Shoua 
mlx4_virt2phy_port_map(struct mlx4_dev * dev,u32 port1,u32 port2)255359e14e32SMoni Shoua int mlx4_virt2phy_port_map(struct mlx4_dev *dev, u32 port1, u32 port2)
255459e14e32SMoni Shoua {
255559e14e32SMoni Shoua 	struct mlx4_cmd_mailbox *mailbox;
255659e14e32SMoni Shoua 	struct {
255759e14e32SMoni Shoua 		__be32 v_port1;
255859e14e32SMoni Shoua 		__be32 v_port2;
255959e14e32SMoni Shoua 	} *v2p;
256059e14e32SMoni Shoua 	int err;
256159e14e32SMoni Shoua 
256259e14e32SMoni Shoua 	mailbox = mlx4_alloc_cmd_mailbox(dev);
256359e14e32SMoni Shoua 	if (IS_ERR(mailbox))
256459e14e32SMoni Shoua 		return -ENOMEM;
256559e14e32SMoni Shoua 
256659e14e32SMoni Shoua 	v2p = mailbox->buf;
256759e14e32SMoni Shoua 	v2p->v_port1 = cpu_to_be32(port1);
256859e14e32SMoni Shoua 	v2p->v_port2 = cpu_to_be32(port2);
256959e14e32SMoni Shoua 
257059e14e32SMoni Shoua 	err = mlx4_cmd(dev, mailbox->dma, 0,
257159e14e32SMoni Shoua 		       MLX4_SET_PORT_VIRT2PHY, MLX4_CMD_VIRT_PORT_MAP,
257259e14e32SMoni Shoua 		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
257359e14e32SMoni Shoua 
257459e14e32SMoni Shoua 	mlx4_free_cmd_mailbox(dev, mailbox);
257559e14e32SMoni Shoua 	return err;
257659e14e32SMoni Shoua }
257759e14e32SMoni Shoua 
2578d18f141aSOr Gerlitz 
mlx4_SET_ICM_SIZE(struct mlx4_dev * dev,u64 icm_size,u64 * aux_pages)25795a2cc190SJeff Kirsher int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages)
25805a2cc190SJeff Kirsher {
25815a2cc190SJeff Kirsher 	int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0,
25825a2cc190SJeff Kirsher 			       MLX4_CMD_SET_ICM_SIZE,
2583f9baff50SJack Morgenstein 			       MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
25845a2cc190SJeff Kirsher 	if (ret)
25855a2cc190SJeff Kirsher 		return ret;
25865a2cc190SJeff Kirsher 
25875a2cc190SJeff Kirsher 	/*
25885a2cc190SJeff Kirsher 	 * Round up number of system pages needed in case
25895a2cc190SJeff Kirsher 	 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
25905a2cc190SJeff Kirsher 	 */
25915a2cc190SJeff Kirsher 	*aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >>
25925a2cc190SJeff Kirsher 		(PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT);
25935a2cc190SJeff Kirsher 
25945a2cc190SJeff Kirsher 	return 0;
25955a2cc190SJeff Kirsher }
25965a2cc190SJeff Kirsher 
mlx4_NOP(struct mlx4_dev * dev)25975a2cc190SJeff Kirsher int mlx4_NOP(struct mlx4_dev *dev)
25985a2cc190SJeff Kirsher {
25995a2cc190SJeff Kirsher 	/* Input modifier of 0x1f means "finish as soon as possible." */
26005a031086SJack Morgenstein 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, MLX4_CMD_TIME_CLASS_A,
26015a031086SJack Morgenstein 			MLX4_CMD_NATIVE);
26025a2cc190SJeff Kirsher }
26035a2cc190SJeff Kirsher 
mlx4_query_diag_counters(struct mlx4_dev * dev,u8 op_modifier,const u32 offset[],u32 value[],size_t array_len,u8 port)2604bfaf3168SMark Bloch int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
2605bfaf3168SMark Bloch 			     const u32 offset[],
2606bfaf3168SMark Bloch 			     u32 value[], size_t array_len, u8 port)
2607bfaf3168SMark Bloch {
2608bfaf3168SMark Bloch 	struct mlx4_cmd_mailbox *mailbox;
2609bfaf3168SMark Bloch 	u32 *outbox;
2610bfaf3168SMark Bloch 	size_t i;
2611bfaf3168SMark Bloch 	int ret;
2612bfaf3168SMark Bloch 
2613bfaf3168SMark Bloch 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2614bfaf3168SMark Bloch 	if (IS_ERR(mailbox))
2615bfaf3168SMark Bloch 		return PTR_ERR(mailbox);
2616bfaf3168SMark Bloch 
2617bfaf3168SMark Bloch 	outbox = mailbox->buf;
2618bfaf3168SMark Bloch 
2619bfaf3168SMark Bloch 	ret = mlx4_cmd_box(dev, 0, mailbox->dma, port, op_modifier,
2620bfaf3168SMark Bloch 			   MLX4_CMD_DIAG_RPRT, MLX4_CMD_TIME_CLASS_A,
2621bfaf3168SMark Bloch 			   MLX4_CMD_NATIVE);
2622bfaf3168SMark Bloch 	if (ret)
2623bfaf3168SMark Bloch 		goto out;
2624bfaf3168SMark Bloch 
2625bfaf3168SMark Bloch 	for (i = 0; i < array_len; i++) {
2626bfaf3168SMark Bloch 		if (offset[i] > MLX4_MAILBOX_SIZE) {
2627bfaf3168SMark Bloch 			ret = -EINVAL;
2628bfaf3168SMark Bloch 			goto out;
2629bfaf3168SMark Bloch 		}
2630bfaf3168SMark Bloch 
2631bfaf3168SMark Bloch 		MLX4_GET(value[i], outbox, offset[i]);
2632bfaf3168SMark Bloch 	}
2633bfaf3168SMark Bloch 
2634bfaf3168SMark Bloch out:
2635bfaf3168SMark Bloch 	mlx4_free_cmd_mailbox(dev, mailbox);
2636bfaf3168SMark Bloch 	return ret;
2637bfaf3168SMark Bloch }
2638bfaf3168SMark Bloch EXPORT_SYMBOL(mlx4_query_diag_counters);
2639bfaf3168SMark Bloch 
mlx4_get_phys_port_id(struct mlx4_dev * dev)26408e1a28e8SHadar Hen Zion int mlx4_get_phys_port_id(struct mlx4_dev *dev)
26418e1a28e8SHadar Hen Zion {
26428e1a28e8SHadar Hen Zion 	u8 port;
26438e1a28e8SHadar Hen Zion 	u32 *outbox;
26448e1a28e8SHadar Hen Zion 	struct mlx4_cmd_mailbox *mailbox;
26458e1a28e8SHadar Hen Zion 	u32 in_mod;
26468e1a28e8SHadar Hen Zion 	u32 guid_hi, guid_lo;
26478e1a28e8SHadar Hen Zion 	int err, ret = 0;
26488e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_PORT_OFFSET 8
26498e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_H	 0X14
26508e1a28e8SHadar Hen Zion #define MOD_STAT_CFG_GUID_L	 0X1c
26518e1a28e8SHadar Hen Zion 
26528e1a28e8SHadar Hen Zion 	mailbox = mlx4_alloc_cmd_mailbox(dev);
26538e1a28e8SHadar Hen Zion 	if (IS_ERR(mailbox))
26548e1a28e8SHadar Hen Zion 		return PTR_ERR(mailbox);
26558e1a28e8SHadar Hen Zion 	outbox = mailbox->buf;
26568e1a28e8SHadar Hen Zion 
26578e1a28e8SHadar Hen Zion 	for (port = 1; port <= dev->caps.num_ports; port++) {
26588e1a28e8SHadar Hen Zion 		in_mod = port << MOD_STAT_CFG_PORT_OFFSET;
26598e1a28e8SHadar Hen Zion 		err = mlx4_cmd_box(dev, 0, mailbox->dma, in_mod, 0x2,
26608e1a28e8SHadar Hen Zion 				   MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A,
26618e1a28e8SHadar Hen Zion 				   MLX4_CMD_NATIVE);
26628e1a28e8SHadar Hen Zion 		if (err) {
26638e1a28e8SHadar Hen Zion 			mlx4_err(dev, "Fail to get port %d uplink guid\n",
26648e1a28e8SHadar Hen Zion 				 port);
26658e1a28e8SHadar Hen Zion 			ret = err;
26668e1a28e8SHadar Hen Zion 		} else {
26678e1a28e8SHadar Hen Zion 			MLX4_GET(guid_hi, outbox, MOD_STAT_CFG_GUID_H);
26688e1a28e8SHadar Hen Zion 			MLX4_GET(guid_lo, outbox, MOD_STAT_CFG_GUID_L);
26698e1a28e8SHadar Hen Zion 			dev->caps.phys_port_id[port] = (u64)guid_lo |
26708e1a28e8SHadar Hen Zion 						       (u64)guid_hi << 32;
26718e1a28e8SHadar Hen Zion 		}
26728e1a28e8SHadar Hen Zion 	}
26738e1a28e8SHadar Hen Zion 	mlx4_free_cmd_mailbox(dev, mailbox);
26748e1a28e8SHadar Hen Zion 	return ret;
26758e1a28e8SHadar Hen Zion }
26768e1a28e8SHadar Hen Zion 
26775a2cc190SJeff Kirsher #define MLX4_WOL_SETUP_MODE (5 << 28)
mlx4_wol_read(struct mlx4_dev * dev,u64 * config,int port)26785a2cc190SJeff Kirsher int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
26795a2cc190SJeff Kirsher {
26805a2cc190SJeff Kirsher 	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
26815a2cc190SJeff Kirsher 
26825a2cc190SJeff Kirsher 	return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
2683f9baff50SJack Morgenstein 			    MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A,
2684f9baff50SJack Morgenstein 			    MLX4_CMD_NATIVE);
26855a2cc190SJeff Kirsher }
26865a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_read);
26875a2cc190SJeff Kirsher 
mlx4_wol_write(struct mlx4_dev * dev,u64 config,int port)26885a2cc190SJeff Kirsher int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
26895a2cc190SJeff Kirsher {
26905a2cc190SJeff Kirsher 	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
26915a2cc190SJeff Kirsher 
26925a2cc190SJeff Kirsher 	return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
2693f9baff50SJack Morgenstein 			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
26945a2cc190SJeff Kirsher }
26955a2cc190SJeff Kirsher EXPORT_SYMBOL_GPL(mlx4_wol_write);
2696fe6f700dSYevgeny Petrilin 
2697fe6f700dSYevgeny Petrilin enum {
2698fe6f700dSYevgeny Petrilin 	ADD_TO_MCG = 0x26,
2699fe6f700dSYevgeny Petrilin };
2700fe6f700dSYevgeny Petrilin 
2701fe6f700dSYevgeny Petrilin 
mlx4_opreq_action(struct work_struct * work)2702fe6f700dSYevgeny Petrilin void mlx4_opreq_action(struct work_struct *work)
2703fe6f700dSYevgeny Petrilin {
2704fe6f700dSYevgeny Petrilin 	struct mlx4_priv *priv = container_of(work, struct mlx4_priv,
2705fe6f700dSYevgeny Petrilin 					      opreq_task);
2706fe6f700dSYevgeny Petrilin 	struct mlx4_dev *dev = &priv->dev;
2707fe6f700dSYevgeny Petrilin 	int num_tasks = atomic_read(&priv->opreq_count);
2708fe6f700dSYevgeny Petrilin 	struct mlx4_cmd_mailbox *mailbox;
2709fe6f700dSYevgeny Petrilin 	struct mlx4_mgm *mgm;
2710fe6f700dSYevgeny Petrilin 	u32 *outbox;
2711fe6f700dSYevgeny Petrilin 	u32 modifier;
2712fe6f700dSYevgeny Petrilin 	u16 token;
2713fe6f700dSYevgeny Petrilin 	u16 type;
2714fe6f700dSYevgeny Petrilin 	int err;
2715fe6f700dSYevgeny Petrilin 	u32 num_qps;
2716fe6f700dSYevgeny Petrilin 	struct mlx4_qp qp;
2717fe6f700dSYevgeny Petrilin 	int i;
2718fe6f700dSYevgeny Petrilin 	u8 rem_mcg;
2719fe6f700dSYevgeny Petrilin 	u8 prot;
2720fe6f700dSYevgeny Petrilin 
2721fe6f700dSYevgeny Petrilin #define GET_OP_REQ_MODIFIER_OFFSET	0x08
2722fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TOKEN_OFFSET		0x14
2723fe6f700dSYevgeny Petrilin #define GET_OP_REQ_TYPE_OFFSET		0x1a
2724fe6f700dSYevgeny Petrilin #define GET_OP_REQ_DATA_OFFSET		0x20
2725fe6f700dSYevgeny Petrilin 
2726fe6f700dSYevgeny Petrilin 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2727fe6f700dSYevgeny Petrilin 	if (IS_ERR(mailbox)) {
2728fe6f700dSYevgeny Petrilin 		mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n");
2729fe6f700dSYevgeny Petrilin 		return;
2730fe6f700dSYevgeny Petrilin 	}
2731fe6f700dSYevgeny Petrilin 	outbox = mailbox->buf;
2732fe6f700dSYevgeny Petrilin 
2733fe6f700dSYevgeny Petrilin 	while (num_tasks) {
2734fe6f700dSYevgeny Petrilin 		err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
2735fe6f700dSYevgeny Petrilin 				   MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
2736fe6f700dSYevgeny Petrilin 				   MLX4_CMD_NATIVE);
2737fe6f700dSYevgeny Petrilin 		if (err) {
27386d3be300SMasanari Iida 			mlx4_err(dev, "Failed to retrieve required operation: %d\n",
2739fe6f700dSYevgeny Petrilin 				 err);
2740febfd9d3SQiushi Wu 			goto out;
2741fe6f700dSYevgeny Petrilin 		}
2742fe6f700dSYevgeny Petrilin 		MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
2743fe6f700dSYevgeny Petrilin 		MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);
2744fe6f700dSYevgeny Petrilin 		MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET);
2745fe6f700dSYevgeny Petrilin 		type &= 0xfff;
2746fe6f700dSYevgeny Petrilin 
2747fe6f700dSYevgeny Petrilin 		switch (type) {
2748fe6f700dSYevgeny Petrilin 		case ADD_TO_MCG:
2749fe6f700dSYevgeny Petrilin 			if (dev->caps.steering_mode ==
2750fe6f700dSYevgeny Petrilin 			    MLX4_STEERING_MODE_DEVICE_MANAGED) {
2751fe6f700dSYevgeny Petrilin 				mlx4_warn(dev, "ADD MCG operation is not supported in DEVICE_MANAGED steering mode\n");
2752fe6f700dSYevgeny Petrilin 				err = EPERM;
2753fe6f700dSYevgeny Petrilin 				break;
2754fe6f700dSYevgeny Petrilin 			}
2755fe6f700dSYevgeny Petrilin 			mgm = (struct mlx4_mgm *)((u8 *)(outbox) +
2756fe6f700dSYevgeny Petrilin 						  GET_OP_REQ_DATA_OFFSET);
2757fe6f700dSYevgeny Petrilin 			num_qps = be32_to_cpu(mgm->members_count) &
2758fe6f700dSYevgeny Petrilin 				  MGM_QPN_MASK;
2759fe6f700dSYevgeny Petrilin 			rem_mcg = ((u8 *)(&mgm->members_count))[0] & 1;
2760fe6f700dSYevgeny Petrilin 			prot = ((u8 *)(&mgm->members_count))[0] >> 6;
2761fe6f700dSYevgeny Petrilin 
2762fe6f700dSYevgeny Petrilin 			for (i = 0; i < num_qps; i++) {
2763fe6f700dSYevgeny Petrilin 				qp.qpn = be32_to_cpu(mgm->qp[i]);
2764fe6f700dSYevgeny Petrilin 				if (rem_mcg)
2765fe6f700dSYevgeny Petrilin 					err = mlx4_multicast_detach(dev, &qp,
2766fe6f700dSYevgeny Petrilin 								    mgm->gid,
2767fe6f700dSYevgeny Petrilin 								    prot, 0);
2768fe6f700dSYevgeny Petrilin 				else
2769fe6f700dSYevgeny Petrilin 					err = mlx4_multicast_attach(dev, &qp,
2770fe6f700dSYevgeny Petrilin 								    mgm->gid,
2771fe6f700dSYevgeny Petrilin 								    mgm->gid[5]
2772fe6f700dSYevgeny Petrilin 								    , 0, prot,
2773fe6f700dSYevgeny Petrilin 								    NULL);
2774fe6f700dSYevgeny Petrilin 				if (err)
2775fe6f700dSYevgeny Petrilin 					break;
2776fe6f700dSYevgeny Petrilin 			}
2777fe6f700dSYevgeny Petrilin 			break;
2778fe6f700dSYevgeny Petrilin 		default:
2779fe6f700dSYevgeny Petrilin 			mlx4_warn(dev, "Bad type for required operation\n");
2780fe6f700dSYevgeny Petrilin 			err = EINVAL;
2781fe6f700dSYevgeny Petrilin 			break;
2782fe6f700dSYevgeny Petrilin 		}
278328d222bbSEyal Perry 		err = mlx4_cmd(dev, 0, ((u32) err |
278428d222bbSEyal Perry 					(__force u32)cpu_to_be32(token) << 16),
2785fe6f700dSYevgeny Petrilin 			       1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
2786fe6f700dSYevgeny Petrilin 			       MLX4_CMD_NATIVE);
2787fe6f700dSYevgeny Petrilin 		if (err) {
2788fe6f700dSYevgeny Petrilin 			mlx4_err(dev, "Failed to acknowledge required request: %d\n",
2789fe6f700dSYevgeny Petrilin 				 err);
2790fe6f700dSYevgeny Petrilin 			goto out;
2791fe6f700dSYevgeny Petrilin 		}
2792fe6f700dSYevgeny Petrilin 		memset(outbox, 0, 0xffc);
2793fe6f700dSYevgeny Petrilin 		num_tasks = atomic_dec_return(&priv->opreq_count);
2794fe6f700dSYevgeny Petrilin 	}
2795fe6f700dSYevgeny Petrilin 
2796fe6f700dSYevgeny Petrilin out:
2797fe6f700dSYevgeny Petrilin 	mlx4_free_cmd_mailbox(dev, mailbox);
2798fe6f700dSYevgeny Petrilin }
2799114840c3SJack Morgenstein 
mlx4_check_smp_firewall_active(struct mlx4_dev * dev,struct mlx4_cmd_mailbox * mailbox)2800114840c3SJack Morgenstein static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev,
2801114840c3SJack Morgenstein 					  struct mlx4_cmd_mailbox *mailbox)
2802114840c3SJack Morgenstein {
2803114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET		0x10
2804114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET		0x20
2805114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET		0x40
2806114840c3SJack Morgenstein #define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET	0x70
2807114840c3SJack Morgenstein 
2808114840c3SJack Morgenstein 	u32 set_attr_mask, getresp_attr_mask;
2809114840c3SJack Morgenstein 	u32 trap_attr_mask, traprepress_attr_mask;
2810114840c3SJack Morgenstein 
2811114840c3SJack Morgenstein 	MLX4_GET(set_attr_mask, mailbox->buf,
2812114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET);
2813114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n",
2814114840c3SJack Morgenstein 		 set_attr_mask);
2815114840c3SJack Morgenstein 
2816114840c3SJack Morgenstein 	MLX4_GET(getresp_attr_mask, mailbox->buf,
2817114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET);
2818114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n",
2819114840c3SJack Morgenstein 		 getresp_attr_mask);
2820114840c3SJack Morgenstein 
2821114840c3SJack Morgenstein 	MLX4_GET(trap_attr_mask, mailbox->buf,
2822114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET);
2823114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n",
2824114840c3SJack Morgenstein 		 trap_attr_mask);
2825114840c3SJack Morgenstein 
2826114840c3SJack Morgenstein 	MLX4_GET(traprepress_attr_mask, mailbox->buf,
2827114840c3SJack Morgenstein 		 MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET);
2828114840c3SJack Morgenstein 	mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n",
2829114840c3SJack Morgenstein 		 traprepress_attr_mask);
2830114840c3SJack Morgenstein 
2831114840c3SJack Morgenstein 	if (set_attr_mask && getresp_attr_mask && trap_attr_mask &&
2832114840c3SJack Morgenstein 	    traprepress_attr_mask)
2833114840c3SJack Morgenstein 		return 1;
2834114840c3SJack Morgenstein 
2835114840c3SJack Morgenstein 	return 0;
2836114840c3SJack Morgenstein }
2837114840c3SJack Morgenstein 
mlx4_config_mad_demux(struct mlx4_dev * dev)2838114840c3SJack Morgenstein int mlx4_config_mad_demux(struct mlx4_dev *dev)
2839114840c3SJack Morgenstein {
2840114840c3SJack Morgenstein 	struct mlx4_cmd_mailbox *mailbox;
2841114840c3SJack Morgenstein 	int err;
2842114840c3SJack Morgenstein 
2843114840c3SJack Morgenstein 	/* Check if mad_demux is supported */
2844114840c3SJack Morgenstein 	if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX))
2845114840c3SJack Morgenstein 		return 0;
2846114840c3SJack Morgenstein 
2847114840c3SJack Morgenstein 	mailbox = mlx4_alloc_cmd_mailbox(dev);
2848114840c3SJack Morgenstein 	if (IS_ERR(mailbox)) {
2849114840c3SJack Morgenstein 		mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX");
2850114840c3SJack Morgenstein 		return -ENOMEM;
2851114840c3SJack Morgenstein 	}
2852114840c3SJack Morgenstein 
2853114840c3SJack Morgenstein 	/* Query mad_demux to find out which MADs are handled by internal sma */
2854114840c3SJack Morgenstein 	err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */,
2855114840c3SJack Morgenstein 			   MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX,
2856114840c3SJack Morgenstein 			   MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
2857114840c3SJack Morgenstein 	if (err) {
2858114840c3SJack Morgenstein 		mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n",
2859114840c3SJack Morgenstein 			  err);
2860114840c3SJack Morgenstein 		goto out;
2861114840c3SJack Morgenstein 	}
2862114840c3SJack Morgenstein 
2863fd10ed8eSJack Morgenstein 	if (mlx4_check_smp_firewall_active(dev, mailbox))
2864fd10ed8eSJack Morgenstein 		dev->flags |= MLX4_FLAG_SECURE_HOST;
2865114840c3SJack Morgenstein 
2866114840c3SJack Morgenstein 	/* Config mad_demux to handle all MADs returned by the query above */
2867114840c3SJack Morgenstein 	err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */,
2868114840c3SJack Morgenstein 		       MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX,
2869114840c3SJack Morgenstein 		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
2870114840c3SJack Morgenstein 	if (err) {
2871114840c3SJack Morgenstein 		mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err);
2872114840c3SJack Morgenstein 		goto out;
2873114840c3SJack Morgenstein 	}
2874114840c3SJack Morgenstein 
2875fd10ed8eSJack Morgenstein 	if (dev->flags & MLX4_FLAG_SECURE_HOST)
2876114840c3SJack Morgenstein 		mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n");
2877114840c3SJack Morgenstein out:
2878114840c3SJack Morgenstein 	mlx4_free_cmd_mailbox(dev, mailbox);
2879114840c3SJack Morgenstein 	return err;
2880114840c3SJack Morgenstein }
2881adbc7ac5SSaeed Mahameed 
2882adbc7ac5SSaeed Mahameed /* Access Reg commands */
2883adbc7ac5SSaeed Mahameed enum mlx4_access_reg_masks {
2884adbc7ac5SSaeed Mahameed 	MLX4_ACCESS_REG_STATUS_MASK = 0x7f,
2885adbc7ac5SSaeed Mahameed 	MLX4_ACCESS_REG_METHOD_MASK = 0x7f,
2886adbc7ac5SSaeed Mahameed 	MLX4_ACCESS_REG_LEN_MASK = 0x7ff
2887adbc7ac5SSaeed Mahameed };
2888adbc7ac5SSaeed Mahameed 
2889adbc7ac5SSaeed Mahameed struct mlx4_access_reg {
2890adbc7ac5SSaeed Mahameed 	__be16 constant1;
2891adbc7ac5SSaeed Mahameed 	u8 status;
2892adbc7ac5SSaeed Mahameed 	u8 resrvd1;
2893adbc7ac5SSaeed Mahameed 	__be16 reg_id;
2894adbc7ac5SSaeed Mahameed 	u8 method;
2895adbc7ac5SSaeed Mahameed 	u8 constant2;
2896adbc7ac5SSaeed Mahameed 	__be32 resrvd2[2];
2897adbc7ac5SSaeed Mahameed 	__be16 len_const;
2898adbc7ac5SSaeed Mahameed 	__be16 resrvd3;
2899adbc7ac5SSaeed Mahameed #define MLX4_ACCESS_REG_HEADER_SIZE (20)
2900adbc7ac5SSaeed Mahameed 	u8 reg_data[MLX4_MAILBOX_SIZE-MLX4_ACCESS_REG_HEADER_SIZE];
2901adbc7ac5SSaeed Mahameed } __attribute__((__packed__));
2902adbc7ac5SSaeed Mahameed 
2903adbc7ac5SSaeed Mahameed /**
2904adbc7ac5SSaeed Mahameed  * mlx4_ACCESS_REG - Generic access reg command.
2905adbc7ac5SSaeed Mahameed  * @dev: mlx4_dev.
2906adbc7ac5SSaeed Mahameed  * @reg_id: register ID to access.
2907adbc7ac5SSaeed Mahameed  * @method: Access method Read/Write.
2908adbc7ac5SSaeed Mahameed  * @reg_len: register length to Read/Write in bytes.
2909adbc7ac5SSaeed Mahameed  * @reg_data: reg_data pointer to Read/Write From/To.
2910adbc7ac5SSaeed Mahameed  *
2911adbc7ac5SSaeed Mahameed  * Access ConnectX registers FW command.
2912adbc7ac5SSaeed Mahameed  * Returns 0 on success and copies outbox mlx4_access_reg data
2913adbc7ac5SSaeed Mahameed  * field into reg_data or a negative error code.
2914adbc7ac5SSaeed Mahameed  */
mlx4_ACCESS_REG(struct mlx4_dev * dev,u16 reg_id,enum mlx4_access_reg_method method,u16 reg_len,void * reg_data)2915adbc7ac5SSaeed Mahameed static int mlx4_ACCESS_REG(struct mlx4_dev *dev, u16 reg_id,
2916adbc7ac5SSaeed Mahameed 			   enum mlx4_access_reg_method method,
2917adbc7ac5SSaeed Mahameed 			   u16 reg_len, void *reg_data)
2918adbc7ac5SSaeed Mahameed {
2919adbc7ac5SSaeed Mahameed 	struct mlx4_cmd_mailbox *inbox, *outbox;
2920adbc7ac5SSaeed Mahameed 	struct mlx4_access_reg *inbuf, *outbuf;
2921adbc7ac5SSaeed Mahameed 	int err;
2922adbc7ac5SSaeed Mahameed 
2923adbc7ac5SSaeed Mahameed 	inbox = mlx4_alloc_cmd_mailbox(dev);
2924adbc7ac5SSaeed Mahameed 	if (IS_ERR(inbox))
2925adbc7ac5SSaeed Mahameed 		return PTR_ERR(inbox);
2926adbc7ac5SSaeed Mahameed 
2927adbc7ac5SSaeed Mahameed 	outbox = mlx4_alloc_cmd_mailbox(dev);
2928adbc7ac5SSaeed Mahameed 	if (IS_ERR(outbox)) {
2929adbc7ac5SSaeed Mahameed 		mlx4_free_cmd_mailbox(dev, inbox);
2930adbc7ac5SSaeed Mahameed 		return PTR_ERR(outbox);
2931adbc7ac5SSaeed Mahameed 	}
2932adbc7ac5SSaeed Mahameed 
2933adbc7ac5SSaeed Mahameed 	inbuf = inbox->buf;
2934adbc7ac5SSaeed Mahameed 	outbuf = outbox->buf;
2935adbc7ac5SSaeed Mahameed 
2936adbc7ac5SSaeed Mahameed 	inbuf->constant1 = cpu_to_be16(0x1<<11 | 0x4);
2937adbc7ac5SSaeed Mahameed 	inbuf->constant2 = 0x1;
2938adbc7ac5SSaeed Mahameed 	inbuf->reg_id = cpu_to_be16(reg_id);
2939adbc7ac5SSaeed Mahameed 	inbuf->method = method & MLX4_ACCESS_REG_METHOD_MASK;
2940adbc7ac5SSaeed Mahameed 
2941adbc7ac5SSaeed Mahameed 	reg_len = min(reg_len, (u16)(sizeof(inbuf->reg_data)));
2942adbc7ac5SSaeed Mahameed 	inbuf->len_const =
2943adbc7ac5SSaeed Mahameed 		cpu_to_be16(((reg_len/4 + 1) & MLX4_ACCESS_REG_LEN_MASK) |
2944adbc7ac5SSaeed Mahameed 			    ((0x3) << 12));
2945adbc7ac5SSaeed Mahameed 
2946adbc7ac5SSaeed Mahameed 	memcpy(inbuf->reg_data, reg_data, reg_len);
2947adbc7ac5SSaeed Mahameed 	err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 0, 0,
2948adbc7ac5SSaeed Mahameed 			   MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C,
29496e806699SSaeed Mahameed 			   MLX4_CMD_WRAPPED);
2950adbc7ac5SSaeed Mahameed 	if (err)
2951adbc7ac5SSaeed Mahameed 		goto out;
2952adbc7ac5SSaeed Mahameed 
2953adbc7ac5SSaeed Mahameed 	if (outbuf->status & MLX4_ACCESS_REG_STATUS_MASK) {
2954adbc7ac5SSaeed Mahameed 		err = outbuf->status & MLX4_ACCESS_REG_STATUS_MASK;
2955adbc7ac5SSaeed Mahameed 		mlx4_err(dev,
2956adbc7ac5SSaeed Mahameed 			 "MLX4_CMD_ACCESS_REG(%x) returned REG status (%x)\n",
2957adbc7ac5SSaeed Mahameed 			 reg_id, err);
2958adbc7ac5SSaeed Mahameed 		goto out;
2959adbc7ac5SSaeed Mahameed 	}
2960adbc7ac5SSaeed Mahameed 
2961adbc7ac5SSaeed Mahameed 	memcpy(reg_data, outbuf->reg_data, reg_len);
2962adbc7ac5SSaeed Mahameed out:
2963adbc7ac5SSaeed Mahameed 	mlx4_free_cmd_mailbox(dev, inbox);
2964adbc7ac5SSaeed Mahameed 	mlx4_free_cmd_mailbox(dev, outbox);
2965adbc7ac5SSaeed Mahameed 	return err;
2966adbc7ac5SSaeed Mahameed }
2967adbc7ac5SSaeed Mahameed 
2968adbc7ac5SSaeed Mahameed /* ConnectX registers IDs */
2969adbc7ac5SSaeed Mahameed enum mlx4_reg_id {
2970adbc7ac5SSaeed Mahameed 	MLX4_REG_ID_PTYS = 0x5004,
2971adbc7ac5SSaeed Mahameed };
2972adbc7ac5SSaeed Mahameed 
2973adbc7ac5SSaeed Mahameed /**
2974adbc7ac5SSaeed Mahameed  * mlx4_ACCESS_PTYS_REG - Access PTYs (Port Type and Speed)
2975adbc7ac5SSaeed Mahameed  * register
2976adbc7ac5SSaeed Mahameed  * @dev: mlx4_dev.
2977adbc7ac5SSaeed Mahameed  * @method: Access method Read/Write.
2978adbc7ac5SSaeed Mahameed  * @ptys_reg: PTYS register data pointer.
2979adbc7ac5SSaeed Mahameed  *
2980adbc7ac5SSaeed Mahameed  * Access ConnectX PTYS register, to Read/Write Port Type/Speed
2981adbc7ac5SSaeed Mahameed  * configuration
2982adbc7ac5SSaeed Mahameed  * Returns 0 on success or a negative error code.
2983adbc7ac5SSaeed Mahameed  */
mlx4_ACCESS_PTYS_REG(struct mlx4_dev * dev,enum mlx4_access_reg_method method,struct mlx4_ptys_reg * ptys_reg)2984adbc7ac5SSaeed Mahameed int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev,
2985adbc7ac5SSaeed Mahameed 			 enum mlx4_access_reg_method method,
2986adbc7ac5SSaeed Mahameed 			 struct mlx4_ptys_reg *ptys_reg)
2987adbc7ac5SSaeed Mahameed {
2988adbc7ac5SSaeed Mahameed 	return mlx4_ACCESS_REG(dev, MLX4_REG_ID_PTYS,
2989adbc7ac5SSaeed Mahameed 			       method, sizeof(*ptys_reg), ptys_reg);
2990adbc7ac5SSaeed Mahameed }
2991adbc7ac5SSaeed Mahameed EXPORT_SYMBOL_GPL(mlx4_ACCESS_PTYS_REG);
29926e806699SSaeed Mahameed 
mlx4_ACCESS_REG_wrapper(struct mlx4_dev * dev,int slave,struct mlx4_vhcr * vhcr,struct mlx4_cmd_mailbox * inbox,struct mlx4_cmd_mailbox * outbox,struct mlx4_cmd_info * cmd)29936e806699SSaeed Mahameed int mlx4_ACCESS_REG_wrapper(struct mlx4_dev *dev, int slave,
29946e806699SSaeed Mahameed 			    struct mlx4_vhcr *vhcr,
29956e806699SSaeed Mahameed 			    struct mlx4_cmd_mailbox *inbox,
29966e806699SSaeed Mahameed 			    struct mlx4_cmd_mailbox *outbox,
29976e806699SSaeed Mahameed 			    struct mlx4_cmd_info *cmd)
29986e806699SSaeed Mahameed {
29996e806699SSaeed Mahameed 	struct mlx4_access_reg *inbuf = inbox->buf;
30006e806699SSaeed Mahameed 	u8 method = inbuf->method & MLX4_ACCESS_REG_METHOD_MASK;
30016e806699SSaeed Mahameed 	u16 reg_id = be16_to_cpu(inbuf->reg_id);
30026e806699SSaeed Mahameed 
30036e806699SSaeed Mahameed 	if (slave != mlx4_master_func_num(dev) &&
30046e806699SSaeed Mahameed 	    method == MLX4_ACCESS_REG_WRITE)
30056e806699SSaeed Mahameed 		return -EPERM;
30066e806699SSaeed Mahameed 
30076e806699SSaeed Mahameed 	if (reg_id == MLX4_REG_ID_PTYS) {
30086e806699SSaeed Mahameed 		struct mlx4_ptys_reg *ptys_reg =
30096e806699SSaeed Mahameed 			(struct mlx4_ptys_reg *)inbuf->reg_data;
30106e806699SSaeed Mahameed 
30116e806699SSaeed Mahameed 		ptys_reg->local_port =
30126e806699SSaeed Mahameed 			mlx4_slave_convert_port(dev, slave,
30136e806699SSaeed Mahameed 						ptys_reg->local_port);
30146e806699SSaeed Mahameed 	}
30156e806699SSaeed Mahameed 
30166e806699SSaeed Mahameed 	return mlx4_cmd_box(dev, inbox->dma, outbox->dma, vhcr->in_modifier,
30176e806699SSaeed Mahameed 			    0, MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C,
30186e806699SSaeed Mahameed 			    MLX4_CMD_NATIVE);
30196e806699SSaeed Mahameed }
302077fc29c4SHadar Hen Zion 
mlx4_SET_PORT_phv_bit(struct mlx4_dev * dev,u8 port,u8 phv_bit)302177fc29c4SHadar Hen Zion static int mlx4_SET_PORT_phv_bit(struct mlx4_dev *dev, u8 port, u8 phv_bit)
302277fc29c4SHadar Hen Zion {
302377fc29c4SHadar Hen Zion #define SET_PORT_GEN_PHV_VALID	0x10
302477fc29c4SHadar Hen Zion #define SET_PORT_GEN_PHV_EN	0x80
302577fc29c4SHadar Hen Zion 
302677fc29c4SHadar Hen Zion 	struct mlx4_cmd_mailbox *mailbox;
302777fc29c4SHadar Hen Zion 	struct mlx4_set_port_general_context *context;
302877fc29c4SHadar Hen Zion 	u32 in_mod;
302977fc29c4SHadar Hen Zion 	int err;
303077fc29c4SHadar Hen Zion 
303177fc29c4SHadar Hen Zion 	mailbox = mlx4_alloc_cmd_mailbox(dev);
303277fc29c4SHadar Hen Zion 	if (IS_ERR(mailbox))
303377fc29c4SHadar Hen Zion 		return PTR_ERR(mailbox);
303477fc29c4SHadar Hen Zion 	context = mailbox->buf;
303577fc29c4SHadar Hen Zion 
303640fb4fc1SShaker Daibes 	context->flags2 |=  SET_PORT_GEN_PHV_VALID;
303777fc29c4SHadar Hen Zion 	if (phv_bit)
303877fc29c4SHadar Hen Zion 		context->phv_en |=  SET_PORT_GEN_PHV_EN;
303977fc29c4SHadar Hen Zion 
304077fc29c4SHadar Hen Zion 	in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
304177fc29c4SHadar Hen Zion 	err = mlx4_cmd(dev, mailbox->dma, in_mod, MLX4_SET_PORT_ETH_OPCODE,
304277fc29c4SHadar Hen Zion 		       MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
304377fc29c4SHadar Hen Zion 		       MLX4_CMD_NATIVE);
304477fc29c4SHadar Hen Zion 
304577fc29c4SHadar Hen Zion 	mlx4_free_cmd_mailbox(dev, mailbox);
304677fc29c4SHadar Hen Zion 	return err;
304777fc29c4SHadar Hen Zion }
304877fc29c4SHadar Hen Zion 
get_phv_bit(struct mlx4_dev * dev,u8 port,int * phv)304977fc29c4SHadar Hen Zion int get_phv_bit(struct mlx4_dev *dev, u8 port, int *phv)
305077fc29c4SHadar Hen Zion {
305177fc29c4SHadar Hen Zion 	int err;
305277fc29c4SHadar Hen Zion 	struct mlx4_func_cap func_cap;
305377fc29c4SHadar Hen Zion 
305477fc29c4SHadar Hen Zion 	memset(&func_cap, 0, sizeof(func_cap));
305535e455f4SAmir Vadai 	err = mlx4_QUERY_FUNC_CAP(dev, port, &func_cap);
305677fc29c4SHadar Hen Zion 	if (!err)
3057c9cc599aSMoshe Shemesh 		*phv = func_cap.flags0 & QUERY_FUNC_CAP_PHV_BIT;
305877fc29c4SHadar Hen Zion 	return err;
305977fc29c4SHadar Hen Zion }
306077fc29c4SHadar Hen Zion EXPORT_SYMBOL(get_phv_bit);
306177fc29c4SHadar Hen Zion 
set_phv_bit(struct mlx4_dev * dev,u8 port,int new_val)306277fc29c4SHadar Hen Zion int set_phv_bit(struct mlx4_dev *dev, u8 port, int new_val)
306377fc29c4SHadar Hen Zion {
306477fc29c4SHadar Hen Zion 	int ret;
306577fc29c4SHadar Hen Zion 
306677fc29c4SHadar Hen Zion 	if (mlx4_is_slave(dev))
306777fc29c4SHadar Hen Zion 		return -EPERM;
306877fc29c4SHadar Hen Zion 
306977fc29c4SHadar Hen Zion 	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN &&
307077fc29c4SHadar Hen Zion 	    !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
307177fc29c4SHadar Hen Zion 		ret = mlx4_SET_PORT_phv_bit(dev, port, new_val);
307277fc29c4SHadar Hen Zion 		if (!ret)
307377fc29c4SHadar Hen Zion 			dev->caps.phv_bit[port] = new_val;
307477fc29c4SHadar Hen Zion 		return ret;
307577fc29c4SHadar Hen Zion 	}
307677fc29c4SHadar Hen Zion 
307777fc29c4SHadar Hen Zion 	return -EOPNOTSUPP;
307877fc29c4SHadar Hen Zion }
307977fc29c4SHadar Hen Zion EXPORT_SYMBOL(set_phv_bit);
30802b3ddf27SJack Morgenstein 
mlx4_get_is_vlan_offload_disabled(struct mlx4_dev * dev,u8 port,bool * vlan_offload_disabled)30817c3d21c8SMoshe Shemesh int mlx4_get_is_vlan_offload_disabled(struct mlx4_dev *dev, u8 port,
30827c3d21c8SMoshe Shemesh 				      bool *vlan_offload_disabled)
30837c3d21c8SMoshe Shemesh {
30847c3d21c8SMoshe Shemesh 	struct mlx4_func_cap func_cap;
30857c3d21c8SMoshe Shemesh 	int err;
30867c3d21c8SMoshe Shemesh 
30877c3d21c8SMoshe Shemesh 	memset(&func_cap, 0, sizeof(func_cap));
30887c3d21c8SMoshe Shemesh 	err = mlx4_QUERY_FUNC_CAP(dev, port, &func_cap);
30897c3d21c8SMoshe Shemesh 	if (!err)
30907c3d21c8SMoshe Shemesh 		*vlan_offload_disabled =
30917c3d21c8SMoshe Shemesh 			!!(func_cap.flags0 &
30927c3d21c8SMoshe Shemesh 			   QUERY_FUNC_CAP_VLAN_OFFLOAD_DISABLE);
30937c3d21c8SMoshe Shemesh 	return err;
30947c3d21c8SMoshe Shemesh }
30957c3d21c8SMoshe Shemesh EXPORT_SYMBOL(mlx4_get_is_vlan_offload_disabled);
30967c3d21c8SMoshe Shemesh 
mlx4_replace_zero_macs(struct mlx4_dev * dev)30972b3ddf27SJack Morgenstein void mlx4_replace_zero_macs(struct mlx4_dev *dev)
30982b3ddf27SJack Morgenstein {
30992b3ddf27SJack Morgenstein 	int i;
31002b3ddf27SJack Morgenstein 	u8 mac_addr[ETH_ALEN];
31012b3ddf27SJack Morgenstein 
31022b3ddf27SJack Morgenstein 	dev->port_random_macs = 0;
31032b3ddf27SJack Morgenstein 	for (i = 1; i <= dev->caps.num_ports; ++i)
31042b3ddf27SJack Morgenstein 		if (!dev->caps.def_mac[i] &&
31052b3ddf27SJack Morgenstein 		    dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH) {
31062b3ddf27SJack Morgenstein 			eth_random_addr(mac_addr);
31072b3ddf27SJack Morgenstein 			dev->port_random_macs |= 1 << i;
3108ded6e16bSJakub Kicinski 			dev->caps.def_mac[i] = ether_addr_to_u64(mac_addr);
31092b3ddf27SJack Morgenstein 		}
31102b3ddf27SJack Morgenstein }
31112b3ddf27SJack Morgenstein EXPORT_SYMBOL_GPL(mlx4_replace_zero_macs);
3112