1ebb7c6fdSAlex Wilson /*
2ebb7c6fdSAlex Wilson  * This file and its contents are supplied under the terms of the
3ebb7c6fdSAlex Wilson  * Common Development and Distribution License ("CDDL"), version 1.0.
4ebb7c6fdSAlex Wilson  * You may only use this file in accordance with the terms of version
5ebb7c6fdSAlex Wilson  * 1.0 of the CDDL.
6ebb7c6fdSAlex Wilson  *
7ebb7c6fdSAlex Wilson  * A full copy of the text of the CDDL should have accompanied this
8ebb7c6fdSAlex Wilson  * source.  A copy of the CDDL is also available via the Internet at
9ebb7c6fdSAlex Wilson  * http://www.illumos.org/license/CDDL.
10ebb7c6fdSAlex Wilson  */
11ebb7c6fdSAlex Wilson 
12ebb7c6fdSAlex Wilson /*
13ebb7c6fdSAlex Wilson  * Copyright 2020, The University of Queensland
14ebb7c6fdSAlex Wilson  * Copyright (c) 2018, Joyent, Inc.
15d77e6e0fSPaul Winder  * Copyright 2020 RackTop Systems, Inc.
16*85e4aa97SDan McDonald  * Copyright 2023 MNX Cloud, Inc.
17ebb7c6fdSAlex Wilson  */
18ebb7c6fdSAlex Wilson 
19ebb7c6fdSAlex Wilson /*
20ebb7c6fdSAlex Wilson  * Controls the management of commands that are issues to and from the HCA
21ebb7c6fdSAlex Wilson  * command queue.
22ebb7c6fdSAlex Wilson  */
23ebb7c6fdSAlex Wilson 
24ebb7c6fdSAlex Wilson #include <mlxcx.h>
25ebb7c6fdSAlex Wilson 
26ebb7c6fdSAlex Wilson #include <sys/debug.h>
27ebb7c6fdSAlex Wilson #include <sys/sysmacros.h>
28ebb7c6fdSAlex Wilson 
29ebb7c6fdSAlex Wilson /*
30ebb7c6fdSAlex Wilson  * When we start up the command queue, it will undergo some internal
31ebb7c6fdSAlex Wilson  * initialization after we set the command queue address. These values allow us
32ebb7c6fdSAlex Wilson  * to control how much time we should wait for that to occur.
33ebb7c6fdSAlex Wilson  */
34ebb7c6fdSAlex Wilson clock_t mlxcx_cmd_init_delay = 1000 * 10; /* 10 ms in us */
35ebb7c6fdSAlex Wilson uint_t mlxcx_cmd_init_trys = 100; /* Wait at most 1s */
36ebb7c6fdSAlex Wilson 
37ebb7c6fdSAlex Wilson clock_t mlxcx_cmd_delay = 1000 * 1; /* 1 ms in us */
38ebb7c6fdSAlex Wilson uint_t mlxcx_cmd_tries = 5000; /* Wait at most 1s */
39ebb7c6fdSAlex Wilson 
40ebb7c6fdSAlex Wilson /*
41ebb7c6fdSAlex Wilson  * This macro is used to identify that we care about our own function that we're
42ebb7c6fdSAlex Wilson  * communicating with. We always use this function.
43ebb7c6fdSAlex Wilson  */
44ebb7c6fdSAlex Wilson #define	MLXCX_FUNCTION_SELF	(to_be16(0))
45ebb7c6fdSAlex Wilson 
46ebb7c6fdSAlex Wilson static const char *
mlxcx_cmd_response_string(mlxcx_cmd_ret_t ret)47ebb7c6fdSAlex Wilson mlxcx_cmd_response_string(mlxcx_cmd_ret_t ret)
48ebb7c6fdSAlex Wilson {
49ebb7c6fdSAlex Wilson 	switch (ret) {
50ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_OK:
51ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_OK");
52ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_INTERNAL_ERR:
53ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_INTERNAL_ERR");
54ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_OP:
55ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_OP");
56ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_PARAM:
57ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_PARAM");
58ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_SYS_STATE:
59ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_SYS_STATE");
60ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_RESOURCE:
61ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_RESOURCE");
62ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_RESOURCE_BUSY:
63ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_RESOURCE_BUSY");
64ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_EXCEED_LIM:
65ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_EXCEED_LIM");
66ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_RES_STATE:
67ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_RES_STATE");
68ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_INDEX:
69ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_INDEX");
70ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_NO_RESOURCES:
71ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_NO_RESOURCES");
72ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_INPUT_LEN:
73ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_INPUT_LEN");
74ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_OUTPUT_LEN:
75ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_OUTPUT_LEN");
76ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_RESOURCE_STATE:
77ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_RESOURCE_STATE");
78ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_PKT:
79ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_PKT");
80ebb7c6fdSAlex Wilson 	case MLXCX_CMD_R_BAD_SIZE:
81ebb7c6fdSAlex Wilson 		return ("MLXCX_CMD_R_BAD_SIZE");
82ebb7c6fdSAlex Wilson 	default:
83ebb7c6fdSAlex Wilson 		return ("Unknown command");
84ebb7c6fdSAlex Wilson 	}
85ebb7c6fdSAlex Wilson }
86ebb7c6fdSAlex Wilson 
87ebb7c6fdSAlex Wilson static const char *
mlxcx_cmd_opcode_string(mlxcx_cmd_op_t op)88ebb7c6fdSAlex Wilson mlxcx_cmd_opcode_string(mlxcx_cmd_op_t op)
89ebb7c6fdSAlex Wilson {
90ebb7c6fdSAlex Wilson 	switch (op) {
91ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_HCA_CAP:
92ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_HCA_CAP");
93ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_ADAPTER:
94ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_ADAPTER");
95ebb7c6fdSAlex Wilson 	case MLXCX_OP_INIT_HCA:
96ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_INIT_HCA");
97ebb7c6fdSAlex Wilson 	case MLXCX_OP_TEARDOWN_HCA:
98ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_TEARDOWN_HCA");
99ebb7c6fdSAlex Wilson 	case MLXCX_OP_ENABLE_HCA:
100ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ENABLE_HCA");
101ebb7c6fdSAlex Wilson 	case MLXCX_OP_DISABLE_HCA:
102ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DISABLE_HCA");
103ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_PAGES:
104ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_PAGES");
105ebb7c6fdSAlex Wilson 	case MLXCX_OP_MANAGE_PAGES:
106ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MANAGE_PAGES");
107ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_HCA_CAP:
108ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_HCA_CAP");
109ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_ISSI:
110ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_ISSI");
111ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_ISSI:
112ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_ISSI");
113ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_DRIVER_VERSION:
114ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_DRIVER_VERSION");
115ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_OTHER_HCA_CAP:
116ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_OTHER_HCA_CAP");
117ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_OTHER_HCA_CAP:
118ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_OTHER_HCA_CAP");
119ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_TUNNELED_OPERATIONS:
120ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_TUNNELED_OPERATIONS");
121ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_MKEY:
122ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_MKEY");
123ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_MKEY:
124ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_MKEY");
125ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_MKEY:
126ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_MKEY");
127ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_SPECIAL_CONTEXTS:
128ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_SPECIAL_CONTEXTS");
129ebb7c6fdSAlex Wilson 	case MLXCX_OP_PAGE_FAULT_RESUME:
130ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_PAGE_FAULT_RESUME");
131ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_EQ:
132ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_EQ");
133ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_EQ:
134ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_EQ");
135ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_EQ:
136ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_EQ");
137ebb7c6fdSAlex Wilson 	case MLXCX_OP_GEN_EQE:
138ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_GEN_EQE");
139ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_CQ:
140ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_CQ");
141ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_CQ:
142ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_CQ");
143ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_CQ:
144ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_CQ");
145ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_CQ:
146ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_CQ");
147ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_QP:
148ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_QP");
149ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_QP:
150ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_QP");
151ebb7c6fdSAlex Wilson 	case MLXCX_OP_RST2INIT_QP:
152ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_RST2INIT_QP");
153ebb7c6fdSAlex Wilson 	case MLXCX_OP_INIT2RTR_QP:
154ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_INIT2RTR_QP");
155ebb7c6fdSAlex Wilson 	case MLXCX_OP_RTR2RTS_QP:
156ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_RTR2RTS_QP");
157ebb7c6fdSAlex Wilson 	case MLXCX_OP_RTS2RTS_QP:
158ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_RTS2RTS_QP");
159ebb7c6fdSAlex Wilson 	case MLXCX_OP_SQERR2RTS_QP:
160ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SQERR2RTS_QP");
161ebb7c6fdSAlex Wilson 	case MLXCX_OP__2ERR_QP:
162ebb7c6fdSAlex Wilson 		return ("MLXCX_OP__2ERR_QP");
163ebb7c6fdSAlex Wilson 	case MLXCX_OP__2RST_QP:
164ebb7c6fdSAlex Wilson 		return ("MLXCX_OP__2RST_QP");
165ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_QP:
166ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_QP");
167ebb7c6fdSAlex Wilson 	case MLXCX_OP_SQD_RTS_QP:
168ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SQD_RTS_QP");
169ebb7c6fdSAlex Wilson 	case MLXCX_OP_INIT2INIT_QP:
170ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_INIT2INIT_QP");
171ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_PSV:
172ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_PSV");
173ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_PSV:
174ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_PSV");
175ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_SRQ:
176ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_SRQ");
177ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_SRQ:
178ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_SRQ");
179ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_SRQ:
180ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_SRQ");
181ebb7c6fdSAlex Wilson 	case MLXCX_OP_ARM_RQ:
182ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ARM_RQ");
183ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_XRC_SRQ:
184ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_XRC_SRQ");
185ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_XRC_SRQ:
186ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_XRC_SRQ");
187ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_XRC_SRQ:
188ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_XRC_SRQ");
189ebb7c6fdSAlex Wilson 	case MLXCX_OP_ARM_XRC_SRQ:
190ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ARM_XRC_SRQ");
191ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_DCT:
192ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_DCT");
193ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_DCT:
194ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_DCT");
195ebb7c6fdSAlex Wilson 	case MLXCX_OP_DRAIN_DCT:
196ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DRAIN_DCT");
197ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_DCT:
198ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_DCT");
199ebb7c6fdSAlex Wilson 	case MLXCX_OP_ARM_DCT_FOR_KEY_VIOLATION:
200ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ARM_DCT_FOR_KEY_VIOLATION");
201ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_XRQ:
202ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_XRQ");
203ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_XRQ:
204ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_XRQ");
205ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_XRQ:
206ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_XRQ");
207ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_NVMF_BACKEND_CONTROLLER:
208ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_NVMF_BACKEND_CONTROLLER");
209ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_NVMF_BACKEND_CONTROLLER:
210ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_NVMF_BACKEND_CONTROLLER");
211ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_NVMF_BACKEND_CONTROLLER:
212ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_NVMF_BACKEND_CONTROLLER");
213ebb7c6fdSAlex Wilson 	case MLXCX_OP_ATTACH_NVMF_NAMESPACE:
214ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ATTACH_NVMF_NAMESPACE");
215ebb7c6fdSAlex Wilson 	case MLXCX_OP_DETACH_NVMF_NAMESPACE:
216ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DETACH_NVMF_NAMESPACE");
217ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
218ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_XRQ_DC_PARAMS_ENTRY");
219ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_XRQ_DC_PARAMS_ENTRY:
220ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_XRQ_DC_PARAMS_ENTRY");
221ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_XRQ_ERROR_PARAMS:
222ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_XRQ_ERROR_PARAMS");
223ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_VPORT_STATE:
224ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_VPORT_STATE");
225ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_VPORT_STATE:
226ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_VPORT_STATE");
227ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_ESW_VPORT_CONTEXT:
228ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_ESW_VPORT_CONTEXT");
229ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_ESW_VPORT_CONTEXT:
230ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_ESW_VPORT_CONTEXT");
231ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_NIC_VPORT_CONTEXT:
232ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_NIC_VPORT_CONTEXT");
233ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_NIC_VPORT_CONTEXT:
234ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_NIC_VPORT_CONTEXT");
235ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_ROCE_ADDRESS:
236ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_ROCE_ADDRESS");
237ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_ROCE_ADDRESS:
238ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_ROCE_ADDRESS");
239ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_HCA_VPORT_CONTEXT:
240ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_HCA_VPORT_CONTEXT");
241ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_HCA_VPORT_CONTEXT:
242ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_HCA_VPORT_CONTEXT");
243ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_HCA_VPORT_GID:
244ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_HCA_VPORT_GID");
245ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_HCA_VPORT_PKEY:
246ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_HCA_VPORT_PKEY");
247ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_VPORT_COUNTER:
248ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_VPORT_COUNTER");
249ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_Q_COUNTER:
250ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_Q_COUNTER");
251ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_Q_COUNTER:
252ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_Q_COUNTER");
253ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_Q_COUNTER:
254ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_Q_COUNTER");
255ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_PP_RATE_LIMIT:
256ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_PP_RATE_LIMIT");
257ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_PP_RATE_LIMIT:
258ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_PP_RATE_LIMIT");
259ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_PD:
260ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_PD");
261ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_PD:
262ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_PD");
263ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_UAR:
264ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_UAR");
265ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_UAR:
266ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_UAR");
267ebb7c6fdSAlex Wilson 	case MLXCX_OP_CONFIG_INT_MODERATION:
268ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CONFIG_INT_MODERATION");
269ebb7c6fdSAlex Wilson 	case MLXCX_OP_ACCESS_REG:
270ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ACCESS_REG");
271ebb7c6fdSAlex Wilson 	case MLXCX_OP_ATTACH_TO_MCG:
272ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ATTACH_TO_MCG");
273ebb7c6fdSAlex Wilson 	case MLXCX_OP_DETACH_FROM_MCG:
274ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DETACH_FROM_MCG");
275ebb7c6fdSAlex Wilson 	case MLXCX_OP_MAD_IFC:
276ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MAD_IFC");
277ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_MAD_DEMUX:
278ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_MAD_DEMUX");
279ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_MAD_DEMUX:
280ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_MAD_DEMUX");
281ebb7c6fdSAlex Wilson 	case MLXCX_OP_NOP:
282ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_NOP");
283ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_XRCD:
284ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_XRCD");
285ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_XRCD:
286ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_XRCD");
287ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_TRANSPORT_DOMAIN:
288ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_TRANSPORT_DOMAIN");
289ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_TRANSPORT_DOMAIN:
290ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_TRANSPORT_DOMAIN");
291ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_CONG_STATUS:
292ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_CONG_STATUS");
293ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_CONG_STATUS:
294ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_CONG_STATUS");
295ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_CONG_PARAMS:
296ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_CONG_PARAMS");
297ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_CONG_PARAMS:
298ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_CONG_PARAMS");
299ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_CONG_STATISTICS:
300ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_CONG_STATISTICS");
301ebb7c6fdSAlex Wilson 	case MLXCX_OP_ADD_VXLAN_UDP_DPORT:
302ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ADD_VXLAN_UDP_DPORT");
303ebb7c6fdSAlex Wilson 	case MLXCX_OP_DELETE_VXLAN_UDP_DPORT:
304ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DELETE_VXLAN_UDP_DPORT");
305ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_L2_TABLE_ENTRY:
306ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_L2_TABLE_ENTRY");
307ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_L2_TABLE_ENTRY:
308ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_L2_TABLE_ENTRY");
309ebb7c6fdSAlex Wilson 	case MLXCX_OP_DELETE_L2_TABLE_ENTRY:
310ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DELETE_L2_TABLE_ENTRY");
311ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_WOL_ROL:
312ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_WOL_ROL");
313ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_WOL_ROL:
314ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_WOL_ROL");
315ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_TIR:
316ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_TIR");
317ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_TIR:
318ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_TIR");
319ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_TIR:
320ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_TIR");
321ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_TIR:
322ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_TIR");
323ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_SQ:
324ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_SQ");
325ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_SQ:
326ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_SQ");
327ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_SQ:
328ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_SQ");
329ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_SQ:
330ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_SQ");
331ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_RQ:
332ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_RQ");
333ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_RQ:
334ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_RQ");
335ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_RQ:
336ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_RQ");
337ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_RQ:
338ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_RQ");
339ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_RMP:
340ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_RMP");
341ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_RMP:
342ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_RMP");
343ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_RMP:
344ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_RMP");
345ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_RMP:
346ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_RMP");
347ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_TIS:
348ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_TIS");
349ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_TIS:
350ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_TIS");
351ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_TIS:
352ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_TIS");
353ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_TIS:
354ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_TIS");
355ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_RQT:
356ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_RQT");
357ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_RQT:
358ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_RQT");
359ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_RQT:
360ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_RQT");
361ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_RQT:
362ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_RQT");
363ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_FLOW_TABLE_ROOT:
364ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_FLOW_TABLE_ROOT");
365ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_FLOW_TABLE:
366ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_FLOW_TABLE");
367ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_FLOW_TABLE:
368ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_FLOW_TABLE");
369ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_FLOW_TABLE:
370ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_FLOW_TABLE");
371ebb7c6fdSAlex Wilson 	case MLXCX_OP_CREATE_FLOW_GROUP:
372ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_CREATE_FLOW_GROUP");
373ebb7c6fdSAlex Wilson 	case MLXCX_OP_DESTROY_FLOW_GROUP:
374ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DESTROY_FLOW_GROUP");
375ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_FLOW_GROUP:
376ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_FLOW_GROUP");
377ebb7c6fdSAlex Wilson 	case MLXCX_OP_SET_FLOW_TABLE_ENTRY:
378ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_SET_FLOW_TABLE_ENTRY");
379ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_FLOW_TABLE_ENTRY:
380ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_FLOW_TABLE_ENTRY");
381ebb7c6fdSAlex Wilson 	case MLXCX_OP_DELETE_FLOW_TABLE_ENTRY:
382ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DELETE_FLOW_TABLE_ENTRY");
383ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_FLOW_COUNTER:
384ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_FLOW_COUNTER");
385ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_FLOW_COUNTER:
386ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_FLOW_COUNTER");
387ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_FLOW_COUNTER:
388ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_FLOW_COUNTER");
389ebb7c6fdSAlex Wilson 	case MLXCX_OP_MODIFY_FLOW_TABLE:
390ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_MODIFY_FLOW_TABLE");
391ebb7c6fdSAlex Wilson 	case MLXCX_OP_ALLOC_ENCAP_HEADER:
392ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_ALLOC_ENCAP_HEADER");
393ebb7c6fdSAlex Wilson 	case MLXCX_OP_DEALLOC_ENCAP_HEADER:
394ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_DEALLOC_ENCAP_HEADER");
395ebb7c6fdSAlex Wilson 	case MLXCX_OP_QUERY_ENCAP_HEADER:
396ebb7c6fdSAlex Wilson 		return ("MLXCX_OP_QUERY_ENCAP_HEADER");
397ebb7c6fdSAlex Wilson 	default:
398ebb7c6fdSAlex Wilson 		return ("Unknown Opcode");
399ebb7c6fdSAlex Wilson 	}
400ebb7c6fdSAlex Wilson }
401ebb7c6fdSAlex Wilson 
402ebb7c6fdSAlex Wilson const char *
mlxcx_port_status_string(mlxcx_port_status_t st)403ebb7c6fdSAlex Wilson mlxcx_port_status_string(mlxcx_port_status_t st)
404ebb7c6fdSAlex Wilson {
405ebb7c6fdSAlex Wilson 	switch (st) {
406ebb7c6fdSAlex Wilson 	case MLXCX_PORT_STATUS_UP:
407ebb7c6fdSAlex Wilson 		return ("UP");
408ebb7c6fdSAlex Wilson 	case MLXCX_PORT_STATUS_DOWN:
409ebb7c6fdSAlex Wilson 		return ("DOWN");
410ebb7c6fdSAlex Wilson 	case MLXCX_PORT_STATUS_UP_ONCE:
411ebb7c6fdSAlex Wilson 		return ("UP_ONCE");
412ebb7c6fdSAlex Wilson 	case MLXCX_PORT_STATUS_DISABLED:
413ebb7c6fdSAlex Wilson 		return ("DISABLED");
414ebb7c6fdSAlex Wilson 	default:
415ebb7c6fdSAlex Wilson 		return ("UNKNOWN");
416ebb7c6fdSAlex Wilson 	}
417ebb7c6fdSAlex Wilson }
418ebb7c6fdSAlex Wilson 
419ebb7c6fdSAlex Wilson void
mlxcx_eth_proto_to_string(mlxcx_eth_proto_t p,mlxcx_ext_eth_proto_t ep,char * buf,size_t size)420*85e4aa97SDan McDonald mlxcx_eth_proto_to_string(mlxcx_eth_proto_t p, mlxcx_ext_eth_proto_t ep,
421*85e4aa97SDan McDonald     char *buf, size_t size)
422ebb7c6fdSAlex Wilson {
423ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_SGMII)
424ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "SGMII|", size);
425ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_1000BASE_KX)
426ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "1000BASE_KX|", size);
427ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_10GBASE_CX4)
428ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "10GBASE_CX4|", size);
429ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_10GBASE_KX4)
430ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "10GBASE_KX4|", size);
431ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_10GBASE_KR)
432ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "10GBASE_KR|", size);
433ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_40GBASE_CR4)
434ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "40GBASE_CR4|", size);
435ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_40GBASE_KR4)
436ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "40GBASE_KR4|", size);
437ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_SGMII_100BASE)
438ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "SGMII_100BASE|", size);
439ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_10GBASE_CR)
440ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "10GBASE_CR|", size);
441ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_10GBASE_SR)
442ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "10GBASE_SR|", size);
443ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_10GBASE_ER_LR)
444ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "10GBASE_ER_LR|", size);
445ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_40GBASE_SR4)
446ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "40GBASE_SR4|", size);
447ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_40GBASE_LR4_ER4)
448ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "40GBASE_LR4_ER4|", size);
449ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_50GBASE_SR2)
450ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "50GBASE_SR2|", size);
451ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_100GBASE_CR4)
452ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "100GBASE_CR4|", size);
453ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_100GBASE_SR4)
454ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "100GBASE_SR4|", size);
455ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_100GBASE_KR4)
456ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "100GBASE_KR4|", size);
457*85e4aa97SDan McDonald 	if (p & MLXCX_PROTO_100GBASE_LR4_ER4)
458*85e4aa97SDan McDonald 		(void) strlcat(buf, "100GBASE_LR4_ER4|", size);
459*85e4aa97SDan McDonald 	if (p & MLXCX_PROTO_100BASE_TX)
460*85e4aa97SDan McDonald 		(void) strlcat(buf, "100BASE_TX|", size);
461*85e4aa97SDan McDonald 	if (p & MLXCX_PROTO_1000BASE_T)
462*85e4aa97SDan McDonald 		(void) strlcat(buf, "1000BASE_T|", size);
463*85e4aa97SDan McDonald 	if (p & MLXCX_PROTO_10GBASE_T)
464*85e4aa97SDan McDonald 		(void) strlcat(buf, "10GBASE_T|", size);
465ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_25GBASE_CR)
466ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "25GBASE_CR|", size);
467ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_25GBASE_KR)
468ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "25GBASE_KR|", size);
469ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_25GBASE_SR)
470ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "25GBASE_SR|", size);
471ebb7c6fdSAlex Wilson 	if (p & MLXCX_PROTO_50GBASE_CR2)
472ebb7c6fdSAlex Wilson 		(void) strlcat(buf, "50GBASE_CR2|", size);
473*85e4aa97SDan McDonald 	if (p & MLXCX_PROTO_50GBASE_KR2)
474*85e4aa97SDan McDonald 		(void) strlcat(buf, "50GBASE_KR2|", size);
475*85e4aa97SDan McDonald 
476*85e4aa97SDan McDonald 	/* Now, for the extended bits... */
477*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_SGMII_100BASE)
478*85e4aa97SDan McDonald 		(void) strlcat(buf, "SGMII_100BASE|", size);
479*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_1000BASE_X_SGMII)
480*85e4aa97SDan McDonald 		(void) strlcat(buf, "1000BASE_X_SGMII|", size);
481*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_5GBASE_R)
482*85e4aa97SDan McDonald 		(void) strlcat(buf, "5GBASE_R|", size);
483*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_10GBASE_XFI_XAUI_1)
484*85e4aa97SDan McDonald 		(void) strlcat(buf, "10GBASE_XFI_XAUI_1|", size);
485*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_40GBASE_XLAUI_4_XLPPI_4)
486*85e4aa97SDan McDonald 		(void) strlcat(buf, "40GBASE_XLAUI_4_XLPPI_4|", size);
487*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_25GAUI_1_25GBASE_CR_KR)
488*85e4aa97SDan McDonald 		(void) strlcat(buf, "25GAUI_1_25GBASE_CR_KR|", size);
489*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_50GAUI_2_LAUI_2_50GBASE_CR2_KR2)
490*85e4aa97SDan McDonald 		(void) strlcat(buf, "50GAUI_2_LAUI_2_50GBASE_CR2_KR2|", size);
491*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_50GAUI_1_LAUI_1_50GBASE_CR_KR)
492*85e4aa97SDan McDonald 		(void) strlcat(buf, "50GAUI_1_LAUI_1_50GBASE_CR_KR|", size);
493*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_CAUI_4_100GBASE_CR4_KR4)
494*85e4aa97SDan McDonald 		(void) strlcat(buf, "CAUI_4_100GBASE_CR4_KR4|", size);
495*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_100GAUI_2_100GBASE_CR2_KR2)
496*85e4aa97SDan McDonald 		(void) strlcat(buf, "100GAUI_2_100GBASE_CR2_KR2|", size);
497*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_100GAUI_1_100GBASE_CR_KR)
498*85e4aa97SDan McDonald 		(void) strlcat(buf, "100GAUI_1_100GBASE_CR_KR|", size);
499*85e4aa97SDan McDonald 	/* Print these if we need 'em for debugging... */
500*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_200GAUI_4_200GBASE_CR4_KR4)
501*85e4aa97SDan McDonald 		(void) strlcat(buf, "200GAUI_4_200GBASE_CR4_KR4|", size);
502*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_200GAUI_2_200GBASE_CR2_KR2)
503*85e4aa97SDan McDonald 		(void) strlcat(buf, "200GAUI_2_200GBASE_CR2_KR2|", size);
504*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_400GAUI_8_400GBASE_CR8)
505*85e4aa97SDan McDonald 		(void) strlcat(buf, "400GAUI_8_400GBASE_CR8|", size);
506*85e4aa97SDan McDonald 	if (ep & MLXCX_EXTPROTO_400GAUI_4_400GBASE_CR4)
507*85e4aa97SDan McDonald 		(void) strlcat(buf, "400GAUI_4_400GBASE_CR4|", size);
508*85e4aa97SDan McDonald 
509ebb7c6fdSAlex Wilson 	/* Chop off the trailing '|' */
510ebb7c6fdSAlex Wilson 	if (strlen(buf) > 0)
511ebb7c6fdSAlex Wilson 		buf[strlen(buf) - 1] = '\0';
512ebb7c6fdSAlex Wilson }
513ebb7c6fdSAlex Wilson 
514ebb7c6fdSAlex Wilson void
mlxcx_cmd_queue_fini(mlxcx_t * mlxp)515ebb7c6fdSAlex Wilson mlxcx_cmd_queue_fini(mlxcx_t *mlxp)
516ebb7c6fdSAlex Wilson {
517ebb7c6fdSAlex Wilson 	mlxcx_cmd_queue_t *cmd = &mlxp->mlx_cmd;
518ebb7c6fdSAlex Wilson 
519ebb7c6fdSAlex Wilson 	if (cmd->mcmd_tokens != NULL) {
520ebb7c6fdSAlex Wilson 		id_space_destroy(cmd->mcmd_tokens);
521ebb7c6fdSAlex Wilson 		cmd->mcmd_tokens = NULL;
522ebb7c6fdSAlex Wilson 	}
523ebb7c6fdSAlex Wilson 
524ebb7c6fdSAlex Wilson 	if (cmd->mcmd_taskq != NULL) {
525ebb7c6fdSAlex Wilson 		ddi_taskq_destroy(cmd->mcmd_taskq);
526ebb7c6fdSAlex Wilson 		cmd->mcmd_taskq = NULL;
527ebb7c6fdSAlex Wilson 	}
528ebb7c6fdSAlex Wilson 
529ebb7c6fdSAlex Wilson 	cv_destroy(&cmd->mcmd_cv);
530ebb7c6fdSAlex Wilson 	mutex_destroy(&cmd->mcmd_lock);
531ebb7c6fdSAlex Wilson 
532ebb7c6fdSAlex Wilson 	mlxcx_dma_free(&cmd->mcmd_dma);
533ebb7c6fdSAlex Wilson }
534ebb7c6fdSAlex Wilson 
535ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_queue_init(mlxcx_t * mlxp)536ebb7c6fdSAlex Wilson mlxcx_cmd_queue_init(mlxcx_t *mlxp)
537ebb7c6fdSAlex Wilson {
538ebb7c6fdSAlex Wilson 	uint32_t tmp, cmd_low, cmd_high, i;
539ebb7c6fdSAlex Wilson 	mlxcx_cmd_queue_t *cmd = &mlxp->mlx_cmd;
5405f0e3176SPaul Winder 	char buf[32];
5415f0e3176SPaul Winder 	char tq_name[TASKQ_NAMELEN];
542ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *ck;
543ebb7c6fdSAlex Wilson 
544ebb7c6fdSAlex Wilson 	ddi_device_acc_attr_t acc;
545ebb7c6fdSAlex Wilson 	ddi_dma_attr_t attr;
546ebb7c6fdSAlex Wilson 
547ebb7c6fdSAlex Wilson 	tmp = mlxcx_get32(mlxp, MLXCX_ISS_FIRMWARE);
548ebb7c6fdSAlex Wilson 	mlxp->mlx_fw_maj = MLXCX_ISS_FW_MAJOR(tmp);
549ebb7c6fdSAlex Wilson 	mlxp->mlx_fw_min = MLXCX_ISS_FW_MINOR(tmp);
550ebb7c6fdSAlex Wilson 
551ebb7c6fdSAlex Wilson 	tmp = mlxcx_get32(mlxp, MLXCX_ISS_FW_CMD);
552ebb7c6fdSAlex Wilson 	mlxp->mlx_fw_rev = MLXCX_ISS_FW_REV(tmp);
553ebb7c6fdSAlex Wilson 	mlxp->mlx_cmd_rev = MLXCX_ISS_CMD_REV(tmp);
554ebb7c6fdSAlex Wilson 
555ebb7c6fdSAlex Wilson 	if (mlxp->mlx_cmd_rev != MLXCX_CMD_REVISION) {
556ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "found unsupported command revision: %u, "
557ebb7c6fdSAlex Wilson 		    "expected %u", mlxp->mlx_cmd_rev, MLXCX_CMD_REVISION);
558ebb7c6fdSAlex Wilson 		return (B_FALSE);
559ebb7c6fdSAlex Wilson 	}
560ebb7c6fdSAlex Wilson 
561ebb7c6fdSAlex Wilson 	cmd_low = mlxcx_get32(mlxp, MLXCX_ISS_CMD_LOW);
562ebb7c6fdSAlex Wilson 	cmd->mcmd_size_l2 = MLXCX_ISS_CMDQ_SIZE(cmd_low);
563ebb7c6fdSAlex Wilson 	cmd->mcmd_stride_l2 = MLXCX_ISS_CMDQ_STRIDE(cmd_low);
5645f0e3176SPaul Winder 	cmd->mcmd_size = 1U << cmd->mcmd_size_l2;
5655f0e3176SPaul Winder 
5665f0e3176SPaul Winder 	if (cmd->mcmd_size > MLXCX_CMD_MAX) {
5675f0e3176SPaul Winder 		mlxcx_warn(mlxp, "command queue size %u is too "
5685f0e3176SPaul Winder 		    "large. Maximum is %u", cmd->mcmd_size, MLXCX_CMD_MAX);
5695f0e3176SPaul Winder 		return (B_FALSE);
5705f0e3176SPaul Winder 	}
5715f0e3176SPaul Winder 
5725f0e3176SPaul Winder 	cmd->mcmd_mask = (uint32_t)((1ULL << cmd->mcmd_size) - 1);
573ebb7c6fdSAlex Wilson 
574ebb7c6fdSAlex Wilson 	mutex_init(&cmd->mcmd_lock, NULL, MUTEX_DRIVER, NULL);
575ebb7c6fdSAlex Wilson 	cv_init(&cmd->mcmd_cv, NULL, CV_DRIVER, NULL);
576ebb7c6fdSAlex Wilson 
577ebb7c6fdSAlex Wilson 	(void) snprintf(buf, sizeof (buf), "mlxcx_tokens_%d", mlxp->mlx_inst);
578ebb7c6fdSAlex Wilson 	if ((cmd->mcmd_tokens = id_space_create(buf, 1, UINT8_MAX)) == NULL) {
579ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "failed to allocate token id space");
580ebb7c6fdSAlex Wilson 		mlxcx_cmd_queue_fini(mlxp);
581ebb7c6fdSAlex Wilson 		return (B_FALSE);
582ebb7c6fdSAlex Wilson 	}
583ebb7c6fdSAlex Wilson 
5845f0e3176SPaul Winder 	(void) snprintf(tq_name, sizeof (tq_name), "cmdq_%d", mlxp->mlx_inst);
5855f0e3176SPaul Winder 	if ((cmd->mcmd_taskq = ddi_taskq_create(mlxp->mlx_dip, tq_name, 1,
586ebb7c6fdSAlex Wilson 	    TASKQ_DEFAULTPRI, 0)) == NULL) {
587ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "failed to create command queue task queue");
588ebb7c6fdSAlex Wilson 		mlxcx_cmd_queue_fini(mlxp);
589ebb7c6fdSAlex Wilson 		return (B_FALSE);
590ebb7c6fdSAlex Wilson 	}
591ebb7c6fdSAlex Wilson 
592ebb7c6fdSAlex Wilson 	mlxcx_dma_acc_attr(mlxp, &acc);
593ebb7c6fdSAlex Wilson 	mlxcx_dma_page_attr(mlxp, &attr);
594ebb7c6fdSAlex Wilson 
595ebb7c6fdSAlex Wilson 	if (!mlxcx_dma_alloc(mlxp, &cmd->mcmd_dma, &attr, &acc, B_TRUE,
596ebb7c6fdSAlex Wilson 	    MLXCX_CMD_DMA_PAGE_SIZE, B_TRUE)) {
597ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "failed to allocate command dma buffer");
598ebb7c6fdSAlex Wilson 		mlxcx_cmd_queue_fini(mlxp);
599ebb7c6fdSAlex Wilson 		return (B_FALSE);
600ebb7c6fdSAlex Wilson 	}
601ebb7c6fdSAlex Wilson 
602ebb7c6fdSAlex Wilson 	ck = mlxcx_dma_cookie_one(&cmd->mcmd_dma);
603ebb7c6fdSAlex Wilson 	cmd_high = (uint32_t)(ck->dmac_laddress >> 32);
604ebb7c6fdSAlex Wilson 	cmd_low = (uint32_t)(ck->dmac_laddress & UINT32_MAX);
605ebb7c6fdSAlex Wilson 
606ebb7c6fdSAlex Wilson 	mlxcx_put32(mlxp, MLXCX_ISS_CMD_HIGH, cmd_high);
607ebb7c6fdSAlex Wilson 	mlxcx_put32(mlxp, MLXCX_ISS_CMD_LOW, cmd_low);
608ebb7c6fdSAlex Wilson 
609ebb7c6fdSAlex Wilson 	/*
610ebb7c6fdSAlex Wilson 	 * Before this is ready, the initializing bit must become zero.
611ebb7c6fdSAlex Wilson 	 */
612ebb7c6fdSAlex Wilson 	for (i = 0; i < mlxcx_cmd_init_trys; i++) {
613ebb7c6fdSAlex Wilson 		uint32_t init = mlxcx_get32(mlxp, MLXCX_ISS_INIT);
614ebb7c6fdSAlex Wilson 
615ebb7c6fdSAlex Wilson 		if (MLXCX_ISS_INITIALIZING(init) == 0)
616ebb7c6fdSAlex Wilson 			break;
617ebb7c6fdSAlex Wilson 		delay(drv_usectohz(mlxcx_cmd_init_delay));
618ebb7c6fdSAlex Wilson 	}
619ebb7c6fdSAlex Wilson 	if (i == mlxcx_cmd_init_trys) {
620ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "timed out initializing command queue");
621ebb7c6fdSAlex Wilson 		mlxcx_cmd_queue_fini(mlxp);
622ebb7c6fdSAlex Wilson 		return (B_FALSE);
623ebb7c6fdSAlex Wilson 	}
624ebb7c6fdSAlex Wilson 
6255f0e3176SPaul Winder 	/*
6265f0e3176SPaul Winder 	 * start in polling mode.
6275f0e3176SPaul Winder 	 */
6285f0e3176SPaul Winder 	mlxcx_cmd_eq_disable(mlxp);
629ebb7c6fdSAlex Wilson 
630ebb7c6fdSAlex Wilson 	return (B_TRUE);
631ebb7c6fdSAlex Wilson }
632ebb7c6fdSAlex Wilson 
6335f0e3176SPaul Winder void
mlxcx_cmd_eq_enable(mlxcx_t * mlxp)6345f0e3176SPaul Winder mlxcx_cmd_eq_enable(mlxcx_t *mlxp)
6355f0e3176SPaul Winder {
6365f0e3176SPaul Winder 	mlxp->mlx_cmd.mcmd_polled = B_FALSE;
6375f0e3176SPaul Winder }
6385f0e3176SPaul Winder 
6395f0e3176SPaul Winder void
mlxcx_cmd_eq_disable(mlxcx_t * mlxp)6405f0e3176SPaul Winder mlxcx_cmd_eq_disable(mlxcx_t *mlxp)
6415f0e3176SPaul Winder {
6425f0e3176SPaul Winder 	mlxp->mlx_cmd.mcmd_polled = B_TRUE;
6435f0e3176SPaul Winder }
6445f0e3176SPaul Winder 
645ebb7c6fdSAlex Wilson static void
mlxcx_cmd_in_header_init(mlxcx_cmd_t * cmd,mlxcx_cmd_in_t * in,mlxcx_cmd_op_t op,uint16_t mod)646ebb7c6fdSAlex Wilson mlxcx_cmd_in_header_init(mlxcx_cmd_t *cmd, mlxcx_cmd_in_t *in,
647ebb7c6fdSAlex Wilson     mlxcx_cmd_op_t op, uint16_t mod)
648ebb7c6fdSAlex Wilson {
649ebb7c6fdSAlex Wilson 	ASSERT3U(op, <=, UINT16_MAX);
650ebb7c6fdSAlex Wilson 	in->mci_opcode = to_be16(op);
651ebb7c6fdSAlex Wilson 	in->mci_op_mod = to_be16(mod);
652ebb7c6fdSAlex Wilson 	cmd->mlcmd_op = op;
653ebb7c6fdSAlex Wilson }
654ebb7c6fdSAlex Wilson 
655ebb7c6fdSAlex Wilson static boolean_t
mlxcx_cmd_mbox_alloc(mlxcx_t * mlxp,list_t * listp,uint8_t nblocks)656ebb7c6fdSAlex Wilson mlxcx_cmd_mbox_alloc(mlxcx_t *mlxp, list_t *listp, uint8_t nblocks)
657ebb7c6fdSAlex Wilson {
658ebb7c6fdSAlex Wilson 	uint8_t i;
659ebb7c6fdSAlex Wilson 	ddi_device_acc_attr_t acc;
660ebb7c6fdSAlex Wilson 	ddi_dma_attr_t attr;
661ebb7c6fdSAlex Wilson 
662ebb7c6fdSAlex Wilson 	mlxcx_dma_acc_attr(mlxp, &acc);
663ebb7c6fdSAlex Wilson 	mlxcx_dma_page_attr(mlxp, &attr);
664ebb7c6fdSAlex Wilson 
665ebb7c6fdSAlex Wilson 	for (i = 0; i < nblocks; i++) {
666ebb7c6fdSAlex Wilson 		mlxcx_cmd_mbox_t *mbox;
667ebb7c6fdSAlex Wilson 
668ebb7c6fdSAlex Wilson 		mbox = kmem_zalloc(sizeof (*mbox), KM_SLEEP);
669ebb7c6fdSAlex Wilson 		if (!mlxcx_dma_alloc(mlxp, &mbox->mlbox_dma, &attr, &acc,
670ebb7c6fdSAlex Wilson 		    B_TRUE, sizeof (mlxcx_cmd_mailbox_t), B_TRUE)) {
671ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "failed to allocate mailbox dma "
672ebb7c6fdSAlex Wilson 			    "buffer");
673ebb7c6fdSAlex Wilson 			kmem_free(mbox, sizeof (*mbox));
674ebb7c6fdSAlex Wilson 			/*
675ebb7c6fdSAlex Wilson 			 * mlxcx_cmd_fini will clean up any mboxes that we
676ebb7c6fdSAlex Wilson 			 * already placed onto listp.
677ebb7c6fdSAlex Wilson 			 */
678ebb7c6fdSAlex Wilson 			return (B_FALSE);
679ebb7c6fdSAlex Wilson 		}
680ebb7c6fdSAlex Wilson 		mbox->mlbox_data = (void *)mbox->mlbox_dma.mxdb_va;
681ebb7c6fdSAlex Wilson 		list_insert_tail(listp, mbox);
682ebb7c6fdSAlex Wilson 	}
683ebb7c6fdSAlex Wilson 
684ebb7c6fdSAlex Wilson 	return (B_TRUE);
685ebb7c6fdSAlex Wilson }
686ebb7c6fdSAlex Wilson 
687ebb7c6fdSAlex Wilson static void
mlxcx_cmd_mbox_free(mlxcx_cmd_mbox_t * mbox)688ebb7c6fdSAlex Wilson mlxcx_cmd_mbox_free(mlxcx_cmd_mbox_t *mbox)
689ebb7c6fdSAlex Wilson {
690ebb7c6fdSAlex Wilson 	mlxcx_dma_free(&mbox->mlbox_dma);
691ebb7c6fdSAlex Wilson 	kmem_free(mbox, sizeof (mlxcx_cmd_mbox_t));
692ebb7c6fdSAlex Wilson }
693ebb7c6fdSAlex Wilson 
694ebb7c6fdSAlex Wilson static void
mlxcx_cmd_fini(mlxcx_t * mlxp,mlxcx_cmd_t * cmd)695ebb7c6fdSAlex Wilson mlxcx_cmd_fini(mlxcx_t *mlxp, mlxcx_cmd_t *cmd)
696ebb7c6fdSAlex Wilson {
697ebb7c6fdSAlex Wilson 	mlxcx_cmd_mbox_t *mbox;
698ebb7c6fdSAlex Wilson 
699ebb7c6fdSAlex Wilson 	while ((mbox = list_remove_head(&cmd->mlcmd_mbox_out)) != NULL) {
700ebb7c6fdSAlex Wilson 		mlxcx_cmd_mbox_free(mbox);
701ebb7c6fdSAlex Wilson 	}
702ebb7c6fdSAlex Wilson 	list_destroy(&cmd->mlcmd_mbox_out);
703ebb7c6fdSAlex Wilson 	while ((mbox = list_remove_head(&cmd->mlcmd_mbox_in)) != NULL) {
704ebb7c6fdSAlex Wilson 		mlxcx_cmd_mbox_free(mbox);
705ebb7c6fdSAlex Wilson 	}
706ebb7c6fdSAlex Wilson 	list_destroy(&cmd->mlcmd_mbox_in);
707ebb7c6fdSAlex Wilson 	id_free(mlxp->mlx_cmd.mcmd_tokens, cmd->mlcmd_token);
708ebb7c6fdSAlex Wilson 	cv_destroy(&cmd->mlcmd_cv);
709ebb7c6fdSAlex Wilson 	mutex_destroy(&cmd->mlcmd_lock);
710ebb7c6fdSAlex Wilson }
711ebb7c6fdSAlex Wilson 
712ebb7c6fdSAlex Wilson static void
mlxcx_cmd_init(mlxcx_t * mlxp,mlxcx_cmd_t * cmd)713ebb7c6fdSAlex Wilson mlxcx_cmd_init(mlxcx_t *mlxp, mlxcx_cmd_t *cmd)
714ebb7c6fdSAlex Wilson {
715ebb7c6fdSAlex Wilson 	bzero(cmd, sizeof (*cmd));
716e1447ca9SPaul Winder 	mutex_init(&cmd->mlcmd_lock, NULL, MUTEX_DRIVER,
717e1447ca9SPaul Winder 	    DDI_INTR_PRI(mlxp->mlx_async_intr_pri));
718ebb7c6fdSAlex Wilson 	cv_init(&cmd->mlcmd_cv, NULL, CV_DRIVER, NULL);
719ebb7c6fdSAlex Wilson 	cmd->mlcmd_token = id_alloc(mlxp->mlx_cmd.mcmd_tokens);
7205f0e3176SPaul Winder 	cmd->mlcmd_poll = mlxp->mlx_cmd.mcmd_polled;
721ebb7c6fdSAlex Wilson 	list_create(&cmd->mlcmd_mbox_in, sizeof (mlxcx_cmd_mbox_t),
722ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_cmd_mbox_t, mlbox_node));
723ebb7c6fdSAlex Wilson 	list_create(&cmd->mlcmd_mbox_out, sizeof (mlxcx_cmd_mbox_t),
724ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_cmd_mbox_t, mlbox_node));
725ebb7c6fdSAlex Wilson }
726ebb7c6fdSAlex Wilson 
727ebb7c6fdSAlex Wilson static void
mlxcx_cmd_prep_input(mlxcx_cmd_ent_t * ent,mlxcx_cmd_t * cmd)728ebb7c6fdSAlex Wilson mlxcx_cmd_prep_input(mlxcx_cmd_ent_t *ent, mlxcx_cmd_t *cmd)
729ebb7c6fdSAlex Wilson {
730ebb7c6fdSAlex Wilson 	uint32_t rem = cmd->mlcmd_inlen;
731ebb7c6fdSAlex Wilson 	uint8_t i;
732ebb7c6fdSAlex Wilson 	const void *in = cmd->mlcmd_in;
733ebb7c6fdSAlex Wilson 	uint32_t copy;
734ebb7c6fdSAlex Wilson 	mlxcx_cmd_mbox_t *mbox;
735ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *ck;
736ebb7c6fdSAlex Wilson 
737ebb7c6fdSAlex Wilson 	copy = MIN(MLXCX_CMD_INLINE_INPUT_LEN, rem);
738ebb7c6fdSAlex Wilson 	bcopy(in, ent->mce_input, copy);
739ebb7c6fdSAlex Wilson 
740ebb7c6fdSAlex Wilson 	rem -= copy;
741ebb7c6fdSAlex Wilson 	in += copy;
742ebb7c6fdSAlex Wilson 
743ebb7c6fdSAlex Wilson 	if (rem == 0) {
744ebb7c6fdSAlex Wilson 		ent->mce_in_mbox = to_be64(0);
745ebb7c6fdSAlex Wilson 		VERIFY3U(cmd->mlcmd_nboxes_in, ==, 0);
746ebb7c6fdSAlex Wilson 		return;
747ebb7c6fdSAlex Wilson 	}
748ebb7c6fdSAlex Wilson 
749ebb7c6fdSAlex Wilson 	mbox = list_head(&cmd->mlcmd_mbox_in);
750ebb7c6fdSAlex Wilson 	ck = mlxcx_dma_cookie_one(&mbox->mlbox_dma);
751ebb7c6fdSAlex Wilson 	ent->mce_in_mbox = to_be64(ck->dmac_laddress);
752ebb7c6fdSAlex Wilson 	for (i = 0; mbox != NULL;
753ebb7c6fdSAlex Wilson 	    mbox = list_next(&cmd->mlcmd_mbox_in, mbox), i++) {
754ebb7c6fdSAlex Wilson 		mlxcx_cmd_mbox_t *next;
755ebb7c6fdSAlex Wilson 		mlxcx_cmd_mailbox_t *mp = mbox->mlbox_data;
756ebb7c6fdSAlex Wilson 
757ebb7c6fdSAlex Wilson 		copy = MIN(MLXCX_CMD_MAILBOX_LEN, rem);
758ebb7c6fdSAlex Wilson 		bcopy(in, mp->mlxb_data, copy);
759ebb7c6fdSAlex Wilson 		rem -= copy;
760ebb7c6fdSAlex Wilson 		in += copy;
761ebb7c6fdSAlex Wilson 
762ebb7c6fdSAlex Wilson 		mp->mlxb_token = cmd->mlcmd_token;
763ebb7c6fdSAlex Wilson 		mp->mlxb_blockno = to_be32(i);
764ebb7c6fdSAlex Wilson 
765ebb7c6fdSAlex Wilson 		next = list_next(&cmd->mlcmd_mbox_in, mbox);
766ebb7c6fdSAlex Wilson 		if (next == NULL) {
767ebb7c6fdSAlex Wilson 			mp->mlxb_nextp = to_be64(0);
768ebb7c6fdSAlex Wilson 		} else {
769ebb7c6fdSAlex Wilson 			ck = mlxcx_dma_cookie_one(&next->mlbox_dma);
770ebb7c6fdSAlex Wilson 			mp->mlxb_nextp = to_be64(ck->dmac_laddress);
771ebb7c6fdSAlex Wilson 		}
772ebb7c6fdSAlex Wilson 		MLXCX_DMA_SYNC(mbox->mlbox_dma, DDI_DMA_SYNC_FORDEV);
773ebb7c6fdSAlex Wilson 	}
774ebb7c6fdSAlex Wilson 	VERIFY3U(i, ==, cmd->mlcmd_nboxes_in);
775ebb7c6fdSAlex Wilson 	VERIFY0(rem);
776ebb7c6fdSAlex Wilson }
777ebb7c6fdSAlex Wilson 
778ebb7c6fdSAlex Wilson static void
mlxcx_cmd_prep_output(mlxcx_cmd_ent_t * ent,mlxcx_cmd_t * cmd)779ebb7c6fdSAlex Wilson mlxcx_cmd_prep_output(mlxcx_cmd_ent_t *ent, mlxcx_cmd_t *cmd)
780ebb7c6fdSAlex Wilson {
781ebb7c6fdSAlex Wilson 	uint8_t i;
782ebb7c6fdSAlex Wilson 	mlxcx_cmd_mbox_t *mbox;
783ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *ck;
784ebb7c6fdSAlex Wilson 
785ebb7c6fdSAlex Wilson 	if (cmd->mlcmd_nboxes_out == 0) {
786ebb7c6fdSAlex Wilson 		ent->mce_out_mbox = to_be64(0);
787ebb7c6fdSAlex Wilson 		return;
788ebb7c6fdSAlex Wilson 	}
789ebb7c6fdSAlex Wilson 
790ebb7c6fdSAlex Wilson 	mbox = list_head(&cmd->mlcmd_mbox_out);
791ebb7c6fdSAlex Wilson 	ck = mlxcx_dma_cookie_one(&mbox->mlbox_dma);
792ebb7c6fdSAlex Wilson 	ent->mce_out_mbox = to_be64(ck->dmac_laddress);
793ebb7c6fdSAlex Wilson 	for (i = 0, mbox = list_head(&cmd->mlcmd_mbox_out); mbox != NULL;
794ebb7c6fdSAlex Wilson 	    mbox = list_next(&cmd->mlcmd_mbox_out, mbox), i++) {
795ebb7c6fdSAlex Wilson 		mlxcx_cmd_mbox_t *next;
796ebb7c6fdSAlex Wilson 		mlxcx_cmd_mailbox_t *mp = mbox->mlbox_data;
797ebb7c6fdSAlex Wilson 
798ebb7c6fdSAlex Wilson 		mp->mlxb_token = cmd->mlcmd_token;
799ebb7c6fdSAlex Wilson 		mp->mlxb_blockno = to_be32(i);
800ebb7c6fdSAlex Wilson 
801ebb7c6fdSAlex Wilson 		next = list_next(&cmd->mlcmd_mbox_out, mbox);
802ebb7c6fdSAlex Wilson 		if (next == NULL) {
803ebb7c6fdSAlex Wilson 			mp->mlxb_nextp = to_be64(0);
804ebb7c6fdSAlex Wilson 		} else {
805ebb7c6fdSAlex Wilson 			ck = mlxcx_dma_cookie_one(&next->mlbox_dma);
806ebb7c6fdSAlex Wilson 			mp->mlxb_nextp = to_be64(ck->dmac_laddress);
807ebb7c6fdSAlex Wilson 		}
808ebb7c6fdSAlex Wilson 		MLXCX_DMA_SYNC(mbox->mlbox_dma, DDI_DMA_SYNC_FORDEV);
809ebb7c6fdSAlex Wilson 	}
810ebb7c6fdSAlex Wilson 	VERIFY3U(i, ==, cmd->mlcmd_nboxes_out);
811ebb7c6fdSAlex Wilson }
812ebb7c6fdSAlex Wilson 
813ebb7c6fdSAlex Wilson static void
mlxcx_cmd_copy_output(mlxcx_cmd_ent_t * ent,mlxcx_cmd_t * cmd)814ebb7c6fdSAlex Wilson mlxcx_cmd_copy_output(mlxcx_cmd_ent_t *ent, mlxcx_cmd_t *cmd)
815ebb7c6fdSAlex Wilson {
816ebb7c6fdSAlex Wilson 	void *out = cmd->mlcmd_out;
817ebb7c6fdSAlex Wilson 	uint32_t rem = cmd->mlcmd_outlen;
818ebb7c6fdSAlex Wilson 	uint32_t copy;
819ebb7c6fdSAlex Wilson 	mlxcx_cmd_mbox_t *mbox;
820ebb7c6fdSAlex Wilson 
821ebb7c6fdSAlex Wilson 	copy = MIN(rem, MLXCX_CMD_INLINE_OUTPUT_LEN);
822ebb7c6fdSAlex Wilson 	bcopy(ent->mce_output, out, copy);
823ebb7c6fdSAlex Wilson 	out += copy;
824ebb7c6fdSAlex Wilson 	rem -= copy;
825ebb7c6fdSAlex Wilson 
826ebb7c6fdSAlex Wilson 	if (rem == 0) {
827ebb7c6fdSAlex Wilson 		VERIFY0(cmd->mlcmd_nboxes_out);
828ebb7c6fdSAlex Wilson 		return;
829ebb7c6fdSAlex Wilson 	}
830ebb7c6fdSAlex Wilson 
831ebb7c6fdSAlex Wilson 	for (mbox = list_head(&cmd->mlcmd_mbox_out); mbox != NULL;
832ebb7c6fdSAlex Wilson 	    mbox = list_next(&cmd->mlcmd_mbox_out, mbox)) {
833ebb7c6fdSAlex Wilson 		MLXCX_DMA_SYNC(mbox->mlbox_dma, DDI_DMA_SYNC_FORKERNEL);
834ebb7c6fdSAlex Wilson 		copy = MIN(MLXCX_CMD_MAILBOX_LEN, rem);
835ebb7c6fdSAlex Wilson 		bcopy(mbox->mlbox_data->mlxb_data, out, copy);
836ebb7c6fdSAlex Wilson 		out += copy;
837ebb7c6fdSAlex Wilson 		rem -= copy;
838ebb7c6fdSAlex Wilson 	}
839ebb7c6fdSAlex Wilson 	VERIFY0(rem);
840ebb7c6fdSAlex Wilson }
841ebb7c6fdSAlex Wilson 
8425f0e3176SPaul Winder static uint_t
mlxcx_cmd_reserve_slot(mlxcx_cmd_queue_t * cmdq)8435f0e3176SPaul Winder mlxcx_cmd_reserve_slot(mlxcx_cmd_queue_t *cmdq)
8445f0e3176SPaul Winder {
8455f0e3176SPaul Winder 	uint_t slot;
8465f0e3176SPaul Winder 
8475f0e3176SPaul Winder 	mutex_enter(&cmdq->mcmd_lock);
8485f0e3176SPaul Winder 	slot = ddi_ffs(cmdq->mcmd_mask);
8495f0e3176SPaul Winder 	while (slot == 0) {
8505f0e3176SPaul Winder 		cv_wait(&cmdq->mcmd_cv, &cmdq->mcmd_lock);
8515f0e3176SPaul Winder 		slot = ddi_ffs(cmdq->mcmd_mask);
8525f0e3176SPaul Winder 	}
8535f0e3176SPaul Winder 
8545f0e3176SPaul Winder 	cmdq->mcmd_mask &= ~(1U << --slot);
8555f0e3176SPaul Winder 
8565f0e3176SPaul Winder 	ASSERT3P(cmdq->mcmd_active[slot], ==, NULL);
8575f0e3176SPaul Winder 
8585f0e3176SPaul Winder 	mutex_exit(&cmdq->mcmd_lock);
8595f0e3176SPaul Winder 
8605f0e3176SPaul Winder 	return (slot);
8615f0e3176SPaul Winder }
8625f0e3176SPaul Winder 
8635f0e3176SPaul Winder static void
mlxcx_cmd_release_slot(mlxcx_cmd_queue_t * cmdq,uint_t slot)8645f0e3176SPaul Winder mlxcx_cmd_release_slot(mlxcx_cmd_queue_t *cmdq, uint_t slot)
8655f0e3176SPaul Winder {
8665f0e3176SPaul Winder 	mutex_enter(&cmdq->mcmd_lock);
8675f0e3176SPaul Winder 	cmdq->mcmd_mask |= 1U << slot;
8685f0e3176SPaul Winder 	cv_broadcast(&cmdq->mcmd_cv);
8695f0e3176SPaul Winder 	mutex_exit(&cmdq->mcmd_lock);
8705f0e3176SPaul Winder }
8715f0e3176SPaul Winder 
8725f0e3176SPaul Winder static void
mlxcx_cmd_done(mlxcx_cmd_t * cmd,uint_t slot)8735f0e3176SPaul Winder mlxcx_cmd_done(mlxcx_cmd_t *cmd, uint_t slot)
8745f0e3176SPaul Winder {
8755f0e3176SPaul Winder 	mlxcx_t *mlxp = cmd->mlcmd_mlxp;
8765f0e3176SPaul Winder 	mlxcx_cmd_queue_t *cmdq = &mlxp->mlx_cmd;
8775f0e3176SPaul Winder 	mlxcx_cmd_ent_t *ent;
8785f0e3176SPaul Winder 
8795f0e3176SPaul Winder 	/*
8805f0e3176SPaul Winder 	 * Command is done. Save relevant data. Once we broadcast on the CV and
8815f0e3176SPaul Winder 	 * drop the lock, we must not touch it again.
8825f0e3176SPaul Winder 	 */
8835f0e3176SPaul Winder 	MLXCX_DMA_SYNC(cmdq->mcmd_dma, DDI_DMA_SYNC_FORKERNEL);
8845f0e3176SPaul Winder 
8855f0e3176SPaul Winder 	ent = (mlxcx_cmd_ent_t *)(cmdq->mcmd_dma.mxdb_va +
8865f0e3176SPaul Winder 	    (slot << cmdq->mcmd_stride_l2));
8875f0e3176SPaul Winder 
8885f0e3176SPaul Winder 	mutex_enter(&cmd->mlcmd_lock);
8895f0e3176SPaul Winder 	cmd->mlcmd_status = MLXCX_CMD_STATUS(ent->mce_status);
8905f0e3176SPaul Winder 	if (cmd->mlcmd_status == 0)
8915f0e3176SPaul Winder 		mlxcx_cmd_copy_output(ent, cmd);
8925f0e3176SPaul Winder 
8935f0e3176SPaul Winder 	cmd->mlcmd_state = MLXCX_CMD_S_DONE;
8945f0e3176SPaul Winder 	cv_broadcast(&cmd->mlcmd_cv);
8955f0e3176SPaul Winder 	mutex_exit(&cmd->mlcmd_lock);
8965f0e3176SPaul Winder 
8975f0e3176SPaul Winder 	cmdq->mcmd_active[slot] = NULL;
8985f0e3176SPaul Winder 	mlxcx_cmd_release_slot(cmdq, slot);
8995f0e3176SPaul Winder }
9005f0e3176SPaul Winder 
901ebb7c6fdSAlex Wilson static void
mlxcx_cmd_taskq(void * arg)902ebb7c6fdSAlex Wilson mlxcx_cmd_taskq(void *arg)
903ebb7c6fdSAlex Wilson {
904ebb7c6fdSAlex Wilson 	mlxcx_cmd_t *cmd = arg;
905ebb7c6fdSAlex Wilson 	mlxcx_t *mlxp = cmd->mlcmd_mlxp;
906ebb7c6fdSAlex Wilson 	mlxcx_cmd_queue_t *cmdq = &mlxp->mlx_cmd;
907ebb7c6fdSAlex Wilson 	mlxcx_cmd_ent_t *ent;
9085f0e3176SPaul Winder 	uint_t poll, slot;
909ebb7c6fdSAlex Wilson 
910ebb7c6fdSAlex Wilson 	ASSERT3S(cmd->mlcmd_op, !=, 0);
911ebb7c6fdSAlex Wilson 
9125f0e3176SPaul Winder 	slot = mlxcx_cmd_reserve_slot(cmdq);
9135f0e3176SPaul Winder 	ent = (mlxcx_cmd_ent_t *)(cmdq->mcmd_dma.mxdb_va +
9145f0e3176SPaul Winder 	    (slot << cmdq->mcmd_stride_l2));
915ebb7c6fdSAlex Wilson 
9165f0e3176SPaul Winder 	cmdq->mcmd_active[slot] = cmd;
917ebb7c6fdSAlex Wilson 
918ebb7c6fdSAlex Wilson 	/*
919ebb7c6fdSAlex Wilson 	 * Command queue is currently ours as we set busy.
920ebb7c6fdSAlex Wilson 	 */
921ebb7c6fdSAlex Wilson 	bzero(ent, sizeof (*ent));
922ebb7c6fdSAlex Wilson 	ent->mce_type = MLXCX_CMD_TRANSPORT_PCI;
923ebb7c6fdSAlex Wilson 	ent->mce_in_length = to_be32(cmd->mlcmd_inlen);
924ebb7c6fdSAlex Wilson 	ent->mce_out_length = to_be32(cmd->mlcmd_outlen);
925ebb7c6fdSAlex Wilson 	ent->mce_token = cmd->mlcmd_token;
926ebb7c6fdSAlex Wilson 	ent->mce_sig = 0;
927ebb7c6fdSAlex Wilson 	ent->mce_status = MLXCX_CMD_HW_OWNED;
928ebb7c6fdSAlex Wilson 	mlxcx_cmd_prep_input(ent, cmd);
929ebb7c6fdSAlex Wilson 	mlxcx_cmd_prep_output(ent, cmd);
930ebb7c6fdSAlex Wilson 	MLXCX_DMA_SYNC(cmdq->mcmd_dma, DDI_DMA_SYNC_FORDEV);
931ebb7c6fdSAlex Wilson 
9325f0e3176SPaul Winder 	mlxcx_put32(mlxp, MLXCX_ISS_CMD_DOORBELL, 1 << slot);
9335f0e3176SPaul Winder 
9345f0e3176SPaul Winder 	if (!cmd->mlcmd_poll)
9355f0e3176SPaul Winder 		return;
936ebb7c6fdSAlex Wilson 
937ebb7c6fdSAlex Wilson 	for (poll = 0; poll < mlxcx_cmd_tries; poll++) {
938ebb7c6fdSAlex Wilson 		delay(drv_usectohz(mlxcx_cmd_delay));
939ebb7c6fdSAlex Wilson 		MLXCX_DMA_SYNC(cmdq->mcmd_dma, DDI_DMA_SYNC_FORKERNEL);
940ebb7c6fdSAlex Wilson 		if ((ent->mce_status & MLXCX_CMD_HW_OWNED) == 0)
941ebb7c6fdSAlex Wilson 			break;
942ebb7c6fdSAlex Wilson 	}
943ebb7c6fdSAlex Wilson 
944ebb7c6fdSAlex Wilson 	/*
945ebb7c6fdSAlex Wilson 	 * Command is done (or timed out). Save relevant data. Once we broadcast
946ebb7c6fdSAlex Wilson 	 * on the CV and drop the lock, we must not touch the cmd again.
947ebb7c6fdSAlex Wilson 	 */
948ebb7c6fdSAlex Wilson 
949ebb7c6fdSAlex Wilson 	if (poll == mlxcx_cmd_tries) {
9505f0e3176SPaul Winder 		mutex_enter(&cmd->mlcmd_lock);
951ebb7c6fdSAlex Wilson 		cmd->mlcmd_status = MLXCX_CMD_R_TIMEOUT;
952ebb7c6fdSAlex Wilson 		cmd->mlcmd_state = MLXCX_CMD_S_ERROR;
953ebb7c6fdSAlex Wilson 		cv_broadcast(&cmd->mlcmd_cv);
954ebb7c6fdSAlex Wilson 		mutex_exit(&cmd->mlcmd_lock);
955ebb7c6fdSAlex Wilson 
9565f0e3176SPaul Winder 		mlxcx_fm_ereport(mlxp, DDI_FM_DEVICE_NO_RESPONSE);
9575f0e3176SPaul Winder 
9585f0e3176SPaul Winder 		cmdq->mcmd_active[slot] = NULL;
9595f0e3176SPaul Winder 		mlxcx_cmd_release_slot(cmdq, slot);
9605f0e3176SPaul Winder 
9615f0e3176SPaul Winder 		return;
9625f0e3176SPaul Winder 	}
9635f0e3176SPaul Winder 
9645f0e3176SPaul Winder 	mlxcx_cmd_done(cmd, slot);
9655f0e3176SPaul Winder }
9665f0e3176SPaul Winder 
9675f0e3176SPaul Winder void
mlxcx_cmd_completion(mlxcx_t * mlxp,mlxcx_eventq_ent_t * ent)9685f0e3176SPaul Winder mlxcx_cmd_completion(mlxcx_t *mlxp, mlxcx_eventq_ent_t *ent)
9695f0e3176SPaul Winder {
9705f0e3176SPaul Winder 	mlxcx_cmd_queue_t *cmdq = &mlxp->mlx_cmd;
9715f0e3176SPaul Winder 	mlxcx_evdata_cmd_completion_t *eqe_cmd = &ent->mleqe_cmd_completion;
9725f0e3176SPaul Winder 	mlxcx_cmd_t *cmd;
9735f0e3176SPaul Winder 	uint32_t comp_vec = from_be32(eqe_cmd->mled_cmd_completion_vec);
9745f0e3176SPaul Winder 	uint_t slot;
9755f0e3176SPaul Winder 
9765f0e3176SPaul Winder 	DTRACE_PROBE2(cmd_event, mlxcx_t *, mlxp,
9775f0e3176SPaul Winder 	    mlxcx_evdata_cmd_completion_t *, eqe_cmd);
9785f0e3176SPaul Winder 
9795f0e3176SPaul Winder 	while ((slot = ddi_ffs(comp_vec)) != 0) {
9805f0e3176SPaul Winder 		comp_vec &= ~(1U << --slot);
9815f0e3176SPaul Winder 
9825f0e3176SPaul Winder 		cmd = cmdq->mcmd_active[slot];
9835f0e3176SPaul Winder 		if (cmd->mlcmd_poll)
9845f0e3176SPaul Winder 			continue;
9855f0e3176SPaul Winder 
9865f0e3176SPaul Winder 		mlxcx_cmd_done(cmd, slot);
9875f0e3176SPaul Winder 	}
988ebb7c6fdSAlex Wilson }
989ebb7c6fdSAlex Wilson 
990ebb7c6fdSAlex Wilson static boolean_t
mlxcx_cmd_send(mlxcx_t * mlxp,mlxcx_cmd_t * cmd,const void * in,uint32_t inlen,void * out,uint32_t outlen)991ebb7c6fdSAlex Wilson mlxcx_cmd_send(mlxcx_t *mlxp, mlxcx_cmd_t *cmd, const void *in, uint32_t inlen,
992ebb7c6fdSAlex Wilson     void *out, uint32_t outlen)
993ebb7c6fdSAlex Wilson {
994ebb7c6fdSAlex Wilson 	if (inlen > MLXCX_CMD_INLINE_INPUT_LEN) {
995ebb7c6fdSAlex Wilson 		uint32_t need = inlen - MLXCX_CMD_INLINE_INPUT_LEN;
996ebb7c6fdSAlex Wilson 		uint8_t nblocks;
997ebb7c6fdSAlex Wilson 
998ebb7c6fdSAlex Wilson 		if (need / MLXCX_CMD_MAILBOX_LEN + 1 > UINT8_MAX) {
999ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "requested too many input blocks for "
1000ebb7c6fdSAlex Wilson 			    "%u byte input len", inlen);
1001ebb7c6fdSAlex Wilson 			return (B_FALSE);
1002ebb7c6fdSAlex Wilson 		}
1003ebb7c6fdSAlex Wilson 
1004ebb7c6fdSAlex Wilson 		nblocks = need / MLXCX_CMD_MAILBOX_LEN + 1;
1005ebb7c6fdSAlex Wilson 		if (!mlxcx_cmd_mbox_alloc(mlxp, &cmd->mlcmd_mbox_in, nblocks)) {
1006ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "failed to allocate %u blocks of "
1007ebb7c6fdSAlex Wilson 			    "input mailbox", nblocks);
1008ebb7c6fdSAlex Wilson 			return (B_FALSE);
1009ebb7c6fdSAlex Wilson 		}
1010ebb7c6fdSAlex Wilson 		cmd->mlcmd_nboxes_in = nblocks;
1011ebb7c6fdSAlex Wilson 	}
1012ebb7c6fdSAlex Wilson 
1013ebb7c6fdSAlex Wilson 	if (outlen > MLXCX_CMD_INLINE_OUTPUT_LEN) {
1014ebb7c6fdSAlex Wilson 		uint32_t need = outlen - MLXCX_CMD_INLINE_OUTPUT_LEN;
1015ebb7c6fdSAlex Wilson 		uint8_t nblocks;
1016ebb7c6fdSAlex Wilson 
1017ebb7c6fdSAlex Wilson 		if (need / MLXCX_CMD_MAILBOX_LEN + 1 > UINT8_MAX) {
1018ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "requested too many output blocks for "
1019ebb7c6fdSAlex Wilson 			    "%u byte output len", outlen);
1020ebb7c6fdSAlex Wilson 			return (B_FALSE);
1021ebb7c6fdSAlex Wilson 		}
1022ebb7c6fdSAlex Wilson 
1023ebb7c6fdSAlex Wilson 		nblocks = need / MLXCX_CMD_MAILBOX_LEN + 1;
1024ebb7c6fdSAlex Wilson 		if (!mlxcx_cmd_mbox_alloc(mlxp, &cmd->mlcmd_mbox_out,
1025ebb7c6fdSAlex Wilson 		    nblocks)) {
1026ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "failed to allocate %u blocks of "
1027ebb7c6fdSAlex Wilson 			    "output mailbox", nblocks);
1028ebb7c6fdSAlex Wilson 			return (B_FALSE);
1029ebb7c6fdSAlex Wilson 		}
1030ebb7c6fdSAlex Wilson 		cmd->mlcmd_nboxes_out = nblocks;
1031ebb7c6fdSAlex Wilson 	}
1032ebb7c6fdSAlex Wilson 
1033ebb7c6fdSAlex Wilson 	cmd->mlcmd_in = in;
1034ebb7c6fdSAlex Wilson 	cmd->mlcmd_inlen = inlen;
1035ebb7c6fdSAlex Wilson 	cmd->mlcmd_out = out;
1036ebb7c6fdSAlex Wilson 	cmd->mlcmd_outlen = outlen;
1037ebb7c6fdSAlex Wilson 	cmd->mlcmd_mlxp = mlxp;
1038ebb7c6fdSAlex Wilson 
1039ebb7c6fdSAlex Wilson 	/*
1040ebb7c6fdSAlex Wilson 	 * Now that all allocations have been done, all that remains is for us
1041ebb7c6fdSAlex Wilson 	 * to dispatch the request to process this to the taskq for it to be
1042ebb7c6fdSAlex Wilson 	 * processed.
1043ebb7c6fdSAlex Wilson 	 */
1044ebb7c6fdSAlex Wilson 	if (ddi_taskq_dispatch(mlxp->mlx_cmd.mcmd_taskq, mlxcx_cmd_taskq, cmd,
1045ebb7c6fdSAlex Wilson 	    DDI_SLEEP) != DDI_SUCCESS) {
1046ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "failed to submit command to taskq");
1047ebb7c6fdSAlex Wilson 		return (B_FALSE);
1048ebb7c6fdSAlex Wilson 	}
1049ebb7c6fdSAlex Wilson 
1050ebb7c6fdSAlex Wilson 	return (B_TRUE);
1051ebb7c6fdSAlex Wilson }
1052ebb7c6fdSAlex Wilson 
1053ebb7c6fdSAlex Wilson static void
mlxcx_cmd_wait(mlxcx_cmd_t * cmd)1054ebb7c6fdSAlex Wilson mlxcx_cmd_wait(mlxcx_cmd_t *cmd)
1055ebb7c6fdSAlex Wilson {
1056ebb7c6fdSAlex Wilson 	mutex_enter(&cmd->mlcmd_lock);
1057ebb7c6fdSAlex Wilson 	while (cmd->mlcmd_state == 0) {
1058ebb7c6fdSAlex Wilson 		cv_wait(&cmd->mlcmd_cv, &cmd->mlcmd_lock);
1059ebb7c6fdSAlex Wilson 	}
1060ebb7c6fdSAlex Wilson 	mutex_exit(&cmd->mlcmd_lock);
1061ebb7c6fdSAlex Wilson }
1062ebb7c6fdSAlex Wilson 
1063ebb7c6fdSAlex Wilson static boolean_t
mlxcx_cmd_evaluate(mlxcx_t * mlxp,mlxcx_cmd_t * cmd)1064ebb7c6fdSAlex Wilson mlxcx_cmd_evaluate(mlxcx_t *mlxp, mlxcx_cmd_t *cmd)
1065ebb7c6fdSAlex Wilson {
1066ebb7c6fdSAlex Wilson 	mlxcx_cmd_out_t *out;
1067ebb7c6fdSAlex Wilson 
1068ebb7c6fdSAlex Wilson 	if ((cmd->mlcmd_state & MLXCX_CMD_S_ERROR) != 0) {
1069ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "command %s (0x%x) failed due to an internal "
1070ebb7c6fdSAlex Wilson 		    "driver error",
1071ebb7c6fdSAlex Wilson 		    mlxcx_cmd_opcode_string(cmd->mlcmd_op),
1072ebb7c6fdSAlex Wilson 		    cmd->mlcmd_op);
1073ebb7c6fdSAlex Wilson 		return (B_FALSE);
1074ebb7c6fdSAlex Wilson 	}
1075ebb7c6fdSAlex Wilson 
1076ebb7c6fdSAlex Wilson 	if (cmd->mlcmd_status != 0) {
1077ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "command %s (0x%x) failed with command queue "
1078ebb7c6fdSAlex Wilson 		    "error 0x%x",
1079ebb7c6fdSAlex Wilson 		    mlxcx_cmd_opcode_string(cmd->mlcmd_op),
1080ebb7c6fdSAlex Wilson 		    cmd->mlcmd_op, cmd->mlcmd_status);
1081ebb7c6fdSAlex Wilson 		return (B_FALSE);
1082ebb7c6fdSAlex Wilson 	}
1083ebb7c6fdSAlex Wilson 
1084ebb7c6fdSAlex Wilson 	out = cmd->mlcmd_out;
1085ebb7c6fdSAlex Wilson 	if (out->mco_status != MLXCX_CMD_R_OK) {
1086ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "command %s 0x%x failed with status code %s "
1087ebb7c6fdSAlex Wilson 		    "(0x%x)", mlxcx_cmd_opcode_string(cmd->mlcmd_op),
1088ebb7c6fdSAlex Wilson 		    cmd->mlcmd_op, mlxcx_cmd_response_string(out->mco_status),
1089ebb7c6fdSAlex Wilson 		    out->mco_status);
1090ebb7c6fdSAlex Wilson 		return (B_FALSE);
1091ebb7c6fdSAlex Wilson 	}
1092ebb7c6fdSAlex Wilson 
1093ebb7c6fdSAlex Wilson 	return (B_TRUE);
1094ebb7c6fdSAlex Wilson }
1095ebb7c6fdSAlex Wilson 
1096ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_disable_hca(mlxcx_t * mlxp)1097ebb7c6fdSAlex Wilson mlxcx_cmd_disable_hca(mlxcx_t *mlxp)
1098ebb7c6fdSAlex Wilson {
1099ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1100ebb7c6fdSAlex Wilson 	mlxcx_cmd_disable_hca_in_t in;
1101ebb7c6fdSAlex Wilson 	mlxcx_cmd_disable_hca_out_t out;
1102ebb7c6fdSAlex Wilson 	boolean_t ret;
1103ebb7c6fdSAlex Wilson 
1104ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1105ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1106ebb7c6fdSAlex Wilson 
1107ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1108ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_disable_hca_head,
1109ebb7c6fdSAlex Wilson 	    MLXCX_OP_DISABLE_HCA, 0);
1110ebb7c6fdSAlex Wilson 	in.mlxi_disable_hca_func = MLXCX_FUNCTION_SELF;
1111ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1112ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1113ebb7c6fdSAlex Wilson 		return (B_FALSE);
1114ebb7c6fdSAlex Wilson 	}
1115ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1116ebb7c6fdSAlex Wilson 
1117ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1118ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1119ebb7c6fdSAlex Wilson 	return (ret);
1120ebb7c6fdSAlex Wilson }
1121ebb7c6fdSAlex Wilson 
1122ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_enable_hca(mlxcx_t * mlxp)1123ebb7c6fdSAlex Wilson mlxcx_cmd_enable_hca(mlxcx_t *mlxp)
1124ebb7c6fdSAlex Wilson {
1125ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1126ebb7c6fdSAlex Wilson 	mlxcx_cmd_enable_hca_in_t in;
1127ebb7c6fdSAlex Wilson 	mlxcx_cmd_enable_hca_out_t out;
1128ebb7c6fdSAlex Wilson 	boolean_t ret;
1129ebb7c6fdSAlex Wilson 
1130ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1131ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1132ebb7c6fdSAlex Wilson 
1133ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1134ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_enable_hca_head,
1135ebb7c6fdSAlex Wilson 	    MLXCX_OP_ENABLE_HCA, 0);
1136ebb7c6fdSAlex Wilson 	in.mlxi_enable_hca_func = MLXCX_FUNCTION_SELF;
1137ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1138ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1139ebb7c6fdSAlex Wilson 		return (B_FALSE);
1140ebb7c6fdSAlex Wilson 	}
1141ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1142ebb7c6fdSAlex Wilson 
1143ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1144ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1145ebb7c6fdSAlex Wilson 	return (ret);
1146ebb7c6fdSAlex Wilson }
1147ebb7c6fdSAlex Wilson 
1148ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_issi(mlxcx_t * mlxp,uint32_t * issip)1149ebb7c6fdSAlex Wilson mlxcx_cmd_query_issi(mlxcx_t *mlxp, uint32_t *issip)
1150ebb7c6fdSAlex Wilson {
1151ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1152ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_issi_in_t in;
1153ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_issi_out_t out;
1154ebb7c6fdSAlex Wilson 	boolean_t ret;
1155ebb7c6fdSAlex Wilson 
1156ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1157ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1158ebb7c6fdSAlex Wilson 
1159ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1160ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_issi_head,
1161ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_ISSI, 0);
1162ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1163ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1164ebb7c6fdSAlex Wilson 		return (B_FALSE);
1165ebb7c6fdSAlex Wilson 	}
1166ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1167ebb7c6fdSAlex Wilson 
1168ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1169ebb7c6fdSAlex Wilson 	if (ret) {
1170ebb7c6fdSAlex Wilson 		*issip = out.mlxo_supported_issi;
1171ebb7c6fdSAlex Wilson 	} else if (cmd.mlcmd_status == 0 &&
1172ebb7c6fdSAlex Wilson 	    out.mlxo_query_issi_head.mco_status == MLXCX_CMD_R_BAD_OP) {
1173ebb7c6fdSAlex Wilson 		/*
1174ebb7c6fdSAlex Wilson 		 * The PRM says that if we get a bad operation, that means this
1175ebb7c6fdSAlex Wilson 		 * command isn't supported so it only supports version 1 of the
1176ebb7c6fdSAlex Wilson 		 * ISSI, which means bit zero should be set.
1177ebb7c6fdSAlex Wilson 		 */
1178ebb7c6fdSAlex Wilson 		ret = B_TRUE;
1179ebb7c6fdSAlex Wilson 		*issip = 1;
1180ebb7c6fdSAlex Wilson 	}
1181ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1182ebb7c6fdSAlex Wilson 	return (ret);
1183ebb7c6fdSAlex Wilson }
1184ebb7c6fdSAlex Wilson 
1185ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_issi(mlxcx_t * mlxp,uint16_t issi)1186ebb7c6fdSAlex Wilson mlxcx_cmd_set_issi(mlxcx_t *mlxp, uint16_t issi)
1187ebb7c6fdSAlex Wilson {
1188ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1189ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_issi_in_t in;
1190ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_issi_out_t out;
1191ebb7c6fdSAlex Wilson 	boolean_t ret;
1192ebb7c6fdSAlex Wilson 
1193ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1194ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1195ebb7c6fdSAlex Wilson 
1196ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1197ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_set_issi_head,
1198ebb7c6fdSAlex Wilson 	    MLXCX_OP_SET_ISSI, 0);
1199ebb7c6fdSAlex Wilson 	in.mlxi_set_issi_current = to_be16(issi);
1200ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1201ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1202ebb7c6fdSAlex Wilson 		return (B_FALSE);
1203ebb7c6fdSAlex Wilson 	}
1204ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1205ebb7c6fdSAlex Wilson 
1206ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1207ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1208ebb7c6fdSAlex Wilson 	return (ret);
1209ebb7c6fdSAlex Wilson }
1210ebb7c6fdSAlex Wilson 
1211ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_pages(mlxcx_t * mlxp,uint_t type,int32_t * npages)1212ebb7c6fdSAlex Wilson mlxcx_cmd_query_pages(mlxcx_t *mlxp, uint_t type, int32_t *npages)
1213ebb7c6fdSAlex Wilson {
1214ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1215ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_pages_in_t in;
1216ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_pages_out_t out;
1217ebb7c6fdSAlex Wilson 	boolean_t ret;
1218ebb7c6fdSAlex Wilson 
1219ebb7c6fdSAlex Wilson 	switch (type) {
1220ebb7c6fdSAlex Wilson 	case MLXCX_QUERY_PAGES_OPMOD_BOOT:
1221ebb7c6fdSAlex Wilson 	case MLXCX_QUERY_PAGES_OPMOD_INIT:
1222ebb7c6fdSAlex Wilson 	case MLXCX_QUERY_PAGES_OPMOD_REGULAR:
1223ebb7c6fdSAlex Wilson 		break;
1224ebb7c6fdSAlex Wilson 	default:
1225ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "!passed invalid type to query pages: %u",
1226ebb7c6fdSAlex Wilson 		    type);
1227ebb7c6fdSAlex Wilson 		return (B_FALSE);
1228ebb7c6fdSAlex Wilson 	}
1229ebb7c6fdSAlex Wilson 
1230ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1231ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1232ebb7c6fdSAlex Wilson 
1233ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1234ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_pages_head,
1235ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_PAGES, type);
1236ebb7c6fdSAlex Wilson 	in.mlxi_query_pages_func = MLXCX_FUNCTION_SELF;
1237ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1238ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1239ebb7c6fdSAlex Wilson 		return (B_FALSE);
1240ebb7c6fdSAlex Wilson 	}
1241ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1242ebb7c6fdSAlex Wilson 
1243ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1244ebb7c6fdSAlex Wilson 	if (ret) {
1245ebb7c6fdSAlex Wilson 		*npages = from_be32(out.mlxo_query_pages_npages);
1246ebb7c6fdSAlex Wilson 	}
1247ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1248ebb7c6fdSAlex Wilson 
1249ebb7c6fdSAlex Wilson 	return (ret);
1250ebb7c6fdSAlex Wilson }
1251ebb7c6fdSAlex Wilson 
1252ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_give_pages(mlxcx_t * mlxp,uint_t type,int32_t npages,mlxcx_dev_page_t ** pages)1253ebb7c6fdSAlex Wilson mlxcx_cmd_give_pages(mlxcx_t *mlxp, uint_t type, int32_t npages,
1254ebb7c6fdSAlex Wilson     mlxcx_dev_page_t **pages)
1255ebb7c6fdSAlex Wilson {
1256ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
12575f0e3176SPaul Winder 	mlxcx_cmd_manage_pages_in_t *in;
1258ebb7c6fdSAlex Wilson 	mlxcx_cmd_manage_pages_out_t out;
1259ebb7c6fdSAlex Wilson 	size_t insize, outsize;
1260ebb7c6fdSAlex Wilson 	boolean_t ret;
1261ebb7c6fdSAlex Wilson 	uint32_t i;
1262ebb7c6fdSAlex Wilson 	uint64_t pa;
1263ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *ck;
1264ebb7c6fdSAlex Wilson 
1265ebb7c6fdSAlex Wilson 	switch (type) {
1266ebb7c6fdSAlex Wilson 	case MLXCX_MANAGE_PAGES_OPMOD_ALLOC_FAIL:
1267ebb7c6fdSAlex Wilson 		if (npages != 0) {
1268ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "passed non-zero number of pages (%d) "
1269ebb7c6fdSAlex Wilson 			    "but asked to fail page allocation", npages);
1270ebb7c6fdSAlex Wilson 			return (B_FALSE);
1271ebb7c6fdSAlex Wilson 		}
1272ebb7c6fdSAlex Wilson 		break;
1273ebb7c6fdSAlex Wilson 	case MLXCX_MANAGE_PAGES_OPMOD_GIVE_PAGES:
12745f0e3176SPaul Winder 		ASSERT3S(npages, <=, MLXCX_MANAGE_PAGES_MAX_PAGES);
12755f0e3176SPaul Winder 		if (npages <= 0) {
1276ebb7c6fdSAlex Wilson 			mlxcx_warn(mlxp, "passed invalid number of pages (%d) "
1277ebb7c6fdSAlex Wilson 			    "to give pages", npages);
1278ebb7c6fdSAlex Wilson 			return (B_FALSE);
1279ebb7c6fdSAlex Wilson 		}
1280ebb7c6fdSAlex Wilson 		break;
1281ebb7c6fdSAlex Wilson 	default:
1282ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "!passed invalid type to give pages: %u",
1283ebb7c6fdSAlex Wilson 		    type);
1284ebb7c6fdSAlex Wilson 		return (B_FALSE);
1285ebb7c6fdSAlex Wilson 	}
1286ebb7c6fdSAlex Wilson 
1287ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_manage_pages_in_t, mlxi_manage_pages_pas) +
1288ebb7c6fdSAlex Wilson 	    npages * sizeof (uint64_t);
1289ebb7c6fdSAlex Wilson 	outsize = offsetof(mlxcx_cmd_manage_pages_out_t, mlxo_manage_pages_pas);
1290ebb7c6fdSAlex Wilson 
12915f0e3176SPaul Winder 	in = kmem_zalloc(insize, KM_SLEEP);
12925f0e3176SPaul Winder 	bzero(&out, sizeof (out));
12935f0e3176SPaul Winder 
1294ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
12955f0e3176SPaul Winder 	mlxcx_cmd_in_header_init(&cmd, &in->mlxi_manage_pages_head,
1296ebb7c6fdSAlex Wilson 	    MLXCX_OP_MANAGE_PAGES, type);
12975f0e3176SPaul Winder 	in->mlxi_manage_pages_func = MLXCX_FUNCTION_SELF;
12985f0e3176SPaul Winder 	in->mlxi_manage_pages_npages = to_be32(npages);
1299ebb7c6fdSAlex Wilson 	for (i = 0; i < npages; i++) {
1300ebb7c6fdSAlex Wilson 		ck = mlxcx_dma_cookie_one(&pages[i]->mxdp_dma);
1301ebb7c6fdSAlex Wilson 		pa = ck->dmac_laddress;
1302ebb7c6fdSAlex Wilson 		ASSERT3U(pa & 0xfff, ==, 0);
1303ebb7c6fdSAlex Wilson 		ASSERT3U(ck->dmac_size, ==, MLXCX_HW_PAGE_SIZE);
13045f0e3176SPaul Winder 		in->mlxi_manage_pages_pas[i] = to_be64(pa);
1305ebb7c6fdSAlex Wilson 	}
1306ebb7c6fdSAlex Wilson 
13075f0e3176SPaul Winder 	if ((ret = mlxcx_cmd_send(mlxp, &cmd, in, insize, &out, outsize))) {
1308ebb7c6fdSAlex Wilson 		mlxcx_cmd_wait(&cmd);
1309ebb7c6fdSAlex Wilson 		ret = mlxcx_cmd_evaluate(mlxp, &cmd);
13105f0e3176SPaul Winder 	}
13115f0e3176SPaul Winder 
1312ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1313ebb7c6fdSAlex Wilson 
13145f0e3176SPaul Winder 	kmem_free(in, insize);
1315ebb7c6fdSAlex Wilson 	return (ret);
1316ebb7c6fdSAlex Wilson }
1317ebb7c6fdSAlex Wilson 
1318ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_return_pages(mlxcx_t * mlxp,int32_t nreq,uint64_t * pas,int32_t * nret)1319ebb7c6fdSAlex Wilson mlxcx_cmd_return_pages(mlxcx_t *mlxp, int32_t nreq, uint64_t *pas,
1320ebb7c6fdSAlex Wilson     int32_t *nret)
1321ebb7c6fdSAlex Wilson {
1322ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1323ebb7c6fdSAlex Wilson 	mlxcx_cmd_manage_pages_in_t in;
13245f0e3176SPaul Winder 	mlxcx_cmd_manage_pages_out_t *out;
1325ebb7c6fdSAlex Wilson 	size_t insize, outsize;
1326ebb7c6fdSAlex Wilson 	boolean_t ret;
1327ebb7c6fdSAlex Wilson 	uint32_t i;
1328ebb7c6fdSAlex Wilson 
1329ebb7c6fdSAlex Wilson 	if (nreq <= 0) {
1330ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "passed invalid number of pages (%d) "
1331ebb7c6fdSAlex Wilson 		    "to return pages", nreq);
1332ebb7c6fdSAlex Wilson 		return (B_FALSE);
1333ebb7c6fdSAlex Wilson 	}
1334ebb7c6fdSAlex Wilson 
1335ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_manage_pages_in_t, mlxi_manage_pages_pas);
1336ebb7c6fdSAlex Wilson 	outsize = offsetof(mlxcx_cmd_manage_pages_out_t,
1337ebb7c6fdSAlex Wilson 	    mlxo_manage_pages_pas) + nreq * sizeof (uint64_t);
1338ebb7c6fdSAlex Wilson 
13395f0e3176SPaul Winder 	bzero(&in, sizeof (in));
13405f0e3176SPaul Winder 	out = kmem_alloc(outsize, KM_SLEEP);
13415f0e3176SPaul Winder 
1342ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1343ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_manage_pages_head,
1344ebb7c6fdSAlex Wilson 	    MLXCX_OP_MANAGE_PAGES, MLXCX_MANAGE_PAGES_OPMOD_RETURN_PAGES);
1345ebb7c6fdSAlex Wilson 	in.mlxi_manage_pages_func = MLXCX_FUNCTION_SELF;
1346ebb7c6fdSAlex Wilson 	in.mlxi_manage_pages_npages = to_be32(nreq);
1347ebb7c6fdSAlex Wilson 
13485f0e3176SPaul Winder 	if ((ret = mlxcx_cmd_send(mlxp, &cmd, &in, insize, out, outsize))) {
1349ebb7c6fdSAlex Wilson 		mlxcx_cmd_wait(&cmd);
1350ebb7c6fdSAlex Wilson 
1351ebb7c6fdSAlex Wilson 		ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1352ebb7c6fdSAlex Wilson 		if (ret) {
13535f0e3176SPaul Winder 			*nret = from_be32(out->mlxo_manage_pages_npages);
1354ebb7c6fdSAlex Wilson 			for (i = 0; i < *nret; i++) {
13555f0e3176SPaul Winder 				pas[i] =
13565f0e3176SPaul Winder 				    from_be64(out->mlxo_manage_pages_pas[i]);
1357ebb7c6fdSAlex Wilson 			}
1358ebb7c6fdSAlex Wilson 		}
13595f0e3176SPaul Winder 	}
13605f0e3176SPaul Winder 
1361ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1362ebb7c6fdSAlex Wilson 
13635f0e3176SPaul Winder 	kmem_free(out, outsize);
1364ebb7c6fdSAlex Wilson 	return (ret);
1365ebb7c6fdSAlex Wilson }
1366ebb7c6fdSAlex Wilson 
1367ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_hca_cap(mlxcx_t * mlxp,mlxcx_hca_cap_type_t type,mlxcx_hca_cap_mode_t mode,mlxcx_hca_cap_t * capp)1368ebb7c6fdSAlex Wilson mlxcx_cmd_query_hca_cap(mlxcx_t *mlxp, mlxcx_hca_cap_type_t type,
1369ebb7c6fdSAlex Wilson     mlxcx_hca_cap_mode_t mode, mlxcx_hca_cap_t *capp)
1370ebb7c6fdSAlex Wilson {
1371ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1372ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_hca_cap_in_t in;
1373ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_hca_cap_out_t *out;
1374ebb7c6fdSAlex Wilson 	boolean_t ret;
1375ebb7c6fdSAlex Wilson 	uint16_t opmode;
1376ebb7c6fdSAlex Wilson 
1377ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1378ebb7c6fdSAlex Wilson 	out = kmem_zalloc(sizeof (mlxcx_cmd_query_hca_cap_out_t), KM_SLEEP);
1379ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1380ebb7c6fdSAlex Wilson 
1381ebb7c6fdSAlex Wilson 	opmode = type << 1 | mode;
1382ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_hca_cap_head,
1383ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_HCA_CAP, opmode);
1384ebb7c6fdSAlex Wilson 
1385ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), out, sizeof (*out))) {
1386ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1387ebb7c6fdSAlex Wilson 		kmem_free(out, sizeof (mlxcx_cmd_query_hca_cap_out_t));
1388ebb7c6fdSAlex Wilson 		return (B_FALSE);
1389ebb7c6fdSAlex Wilson 	}
1390ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1391ebb7c6fdSAlex Wilson 
1392ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1393ebb7c6fdSAlex Wilson 	if (ret) {
1394ebb7c6fdSAlex Wilson 		capp->mhc_mode = mode;
1395ebb7c6fdSAlex Wilson 		capp->mhc_type = type;
1396ebb7c6fdSAlex Wilson 		ASSERT3U(sizeof (out->mlxo_query_hca_cap_data), ==,
1397ebb7c6fdSAlex Wilson 		    sizeof (capp->mhc_bulk));
1398ebb7c6fdSAlex Wilson 		bcopy(out->mlxo_query_hca_cap_data, capp->mhc_bulk,
1399ebb7c6fdSAlex Wilson 		    sizeof (capp->mhc_bulk));
1400ebb7c6fdSAlex Wilson 	}
1401ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1402ebb7c6fdSAlex Wilson 
1403ebb7c6fdSAlex Wilson 	kmem_free(out, sizeof (mlxcx_cmd_query_hca_cap_out_t));
1404ebb7c6fdSAlex Wilson 	return (B_TRUE);
1405ebb7c6fdSAlex Wilson }
1406ebb7c6fdSAlex Wilson 
1407ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_init_hca(mlxcx_t * mlxp)1408ebb7c6fdSAlex Wilson mlxcx_cmd_init_hca(mlxcx_t *mlxp)
1409ebb7c6fdSAlex Wilson {
1410ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1411ebb7c6fdSAlex Wilson 	mlxcx_cmd_init_hca_in_t in;
1412ebb7c6fdSAlex Wilson 	mlxcx_cmd_init_hca_out_t out;
1413ebb7c6fdSAlex Wilson 	boolean_t ret;
1414ebb7c6fdSAlex Wilson 
1415ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1416ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1417ebb7c6fdSAlex Wilson 
1418ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1419ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_init_hca_head,
1420ebb7c6fdSAlex Wilson 	    MLXCX_OP_INIT_HCA, 0);
1421ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1422ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1423ebb7c6fdSAlex Wilson 		return (B_FALSE);
1424ebb7c6fdSAlex Wilson 	}
1425ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1426ebb7c6fdSAlex Wilson 
1427ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1428ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1429ebb7c6fdSAlex Wilson 	return (ret);
1430ebb7c6fdSAlex Wilson }
1431ebb7c6fdSAlex Wilson 
1432ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_driver_version(mlxcx_t * mlxp,const char * version)1433ebb7c6fdSAlex Wilson mlxcx_cmd_set_driver_version(mlxcx_t *mlxp, const char *version)
1434ebb7c6fdSAlex Wilson {
1435ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1436ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_driver_version_in_t in;
1437ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_driver_version_out_t out;
1438ebb7c6fdSAlex Wilson 	boolean_t ret;
1439ebb7c6fdSAlex Wilson 
1440ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1441ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1442ebb7c6fdSAlex Wilson 
1443ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1444ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_set_driver_version_head,
1445ebb7c6fdSAlex Wilson 	    MLXCX_OP_SET_DRIVER_VERSION, 0);
1446ebb7c6fdSAlex Wilson 	VERIFY3U(strlcpy(in.mlxi_set_driver_version_version, version,
1447ebb7c6fdSAlex Wilson 	    sizeof (in.mlxi_set_driver_version_version)), <=,
1448ebb7c6fdSAlex Wilson 	    sizeof (in.mlxi_set_driver_version_version));
1449ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1450ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1451ebb7c6fdSAlex Wilson 		return (B_FALSE);
1452ebb7c6fdSAlex Wilson 	}
1453ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1454ebb7c6fdSAlex Wilson 
1455ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1456ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1457ebb7c6fdSAlex Wilson 	return (ret);
1458ebb7c6fdSAlex Wilson }
1459ebb7c6fdSAlex Wilson 
1460ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_alloc_uar(mlxcx_t * mlxp,mlxcx_uar_t * mlup)1461ebb7c6fdSAlex Wilson mlxcx_cmd_alloc_uar(mlxcx_t *mlxp, mlxcx_uar_t *mlup)
1462ebb7c6fdSAlex Wilson {
1463ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1464ebb7c6fdSAlex Wilson 	mlxcx_cmd_alloc_uar_in_t in;
1465ebb7c6fdSAlex Wilson 	mlxcx_cmd_alloc_uar_out_t out;
1466ebb7c6fdSAlex Wilson 	boolean_t ret;
1467ebb7c6fdSAlex Wilson 	size_t i;
1468ebb7c6fdSAlex Wilson 
1469ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1470ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1471ebb7c6fdSAlex Wilson 
1472ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1473ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_alloc_uar_head,
1474ebb7c6fdSAlex Wilson 	    MLXCX_OP_ALLOC_UAR, 0);
1475ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1476ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1477ebb7c6fdSAlex Wilson 		return (B_FALSE);
1478ebb7c6fdSAlex Wilson 	}
1479ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1480ebb7c6fdSAlex Wilson 
1481ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1482ebb7c6fdSAlex Wilson 	if (ret) {
1483ebb7c6fdSAlex Wilson 		mlup->mlu_allocated = B_TRUE;
1484ebb7c6fdSAlex Wilson 		mlup->mlu_num = from_be24(out.mlxo_alloc_uar_uar);
1485ebb7c6fdSAlex Wilson 		VERIFY3U(mlup->mlu_num, >, 0);
1486ebb7c6fdSAlex Wilson 		mlup->mlu_base = mlup->mlu_num * MLXCX_HW_PAGE_SIZE;
1487ebb7c6fdSAlex Wilson 
1488ebb7c6fdSAlex Wilson 		for (i = 0; i < MLXCX_BF_PER_UAR; ++i) {
1489ebb7c6fdSAlex Wilson 			mlup->mlu_bf[i].mbf_even = mlup->mlu_base +
1490ebb7c6fdSAlex Wilson 			    MLXCX_BF_BASE + MLXCX_BF_SIZE * 2 * i;
1491ebb7c6fdSAlex Wilson 			mlup->mlu_bf[i].mbf_odd = mlup->mlu_bf[i].mbf_even +
1492ebb7c6fdSAlex Wilson 			    MLXCX_BF_SIZE;
1493ebb7c6fdSAlex Wilson 		}
1494ebb7c6fdSAlex Wilson 	}
1495ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1496ebb7c6fdSAlex Wilson 	return (ret);
1497ebb7c6fdSAlex Wilson }
1498ebb7c6fdSAlex Wilson 
1499ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_dealloc_uar(mlxcx_t * mlxp,mlxcx_uar_t * mlup)1500ebb7c6fdSAlex Wilson mlxcx_cmd_dealloc_uar(mlxcx_t *mlxp, mlxcx_uar_t *mlup)
1501ebb7c6fdSAlex Wilson {
1502ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1503ebb7c6fdSAlex Wilson 	mlxcx_cmd_dealloc_uar_in_t in;
1504ebb7c6fdSAlex Wilson 	mlxcx_cmd_dealloc_uar_out_t out;
1505ebb7c6fdSAlex Wilson 	boolean_t ret;
1506ebb7c6fdSAlex Wilson 
1507ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1508ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1509ebb7c6fdSAlex Wilson 
1510ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1511ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_dealloc_uar_head,
1512ebb7c6fdSAlex Wilson 	    MLXCX_OP_DEALLOC_UAR, 0);
1513ebb7c6fdSAlex Wilson 	VERIFY(mlup->mlu_allocated);
1514ebb7c6fdSAlex Wilson 	in.mlxi_dealloc_uar_uar = to_be24(mlup->mlu_num);
1515ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1516ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1517ebb7c6fdSAlex Wilson 		return (B_FALSE);
1518ebb7c6fdSAlex Wilson 	}
1519ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1520ebb7c6fdSAlex Wilson 
1521ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1522ebb7c6fdSAlex Wilson 	if (ret) {
1523ebb7c6fdSAlex Wilson 		mlup->mlu_allocated = B_FALSE;
1524ebb7c6fdSAlex Wilson 		mlup->mlu_num = 0;
1525ebb7c6fdSAlex Wilson 	}
1526ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1527ebb7c6fdSAlex Wilson 	return (ret);
1528ebb7c6fdSAlex Wilson }
1529ebb7c6fdSAlex Wilson 
1530ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_alloc_pd(mlxcx_t * mlxp,mlxcx_pd_t * mlpd)1531ebb7c6fdSAlex Wilson mlxcx_cmd_alloc_pd(mlxcx_t *mlxp, mlxcx_pd_t *mlpd)
1532ebb7c6fdSAlex Wilson {
1533ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1534ebb7c6fdSAlex Wilson 	mlxcx_cmd_alloc_pd_in_t in;
1535ebb7c6fdSAlex Wilson 	mlxcx_cmd_alloc_pd_out_t out;
1536ebb7c6fdSAlex Wilson 	boolean_t ret;
1537ebb7c6fdSAlex Wilson 
1538ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1539ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1540ebb7c6fdSAlex Wilson 
1541ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1542ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_alloc_pd_head,
1543ebb7c6fdSAlex Wilson 	    MLXCX_OP_ALLOC_PD, 0);
1544ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1545ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1546ebb7c6fdSAlex Wilson 		return (B_FALSE);
1547ebb7c6fdSAlex Wilson 	}
1548ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1549ebb7c6fdSAlex Wilson 
1550ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1551ebb7c6fdSAlex Wilson 	if (ret) {
1552ebb7c6fdSAlex Wilson 		mlpd->mlpd_allocated = B_TRUE;
1553ebb7c6fdSAlex Wilson 		mlpd->mlpd_num = from_be24(out.mlxo_alloc_pd_pdn);
1554ebb7c6fdSAlex Wilson 	}
1555ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1556ebb7c6fdSAlex Wilson 	return (ret);
1557ebb7c6fdSAlex Wilson }
1558ebb7c6fdSAlex Wilson 
1559ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_dealloc_pd(mlxcx_t * mlxp,mlxcx_pd_t * mlpd)1560ebb7c6fdSAlex Wilson mlxcx_cmd_dealloc_pd(mlxcx_t *mlxp, mlxcx_pd_t *mlpd)
1561ebb7c6fdSAlex Wilson {
1562ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1563ebb7c6fdSAlex Wilson 	mlxcx_cmd_dealloc_pd_in_t in;
1564ebb7c6fdSAlex Wilson 	mlxcx_cmd_dealloc_pd_out_t out;
1565ebb7c6fdSAlex Wilson 	boolean_t ret;
1566ebb7c6fdSAlex Wilson 
1567ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1568ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1569ebb7c6fdSAlex Wilson 
1570ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1571ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_dealloc_pd_head,
1572ebb7c6fdSAlex Wilson 	    MLXCX_OP_DEALLOC_PD, 0);
1573ebb7c6fdSAlex Wilson 	VERIFY(mlpd->mlpd_allocated);
1574ebb7c6fdSAlex Wilson 	in.mlxi_dealloc_pd_pdn = to_be24(mlpd->mlpd_num);
1575ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1576ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1577ebb7c6fdSAlex Wilson 		return (B_FALSE);
1578ebb7c6fdSAlex Wilson 	}
1579ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1580ebb7c6fdSAlex Wilson 
1581ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1582ebb7c6fdSAlex Wilson 	if (ret) {
1583ebb7c6fdSAlex Wilson 		mlpd->mlpd_allocated = B_FALSE;
1584ebb7c6fdSAlex Wilson 		mlpd->mlpd_num = 0;
1585ebb7c6fdSAlex Wilson 	}
1586ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1587ebb7c6fdSAlex Wilson 	return (ret);
1588ebb7c6fdSAlex Wilson }
1589ebb7c6fdSAlex Wilson 
1590ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_alloc_tdom(mlxcx_t * mlxp,mlxcx_tdom_t * mltd)1591ebb7c6fdSAlex Wilson mlxcx_cmd_alloc_tdom(mlxcx_t *mlxp, mlxcx_tdom_t *mltd)
1592ebb7c6fdSAlex Wilson {
1593ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1594ebb7c6fdSAlex Wilson 	mlxcx_cmd_alloc_tdom_in_t in;
1595ebb7c6fdSAlex Wilson 	mlxcx_cmd_alloc_tdom_out_t out;
1596ebb7c6fdSAlex Wilson 	boolean_t ret;
1597ebb7c6fdSAlex Wilson 
1598ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1599ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1600ebb7c6fdSAlex Wilson 
1601ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1602ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_alloc_tdom_head,
1603ebb7c6fdSAlex Wilson 	    MLXCX_OP_ALLOC_TRANSPORT_DOMAIN, 0);
1604ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1605ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1606ebb7c6fdSAlex Wilson 		return (B_FALSE);
1607ebb7c6fdSAlex Wilson 	}
1608ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1609ebb7c6fdSAlex Wilson 
1610ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1611ebb7c6fdSAlex Wilson 	if (ret) {
1612ebb7c6fdSAlex Wilson 		mltd->mltd_allocated = B_TRUE;
1613ebb7c6fdSAlex Wilson 		mltd->mltd_num = from_be24(out.mlxo_alloc_tdom_tdomn);
1614ebb7c6fdSAlex Wilson 	}
1615ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1616ebb7c6fdSAlex Wilson 	return (ret);
1617ebb7c6fdSAlex Wilson }
1618ebb7c6fdSAlex Wilson 
1619ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_dealloc_tdom(mlxcx_t * mlxp,mlxcx_tdom_t * mltd)1620ebb7c6fdSAlex Wilson mlxcx_cmd_dealloc_tdom(mlxcx_t *mlxp, mlxcx_tdom_t *mltd)
1621ebb7c6fdSAlex Wilson {
1622ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1623ebb7c6fdSAlex Wilson 	mlxcx_cmd_dealloc_tdom_in_t in;
1624ebb7c6fdSAlex Wilson 	mlxcx_cmd_dealloc_tdom_out_t out;
1625ebb7c6fdSAlex Wilson 	boolean_t ret;
1626ebb7c6fdSAlex Wilson 
1627ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1628ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1629ebb7c6fdSAlex Wilson 
1630ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1631ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_dealloc_tdom_head,
1632ebb7c6fdSAlex Wilson 	    MLXCX_OP_DEALLOC_TRANSPORT_DOMAIN, 0);
1633ebb7c6fdSAlex Wilson 	VERIFY(mltd->mltd_allocated);
1634ebb7c6fdSAlex Wilson 	in.mlxi_dealloc_tdom_tdomn = to_be24(mltd->mltd_num);
1635ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1636ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1637ebb7c6fdSAlex Wilson 		return (B_FALSE);
1638ebb7c6fdSAlex Wilson 	}
1639ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1640ebb7c6fdSAlex Wilson 
1641ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1642ebb7c6fdSAlex Wilson 	if (ret) {
1643ebb7c6fdSAlex Wilson 		mltd->mltd_allocated = B_FALSE;
1644ebb7c6fdSAlex Wilson 		mltd->mltd_num = 0;
1645ebb7c6fdSAlex Wilson 	}
1646ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1647ebb7c6fdSAlex Wilson 	return (ret);
1648ebb7c6fdSAlex Wilson }
1649ebb7c6fdSAlex Wilson 
1650ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_teardown_hca(mlxcx_t * mlxp)1651ebb7c6fdSAlex Wilson mlxcx_cmd_teardown_hca(mlxcx_t *mlxp)
1652ebb7c6fdSAlex Wilson {
1653ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1654ebb7c6fdSAlex Wilson 	mlxcx_cmd_teardown_hca_in_t in;
1655ebb7c6fdSAlex Wilson 	mlxcx_cmd_teardown_hca_out_t out;
1656ebb7c6fdSAlex Wilson 	boolean_t ret;
1657ebb7c6fdSAlex Wilson 
1658ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1659ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1660ebb7c6fdSAlex Wilson 
1661ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1662ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_teardown_hca_head,
1663ebb7c6fdSAlex Wilson 	    MLXCX_OP_TEARDOWN_HCA, 0);
1664ebb7c6fdSAlex Wilson 	in.mlxi_teardown_hca_profile = to_be16(MLXCX_TEARDOWN_HCA_GRACEFUL);
1665ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1666ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1667ebb7c6fdSAlex Wilson 		return (B_FALSE);
1668ebb7c6fdSAlex Wilson 	}
1669ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1670ebb7c6fdSAlex Wilson 
1671ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1672ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1673ebb7c6fdSAlex Wilson 	return (ret);
1674ebb7c6fdSAlex Wilson }
1675ebb7c6fdSAlex Wilson 
1676ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_nic_vport_ctx(mlxcx_t * mlxp,mlxcx_port_t * mlp)1677ebb7c6fdSAlex Wilson mlxcx_cmd_query_nic_vport_ctx(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1678ebb7c6fdSAlex Wilson {
1679ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1680ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_nic_vport_ctx_in_t in;
1681ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_nic_vport_ctx_out_t out;
1682ebb7c6fdSAlex Wilson 	boolean_t ret;
1683ebb7c6fdSAlex Wilson 	const mlxcx_nic_vport_ctx_t *ctx;
1684ebb7c6fdSAlex Wilson 
1685ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1686ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1687ebb7c6fdSAlex Wilson 
1688ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1689ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1690ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_nic_vport_ctx_head,
1691ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_NIC_VPORT_CONTEXT, MLXCX_VPORT_TYPE_VNIC);
1692ebb7c6fdSAlex Wilson 
1693ebb7c6fdSAlex Wilson 	in.mlxi_query_nic_vport_ctx_vport_number = to_be16(mlp->mlp_num);
1694ebb7c6fdSAlex Wilson 
1695ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1696ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1697ebb7c6fdSAlex Wilson 		return (B_FALSE);
1698ebb7c6fdSAlex Wilson 	}
1699ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1700ebb7c6fdSAlex Wilson 
1701ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1702ebb7c6fdSAlex Wilson 	if (ret) {
1703ebb7c6fdSAlex Wilson 		ctx = &out.mlxo_query_nic_vport_ctx_context;
1704ebb7c6fdSAlex Wilson 		mlp->mlp_guid = from_be64(ctx->mlnvc_port_guid);
1705ebb7c6fdSAlex Wilson 		mlp->mlp_mtu = from_be16(ctx->mlnvc_mtu);
1706ebb7c6fdSAlex Wilson 		bcopy(ctx->mlnvc_permanent_address, mlp->mlp_mac_address,
1707ebb7c6fdSAlex Wilson 		    sizeof (mlp->mlp_mac_address));
1708ebb7c6fdSAlex Wilson 		mlp->mlp_wqe_min_inline = get_bits64(ctx->mlnvc_flags,
1709ebb7c6fdSAlex Wilson 		    MLXCX_VPORT_CTX_MIN_WQE_INLINE);
1710ebb7c6fdSAlex Wilson 	}
1711ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1712ebb7c6fdSAlex Wilson 	return (ret);
1713ebb7c6fdSAlex Wilson }
1714ebb7c6fdSAlex Wilson 
1715ebb7c6fdSAlex Wilson static const char *
mlxcx_reg_name(mlxcx_register_id_t rid)1716ebb7c6fdSAlex Wilson mlxcx_reg_name(mlxcx_register_id_t rid)
1717ebb7c6fdSAlex Wilson {
1718ebb7c6fdSAlex Wilson 	switch (rid) {
1719ebb7c6fdSAlex Wilson 	case MLXCX_REG_PMTU:
1720ebb7c6fdSAlex Wilson 		return ("PMTU");
1721ebb7c6fdSAlex Wilson 	case MLXCX_REG_PAOS:
1722ebb7c6fdSAlex Wilson 		return ("PAOS");
1723*85e4aa97SDan McDonald 	case MLXCX_REG_PCAM:
1724*85e4aa97SDan McDonald 		return ("PCAM");
1725ebb7c6fdSAlex Wilson 	case MLXCX_REG_PTYS:
1726ebb7c6fdSAlex Wilson 		return ("PTYS");
1727ebb7c6fdSAlex Wilson 	case MLXCX_REG_MSGI:
1728ebb7c6fdSAlex Wilson 		return ("MSGI");
1729ebb7c6fdSAlex Wilson 	case MLXCX_REG_PMAOS:
1730ebb7c6fdSAlex Wilson 		return ("PMAOS");
1731ebb7c6fdSAlex Wilson 	case MLXCX_REG_MLCR:
1732ebb7c6fdSAlex Wilson 		return ("MLCR");
1733ebb7c6fdSAlex Wilson 	case MLXCX_REG_MCIA:
1734ebb7c6fdSAlex Wilson 		return ("MCIA");
1735ebb7c6fdSAlex Wilson 	case MLXCX_REG_PPCNT:
1736ebb7c6fdSAlex Wilson 		return ("PPCNT");
1737d77e6e0fSPaul Winder 	case MLXCX_REG_PPLM:
1738d77e6e0fSPaul Winder 		return ("PPLM");
17391718c316SRobert Mustacchi 	case MLXCX_REG_MTCAP:
17401718c316SRobert Mustacchi 		return ("MTCAP");
17411718c316SRobert Mustacchi 	case MLXCX_REG_MTMP:
17421718c316SRobert Mustacchi 		return ("MTMP");
1743ebb7c6fdSAlex Wilson 	default:
1744ebb7c6fdSAlex Wilson 		return ("???");
1745ebb7c6fdSAlex Wilson 	}
1746ebb7c6fdSAlex Wilson }
1747ebb7c6fdSAlex Wilson 
1748ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_access_register(mlxcx_t * mlxp,mlxcx_cmd_reg_opmod_t opmod,mlxcx_register_id_t rid,mlxcx_register_data_t * data)1749ebb7c6fdSAlex Wilson mlxcx_cmd_access_register(mlxcx_t *mlxp, mlxcx_cmd_reg_opmod_t opmod,
1750ebb7c6fdSAlex Wilson     mlxcx_register_id_t rid, mlxcx_register_data_t *data)
1751ebb7c6fdSAlex Wilson {
1752ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
1753ebb7c6fdSAlex Wilson 	mlxcx_cmd_access_register_in_t in;
1754ebb7c6fdSAlex Wilson 	mlxcx_cmd_access_register_out_t out;
1755ebb7c6fdSAlex Wilson 	boolean_t ret;
1756ebb7c6fdSAlex Wilson 	size_t dsize, insize, outsize;
1757ebb7c6fdSAlex Wilson 
1758ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
1759ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
1760ebb7c6fdSAlex Wilson 
1761ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
1762ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_access_register_head,
1763ebb7c6fdSAlex Wilson 	    MLXCX_OP_ACCESS_REG, opmod);
1764ebb7c6fdSAlex Wilson 
1765ebb7c6fdSAlex Wilson 	in.mlxi_access_register_register_id = to_be16(rid);
1766ebb7c6fdSAlex Wilson 
1767ebb7c6fdSAlex Wilson 	switch (rid) {
1768ebb7c6fdSAlex Wilson 	case MLXCX_REG_PMTU:
1769ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_pmtu_t);
1770ebb7c6fdSAlex Wilson 		break;
1771ebb7c6fdSAlex Wilson 	case MLXCX_REG_PAOS:
1772ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_paos_t);
1773ebb7c6fdSAlex Wilson 		break;
1774*85e4aa97SDan McDonald 	case MLXCX_REG_PCAM:
1775*85e4aa97SDan McDonald 		dsize = sizeof (mlxcx_reg_pcam_t);
1776*85e4aa97SDan McDonald 		break;
1777ebb7c6fdSAlex Wilson 	case MLXCX_REG_PTYS:
1778ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_ptys_t);
1779ebb7c6fdSAlex Wilson 		break;
1780ebb7c6fdSAlex Wilson 	case MLXCX_REG_MLCR:
1781ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_mlcr_t);
1782ebb7c6fdSAlex Wilson 		break;
1783ebb7c6fdSAlex Wilson 	case MLXCX_REG_PMAOS:
1784ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_pmaos_t);
1785ebb7c6fdSAlex Wilson 		break;
1786ebb7c6fdSAlex Wilson 	case MLXCX_REG_MCIA:
1787ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_mcia_t);
1788ebb7c6fdSAlex Wilson 		break;
1789ebb7c6fdSAlex Wilson 	case MLXCX_REG_PPCNT:
1790ebb7c6fdSAlex Wilson 		dsize = sizeof (mlxcx_reg_ppcnt_t);
1791ebb7c6fdSAlex Wilson 		break;
1792d77e6e0fSPaul Winder 	case MLXCX_REG_PPLM:
1793d77e6e0fSPaul Winder 		dsize = sizeof (mlxcx_reg_pplm_t);
1794d77e6e0fSPaul Winder 		break;
17951718c316SRobert Mustacchi 	case MLXCX_REG_MTCAP:
17961718c316SRobert Mustacchi 		dsize = sizeof (mlxcx_reg_mtcap_t);
17971718c316SRobert Mustacchi 		break;
17981718c316SRobert Mustacchi 	case MLXCX_REG_MTMP:
17991718c316SRobert Mustacchi 		dsize = sizeof (mlxcx_reg_mtmp_t);
18001718c316SRobert Mustacchi 		break;
1801ebb7c6fdSAlex Wilson 	default:
1802ebb7c6fdSAlex Wilson 		dsize = 0;
1803ebb7c6fdSAlex Wilson 		VERIFY(0);
1804ebb7c6fdSAlex Wilson 		return (B_FALSE);
1805ebb7c6fdSAlex Wilson 	}
1806ebb7c6fdSAlex Wilson 	insize = dsize + offsetof(mlxcx_cmd_access_register_in_t,
1807ebb7c6fdSAlex Wilson 	    mlxi_access_register_data);
1808ebb7c6fdSAlex Wilson 	outsize = dsize + offsetof(mlxcx_cmd_access_register_out_t,
1809ebb7c6fdSAlex Wilson 	    mlxo_access_register_data);
1810ebb7c6fdSAlex Wilson 
1811ebb7c6fdSAlex Wilson 	bcopy(data, &in.mlxi_access_register_data, dsize);
1812ebb7c6fdSAlex Wilson 
1813ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, outsize)) {
1814ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
1815ebb7c6fdSAlex Wilson 		return (B_FALSE);
1816ebb7c6fdSAlex Wilson 	}
1817ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
1818ebb7c6fdSAlex Wilson 
1819ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1820ebb7c6fdSAlex Wilson 	if (ret) {
1821ebb7c6fdSAlex Wilson 		bcopy(&out.mlxo_access_register_data, data, dsize);
1822ebb7c6fdSAlex Wilson 	} else {
1823ebb7c6fdSAlex Wilson 		mlxcx_warn(mlxp, "failed OP_ACCESS_REG was for register "
1824ebb7c6fdSAlex Wilson 		    "%04x (%s)", rid, mlxcx_reg_name(rid));
1825ebb7c6fdSAlex Wilson 	}
1826ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
1827ebb7c6fdSAlex Wilson 	return (ret);
1828ebb7c6fdSAlex Wilson }
1829ebb7c6fdSAlex Wilson 
1830ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_port_mtu(mlxcx_t * mlxp,mlxcx_port_t * mlp)1831ebb7c6fdSAlex Wilson mlxcx_cmd_query_port_mtu(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1832ebb7c6fdSAlex Wilson {
1833ebb7c6fdSAlex Wilson 	mlxcx_register_data_t data;
1834ebb7c6fdSAlex Wilson 	boolean_t ret;
1835ebb7c6fdSAlex Wilson 
1836ebb7c6fdSAlex Wilson 	/*
1837ebb7c6fdSAlex Wilson 	 * Since we modify the port here we require that the caller is holding
1838ebb7c6fdSAlex Wilson 	 * the port mutex.
1839ebb7c6fdSAlex Wilson 	 */
1840ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1841ebb7c6fdSAlex Wilson 	bzero(&data, sizeof (data));
1842ebb7c6fdSAlex Wilson 	data.mlrd_pmtu.mlrd_pmtu_local_port = mlp->mlp_num + 1;
1843ebb7c6fdSAlex Wilson 
1844ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1845ebb7c6fdSAlex Wilson 	    MLXCX_REG_PMTU, &data);
1846ebb7c6fdSAlex Wilson 
1847ebb7c6fdSAlex Wilson 	if (ret) {
1848ebb7c6fdSAlex Wilson 		mlp->mlp_mtu = from_be16(data.mlrd_pmtu.mlrd_pmtu_admin_mtu);
1849ebb7c6fdSAlex Wilson 		mlp->mlp_max_mtu = from_be16(data.mlrd_pmtu.mlrd_pmtu_max_mtu);
1850ebb7c6fdSAlex Wilson 	}
1851ebb7c6fdSAlex Wilson 
1852ebb7c6fdSAlex Wilson 	return (ret);
1853ebb7c6fdSAlex Wilson }
1854ebb7c6fdSAlex Wilson 
1855ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_module_status(mlxcx_t * mlxp,uint_t id,mlxcx_module_status_t * pstatus,mlxcx_module_error_type_t * perr)1856ebb7c6fdSAlex Wilson mlxcx_cmd_query_module_status(mlxcx_t *mlxp, uint_t id,
1857ebb7c6fdSAlex Wilson     mlxcx_module_status_t *pstatus, mlxcx_module_error_type_t *perr)
1858ebb7c6fdSAlex Wilson {
1859ebb7c6fdSAlex Wilson 	mlxcx_register_data_t data;
1860ebb7c6fdSAlex Wilson 	boolean_t ret;
1861ebb7c6fdSAlex Wilson 
1862ebb7c6fdSAlex Wilson 	bzero(&data, sizeof (data));
1863ebb7c6fdSAlex Wilson 	ASSERT3U(id, <, 0xff);
1864ebb7c6fdSAlex Wilson 	data.mlrd_pmaos.mlrd_pmaos_module = (uint8_t)id;
1865ebb7c6fdSAlex Wilson 
1866ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1867ebb7c6fdSAlex Wilson 	    MLXCX_REG_PMAOS, &data);
1868ebb7c6fdSAlex Wilson 
1869ebb7c6fdSAlex Wilson 	if (ret) {
1870ebb7c6fdSAlex Wilson 		if (pstatus != NULL)
1871ebb7c6fdSAlex Wilson 			*pstatus = data.mlrd_pmaos.mlrd_pmaos_oper_status;
1872ebb7c6fdSAlex Wilson 		if (perr != NULL)
1873ebb7c6fdSAlex Wilson 			*perr = data.mlrd_pmaos.mlrd_pmaos_error_type;
1874ebb7c6fdSAlex Wilson 	}
1875ebb7c6fdSAlex Wilson 
1876ebb7c6fdSAlex Wilson 	return (ret);
1877ebb7c6fdSAlex Wilson }
1878ebb7c6fdSAlex Wilson 
1879ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_port_mtu(mlxcx_t * mlxp,mlxcx_port_t * mlp)1880ebb7c6fdSAlex Wilson mlxcx_cmd_set_port_mtu(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1881ebb7c6fdSAlex Wilson {
1882ebb7c6fdSAlex Wilson 	mlxcx_register_data_t data;
1883ebb7c6fdSAlex Wilson 	boolean_t ret;
1884ebb7c6fdSAlex Wilson 
1885ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1886ebb7c6fdSAlex Wilson 	bzero(&data, sizeof (data));
1887ebb7c6fdSAlex Wilson 	data.mlrd_pmtu.mlrd_pmtu_local_port = mlp->mlp_num + 1;
1888ebb7c6fdSAlex Wilson 	data.mlrd_pmtu.mlrd_pmtu_admin_mtu = to_be16(mlp->mlp_mtu);
1889ebb7c6fdSAlex Wilson 
1890ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
1891ebb7c6fdSAlex Wilson 	    MLXCX_REG_PMTU, &data);
1892ebb7c6fdSAlex Wilson 
1893ebb7c6fdSAlex Wilson 	return (ret);
1894ebb7c6fdSAlex Wilson }
1895ebb7c6fdSAlex Wilson 
1896ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_port_led(mlxcx_t * mlxp,mlxcx_port_t * mlp,uint16_t sec)1897ebb7c6fdSAlex Wilson mlxcx_cmd_set_port_led(mlxcx_t *mlxp, mlxcx_port_t *mlp, uint16_t sec)
1898ebb7c6fdSAlex Wilson {
1899ebb7c6fdSAlex Wilson 	mlxcx_register_data_t data;
1900ebb7c6fdSAlex Wilson 	boolean_t ret;
1901ebb7c6fdSAlex Wilson 
1902ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1903ebb7c6fdSAlex Wilson 	bzero(&data, sizeof (data));
1904ebb7c6fdSAlex Wilson 	data.mlrd_mlcr.mlrd_mlcr_local_port = mlp->mlp_num + 1;
1905ebb7c6fdSAlex Wilson 	set_bits8(&data.mlrd_mlcr.mlrd_mlcr_flags, MLXCX_MLCR_LED_TYPE,
1906ebb7c6fdSAlex Wilson 	    MLXCX_LED_TYPE_PORT);
1907ebb7c6fdSAlex Wilson 	data.mlrd_mlcr.mlrd_mlcr_beacon_duration = to_be16(sec);
1908ebb7c6fdSAlex Wilson 
1909ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
1910ebb7c6fdSAlex Wilson 	    MLXCX_REG_MLCR, &data);
1911ebb7c6fdSAlex Wilson 
1912ebb7c6fdSAlex Wilson 	return (ret);
1913ebb7c6fdSAlex Wilson }
1914ebb7c6fdSAlex Wilson 
1915ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_port_status(mlxcx_t * mlxp,mlxcx_port_t * mlp)1916ebb7c6fdSAlex Wilson mlxcx_cmd_query_port_status(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1917ebb7c6fdSAlex Wilson {
1918ebb7c6fdSAlex Wilson 	mlxcx_register_data_t data;
1919ebb7c6fdSAlex Wilson 	boolean_t ret;
1920ebb7c6fdSAlex Wilson 
1921ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1922ebb7c6fdSAlex Wilson 	bzero(&data, sizeof (data));
1923ebb7c6fdSAlex Wilson 	data.mlrd_paos.mlrd_paos_local_port = mlp->mlp_num + 1;
1924ebb7c6fdSAlex Wilson 
1925ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1926ebb7c6fdSAlex Wilson 	    MLXCX_REG_PAOS, &data);
1927ebb7c6fdSAlex Wilson 
1928ebb7c6fdSAlex Wilson 	if (ret) {
1929ebb7c6fdSAlex Wilson 		mlp->mlp_admin_status = data.mlrd_paos.mlrd_paos_admin_status;
1930ebb7c6fdSAlex Wilson 		mlp->mlp_oper_status = data.mlrd_paos.mlrd_paos_oper_status;
1931ebb7c6fdSAlex Wilson 	}
1932ebb7c6fdSAlex Wilson 
1933ebb7c6fdSAlex Wilson 	return (ret);
1934ebb7c6fdSAlex Wilson }
1935ebb7c6fdSAlex Wilson 
1936ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_modify_port_status(mlxcx_t * mlxp,mlxcx_port_t * mlp,mlxcx_port_status_t status)1937d77e6e0fSPaul Winder mlxcx_cmd_modify_port_status(mlxcx_t *mlxp, mlxcx_port_t *mlp,
1938d77e6e0fSPaul Winder     mlxcx_port_status_t status)
1939d77e6e0fSPaul Winder {
1940d77e6e0fSPaul Winder 	mlxcx_register_data_t data;
1941d77e6e0fSPaul Winder 	boolean_t ret;
1942d77e6e0fSPaul Winder 
1943d77e6e0fSPaul Winder 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1944d77e6e0fSPaul Winder 	bzero(&data, sizeof (data));
1945d77e6e0fSPaul Winder 	data.mlrd_paos.mlrd_paos_local_port = mlp->mlp_num + 1;
1946d77e6e0fSPaul Winder 	data.mlrd_paos.mlrd_paos_admin_status = status;
1947d77e6e0fSPaul Winder 	set_bit32(&data.mlrd_paos.mlrd_paos_flags, MLXCX_PAOS_ADMIN_ST_EN);
1948d77e6e0fSPaul Winder 
1949d77e6e0fSPaul Winder 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
1950d77e6e0fSPaul Winder 	    MLXCX_REG_PAOS, &data);
1951d77e6e0fSPaul Winder 
1952d77e6e0fSPaul Winder 	return (ret);
1953d77e6e0fSPaul Winder }
1954d77e6e0fSPaul Winder 
1955d77e6e0fSPaul Winder boolean_t
mlxcx_cmd_query_port_speed(mlxcx_t * mlxp,mlxcx_port_t * mlp)1956ebb7c6fdSAlex Wilson mlxcx_cmd_query_port_speed(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1957ebb7c6fdSAlex Wilson {
1958ebb7c6fdSAlex Wilson 	mlxcx_register_data_t data;
1959ebb7c6fdSAlex Wilson 	boolean_t ret;
1960ebb7c6fdSAlex Wilson 
1961ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1962ebb7c6fdSAlex Wilson 	bzero(&data, sizeof (data));
1963ebb7c6fdSAlex Wilson 	data.mlrd_ptys.mlrd_ptys_local_port = mlp->mlp_num + 1;
1964ebb7c6fdSAlex Wilson 	set_bit8(&data.mlrd_ptys.mlrd_ptys_proto_mask,
1965ebb7c6fdSAlex Wilson 	    MLXCX_PTYS_PROTO_MASK_ETH);
1966ebb7c6fdSAlex Wilson 
1967ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1968ebb7c6fdSAlex Wilson 	    MLXCX_REG_PTYS, &data);
1969ebb7c6fdSAlex Wilson 
1970ebb7c6fdSAlex Wilson 	if (ret) {
1971ebb7c6fdSAlex Wilson 		if (get_bit8(data.mlrd_ptys.mlrd_ptys_autoneg_flags,
1972ebb7c6fdSAlex Wilson 		    MLXCX_AUTONEG_DISABLE)) {
1973ebb7c6fdSAlex Wilson 			mlp->mlp_autoneg = B_FALSE;
1974ebb7c6fdSAlex Wilson 		} else {
1975ebb7c6fdSAlex Wilson 			mlp->mlp_autoneg = B_TRUE;
1976ebb7c6fdSAlex Wilson 		}
1977ebb7c6fdSAlex Wilson 		mlp->mlp_max_proto =
1978ebb7c6fdSAlex Wilson 		    from_bits32(data.mlrd_ptys.mlrd_ptys_proto_cap);
1979ebb7c6fdSAlex Wilson 		mlp->mlp_admin_proto =
1980ebb7c6fdSAlex Wilson 		    from_bits32(data.mlrd_ptys.mlrd_ptys_proto_admin);
1981ebb7c6fdSAlex Wilson 		mlp->mlp_oper_proto =
1982ebb7c6fdSAlex Wilson 		    from_bits32(data.mlrd_ptys.mlrd_ptys_proto_oper);
1983*85e4aa97SDan McDonald 		if (mlxp->mlx_caps->mlc_ext_ptys) {
1984*85e4aa97SDan McDonald 			/*
1985*85e4aa97SDan McDonald 			 * Populate these bits only if we know the HW
1986*85e4aa97SDan McDonald 			 * supports them.  Otherwise keep them zeroed
1987*85e4aa97SDan McDonald 			 * per the above bzero() and use that zero-ness to
1988*85e4aa97SDan McDonald 			 * skip over them as need be.
1989*85e4aa97SDan McDonald 			 */
1990*85e4aa97SDan McDonald 			mlp->mlp_ext_max_proto = from_bits32(
1991*85e4aa97SDan McDonald 			    data.mlrd_ptys.mlrd_ptys_ext_proto_cap);
1992*85e4aa97SDan McDonald 			mlp->mlp_ext_admin_proto = from_bits32(
1993*85e4aa97SDan McDonald 			    data.mlrd_ptys.mlrd_ptys_ext_proto_admin);
1994*85e4aa97SDan McDonald 			mlp->mlp_ext_oper_proto = from_bits32(
1995*85e4aa97SDan McDonald 			    data.mlrd_ptys.mlrd_ptys_ext_proto_oper);
1996*85e4aa97SDan McDonald 		}
1997ebb7c6fdSAlex Wilson 	}
1998ebb7c6fdSAlex Wilson 
1999ebb7c6fdSAlex Wilson 	return (ret);
2000ebb7c6fdSAlex Wilson }
2001ebb7c6fdSAlex Wilson 
2002ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_port_fec(mlxcx_t * mlxp,mlxcx_port_t * mlp)2003d77e6e0fSPaul Winder mlxcx_cmd_query_port_fec(mlxcx_t *mlxp, mlxcx_port_t *mlp)
2004d77e6e0fSPaul Winder {
2005d77e6e0fSPaul Winder 	mlxcx_register_data_t data;
2006d77e6e0fSPaul Winder 	boolean_t ret;
2007d77e6e0fSPaul Winder 
2008d77e6e0fSPaul Winder 	ASSERT(mutex_owned(&mlp->mlp_mtx));
2009d77e6e0fSPaul Winder 	bzero(&data, sizeof (data));
2010d77e6e0fSPaul Winder 	data.mlrd_pplm.mlrd_pplm_local_port = mlp->mlp_num + 1;
2011d77e6e0fSPaul Winder 
2012d77e6e0fSPaul Winder 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
2013d77e6e0fSPaul Winder 	    MLXCX_REG_PPLM, &data);
2014d77e6e0fSPaul Winder 
2015d77e6e0fSPaul Winder 	if (ret) {
2016d77e6e0fSPaul Winder 		mlp->mlp_fec_active =
2017d77e6e0fSPaul Winder 		    from_be24(data.mlrd_pplm.mlrd_pplm_fec_mode_active);
2018d77e6e0fSPaul Winder 	}
2019d77e6e0fSPaul Winder 
2020d77e6e0fSPaul Winder 	return (ret);
2021d77e6e0fSPaul Winder }
2022d77e6e0fSPaul Winder 
2023d77e6e0fSPaul Winder boolean_t
mlxcx_cmd_modify_port_fec(mlxcx_t * mlxp,mlxcx_port_t * mlp,mlxcx_pplm_fec_caps_t fec)2024d77e6e0fSPaul Winder mlxcx_cmd_modify_port_fec(mlxcx_t *mlxp, mlxcx_port_t *mlp,
2025d77e6e0fSPaul Winder     mlxcx_pplm_fec_caps_t fec)
2026d77e6e0fSPaul Winder {
2027d77e6e0fSPaul Winder 	mlxcx_register_data_t data_in, data_out;
2028d77e6e0fSPaul Winder 	mlxcx_pplm_fec_caps_t caps;
2029d77e6e0fSPaul Winder 	mlxcx_reg_pplm_t *pplm_in, *pplm_out;
2030d77e6e0fSPaul Winder 	boolean_t ret;
2031d77e6e0fSPaul Winder 
2032d77e6e0fSPaul Winder 	ASSERT(mutex_owned(&mlp->mlp_mtx));
2033d77e6e0fSPaul Winder 	bzero(&data_in, sizeof (data_in));
2034d77e6e0fSPaul Winder 	pplm_in = &data_in.mlrd_pplm;
2035d77e6e0fSPaul Winder 	pplm_in->mlrd_pplm_local_port = mlp->mlp_num + 1;
2036d77e6e0fSPaul Winder 
2037d77e6e0fSPaul Winder 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
2038d77e6e0fSPaul Winder 	    MLXCX_REG_PPLM, &data_in);
2039d77e6e0fSPaul Winder 
2040d77e6e0fSPaul Winder 	if (!ret)
2041d77e6e0fSPaul Winder 		return (B_FALSE);
2042d77e6e0fSPaul Winder 
2043d77e6e0fSPaul Winder 	bzero(&data_out, sizeof (data_out));
2044d77e6e0fSPaul Winder 	pplm_out = &data_out.mlrd_pplm;
2045d77e6e0fSPaul Winder 	pplm_out->mlrd_pplm_local_port = mlp->mlp_num + 1;
2046d77e6e0fSPaul Winder 
2047d77e6e0fSPaul Winder 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
2048d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_56G);
2049d77e6e0fSPaul Winder 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2050d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_56G, fec & caps);
2051d77e6e0fSPaul Winder 
2052d77e6e0fSPaul Winder 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
2053d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_100G);
2054d77e6e0fSPaul Winder 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2055d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_100G, fec & caps);
2056d77e6e0fSPaul Winder 
2057d77e6e0fSPaul Winder 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
2058d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_50G);
2059d77e6e0fSPaul Winder 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2060d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_50G, fec & caps);
2061d77e6e0fSPaul Winder 
2062d77e6e0fSPaul Winder 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
2063d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_25G);
2064d77e6e0fSPaul Winder 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2065d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_25G, fec & caps);
2066d77e6e0fSPaul Winder 
2067d77e6e0fSPaul Winder 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
2068d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_10_40G);
2069d77e6e0fSPaul Winder 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2070d77e6e0fSPaul Winder 	    MLXCX_PPLM_CAP_10_40G, fec & caps);
2071d77e6e0fSPaul Winder 
2072d77e6e0fSPaul Winder 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
2073d77e6e0fSPaul Winder 	    MLXCX_REG_PPLM, &data_out);
2074d77e6e0fSPaul Winder 
2075d77e6e0fSPaul Winder 	return (ret);
2076d77e6e0fSPaul Winder }
2077d77e6e0fSPaul Winder 
2078d77e6e0fSPaul Winder boolean_t
mlxcx_cmd_modify_nic_vport_ctx(mlxcx_t * mlxp,mlxcx_port_t * mlp,mlxcx_modify_nic_vport_ctx_fields_t fields)2079ebb7c6fdSAlex Wilson mlxcx_cmd_modify_nic_vport_ctx(mlxcx_t *mlxp, mlxcx_port_t *mlp,
2080ebb7c6fdSAlex Wilson     mlxcx_modify_nic_vport_ctx_fields_t fields)
2081ebb7c6fdSAlex Wilson {
2082ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2083ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_nic_vport_ctx_in_t in;
2084ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_nic_vport_ctx_out_t out;
2085ebb7c6fdSAlex Wilson 	boolean_t ret;
2086ebb7c6fdSAlex Wilson 	mlxcx_nic_vport_ctx_t *ctx;
2087ebb7c6fdSAlex Wilson 
2088ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlp->mlp_mtx));
2089ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2090ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2091ebb7c6fdSAlex Wilson 
2092ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2093ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_nic_vport_ctx_head,
2094ebb7c6fdSAlex Wilson 	    MLXCX_OP_MODIFY_NIC_VPORT_CONTEXT, MLXCX_VPORT_TYPE_VNIC);
2095ebb7c6fdSAlex Wilson 
2096ebb7c6fdSAlex Wilson 	in.mlxi_modify_nic_vport_ctx_vport_number = to_be16(mlp->mlp_num);
2097ebb7c6fdSAlex Wilson 	in.mlxi_modify_nic_vport_ctx_field_select = to_be32(fields);
2098ebb7c6fdSAlex Wilson 
2099ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_modify_nic_vport_ctx_context;
2100ebb7c6fdSAlex Wilson 	if (fields & MLXCX_MODIFY_NIC_VPORT_CTX_PROMISC) {
2101ebb7c6fdSAlex Wilson 		set_bit16(&ctx->mlnvc_promisc_list_type,
2102ebb7c6fdSAlex Wilson 		    MLXCX_VPORT_PROMISC_ALL);
2103ebb7c6fdSAlex Wilson 	}
2104ebb7c6fdSAlex Wilson 	if (fields & MLXCX_MODIFY_NIC_VPORT_CTX_MTU) {
2105ebb7c6fdSAlex Wilson 		ctx->mlnvc_mtu = to_be16(mlp->mlp_mtu);
2106ebb7c6fdSAlex Wilson 	}
2107ebb7c6fdSAlex Wilson 
2108ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2109ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2110ebb7c6fdSAlex Wilson 		return (B_FALSE);
2111ebb7c6fdSAlex Wilson 	}
2112ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2113ebb7c6fdSAlex Wilson 
2114ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2115ebb7c6fdSAlex Wilson 	if (ret) {
2116ebb7c6fdSAlex Wilson 		if (fields & MLXCX_MODIFY_NIC_VPORT_CTX_PROMISC) {
2117ebb7c6fdSAlex Wilson 			mlp->mlp_flags |= MLXCX_PORT_VPORT_PROMISC;
2118ebb7c6fdSAlex Wilson 		}
2119ebb7c6fdSAlex Wilson 	}
2120ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2121ebb7c6fdSAlex Wilson 	return (ret);
2122ebb7c6fdSAlex Wilson }
2123ebb7c6fdSAlex Wilson 
2124ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_eq(mlxcx_t * mlxp,mlxcx_event_queue_t * mleq)2125ebb7c6fdSAlex Wilson mlxcx_cmd_create_eq(mlxcx_t *mlxp, mlxcx_event_queue_t *mleq)
2126ebb7c6fdSAlex Wilson {
2127ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2128ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_eq_in_t in;
2129ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_eq_out_t out;
2130ebb7c6fdSAlex Wilson 	boolean_t ret;
2131ebb7c6fdSAlex Wilson 	mlxcx_eventq_ctx_t *ctx;
2132ebb7c6fdSAlex Wilson 	size_t rem, insize;
2133ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *c;
2134ebb7c6fdSAlex Wilson 	uint64_t pa, npages;
2135ebb7c6fdSAlex Wilson 
2136ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2137ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2138ebb7c6fdSAlex Wilson 
2139ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mleq->mleq_mtx));
2140ebb7c6fdSAlex Wilson 	VERIFY(mleq->mleq_state & MLXCX_EQ_ALLOC);
2141ebb7c6fdSAlex Wilson 	VERIFY0(mleq->mleq_state & MLXCX_EQ_CREATED);
2142ebb7c6fdSAlex Wilson 
2143ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2144ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_eq_head,
2145ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_EQ, 0);
2146ebb7c6fdSAlex Wilson 
2147ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_eq_context;
2148ebb7c6fdSAlex Wilson 	ctx->mleqc_uar_page = to_be24(mleq->mleq_uar->mlu_num);
2149ebb7c6fdSAlex Wilson 	ctx->mleqc_log_eq_size = mleq->mleq_entshift;
2150ebb7c6fdSAlex Wilson 	ctx->mleqc_intr = mleq->mleq_intr_index;
2151ebb7c6fdSAlex Wilson 
2152ebb7c6fdSAlex Wilson 	in.mlxi_create_eq_event_bitmask = to_be64(mleq->mleq_events);
2153ebb7c6fdSAlex Wilson 
2154ebb7c6fdSAlex Wilson 	npages = 0;
2155ebb7c6fdSAlex Wilson 	c = NULL;
2156ebb7c6fdSAlex Wilson 	while ((c = mlxcx_dma_cookie_iter(&mleq->mleq_dma, c)) != NULL) {
2157ebb7c6fdSAlex Wilson 		pa = c->dmac_laddress;
2158ebb7c6fdSAlex Wilson 		rem = c->dmac_size;
2159ebb7c6fdSAlex Wilson 		while (rem > 0) {
2160ebb7c6fdSAlex Wilson 			ASSERT3U(pa & 0xfff, ==, 0);
2161ebb7c6fdSAlex Wilson 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
2162ebb7c6fdSAlex Wilson 			in.mlxi_create_eq_pas[npages++] = to_be64(pa);
2163ebb7c6fdSAlex Wilson 			rem -= MLXCX_HW_PAGE_SIZE;
2164ebb7c6fdSAlex Wilson 			pa += MLXCX_HW_PAGE_SIZE;
2165ebb7c6fdSAlex Wilson 		}
2166ebb7c6fdSAlex Wilson 	}
2167ebb7c6fdSAlex Wilson 	ASSERT3U(npages, <=, MLXCX_CREATE_QUEUE_MAX_PAGES);
2168ebb7c6fdSAlex Wilson 
2169ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_create_eq_in_t, mlxi_create_eq_pas) +
2170ebb7c6fdSAlex Wilson 	    sizeof (uint64_t) * npages;
2171ebb7c6fdSAlex Wilson 
2172ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
2173ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2174ebb7c6fdSAlex Wilson 		return (B_FALSE);
2175ebb7c6fdSAlex Wilson 	}
2176ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2177ebb7c6fdSAlex Wilson 
2178ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2179ebb7c6fdSAlex Wilson 	if (ret) {
2180ebb7c6fdSAlex Wilson 		mleq->mleq_state |= MLXCX_EQ_CREATED;
2181ebb7c6fdSAlex Wilson 		mleq->mleq_num = out.mlxo_create_eq_eqn;
2182ebb7c6fdSAlex Wilson 	}
2183ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2184ebb7c6fdSAlex Wilson 	return (ret);
2185ebb7c6fdSAlex Wilson }
2186ebb7c6fdSAlex Wilson 
2187ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_eq(mlxcx_t * mlxp,mlxcx_event_queue_t * mleq,mlxcx_eventq_ctx_t * ctxp)2188ebb7c6fdSAlex Wilson mlxcx_cmd_query_eq(mlxcx_t *mlxp, mlxcx_event_queue_t *mleq,
2189ebb7c6fdSAlex Wilson     mlxcx_eventq_ctx_t *ctxp)
2190ebb7c6fdSAlex Wilson {
2191ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2192ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_eq_in_t in;
2193ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_eq_out_t out;
2194ebb7c6fdSAlex Wilson 	boolean_t ret;
2195ebb7c6fdSAlex Wilson 
2196ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2197ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2198ebb7c6fdSAlex Wilson 
2199ebb7c6fdSAlex Wilson 	VERIFY(mleq->mleq_state & MLXCX_EQ_ALLOC);
2200ebb7c6fdSAlex Wilson 	VERIFY(mleq->mleq_state & MLXCX_EQ_CREATED);
2201ebb7c6fdSAlex Wilson 
2202ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2203ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_eq_head,
2204ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_EQ, 0);
2205ebb7c6fdSAlex Wilson 
2206ebb7c6fdSAlex Wilson 	in.mlxi_query_eq_eqn = mleq->mleq_num;
2207ebb7c6fdSAlex Wilson 
2208ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2209ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2210ebb7c6fdSAlex Wilson 		return (B_FALSE);
2211ebb7c6fdSAlex Wilson 	}
2212ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2213ebb7c6fdSAlex Wilson 
2214ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2215ebb7c6fdSAlex Wilson 	if (ret) {
2216ebb7c6fdSAlex Wilson 		bcopy(&out.mlxo_query_eq_context, ctxp,
2217ebb7c6fdSAlex Wilson 		    sizeof (mlxcx_eventq_ctx_t));
2218ebb7c6fdSAlex Wilson 	}
2219ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2220ebb7c6fdSAlex Wilson 	return (ret);
2221ebb7c6fdSAlex Wilson }
2222ebb7c6fdSAlex Wilson 
2223ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_eq(mlxcx_t * mlxp,mlxcx_event_queue_t * mleq)2224ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_eq(mlxcx_t *mlxp, mlxcx_event_queue_t *mleq)
2225ebb7c6fdSAlex Wilson {
2226ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2227ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_eq_in_t in;
2228ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_eq_out_t out;
2229ebb7c6fdSAlex Wilson 	boolean_t ret;
2230ebb7c6fdSAlex Wilson 
2231ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2232ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2233ebb7c6fdSAlex Wilson 
2234ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mleq->mleq_mtx));
2235ebb7c6fdSAlex Wilson 	VERIFY(mleq->mleq_state & MLXCX_EQ_ALLOC);
2236ebb7c6fdSAlex Wilson 	VERIFY(mleq->mleq_state & MLXCX_EQ_CREATED);
2237ebb7c6fdSAlex Wilson 
2238ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2239ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_eq_head,
2240ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_EQ, 0);
2241ebb7c6fdSAlex Wilson 
2242ebb7c6fdSAlex Wilson 	in.mlxi_destroy_eq_eqn = mleq->mleq_num;
2243ebb7c6fdSAlex Wilson 
2244ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2245ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2246ebb7c6fdSAlex Wilson 		return (B_FALSE);
2247ebb7c6fdSAlex Wilson 	}
2248ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2249ebb7c6fdSAlex Wilson 
2250ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2251ebb7c6fdSAlex Wilson 	if (ret) {
2252ebb7c6fdSAlex Wilson 		mleq->mleq_state |= MLXCX_EQ_DESTROYED;
2253ebb7c6fdSAlex Wilson 	}
2254ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2255ebb7c6fdSAlex Wilson 	return (ret);
2256ebb7c6fdSAlex Wilson }
2257ebb7c6fdSAlex Wilson 
2258ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_special_ctxs(mlxcx_t * mlxp)2259ebb7c6fdSAlex Wilson mlxcx_cmd_query_special_ctxs(mlxcx_t *mlxp)
2260ebb7c6fdSAlex Wilson {
2261ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2262ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_special_ctxs_in_t in;
2263ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_special_ctxs_out_t out;
2264ebb7c6fdSAlex Wilson 	boolean_t ret;
2265ebb7c6fdSAlex Wilson 
2266ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2267ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2268ebb7c6fdSAlex Wilson 
2269ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2270ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_special_ctxs_head,
2271ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_SPECIAL_CONTEXTS, 0);
2272ebb7c6fdSAlex Wilson 
2273ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2274ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2275ebb7c6fdSAlex Wilson 		return (B_FALSE);
2276ebb7c6fdSAlex Wilson 	}
2277ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2278ebb7c6fdSAlex Wilson 
2279ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2280ebb7c6fdSAlex Wilson 	if (ret) {
2281ebb7c6fdSAlex Wilson 		mlxp->mlx_rsvd_lkey = from_be32(
2282ebb7c6fdSAlex Wilson 		    out.mlxo_query_special_ctxs_resd_lkey);
2283ebb7c6fdSAlex Wilson 	}
2284ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2285ebb7c6fdSAlex Wilson 	return (ret);
2286ebb7c6fdSAlex Wilson }
2287ebb7c6fdSAlex Wilson 
2288ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_cq(mlxcx_t * mlxp,mlxcx_completion_queue_t * mlcq)2289ebb7c6fdSAlex Wilson mlxcx_cmd_create_cq(mlxcx_t *mlxp, mlxcx_completion_queue_t *mlcq)
2290ebb7c6fdSAlex Wilson {
2291ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2292ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_cq_in_t in;
2293ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_cq_out_t out;
2294ebb7c6fdSAlex Wilson 	boolean_t ret;
2295ebb7c6fdSAlex Wilson 	mlxcx_completionq_ctx_t *ctx;
2296ebb7c6fdSAlex Wilson 	size_t rem, insize;
2297ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *c;
2298ebb7c6fdSAlex Wilson 	uint64_t pa, npages;
2299ebb7c6fdSAlex Wilson 
2300ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2301ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2302ebb7c6fdSAlex Wilson 
2303ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlcq->mlcq_mtx));
2304ebb7c6fdSAlex Wilson 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_ALLOC);
2305ebb7c6fdSAlex Wilson 	VERIFY0(mlcq->mlcq_state & MLXCX_CQ_CREATED);
2306ebb7c6fdSAlex Wilson 
2307ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2308ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_cq_head,
2309ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_CQ, 0);
2310ebb7c6fdSAlex Wilson 
2311ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_cq_context;
2312ebb7c6fdSAlex Wilson 	ctx->mlcqc_uar_page = to_be24(mlcq->mlcq_uar->mlu_num);
2313ebb7c6fdSAlex Wilson 	ctx->mlcqc_log_cq_size = mlcq->mlcq_entshift;
2314ebb7c6fdSAlex Wilson 	ctx->mlcqc_eqn = mlcq->mlcq_eq->mleq_num;
2315ebb7c6fdSAlex Wilson 	ctx->mlcqc_cq_period = to_be16(mlcq->mlcq_cqemod_period_usec);
2316ebb7c6fdSAlex Wilson 	ctx->mlcqc_cq_max_count = to_be16(mlcq->mlcq_cqemod_count);
2317ebb7c6fdSAlex Wilson 
2318ebb7c6fdSAlex Wilson 	c = mlxcx_dma_cookie_one(&mlcq->mlcq_doorbell_dma);
2319ebb7c6fdSAlex Wilson 	ctx->mlcqc_dbr_addr = to_be64(c->dmac_laddress);
2320ebb7c6fdSAlex Wilson 	ASSERT3U(c->dmac_size, >=, sizeof (mlxcx_completionq_doorbell_t));
2321ebb7c6fdSAlex Wilson 
2322ebb7c6fdSAlex Wilson 	npages = 0;
2323ebb7c6fdSAlex Wilson 	c = NULL;
2324ebb7c6fdSAlex Wilson 	while ((c = mlxcx_dma_cookie_iter(&mlcq->mlcq_dma, c)) != NULL) {
2325ebb7c6fdSAlex Wilson 		pa = c->dmac_laddress;
2326ebb7c6fdSAlex Wilson 		rem = c->dmac_size;
2327ebb7c6fdSAlex Wilson 		while (rem > 0) {
2328ebb7c6fdSAlex Wilson 			ASSERT3U(pa & 0xfff, ==, 0);
2329ebb7c6fdSAlex Wilson 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
2330ebb7c6fdSAlex Wilson 			in.mlxi_create_cq_pas[npages++] = to_be64(pa);
2331ebb7c6fdSAlex Wilson 			rem -= MLXCX_HW_PAGE_SIZE;
2332ebb7c6fdSAlex Wilson 			pa += MLXCX_HW_PAGE_SIZE;
2333ebb7c6fdSAlex Wilson 		}
2334ebb7c6fdSAlex Wilson 	}
2335ebb7c6fdSAlex Wilson 	ASSERT3U(npages, <=, MLXCX_CREATE_QUEUE_MAX_PAGES);
2336ebb7c6fdSAlex Wilson 
2337ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_create_cq_in_t, mlxi_create_cq_pas) +
2338ebb7c6fdSAlex Wilson 	    sizeof (uint64_t) * npages;
2339ebb7c6fdSAlex Wilson 
2340ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
2341ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2342ebb7c6fdSAlex Wilson 		return (B_FALSE);
2343ebb7c6fdSAlex Wilson 	}
2344ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2345ebb7c6fdSAlex Wilson 
2346ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2347ebb7c6fdSAlex Wilson 	if (ret) {
23480207f820SPaul Winder 		atomic_or_uint(&mlcq->mlcq_state, MLXCX_CQ_CREATED);
2349ebb7c6fdSAlex Wilson 		mlcq->mlcq_num = from_be24(out.mlxo_create_cq_cqn);
2350ebb7c6fdSAlex Wilson 	}
2351ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2352ebb7c6fdSAlex Wilson 	return (ret);
2353ebb7c6fdSAlex Wilson }
2354ebb7c6fdSAlex Wilson 
2355ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq,mlxcx_rq_ctx_t * ctxp)2356ebb7c6fdSAlex Wilson mlxcx_cmd_query_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq,
2357ebb7c6fdSAlex Wilson     mlxcx_rq_ctx_t *ctxp)
2358ebb7c6fdSAlex Wilson {
2359ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2360ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_rq_in_t in;
2361ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_rq_out_t out;
2362ebb7c6fdSAlex Wilson 	boolean_t ret;
2363ebb7c6fdSAlex Wilson 
2364ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2365ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2366ebb7c6fdSAlex Wilson 
2367ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2368ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2369ebb7c6fdSAlex Wilson 	ASSERT3S(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_RECVQ);
2370ebb7c6fdSAlex Wilson 
2371ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2372ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_rq_head,
2373ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_RQ, 0);
2374ebb7c6fdSAlex Wilson 
2375ebb7c6fdSAlex Wilson 	in.mlxi_query_rq_rqn = to_be24(mlwq->mlwq_num);
2376ebb7c6fdSAlex Wilson 
2377ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2378ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2379ebb7c6fdSAlex Wilson 		return (B_FALSE);
2380ebb7c6fdSAlex Wilson 	}
2381ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2382ebb7c6fdSAlex Wilson 
2383ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2384ebb7c6fdSAlex Wilson 	if (ret) {
2385ebb7c6fdSAlex Wilson 		bcopy(&out.mlxo_query_rq_context, ctxp,
2386ebb7c6fdSAlex Wilson 		    sizeof (mlxcx_rq_ctx_t));
2387ebb7c6fdSAlex Wilson 	}
2388ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2389ebb7c6fdSAlex Wilson 	return (ret);
2390ebb7c6fdSAlex Wilson }
2391ebb7c6fdSAlex Wilson 
2392ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_sq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq,mlxcx_sq_ctx_t * ctxp)2393ebb7c6fdSAlex Wilson mlxcx_cmd_query_sq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq,
2394ebb7c6fdSAlex Wilson     mlxcx_sq_ctx_t *ctxp)
2395ebb7c6fdSAlex Wilson {
2396ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2397ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_sq_in_t in;
2398ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_sq_out_t out;
2399ebb7c6fdSAlex Wilson 	boolean_t ret;
2400ebb7c6fdSAlex Wilson 
2401ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2402ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2403ebb7c6fdSAlex Wilson 
2404ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2405ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2406ebb7c6fdSAlex Wilson 	ASSERT3S(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_SENDQ);
2407ebb7c6fdSAlex Wilson 
2408ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2409ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_sq_head,
2410ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_SQ, 0);
2411ebb7c6fdSAlex Wilson 
2412ebb7c6fdSAlex Wilson 	in.mlxi_query_sq_sqn = to_be24(mlwq->mlwq_num);
2413ebb7c6fdSAlex Wilson 
2414ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2415ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2416ebb7c6fdSAlex Wilson 		return (B_FALSE);
2417ebb7c6fdSAlex Wilson 	}
2418ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2419ebb7c6fdSAlex Wilson 
2420ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2421ebb7c6fdSAlex Wilson 	if (ret) {
2422ebb7c6fdSAlex Wilson 		bcopy(&out.mlxo_query_sq_context, ctxp,
2423ebb7c6fdSAlex Wilson 		    sizeof (mlxcx_sq_ctx_t));
2424ebb7c6fdSAlex Wilson 	}
2425ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2426ebb7c6fdSAlex Wilson 	return (ret);
2427ebb7c6fdSAlex Wilson }
2428ebb7c6fdSAlex Wilson 
2429ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_query_cq(mlxcx_t * mlxp,mlxcx_completion_queue_t * mlcq,mlxcx_completionq_ctx_t * ctxp)2430ebb7c6fdSAlex Wilson mlxcx_cmd_query_cq(mlxcx_t *mlxp, mlxcx_completion_queue_t *mlcq,
2431ebb7c6fdSAlex Wilson     mlxcx_completionq_ctx_t *ctxp)
2432ebb7c6fdSAlex Wilson {
2433ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2434ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_cq_in_t in;
2435ebb7c6fdSAlex Wilson 	mlxcx_cmd_query_cq_out_t out;
2436ebb7c6fdSAlex Wilson 	boolean_t ret;
2437ebb7c6fdSAlex Wilson 
2438ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2439ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2440ebb7c6fdSAlex Wilson 
2441ebb7c6fdSAlex Wilson 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_ALLOC);
2442ebb7c6fdSAlex Wilson 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_CREATED);
2443ebb7c6fdSAlex Wilson 
2444ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2445ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_cq_head,
2446ebb7c6fdSAlex Wilson 	    MLXCX_OP_QUERY_CQ, 0);
2447ebb7c6fdSAlex Wilson 
2448ebb7c6fdSAlex Wilson 	in.mlxi_query_cq_cqn = to_be24(mlcq->mlcq_num);
2449ebb7c6fdSAlex Wilson 
2450ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2451ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2452ebb7c6fdSAlex Wilson 		return (B_FALSE);
2453ebb7c6fdSAlex Wilson 	}
2454ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2455ebb7c6fdSAlex Wilson 
2456ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2457ebb7c6fdSAlex Wilson 	if (ret) {
2458ebb7c6fdSAlex Wilson 		bcopy(&out.mlxo_query_cq_context, ctxp,
2459ebb7c6fdSAlex Wilson 		    sizeof (mlxcx_completionq_ctx_t));
2460ebb7c6fdSAlex Wilson 	}
2461ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2462ebb7c6fdSAlex Wilson 	return (ret);
2463ebb7c6fdSAlex Wilson }
2464ebb7c6fdSAlex Wilson 
2465ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_cq(mlxcx_t * mlxp,mlxcx_completion_queue_t * mlcq)2466ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_cq(mlxcx_t *mlxp, mlxcx_completion_queue_t *mlcq)
2467ebb7c6fdSAlex Wilson {
2468ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2469ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_cq_in_t in;
2470ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_cq_out_t out;
2471ebb7c6fdSAlex Wilson 	boolean_t ret;
2472ebb7c6fdSAlex Wilson 
2473ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2474ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2475ebb7c6fdSAlex Wilson 
2476ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlcq->mlcq_mtx));
2477ebb7c6fdSAlex Wilson 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_ALLOC);
2478ebb7c6fdSAlex Wilson 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_CREATED);
2479ebb7c6fdSAlex Wilson 
2480ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2481ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_cq_head,
2482ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_CQ, 0);
2483ebb7c6fdSAlex Wilson 
2484ebb7c6fdSAlex Wilson 	in.mlxi_destroy_cq_cqn = to_be24(mlcq->mlcq_num);
2485ebb7c6fdSAlex Wilson 
2486ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2487ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2488ebb7c6fdSAlex Wilson 		return (B_FALSE);
2489ebb7c6fdSAlex Wilson 	}
2490ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2491ebb7c6fdSAlex Wilson 
2492ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2493ebb7c6fdSAlex Wilson 	if (ret) {
24940207f820SPaul Winder 		atomic_or_uint(&mlcq->mlcq_state, MLXCX_CQ_DESTROYED);
2495ebb7c6fdSAlex Wilson 	}
2496ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2497ebb7c6fdSAlex Wilson 	return (ret);
2498ebb7c6fdSAlex Wilson }
2499ebb7c6fdSAlex Wilson 
2500ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2501ebb7c6fdSAlex Wilson mlxcx_cmd_create_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2502ebb7c6fdSAlex Wilson {
2503ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2504ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_rq_in_t in;
2505ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_rq_out_t out;
2506ebb7c6fdSAlex Wilson 	boolean_t ret;
2507ebb7c6fdSAlex Wilson 	mlxcx_rq_ctx_t *ctx;
2508ebb7c6fdSAlex Wilson 	size_t rem, insize;
2509ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *c;
2510ebb7c6fdSAlex Wilson 	uint64_t pa, npages;
2511ebb7c6fdSAlex Wilson 
2512ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2513ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2514ebb7c6fdSAlex Wilson 
2515ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2516ebb7c6fdSAlex Wilson 	VERIFY3U(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_RECVQ);
2517ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2518ebb7c6fdSAlex Wilson 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2519ebb7c6fdSAlex Wilson 
2520ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2521ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_rq_head,
2522ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_RQ, 0);
2523ebb7c6fdSAlex Wilson 
2524ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_rq_context;
2525ebb7c6fdSAlex Wilson 
2526ebb7c6fdSAlex Wilson 	set_bit32(&ctx->mlrqc_flags, MLXCX_RQ_FLAGS_RLKEY);
2527ebb7c6fdSAlex Wilson 	set_bit32(&ctx->mlrqc_flags, MLXCX_RQ_FLAGS_FLUSH_IN_ERROR);
2528ebb7c6fdSAlex Wilson 	set_bit32(&ctx->mlrqc_flags, MLXCX_RQ_FLAGS_VLAN_STRIP_DISABLE);
2529ebb7c6fdSAlex Wilson 	ctx->mlrqc_cqn = to_be24(mlwq->mlwq_cq->mlcq_num);
2530ebb7c6fdSAlex Wilson 
2531ebb7c6fdSAlex Wilson 	set_bits32(&ctx->mlrqc_wq.mlwqc_flags, MLXCX_WORKQ_CTX_TYPE,
2532ebb7c6fdSAlex Wilson 	    MLXCX_WORKQ_TYPE_CYCLIC);
2533ebb7c6fdSAlex Wilson 	ctx->mlrqc_wq.mlwqc_pd = to_be24(mlwq->mlwq_pd->mlpd_num);
2534ebb7c6fdSAlex Wilson 	ctx->mlrqc_wq.mlwqc_log_wq_sz = mlwq->mlwq_entshift;
2535ebb7c6fdSAlex Wilson 	ctx->mlrqc_wq.mlwqc_log_wq_stride = MLXCX_RECVQ_STRIDE_SHIFT;
2536ebb7c6fdSAlex Wilson 
2537ebb7c6fdSAlex Wilson 	c = mlxcx_dma_cookie_one(&mlwq->mlwq_doorbell_dma);
2538ebb7c6fdSAlex Wilson 	ctx->mlrqc_wq.mlwqc_dbr_addr = to_be64(c->dmac_laddress);
2539ebb7c6fdSAlex Wilson 	ASSERT3U(c->dmac_size, >=, sizeof (mlxcx_workq_doorbell_t));
2540ebb7c6fdSAlex Wilson 
2541ebb7c6fdSAlex Wilson 	npages = 0;
2542ebb7c6fdSAlex Wilson 	c = NULL;
2543ebb7c6fdSAlex Wilson 	while ((c = mlxcx_dma_cookie_iter(&mlwq->mlwq_dma, c)) != NULL) {
2544ebb7c6fdSAlex Wilson 		pa = c->dmac_laddress;
2545ebb7c6fdSAlex Wilson 		rem = c->dmac_size;
2546ebb7c6fdSAlex Wilson 		while (rem > 0) {
2547ebb7c6fdSAlex Wilson 			ASSERT3U(pa & 0xfff, ==, 0);
2548ebb7c6fdSAlex Wilson 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
2549ebb7c6fdSAlex Wilson 			ctx->mlrqc_wq.mlwqc_pas[npages++] = to_be64(pa);
2550ebb7c6fdSAlex Wilson 			rem -= MLXCX_HW_PAGE_SIZE;
2551ebb7c6fdSAlex Wilson 			pa += MLXCX_HW_PAGE_SIZE;
2552ebb7c6fdSAlex Wilson 		}
2553ebb7c6fdSAlex Wilson 	}
2554ebb7c6fdSAlex Wilson 	ASSERT3U(npages, <=, MLXCX_WORKQ_CTX_MAX_ADDRESSES);
2555ebb7c6fdSAlex Wilson 
2556ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_create_rq_in_t, mlxi_create_rq_context) +
2557ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_rq_ctx_t, mlrqc_wq) +
2558ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_workq_ctx_t, mlwqc_pas) +
2559ebb7c6fdSAlex Wilson 	    sizeof (uint64_t) * npages;
2560ebb7c6fdSAlex Wilson 
2561ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
2562ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2563ebb7c6fdSAlex Wilson 		return (B_FALSE);
2564ebb7c6fdSAlex Wilson 	}
2565ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2566ebb7c6fdSAlex Wilson 
2567ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2568ebb7c6fdSAlex Wilson 	if (ret) {
2569ebb7c6fdSAlex Wilson 		mlwq->mlwq_state |= MLXCX_WQ_CREATED;
2570ebb7c6fdSAlex Wilson 		mlwq->mlwq_num = from_be24(out.mlxo_create_rq_rqn);
2571ebb7c6fdSAlex Wilson 	}
2572ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2573ebb7c6fdSAlex Wilson 	return (ret);
2574ebb7c6fdSAlex Wilson }
2575ebb7c6fdSAlex Wilson 
2576ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_start_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2577ebb7c6fdSAlex Wilson mlxcx_cmd_start_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2578ebb7c6fdSAlex Wilson {
2579ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2580ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_rq_in_t in;
2581ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_rq_out_t out;
2582ebb7c6fdSAlex Wilson 	boolean_t ret;
2583ebb7c6fdSAlex Wilson 	ddi_fm_error_t err;
2584ebb7c6fdSAlex Wilson 
2585ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2586ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2587ebb7c6fdSAlex Wilson 
2588ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2589ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2590ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2591ebb7c6fdSAlex Wilson 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_STARTED);
2592ebb7c6fdSAlex Wilson 
2593ebb7c6fdSAlex Wilson 	/*
2594ebb7c6fdSAlex Wilson 	 * Before starting the queue, we have to be sure that it is
2595ebb7c6fdSAlex Wilson 	 * empty and the doorbell and counters are set to 0.
2596ebb7c6fdSAlex Wilson 	 */
2597ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_cq->mlcq_mtx));
2598ebb7c6fdSAlex Wilson 	ASSERT(list_is_empty(&mlwq->mlwq_cq->mlcq_buffers));
2599ebb7c6fdSAlex Wilson 	ASSERT(list_is_empty(&mlwq->mlwq_cq->mlcq_buffers_b));
2600ebb7c6fdSAlex Wilson 
2601ebb7c6fdSAlex Wilson 	mlwq->mlwq_doorbell->mlwqd_recv_counter = to_be16(0);
2602ebb7c6fdSAlex Wilson 	MLXCX_DMA_SYNC(mlwq->mlwq_doorbell_dma, DDI_DMA_SYNC_FORDEV);
2603ebb7c6fdSAlex Wilson 	ddi_fm_dma_err_get(mlwq->mlwq_doorbell_dma.mxdb_dma_handle, &err,
2604ebb7c6fdSAlex Wilson 	    DDI_FME_VERSION);
2605ebb7c6fdSAlex Wilson 	if (err.fme_status != DDI_FM_OK)
2606ebb7c6fdSAlex Wilson 		return (B_FALSE);
2607ebb7c6fdSAlex Wilson 	mlwq->mlwq_pc = 0;
2608ebb7c6fdSAlex Wilson 
2609ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2610ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_rq_head,
2611ebb7c6fdSAlex Wilson 	    MLXCX_OP_MODIFY_RQ, 0);
2612ebb7c6fdSAlex Wilson 
2613ebb7c6fdSAlex Wilson 	in.mlxi_modify_rq_rqn = to_be24(mlwq->mlwq_num);
2614ebb7c6fdSAlex Wilson 
2615ebb7c6fdSAlex Wilson 	/* From state */
2616ebb7c6fdSAlex Wilson 	set_bits8(&in.mlxi_modify_rq_state, MLXCX_CMD_MODIFY_RQ_STATE,
2617ebb7c6fdSAlex Wilson 	    MLXCX_RQ_STATE_RST);
2618ebb7c6fdSAlex Wilson 	/* To state */
2619ebb7c6fdSAlex Wilson 	set_bits32(&in.mlxi_modify_rq_context.mlrqc_flags, MLXCX_RQ_STATE,
2620ebb7c6fdSAlex Wilson 	    MLXCX_RQ_STATE_RDY);
2621ebb7c6fdSAlex Wilson 
2622ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2623ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2624ebb7c6fdSAlex Wilson 		return (B_FALSE);
2625ebb7c6fdSAlex Wilson 	}
2626ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2627ebb7c6fdSAlex Wilson 
2628ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2629ebb7c6fdSAlex Wilson 	if (ret) {
2630ebb7c6fdSAlex Wilson 		mlwq->mlwq_state |= MLXCX_WQ_STARTED;
2631ebb7c6fdSAlex Wilson 	}
2632ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2633ebb7c6fdSAlex Wilson 	return (ret);
2634ebb7c6fdSAlex Wilson }
2635ebb7c6fdSAlex Wilson 
2636ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_stop_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2637ebb7c6fdSAlex Wilson mlxcx_cmd_stop_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2638ebb7c6fdSAlex Wilson {
2639ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2640ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_rq_in_t in;
2641ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_rq_out_t out;
2642ebb7c6fdSAlex Wilson 	boolean_t ret;
2643ebb7c6fdSAlex Wilson 
2644ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2645ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2646ebb7c6fdSAlex Wilson 
2647ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2648ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2649ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2650ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_STARTED);
2651ebb7c6fdSAlex Wilson 
2652ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2653ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_rq_head,
2654ebb7c6fdSAlex Wilson 	    MLXCX_OP_MODIFY_RQ, 0);
2655ebb7c6fdSAlex Wilson 
2656ebb7c6fdSAlex Wilson 	in.mlxi_modify_rq_rqn = to_be24(mlwq->mlwq_num);
2657ebb7c6fdSAlex Wilson 
2658ebb7c6fdSAlex Wilson 	/* From state */
2659ebb7c6fdSAlex Wilson 	set_bits8(&in.mlxi_modify_rq_state, MLXCX_CMD_MODIFY_RQ_STATE,
2660ebb7c6fdSAlex Wilson 	    MLXCX_RQ_STATE_RDY);
2661ebb7c6fdSAlex Wilson 	/* To state */
2662ebb7c6fdSAlex Wilson 	set_bits32(&in.mlxi_modify_rq_context.mlrqc_flags, MLXCX_RQ_STATE,
2663ebb7c6fdSAlex Wilson 	    MLXCX_RQ_STATE_RST);
2664ebb7c6fdSAlex Wilson 
2665ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2666ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2667ebb7c6fdSAlex Wilson 		return (B_FALSE);
2668ebb7c6fdSAlex Wilson 	}
2669ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2670ebb7c6fdSAlex Wilson 
2671ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2672ebb7c6fdSAlex Wilson 	if (ret) {
2673ebb7c6fdSAlex Wilson 		mlwq->mlwq_state &= ~MLXCX_WQ_STARTED;
2674ebb7c6fdSAlex Wilson 	}
2675ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2676ebb7c6fdSAlex Wilson 	return (ret);
2677ebb7c6fdSAlex Wilson }
2678ebb7c6fdSAlex Wilson 
2679ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2680ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2681ebb7c6fdSAlex Wilson {
2682ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2683ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_rq_in_t in;
2684ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_rq_out_t out;
2685ebb7c6fdSAlex Wilson 	boolean_t ret;
2686ebb7c6fdSAlex Wilson 
2687ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2688ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2689ebb7c6fdSAlex Wilson 
2690ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2691ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2692ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2693ebb7c6fdSAlex Wilson 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_STARTED);
2694ebb7c6fdSAlex Wilson 
2695ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2696ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_rq_head,
2697ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_RQ, 0);
2698ebb7c6fdSAlex Wilson 
2699ebb7c6fdSAlex Wilson 	in.mlxi_destroy_rq_rqn = to_be24(mlwq->mlwq_num);
2700ebb7c6fdSAlex Wilson 
2701ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2702ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2703ebb7c6fdSAlex Wilson 		return (B_FALSE);
2704ebb7c6fdSAlex Wilson 	}
2705ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2706ebb7c6fdSAlex Wilson 
2707ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2708ebb7c6fdSAlex Wilson 	if (ret) {
2709ebb7c6fdSAlex Wilson 		mlwq->mlwq_state |= MLXCX_WQ_DESTROYED;
2710ebb7c6fdSAlex Wilson 	}
2711ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2712ebb7c6fdSAlex Wilson 	return (ret);
2713ebb7c6fdSAlex Wilson }
2714ebb7c6fdSAlex Wilson 
2715ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_tir(mlxcx_t * mlxp,mlxcx_tir_t * mltir)2716ebb7c6fdSAlex Wilson mlxcx_cmd_create_tir(mlxcx_t *mlxp, mlxcx_tir_t *mltir)
2717ebb7c6fdSAlex Wilson {
2718ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2719ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_tir_in_t in;
2720ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_tir_out_t out;
2721ebb7c6fdSAlex Wilson 	mlxcx_tir_ctx_t *ctx;
2722ebb7c6fdSAlex Wilson 	boolean_t ret;
2723ebb7c6fdSAlex Wilson 
2724ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2725ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2726ebb7c6fdSAlex Wilson 
2727ebb7c6fdSAlex Wilson 	VERIFY0(mltir->mltir_state & MLXCX_TIR_CREATED);
2728ebb7c6fdSAlex Wilson 
2729ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2730ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_tir_head,
2731ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_TIR, 0);
2732ebb7c6fdSAlex Wilson 
2733ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_tir_context;
2734ebb7c6fdSAlex Wilson 	ctx->mltirc_transport_domain = to_be24(mltir->mltir_tdom->mltd_num);
2735ebb7c6fdSAlex Wilson 	set_bits8(&ctx->mltirc_disp_type, MLXCX_TIR_CTX_DISP_TYPE,
2736ebb7c6fdSAlex Wilson 	    mltir->mltir_type);
2737ebb7c6fdSAlex Wilson 	switch (mltir->mltir_type) {
2738ebb7c6fdSAlex Wilson 	case MLXCX_TIR_INDIRECT:
2739ebb7c6fdSAlex Wilson 		VERIFY(mltir->mltir_rqtable != NULL);
2740ebb7c6fdSAlex Wilson 		VERIFY(mltir->mltir_rqtable->mlrqt_state & MLXCX_RQT_CREATED);
2741ebb7c6fdSAlex Wilson 		ctx->mltirc_indirect_table =
2742ebb7c6fdSAlex Wilson 		    to_be24(mltir->mltir_rqtable->mlrqt_num);
2743ebb7c6fdSAlex Wilson 		set_bits8(&ctx->mltirc_hash_lb, MLXCX_TIR_RX_HASH_FN,
2744ebb7c6fdSAlex Wilson 		    mltir->mltir_hash_fn);
2745ebb7c6fdSAlex Wilson 		bcopy(mltir->mltir_toeplitz_key,
2746ebb7c6fdSAlex Wilson 		    ctx->mltirc_rx_hash_toeplitz_key,
2747ebb7c6fdSAlex Wilson 		    sizeof (ctx->mltirc_rx_hash_toeplitz_key));
2748ebb7c6fdSAlex Wilson 		set_bits32(&ctx->mltirc_rx_hash_fields_outer,
2749ebb7c6fdSAlex Wilson 		    MLXCX_RX_HASH_L3_TYPE, mltir->mltir_l3_type);
2750ebb7c6fdSAlex Wilson 		set_bits32(&ctx->mltirc_rx_hash_fields_outer,
2751ebb7c6fdSAlex Wilson 		    MLXCX_RX_HASH_L4_TYPE, mltir->mltir_l4_type);
2752ebb7c6fdSAlex Wilson 		set_bits32(&ctx->mltirc_rx_hash_fields_outer,
2753ebb7c6fdSAlex Wilson 		    MLXCX_RX_HASH_FIELDS, mltir->mltir_hash_fields);
2754ebb7c6fdSAlex Wilson 		break;
2755ebb7c6fdSAlex Wilson 	case MLXCX_TIR_DIRECT:
2756ebb7c6fdSAlex Wilson 		VERIFY(mltir->mltir_rq != NULL);
2757ebb7c6fdSAlex Wilson 		VERIFY(mltir->mltir_rq->mlwq_state & MLXCX_WQ_CREATED);
2758ebb7c6fdSAlex Wilson 		ctx->mltirc_inline_rqn = to_be24(mltir->mltir_rq->mlwq_num);
2759ebb7c6fdSAlex Wilson 		break;
2760ebb7c6fdSAlex Wilson 	default:
2761ebb7c6fdSAlex Wilson 		VERIFY(0);
2762ebb7c6fdSAlex Wilson 	}
2763ebb7c6fdSAlex Wilson 
2764ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2765ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2766ebb7c6fdSAlex Wilson 		return (B_FALSE);
2767ebb7c6fdSAlex Wilson 	}
2768ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2769ebb7c6fdSAlex Wilson 
2770ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2771ebb7c6fdSAlex Wilson 	if (ret) {
2772ebb7c6fdSAlex Wilson 		mltir->mltir_state |= MLXCX_TIR_CREATED;
2773ebb7c6fdSAlex Wilson 		mltir->mltir_num = from_be24(out.mlxo_create_tir_tirn);
2774ebb7c6fdSAlex Wilson 	}
2775ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2776ebb7c6fdSAlex Wilson 	return (ret);
2777ebb7c6fdSAlex Wilson }
2778ebb7c6fdSAlex Wilson 
2779ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_tir(mlxcx_t * mlxp,mlxcx_tir_t * mltir)2780ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_tir(mlxcx_t *mlxp, mlxcx_tir_t *mltir)
2781ebb7c6fdSAlex Wilson {
2782ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2783ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_tir_in_t in;
2784ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_tir_out_t out;
2785ebb7c6fdSAlex Wilson 	boolean_t ret;
2786ebb7c6fdSAlex Wilson 
2787ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2788ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2789ebb7c6fdSAlex Wilson 
2790ebb7c6fdSAlex Wilson 	VERIFY(mltir->mltir_state & MLXCX_TIR_CREATED);
2791ebb7c6fdSAlex Wilson 	VERIFY0(mltir->mltir_state & MLXCX_TIR_DESTROYED);
2792ebb7c6fdSAlex Wilson 
2793ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2794ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_tir_head,
2795ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_TIR, 0);
2796ebb7c6fdSAlex Wilson 
2797ebb7c6fdSAlex Wilson 	in.mlxi_destroy_tir_tirn = to_be24(mltir->mltir_num);
2798ebb7c6fdSAlex Wilson 
2799ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2800ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2801ebb7c6fdSAlex Wilson 		return (B_FALSE);
2802ebb7c6fdSAlex Wilson 	}
2803ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2804ebb7c6fdSAlex Wilson 
2805ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2806ebb7c6fdSAlex Wilson 	if (ret) {
2807ebb7c6fdSAlex Wilson 		mltir->mltir_state |= MLXCX_TIR_DESTROYED;
2808ebb7c6fdSAlex Wilson 	}
2809ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2810ebb7c6fdSAlex Wilson 	return (ret);
2811ebb7c6fdSAlex Wilson }
2812ebb7c6fdSAlex Wilson 
2813ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_tis(mlxcx_t * mlxp,mlxcx_tis_t * mltis)2814ebb7c6fdSAlex Wilson mlxcx_cmd_create_tis(mlxcx_t *mlxp, mlxcx_tis_t *mltis)
2815ebb7c6fdSAlex Wilson {
2816ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2817ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_tis_in_t in;
2818ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_tis_out_t out;
2819ebb7c6fdSAlex Wilson 	mlxcx_tis_ctx_t *ctx;
2820ebb7c6fdSAlex Wilson 	boolean_t ret;
2821ebb7c6fdSAlex Wilson 
2822ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2823ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2824ebb7c6fdSAlex Wilson 
2825ebb7c6fdSAlex Wilson 	VERIFY0(mltis->mltis_state & MLXCX_TIS_CREATED);
2826ebb7c6fdSAlex Wilson 
2827ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2828ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_tis_head,
2829ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_TIS, 0);
2830ebb7c6fdSAlex Wilson 
2831ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_tis_context;
2832ebb7c6fdSAlex Wilson 	ctx->mltisc_transport_domain = to_be24(mltis->mltis_tdom->mltd_num);
2833ebb7c6fdSAlex Wilson 
2834ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2835ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2836ebb7c6fdSAlex Wilson 		return (B_FALSE);
2837ebb7c6fdSAlex Wilson 	}
2838ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2839ebb7c6fdSAlex Wilson 
2840ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2841ebb7c6fdSAlex Wilson 	if (ret) {
2842ebb7c6fdSAlex Wilson 		mltis->mltis_state |= MLXCX_TIS_CREATED;
2843ebb7c6fdSAlex Wilson 		mltis->mltis_num = from_be24(out.mlxo_create_tis_tisn);
2844ebb7c6fdSAlex Wilson 	}
2845ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2846ebb7c6fdSAlex Wilson 	return (ret);
2847ebb7c6fdSAlex Wilson }
2848ebb7c6fdSAlex Wilson 
2849ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_tis(mlxcx_t * mlxp,mlxcx_tis_t * mltis)2850ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_tis(mlxcx_t *mlxp, mlxcx_tis_t *mltis)
2851ebb7c6fdSAlex Wilson {
2852ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2853ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_tis_in_t in;
2854ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_tis_out_t out;
2855ebb7c6fdSAlex Wilson 	boolean_t ret;
2856ebb7c6fdSAlex Wilson 
2857ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2858ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2859ebb7c6fdSAlex Wilson 
2860ebb7c6fdSAlex Wilson 	VERIFY(mltis->mltis_state & MLXCX_TIR_CREATED);
2861ebb7c6fdSAlex Wilson 	VERIFY0(mltis->mltis_state & MLXCX_TIR_DESTROYED);
2862ebb7c6fdSAlex Wilson 
2863ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2864ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_tis_head,
2865ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_TIS, 0);
2866ebb7c6fdSAlex Wilson 
2867ebb7c6fdSAlex Wilson 	in.mlxi_destroy_tis_tisn = to_be24(mltis->mltis_num);
2868ebb7c6fdSAlex Wilson 
2869ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2870ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2871ebb7c6fdSAlex Wilson 		return (B_FALSE);
2872ebb7c6fdSAlex Wilson 	}
2873ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2874ebb7c6fdSAlex Wilson 
2875ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2876ebb7c6fdSAlex Wilson 	if (ret) {
2877ebb7c6fdSAlex Wilson 		mltis->mltis_state |= MLXCX_TIS_DESTROYED;
2878ebb7c6fdSAlex Wilson 	}
2879ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2880ebb7c6fdSAlex Wilson 	return (ret);
2881ebb7c6fdSAlex Wilson }
2882ebb7c6fdSAlex Wilson 
2883ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_flow_table(mlxcx_t * mlxp,mlxcx_flow_table_t * mlft)2884ebb7c6fdSAlex Wilson mlxcx_cmd_create_flow_table(mlxcx_t *mlxp, mlxcx_flow_table_t *mlft)
2885ebb7c6fdSAlex Wilson {
2886ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2887ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_flow_table_in_t in;
2888ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_flow_table_out_t out;
2889ebb7c6fdSAlex Wilson 	mlxcx_flow_table_ctx_t *ctx;
2890ebb7c6fdSAlex Wilson 	boolean_t ret;
2891ebb7c6fdSAlex Wilson 
2892ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2893ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2894ebb7c6fdSAlex Wilson 
2895ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
2896ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
2897ebb7c6fdSAlex Wilson 
2898ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2899ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_flow_table_head,
2900ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_FLOW_TABLE, 0);
2901ebb7c6fdSAlex Wilson 
2902ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_table_vport_number =
2903ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
2904ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_table_table_type = mlft->mlft_type;
2905ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_flow_table_context;
2906ebb7c6fdSAlex Wilson 	ctx->mlftc_log_size = mlft->mlft_entshift;
2907ebb7c6fdSAlex Wilson 	ctx->mlftc_level = mlft->mlft_level;
2908ebb7c6fdSAlex Wilson 
2909ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2910ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2911ebb7c6fdSAlex Wilson 		return (B_FALSE);
2912ebb7c6fdSAlex Wilson 	}
2913ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2914ebb7c6fdSAlex Wilson 
2915ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2916ebb7c6fdSAlex Wilson 	if (ret) {
2917ebb7c6fdSAlex Wilson 		mlft->mlft_num = from_be24(out.mlxo_create_flow_table_table_id);
2918ebb7c6fdSAlex Wilson 		mlft->mlft_state |= MLXCX_FLOW_TABLE_CREATED;
2919ebb7c6fdSAlex Wilson 	}
2920ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2921ebb7c6fdSAlex Wilson 	return (ret);
2922ebb7c6fdSAlex Wilson }
2923ebb7c6fdSAlex Wilson 
2924ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_flow_table(mlxcx_t * mlxp,mlxcx_flow_table_t * mlft)2925ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_flow_table(mlxcx_t *mlxp, mlxcx_flow_table_t *mlft)
2926ebb7c6fdSAlex Wilson {
2927ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2928ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_flow_table_in_t in;
2929ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_flow_table_out_t out;
2930ebb7c6fdSAlex Wilson 	boolean_t ret;
2931ebb7c6fdSAlex Wilson 
2932ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2933ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2934ebb7c6fdSAlex Wilson 
2935ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
2936ebb7c6fdSAlex Wilson 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
2937ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
2938ebb7c6fdSAlex Wilson 
2939ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2940ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_flow_table_head,
2941ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_FLOW_TABLE, 0);
2942ebb7c6fdSAlex Wilson 
2943ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_table_vport_number =
2944ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
2945ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_table_table_type = mlft->mlft_type;
2946ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_table_table_id = to_be24(mlft->mlft_num);
2947ebb7c6fdSAlex Wilson 
2948ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2949ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2950ebb7c6fdSAlex Wilson 		return (B_FALSE);
2951ebb7c6fdSAlex Wilson 	}
2952ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2953ebb7c6fdSAlex Wilson 
2954ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2955ebb7c6fdSAlex Wilson 	if (ret) {
2956ebb7c6fdSAlex Wilson 		mlft->mlft_state |= MLXCX_FLOW_TABLE_DESTROYED;
2957ebb7c6fdSAlex Wilson 	}
2958ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2959ebb7c6fdSAlex Wilson 	return (ret);
2960ebb7c6fdSAlex Wilson }
2961ebb7c6fdSAlex Wilson 
2962ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_flow_table_root(mlxcx_t * mlxp,mlxcx_flow_table_t * mlft)2963ebb7c6fdSAlex Wilson mlxcx_cmd_set_flow_table_root(mlxcx_t *mlxp, mlxcx_flow_table_t *mlft)
2964ebb7c6fdSAlex Wilson {
2965ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
2966ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_flow_table_root_in_t in;
2967ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_flow_table_root_out_t out;
2968ebb7c6fdSAlex Wilson 	boolean_t ret;
2969ebb7c6fdSAlex Wilson 
2970ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
2971ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
2972ebb7c6fdSAlex Wilson 
2973ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
2974ebb7c6fdSAlex Wilson 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
2975ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
2976ebb7c6fdSAlex Wilson 
2977ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
2978ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_set_flow_table_root_head,
2979ebb7c6fdSAlex Wilson 	    MLXCX_OP_SET_FLOW_TABLE_ROOT, 0);
2980ebb7c6fdSAlex Wilson 
2981ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_root_vport_number =
2982ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
2983ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_root_table_type = mlft->mlft_type;
2984ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_root_table_id = to_be24(mlft->mlft_num);
2985ebb7c6fdSAlex Wilson 
2986ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2987ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
2988ebb7c6fdSAlex Wilson 		return (B_FALSE);
2989ebb7c6fdSAlex Wilson 	}
2990ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
2991ebb7c6fdSAlex Wilson 
2992ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2993ebb7c6fdSAlex Wilson 	if (ret) {
2994ebb7c6fdSAlex Wilson 		mlft->mlft_state |= MLXCX_FLOW_TABLE_ROOT;
2995ebb7c6fdSAlex Wilson 	}
2996ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
2997ebb7c6fdSAlex Wilson 	return (ret);
2998ebb7c6fdSAlex Wilson }
2999ebb7c6fdSAlex Wilson 
3000ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_flow_group(mlxcx_t * mlxp,mlxcx_flow_group_t * mlfg)3001ebb7c6fdSAlex Wilson mlxcx_cmd_create_flow_group(mlxcx_t *mlxp, mlxcx_flow_group_t *mlfg)
3002ebb7c6fdSAlex Wilson {
3003ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3004ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_flow_group_in_t in;
3005ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_flow_group_out_t out;
3006ebb7c6fdSAlex Wilson 	boolean_t ret;
3007ebb7c6fdSAlex Wilson 	const mlxcx_flow_table_t *mlft;
3008ebb7c6fdSAlex Wilson 	mlxcx_flow_header_match_t *hdrs;
3009ebb7c6fdSAlex Wilson 	mlxcx_flow_params_match_t *params;
3010ebb7c6fdSAlex Wilson 
3011ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3012ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3013ebb7c6fdSAlex Wilson 
3014ebb7c6fdSAlex Wilson 	mlft = mlfg->mlfg_table;
3015ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
3016ebb7c6fdSAlex Wilson 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
3017ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
3018ebb7c6fdSAlex Wilson 	VERIFY0(mlfg->mlfg_state & MLXCX_FLOW_GROUP_CREATED);
3019ebb7c6fdSAlex Wilson 
3020ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3021ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_flow_group_head,
3022ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_FLOW_GROUP, 0);
3023ebb7c6fdSAlex Wilson 
3024ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_group_vport_number =
3025ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
3026ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_group_table_type = mlft->mlft_type;
3027ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_group_table_id = to_be24(mlft->mlft_num);
3028ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_group_start_flow_index =
3029ebb7c6fdSAlex Wilson 	    to_be32(mlfg->mlfg_start_idx);
3030ebb7c6fdSAlex Wilson 	in.mlxi_create_flow_group_end_flow_index =
3031ebb7c6fdSAlex Wilson 	    to_be32(mlfg->mlfg_start_idx + (mlfg->mlfg_size - 1));
3032ebb7c6fdSAlex Wilson 
3033ebb7c6fdSAlex Wilson 	hdrs = &in.mlxi_create_flow_group_match_criteria.mlfm_outer_headers;
3034ebb7c6fdSAlex Wilson 	params = &in.mlxi_create_flow_group_match_criteria.mlfm_misc_parameters;
3035ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SMAC) {
3036ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3037ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_OUTER_HDRS;
3038ebb7c6fdSAlex Wilson 		(void) memset(&hdrs->mlfh_smac, 0xff, sizeof (hdrs->mlfh_smac));
3039ebb7c6fdSAlex Wilson 	}
3040ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_DMAC) {
3041ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3042ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_OUTER_HDRS;
3043ebb7c6fdSAlex Wilson 		(void) memset(&hdrs->mlfh_dmac, 0xff, sizeof (hdrs->mlfh_dmac));
3044ebb7c6fdSAlex Wilson 	}
3045ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VLAN) {
3046ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3047ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_OUTER_HDRS;
3048ebb7c6fdSAlex Wilson 		set_bit24(&hdrs->mlfh_tcp_ip_flags, MLXCX_FLOW_HDR_CVLAN_TAG);
3049ebb7c6fdSAlex Wilson 		set_bit24(&hdrs->mlfh_tcp_ip_flags, MLXCX_FLOW_HDR_SVLAN_TAG);
3050ebb7c6fdSAlex Wilson 	}
3051ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VID) {
3052ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VLAN);
3053ebb7c6fdSAlex Wilson 		set_bits16(&hdrs->mlfh_first_vid_flags,
3054ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_HDR_FIRST_VID, UINT16_MAX);
3055ebb7c6fdSAlex Wilson 	}
3056ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER) {
3057ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3058ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_OUTER_HDRS;
3059ebb7c6fdSAlex Wilson 		set_bits24(&hdrs->mlfh_tcp_ip_flags, MLXCX_FLOW_HDR_IP_VERSION,
3060ebb7c6fdSAlex Wilson 		    UINT32_MAX);
3061ebb7c6fdSAlex Wilson 	}
3062ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SRCIP) {
3063ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER);
3064ebb7c6fdSAlex Wilson 		(void) memset(&hdrs->mlfh_src_ip, 0xff,
3065ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_src_ip));
3066ebb7c6fdSAlex Wilson 	}
3067ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_DSTIP) {
3068ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER);
3069ebb7c6fdSAlex Wilson 		(void) memset(&hdrs->mlfh_src_ip, 0xff,
3070ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_dst_ip));
3071ebb7c6fdSAlex Wilson 	}
3072ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_PROTO) {
3073ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3074ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_OUTER_HDRS;
3075ebb7c6fdSAlex Wilson 		hdrs->mlfh_ip_protocol = UINT8_MAX;
3076ebb7c6fdSAlex Wilson 	}
3077ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SRCIP) {
3078ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER);
3079ebb7c6fdSAlex Wilson 		(void) memset(&hdrs->mlfh_src_ip, 0xff,
3080ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_src_ip));
3081ebb7c6fdSAlex Wilson 	}
3082ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_DSTIP) {
3083ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER);
3084ebb7c6fdSAlex Wilson 		(void) memset(&hdrs->mlfh_src_ip, 0xff,
3085ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_dst_ip));
3086ebb7c6fdSAlex Wilson 	}
3087ebb7c6fdSAlex Wilson 
3088ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SQN) {
3089ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3090ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_MISC_PARAMS;
3091ebb7c6fdSAlex Wilson 		params->mlfp_source_sqn = to_be24(UINT32_MAX);
3092ebb7c6fdSAlex Wilson 	}
3093ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VXLAN) {
3094ebb7c6fdSAlex Wilson 		in.mlxi_create_flow_group_match_criteria_en |=
3095ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_GROUP_MATCH_MISC_PARAMS;
3096ebb7c6fdSAlex Wilson 		params->mlfp_vxlan_vni = to_be24(UINT32_MAX);
3097ebb7c6fdSAlex Wilson 	}
3098ebb7c6fdSAlex Wilson 
3099ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3100ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3101ebb7c6fdSAlex Wilson 		return (B_FALSE);
3102ebb7c6fdSAlex Wilson 	}
3103ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3104ebb7c6fdSAlex Wilson 
3105ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3106ebb7c6fdSAlex Wilson 	if (ret) {
3107ebb7c6fdSAlex Wilson 		mlfg->mlfg_state |= MLXCX_FLOW_GROUP_CREATED;
3108ebb7c6fdSAlex Wilson 		mlfg->mlfg_num = from_be24(out.mlxo_create_flow_group_group_id);
3109ebb7c6fdSAlex Wilson 	}
3110ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3111ebb7c6fdSAlex Wilson 	return (ret);
3112ebb7c6fdSAlex Wilson }
3113ebb7c6fdSAlex Wilson 
3114ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_flow_group(mlxcx_t * mlxp,mlxcx_flow_group_t * mlfg)3115ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_flow_group(mlxcx_t *mlxp, mlxcx_flow_group_t *mlfg)
3116ebb7c6fdSAlex Wilson {
3117ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3118ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_flow_group_in_t in;
3119ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_flow_group_out_t out;
3120ebb7c6fdSAlex Wilson 	boolean_t ret;
3121ebb7c6fdSAlex Wilson 	const mlxcx_flow_table_t *mlft;
3122ebb7c6fdSAlex Wilson 
3123ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3124ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3125ebb7c6fdSAlex Wilson 
3126ebb7c6fdSAlex Wilson 	mlft = mlfg->mlfg_table;
3127ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
3128ebb7c6fdSAlex Wilson 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
3129ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
3130ebb7c6fdSAlex Wilson 	VERIFY(mlfg->mlfg_state & MLXCX_FLOW_GROUP_CREATED);
3131ebb7c6fdSAlex Wilson 	VERIFY0(mlfg->mlfg_state & MLXCX_FLOW_GROUP_DESTROYED);
3132ebb7c6fdSAlex Wilson 
3133ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3134ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_flow_group_head,
3135ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_FLOW_GROUP, 0);
3136ebb7c6fdSAlex Wilson 
3137ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_group_vport_number =
3138ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
3139ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_group_table_type = mlft->mlft_type;
3140ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_group_table_id = to_be24(mlft->mlft_num);
3141ebb7c6fdSAlex Wilson 	in.mlxi_destroy_flow_group_group_id = to_be32(mlfg->mlfg_num);
3142ebb7c6fdSAlex Wilson 
3143ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3144ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3145ebb7c6fdSAlex Wilson 		return (B_FALSE);
3146ebb7c6fdSAlex Wilson 	}
3147ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3148ebb7c6fdSAlex Wilson 
3149ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3150ebb7c6fdSAlex Wilson 	if (ret) {
3151ebb7c6fdSAlex Wilson 		mlfg->mlfg_state |= MLXCX_FLOW_GROUP_DESTROYED;
3152ebb7c6fdSAlex Wilson 	}
3153ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3154ebb7c6fdSAlex Wilson 	return (ret);
3155ebb7c6fdSAlex Wilson }
3156ebb7c6fdSAlex Wilson 
3157ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_flow_table_entry(mlxcx_t * mlxp,mlxcx_flow_entry_t * mlfe)3158ebb7c6fdSAlex Wilson mlxcx_cmd_set_flow_table_entry(mlxcx_t *mlxp, mlxcx_flow_entry_t *mlfe)
3159ebb7c6fdSAlex Wilson {
3160ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3161ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_flow_table_entry_in_t in;
3162ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_flow_table_entry_out_t out;
3163ebb7c6fdSAlex Wilson 	boolean_t ret;
3164ebb7c6fdSAlex Wilson 	size_t insize;
3165ebb7c6fdSAlex Wilson 	mlxcx_flow_entry_ctx_t *ctx;
3166ebb7c6fdSAlex Wilson 	const mlxcx_flow_table_t *mlft;
3167ebb7c6fdSAlex Wilson 	mlxcx_flow_group_t *mlfg;
3168ebb7c6fdSAlex Wilson 	mlxcx_flow_dest_t *d;
3169ebb7c6fdSAlex Wilson 	uint_t i;
3170ebb7c6fdSAlex Wilson 	mlxcx_flow_header_match_t *hdrs;
3171ebb7c6fdSAlex Wilson 	mlxcx_flow_params_match_t *params;
3172ebb7c6fdSAlex Wilson 	mlxcx_cmd_set_flow_table_entry_opmod_t opmod;
3173ebb7c6fdSAlex Wilson 
3174ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3175ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3176ebb7c6fdSAlex Wilson 
3177ebb7c6fdSAlex Wilson 	mlft = mlfe->mlfe_table;
3178ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
3179ebb7c6fdSAlex Wilson 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
3180ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
3181ebb7c6fdSAlex Wilson 
3182ebb7c6fdSAlex Wilson 	mlfg = mlfe->mlfe_group;
3183ebb7c6fdSAlex Wilson 	VERIFY(mlfg->mlfg_state & MLXCX_FLOW_GROUP_CREATED);
3184ebb7c6fdSAlex Wilson 	VERIFY0(mlfg->mlfg_state & MLXCX_FLOW_GROUP_DESTROYED);
3185ebb7c6fdSAlex Wilson 
3186ebb7c6fdSAlex Wilson 	opmod = MLXCX_CMD_FLOW_ENTRY_SET_NEW;
3187ebb7c6fdSAlex Wilson 	if (mlfe->mlfe_state & MLXCX_FLOW_ENTRY_CREATED) {
3188ebb7c6fdSAlex Wilson 		ASSERT(mlfe->mlfe_state & MLXCX_FLOW_ENTRY_DIRTY);
3189ebb7c6fdSAlex Wilson 		opmod = MLXCX_CMD_FLOW_ENTRY_MODIFY;
3190ebb7c6fdSAlex Wilson 	}
3191ebb7c6fdSAlex Wilson 
3192ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3193ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_set_flow_table_entry_head,
3194ebb7c6fdSAlex Wilson 	    MLXCX_OP_SET_FLOW_TABLE_ENTRY, opmod);
3195ebb7c6fdSAlex Wilson 
3196ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_entry_vport_number =
3197ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
3198ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_entry_table_type = mlft->mlft_type;
3199ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_entry_table_id = to_be24(mlft->mlft_num);
3200ebb7c6fdSAlex Wilson 	in.mlxi_set_flow_table_entry_flow_index = to_be32(mlfe->mlfe_index);
3201ebb7c6fdSAlex Wilson 
3202ebb7c6fdSAlex Wilson 	if (mlfe->mlfe_state & MLXCX_FLOW_ENTRY_CREATED) {
3203ebb7c6fdSAlex Wilson 		set_bit8(&in.mlxi_set_flow_table_entry_modify_bitmask,
3204ebb7c6fdSAlex Wilson 		    MLXCX_CMD_FLOW_ENTRY_SET_ACTION);
3205ebb7c6fdSAlex Wilson 		set_bit8(&in.mlxi_set_flow_table_entry_modify_bitmask,
3206ebb7c6fdSAlex Wilson 		    MLXCX_CMD_FLOW_ENTRY_SET_DESTINATION);
3207ebb7c6fdSAlex Wilson 	}
3208ebb7c6fdSAlex Wilson 
3209ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_set_flow_table_entry_context;
3210ebb7c6fdSAlex Wilson 	ctx->mlfec_group_id = to_be32(mlfg->mlfg_num);
3211ebb7c6fdSAlex Wilson 
3212ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_set_flow_table_entry_in_t,
3213ebb7c6fdSAlex Wilson 	    mlxi_set_flow_table_entry_context) +
3214ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_flow_entry_ctx_t, mlfec_destination);
3215ebb7c6fdSAlex Wilson 
3216ebb7c6fdSAlex Wilson 	ctx->mlfec_action = to_be16(mlfe->mlfe_action);
3217ebb7c6fdSAlex Wilson 
3218ebb7c6fdSAlex Wilson 	switch (mlfe->mlfe_action) {
3219ebb7c6fdSAlex Wilson 	case MLXCX_FLOW_ACTION_ALLOW:
3220ebb7c6fdSAlex Wilson 	case MLXCX_FLOW_ACTION_DROP:
3221ebb7c6fdSAlex Wilson 		break;
3222ebb7c6fdSAlex Wilson 	case MLXCX_FLOW_ACTION_FORWARD:
3223ebb7c6fdSAlex Wilson 		ASSERT3U(mlfe->mlfe_ndest, <=, MLXCX_FLOW_MAX_DESTINATIONS);
3224ebb7c6fdSAlex Wilson 		ASSERT3U(mlfe->mlfe_ndest, <=,
3225ebb7c6fdSAlex Wilson 		    mlxp->mlx_caps->mlc_max_rx_fe_dest);
3226ebb7c6fdSAlex Wilson 		ctx->mlfec_destination_list_size = to_be24(mlfe->mlfe_ndest);
3227ebb7c6fdSAlex Wilson 		for (i = 0; i < mlfe->mlfe_ndest; ++i) {
3228ebb7c6fdSAlex Wilson 			insize += sizeof (mlxcx_flow_dest_t);
3229ebb7c6fdSAlex Wilson 			d = &ctx->mlfec_destination[i];
3230ebb7c6fdSAlex Wilson 			if (mlfe->mlfe_dest[i].mlfed_tir != NULL) {
3231ebb7c6fdSAlex Wilson 				d->mlfd_destination_type = MLXCX_FLOW_DEST_TIR;
3232ebb7c6fdSAlex Wilson 				d->mlfd_destination_id = to_be24(
3233ebb7c6fdSAlex Wilson 				    mlfe->mlfe_dest[i].mlfed_tir->mltir_num);
3234ebb7c6fdSAlex Wilson 			} else if (mlfe->mlfe_dest[i].mlfed_flow != NULL) {
3235ebb7c6fdSAlex Wilson 				d->mlfd_destination_type =
3236ebb7c6fdSAlex Wilson 				    MLXCX_FLOW_DEST_FLOW_TABLE;
3237ebb7c6fdSAlex Wilson 				d->mlfd_destination_id = to_be24(
3238ebb7c6fdSAlex Wilson 				    mlfe->mlfe_dest[i].mlfed_flow->mlft_num);
3239ebb7c6fdSAlex Wilson 			} else {
3240ebb7c6fdSAlex Wilson 				/* Invalid flow entry destination */
3241ebb7c6fdSAlex Wilson 				VERIFY(0);
3242ebb7c6fdSAlex Wilson 			}
3243ebb7c6fdSAlex Wilson 		}
3244ebb7c6fdSAlex Wilson 		break;
3245ebb7c6fdSAlex Wilson 	case MLXCX_FLOW_ACTION_COUNT:
3246ebb7c6fdSAlex Wilson 		/* We don't support count actions yet. */
3247ebb7c6fdSAlex Wilson 		VERIFY(0);
3248ebb7c6fdSAlex Wilson 		break;
3249ebb7c6fdSAlex Wilson 	case MLXCX_FLOW_ACTION_ENCAP:
3250ebb7c6fdSAlex Wilson 	case MLXCX_FLOW_ACTION_DECAP:
3251ebb7c6fdSAlex Wilson 		/* We don't support encap/decap actions yet. */
3252ebb7c6fdSAlex Wilson 		VERIFY(0);
3253ebb7c6fdSAlex Wilson 		break;
3254ebb7c6fdSAlex Wilson 	}
3255ebb7c6fdSAlex Wilson 
3256ebb7c6fdSAlex Wilson 	hdrs = &ctx->mlfec_match_value.mlfm_outer_headers;
3257ebb7c6fdSAlex Wilson 	params = &ctx->mlfec_match_value.mlfm_misc_parameters;
3258ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SMAC) {
3259ebb7c6fdSAlex Wilson 		bcopy(mlfe->mlfe_smac, hdrs->mlfh_smac,
3260ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_smac));
3261ebb7c6fdSAlex Wilson 	}
3262ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_DMAC) {
3263ebb7c6fdSAlex Wilson 		bcopy(mlfe->mlfe_dmac, hdrs->mlfh_dmac,
3264ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_dmac));
3265ebb7c6fdSAlex Wilson 	}
3266ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VLAN) {
3267ebb7c6fdSAlex Wilson 		switch (mlfe->mlfe_vlan_type) {
3268ebb7c6fdSAlex Wilson 		case MLXCX_VLAN_TYPE_CVLAN:
3269ebb7c6fdSAlex Wilson 			set_bit24(&hdrs->mlfh_tcp_ip_flags,
3270ebb7c6fdSAlex Wilson 			    MLXCX_FLOW_HDR_CVLAN_TAG);
3271ebb7c6fdSAlex Wilson 			break;
3272ebb7c6fdSAlex Wilson 		case MLXCX_VLAN_TYPE_SVLAN:
3273ebb7c6fdSAlex Wilson 			set_bit24(&hdrs->mlfh_tcp_ip_flags,
3274ebb7c6fdSAlex Wilson 			    MLXCX_FLOW_HDR_SVLAN_TAG);
3275ebb7c6fdSAlex Wilson 			break;
3276ebb7c6fdSAlex Wilson 		default:
3277ebb7c6fdSAlex Wilson 			break;
3278ebb7c6fdSAlex Wilson 		}
3279ebb7c6fdSAlex Wilson 	}
3280ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VID) {
3281ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VLAN);
3282ebb7c6fdSAlex Wilson 		set_bits16(&hdrs->mlfh_first_vid_flags,
3283ebb7c6fdSAlex Wilson 		    MLXCX_FLOW_HDR_FIRST_VID, mlfe->mlfe_vid);
3284ebb7c6fdSAlex Wilson 	}
3285ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER) {
3286ebb7c6fdSAlex Wilson 		set_bits24(&hdrs->mlfh_tcp_ip_flags, MLXCX_FLOW_HDR_IP_VERSION,
3287ebb7c6fdSAlex Wilson 		    mlfe->mlfe_ip_version);
3288ebb7c6fdSAlex Wilson 	}
3289ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SRCIP) {
3290ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER);
3291ebb7c6fdSAlex Wilson 		bcopy(mlfe->mlfe_srcip, hdrs->mlfh_src_ip,
3292ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_src_ip));
3293ebb7c6fdSAlex Wilson 	}
3294ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_DSTIP) {
3295ebb7c6fdSAlex Wilson 		ASSERT(mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_VER);
3296ebb7c6fdSAlex Wilson 		bcopy(mlfe->mlfe_dstip, hdrs->mlfh_src_ip,
3297ebb7c6fdSAlex Wilson 		    sizeof (hdrs->mlfh_dst_ip));
3298ebb7c6fdSAlex Wilson 	}
3299ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_IP_PROTO) {
3300ebb7c6fdSAlex Wilson 		hdrs->mlfh_ip_protocol = mlfe->mlfe_ip_proto;
3301ebb7c6fdSAlex Wilson 	}
3302ebb7c6fdSAlex Wilson 
3303ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_SQN) {
3304ebb7c6fdSAlex Wilson 		params->mlfp_source_sqn = to_be24(mlfe->mlfe_sqn);
3305ebb7c6fdSAlex Wilson 	}
3306ebb7c6fdSAlex Wilson 	if (mlfg->mlfg_mask & MLXCX_FLOW_MATCH_VXLAN) {
3307ebb7c6fdSAlex Wilson 		params->mlfp_vxlan_vni = to_be24(mlfe->mlfe_vxlan_vni);
3308ebb7c6fdSAlex Wilson 	}
3309ebb7c6fdSAlex Wilson 
3310ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
3311ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3312ebb7c6fdSAlex Wilson 		return (B_FALSE);
3313ebb7c6fdSAlex Wilson 	}
3314ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3315ebb7c6fdSAlex Wilson 
3316ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3317ebb7c6fdSAlex Wilson 	if (ret) {
3318ebb7c6fdSAlex Wilson 		mlfe->mlfe_state |= MLXCX_FLOW_ENTRY_CREATED;
3319ebb7c6fdSAlex Wilson 		mlfe->mlfe_state &= ~MLXCX_FLOW_ENTRY_DIRTY;
3320ebb7c6fdSAlex Wilson 		mlfg->mlfg_state |= MLXCX_FLOW_GROUP_BUSY;
3321ebb7c6fdSAlex Wilson 	}
3322ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3323ebb7c6fdSAlex Wilson 	return (ret);
3324ebb7c6fdSAlex Wilson }
3325ebb7c6fdSAlex Wilson 
3326ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_delete_flow_table_entry(mlxcx_t * mlxp,mlxcx_flow_entry_t * mlfe)3327ebb7c6fdSAlex Wilson mlxcx_cmd_delete_flow_table_entry(mlxcx_t *mlxp, mlxcx_flow_entry_t *mlfe)
3328ebb7c6fdSAlex Wilson {
3329ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3330ebb7c6fdSAlex Wilson 	mlxcx_cmd_delete_flow_table_entry_in_t in;
3331ebb7c6fdSAlex Wilson 	mlxcx_cmd_delete_flow_table_entry_out_t out;
3332ebb7c6fdSAlex Wilson 	boolean_t ret;
3333ebb7c6fdSAlex Wilson 	const mlxcx_flow_table_t *mlft;
3334ebb7c6fdSAlex Wilson 
3335ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3336ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3337ebb7c6fdSAlex Wilson 
3338ebb7c6fdSAlex Wilson 	mlft = mlfe->mlfe_table;
3339ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlft->mlft_mtx));
3340ebb7c6fdSAlex Wilson 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
3341ebb7c6fdSAlex Wilson 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
3342ebb7c6fdSAlex Wilson 
3343ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3344ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_delete_flow_table_entry_head,
3345ebb7c6fdSAlex Wilson 	    MLXCX_OP_DELETE_FLOW_TABLE_ENTRY, 0);
3346ebb7c6fdSAlex Wilson 
3347ebb7c6fdSAlex Wilson 	in.mlxi_delete_flow_table_entry_vport_number =
3348ebb7c6fdSAlex Wilson 	    to_be16(mlft->mlft_port->mlp_num);
3349ebb7c6fdSAlex Wilson 	in.mlxi_delete_flow_table_entry_table_type = mlft->mlft_type;
3350ebb7c6fdSAlex Wilson 	in.mlxi_delete_flow_table_entry_table_id = to_be24(mlft->mlft_num);
3351ebb7c6fdSAlex Wilson 	in.mlxi_delete_flow_table_entry_flow_index = to_be32(mlfe->mlfe_index);
3352ebb7c6fdSAlex Wilson 
3353ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3354ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3355ebb7c6fdSAlex Wilson 		return (B_FALSE);
3356ebb7c6fdSAlex Wilson 	}
3357ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3358ebb7c6fdSAlex Wilson 
3359ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3360ebb7c6fdSAlex Wilson 	if (ret) {
3361ebb7c6fdSAlex Wilson 		/*
3362ebb7c6fdSAlex Wilson 		 * Note that flow entries have a different lifecycle to most
3363ebb7c6fdSAlex Wilson 		 * other things we create -- we have to be able to re-use them
3364ebb7c6fdSAlex Wilson 		 * after they have been deleted, since they exist at a fixed
3365ebb7c6fdSAlex Wilson 		 * position in their flow table.
3366ebb7c6fdSAlex Wilson 		 *
3367ebb7c6fdSAlex Wilson 		 * So we clear the CREATED bit here for them to let us call
3368ebb7c6fdSAlex Wilson 		 * create_flow_table_entry() on the same entry again later.
3369ebb7c6fdSAlex Wilson 		 */
3370ebb7c6fdSAlex Wilson 		mlfe->mlfe_state &= ~MLXCX_FLOW_ENTRY_CREATED;
3371ebb7c6fdSAlex Wilson 		mlfe->mlfe_state |= MLXCX_FLOW_ENTRY_DELETED;
3372ebb7c6fdSAlex Wilson 	}
3373ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3374ebb7c6fdSAlex Wilson 	return (ret);
3375ebb7c6fdSAlex Wilson }
3376ebb7c6fdSAlex Wilson 
3377ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_sq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)3378ebb7c6fdSAlex Wilson mlxcx_cmd_create_sq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
3379ebb7c6fdSAlex Wilson {
3380ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3381ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_sq_in_t in;
3382ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_sq_out_t out;
3383ebb7c6fdSAlex Wilson 	boolean_t ret;
3384ebb7c6fdSAlex Wilson 	mlxcx_sq_ctx_t *ctx;
3385ebb7c6fdSAlex Wilson 	size_t rem, insize;
3386ebb7c6fdSAlex Wilson 	const ddi_dma_cookie_t *c;
3387ebb7c6fdSAlex Wilson 	uint64_t pa, npages;
3388ebb7c6fdSAlex Wilson 
3389ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3390ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3391ebb7c6fdSAlex Wilson 
3392ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
3393ebb7c6fdSAlex Wilson 	VERIFY3U(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_SENDQ);
3394ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
3395ebb7c6fdSAlex Wilson 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_CREATED);
3396ebb7c6fdSAlex Wilson 
3397ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3398ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_sq_head,
3399ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_SQ, 0);
3400ebb7c6fdSAlex Wilson 
3401ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_sq_context;
3402ebb7c6fdSAlex Wilson 
3403ebb7c6fdSAlex Wilson 	set_bit32(&ctx->mlsqc_flags, MLXCX_SQ_FLAGS_RLKEY);
3404ebb7c6fdSAlex Wilson 	set_bit32(&ctx->mlsqc_flags, MLXCX_SQ_FLAGS_FLUSH_IN_ERROR);
3405ebb7c6fdSAlex Wilson 	set_bits32(&ctx->mlsqc_flags, MLXCX_SQ_MIN_WQE_INLINE,
3406ebb7c6fdSAlex Wilson 	    mlwq->mlwq_inline_mode);
3407ebb7c6fdSAlex Wilson 	ctx->mlsqc_cqn = to_be24(mlwq->mlwq_cq->mlcq_num);
3408ebb7c6fdSAlex Wilson 
3409ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_tis != NULL);
3410ebb7c6fdSAlex Wilson 	ctx->mlsqc_tis_lst_sz = to_be16(1);
3411ebb7c6fdSAlex Wilson 	ctx->mlsqc_tis_num = to_be24(mlwq->mlwq_tis->mltis_num);
3412ebb7c6fdSAlex Wilson 
3413ebb7c6fdSAlex Wilson 	set_bits32(&ctx->mlsqc_wq.mlwqc_flags, MLXCX_WORKQ_CTX_TYPE,
3414ebb7c6fdSAlex Wilson 	    MLXCX_WORKQ_TYPE_CYCLIC);
3415ebb7c6fdSAlex Wilson 	ctx->mlsqc_wq.mlwqc_pd = to_be24(mlwq->mlwq_pd->mlpd_num);
3416ebb7c6fdSAlex Wilson 	ctx->mlsqc_wq.mlwqc_uar_page = to_be24(mlwq->mlwq_uar->mlu_num);
3417ebb7c6fdSAlex Wilson 	ctx->mlsqc_wq.mlwqc_log_wq_sz = mlwq->mlwq_entshift;
3418ebb7c6fdSAlex Wilson 	ctx->mlsqc_wq.mlwqc_log_wq_stride = MLXCX_SENDQ_STRIDE_SHIFT;
3419ebb7c6fdSAlex Wilson 
3420ebb7c6fdSAlex Wilson 	c = mlxcx_dma_cookie_one(&mlwq->mlwq_doorbell_dma);
3421ebb7c6fdSAlex Wilson 	ctx->mlsqc_wq.mlwqc_dbr_addr = to_be64(c->dmac_laddress);
3422ebb7c6fdSAlex Wilson 	ASSERT3U(c->dmac_size, >=, sizeof (mlxcx_workq_doorbell_t));
3423ebb7c6fdSAlex Wilson 
3424ebb7c6fdSAlex Wilson 	npages = 0;
3425ebb7c6fdSAlex Wilson 	c = NULL;
3426ebb7c6fdSAlex Wilson 	while ((c = mlxcx_dma_cookie_iter(&mlwq->mlwq_dma, c)) != NULL) {
3427ebb7c6fdSAlex Wilson 		pa = c->dmac_laddress;
3428ebb7c6fdSAlex Wilson 		rem = c->dmac_size;
3429ebb7c6fdSAlex Wilson 		while (rem > 0) {
3430ebb7c6fdSAlex Wilson 			ASSERT3U(pa & 0xfff, ==, 0);
3431ebb7c6fdSAlex Wilson 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
3432ebb7c6fdSAlex Wilson 			ctx->mlsqc_wq.mlwqc_pas[npages++] = to_be64(pa);
3433ebb7c6fdSAlex Wilson 			rem -= MLXCX_HW_PAGE_SIZE;
3434ebb7c6fdSAlex Wilson 			pa += MLXCX_HW_PAGE_SIZE;
3435ebb7c6fdSAlex Wilson 		}
3436ebb7c6fdSAlex Wilson 	}
3437ebb7c6fdSAlex Wilson 	ASSERT3U(npages, <=, MLXCX_WORKQ_CTX_MAX_ADDRESSES);
3438ebb7c6fdSAlex Wilson 
3439ebb7c6fdSAlex Wilson 	insize = offsetof(mlxcx_cmd_create_sq_in_t, mlxi_create_sq_context) +
3440ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_sq_ctx_t, mlsqc_wq) +
3441ebb7c6fdSAlex Wilson 	    offsetof(mlxcx_workq_ctx_t, mlwqc_pas) +
3442ebb7c6fdSAlex Wilson 	    sizeof (uint64_t) * npages;
3443ebb7c6fdSAlex Wilson 
3444ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
3445ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3446ebb7c6fdSAlex Wilson 		return (B_FALSE);
3447ebb7c6fdSAlex Wilson 	}
3448ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3449ebb7c6fdSAlex Wilson 
3450ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3451ebb7c6fdSAlex Wilson 	if (ret) {
3452ebb7c6fdSAlex Wilson 		mlwq->mlwq_state |= MLXCX_WQ_CREATED;
3453ebb7c6fdSAlex Wilson 		mlwq->mlwq_num = from_be24(out.mlxo_create_sq_sqn);
3454ebb7c6fdSAlex Wilson 	}
3455ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3456ebb7c6fdSAlex Wilson 	return (ret);
3457ebb7c6fdSAlex Wilson }
3458ebb7c6fdSAlex Wilson 
3459ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_start_sq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)3460ebb7c6fdSAlex Wilson mlxcx_cmd_start_sq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
3461ebb7c6fdSAlex Wilson {
3462ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3463ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_sq_in_t in;
3464ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_sq_out_t out;
3465ebb7c6fdSAlex Wilson 	boolean_t ret;
3466ebb7c6fdSAlex Wilson 	ddi_fm_error_t err;
3467ebb7c6fdSAlex Wilson 
3468ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3469ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3470ebb7c6fdSAlex Wilson 
3471ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
3472ebb7c6fdSAlex Wilson 	ASSERT(mlwq->mlwq_cq != NULL);
3473ebb7c6fdSAlex Wilson 
3474ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
3475ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
3476ebb7c6fdSAlex Wilson 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_STARTED);
3477ebb7c6fdSAlex Wilson 
3478ebb7c6fdSAlex Wilson 	/*
3479ebb7c6fdSAlex Wilson 	 * Before starting the queue, we have to be sure that it is
3480ebb7c6fdSAlex Wilson 	 * empty and the doorbell and counters are set to 0.
3481ebb7c6fdSAlex Wilson 	 */
3482ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_cq->mlcq_mtx));
3483ebb7c6fdSAlex Wilson 	ASSERT(list_is_empty(&mlwq->mlwq_cq->mlcq_buffers));
3484ebb7c6fdSAlex Wilson 	ASSERT(list_is_empty(&mlwq->mlwq_cq->mlcq_buffers_b));
3485ebb7c6fdSAlex Wilson 
3486ebb7c6fdSAlex Wilson 	mlwq->mlwq_doorbell->mlwqd_recv_counter = to_be16(0);
3487ebb7c6fdSAlex Wilson 	MLXCX_DMA_SYNC(mlwq->mlwq_doorbell_dma, DDI_DMA_SYNC_FORDEV);
3488ebb7c6fdSAlex Wilson 	ddi_fm_dma_err_get(mlwq->mlwq_doorbell_dma.mxdb_dma_handle, &err,
3489ebb7c6fdSAlex Wilson 	    DDI_FME_VERSION);
3490ebb7c6fdSAlex Wilson 	if (err.fme_status != DDI_FM_OK)
3491ebb7c6fdSAlex Wilson 		return (B_FALSE);
3492ebb7c6fdSAlex Wilson 	mlwq->mlwq_pc = 0;
3493ebb7c6fdSAlex Wilson 
3494ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3495ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_sq_head,
3496ebb7c6fdSAlex Wilson 	    MLXCX_OP_MODIFY_SQ, 0);
3497ebb7c6fdSAlex Wilson 
3498ebb7c6fdSAlex Wilson 	in.mlxi_modify_sq_sqn = to_be24(mlwq->mlwq_num);
3499ebb7c6fdSAlex Wilson 
3500ebb7c6fdSAlex Wilson 	/* From state */
3501ebb7c6fdSAlex Wilson 	set_bits8(&in.mlxi_modify_sq_state, MLXCX_CMD_MODIFY_SQ_STATE,
3502ebb7c6fdSAlex Wilson 	    MLXCX_SQ_STATE_RST);
3503ebb7c6fdSAlex Wilson 	/* To state */
3504ebb7c6fdSAlex Wilson 	set_bits32(&in.mlxi_modify_sq_context.mlsqc_flags, MLXCX_SQ_STATE,
3505ebb7c6fdSAlex Wilson 	    MLXCX_SQ_STATE_RDY);
3506ebb7c6fdSAlex Wilson 
3507ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3508ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3509ebb7c6fdSAlex Wilson 		return (B_FALSE);
3510ebb7c6fdSAlex Wilson 	}
3511ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3512ebb7c6fdSAlex Wilson 
3513ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3514ebb7c6fdSAlex Wilson 	if (ret) {
3515ebb7c6fdSAlex Wilson 		mlwq->mlwq_state |= MLXCX_WQ_STARTED;
3516ebb7c6fdSAlex Wilson 	}
3517ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3518ebb7c6fdSAlex Wilson 	return (ret);
3519ebb7c6fdSAlex Wilson }
3520ebb7c6fdSAlex Wilson 
3521ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_stop_sq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)3522ebb7c6fdSAlex Wilson mlxcx_cmd_stop_sq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
3523ebb7c6fdSAlex Wilson {
3524ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3525ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_sq_in_t in;
3526ebb7c6fdSAlex Wilson 	mlxcx_cmd_modify_sq_out_t out;
3527ebb7c6fdSAlex Wilson 	boolean_t ret;
3528ebb7c6fdSAlex Wilson 
3529ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3530ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3531ebb7c6fdSAlex Wilson 
3532ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
3533ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
3534ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
3535ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_STARTED);
3536ebb7c6fdSAlex Wilson 
3537ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3538ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_sq_head,
3539ebb7c6fdSAlex Wilson 	    MLXCX_OP_MODIFY_SQ, 0);
3540ebb7c6fdSAlex Wilson 
3541ebb7c6fdSAlex Wilson 	in.mlxi_modify_sq_sqn = to_be24(mlwq->mlwq_num);
3542ebb7c6fdSAlex Wilson 
3543ebb7c6fdSAlex Wilson 	/* From state */
3544ebb7c6fdSAlex Wilson 	set_bits8(&in.mlxi_modify_sq_state, MLXCX_CMD_MODIFY_SQ_STATE,
3545ebb7c6fdSAlex Wilson 	    MLXCX_SQ_STATE_RDY);
3546ebb7c6fdSAlex Wilson 	/* To state */
3547ebb7c6fdSAlex Wilson 	set_bits32(&in.mlxi_modify_sq_context.mlsqc_flags, MLXCX_SQ_STATE,
3548ebb7c6fdSAlex Wilson 	    MLXCX_SQ_STATE_RST);
3549ebb7c6fdSAlex Wilson 
3550ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3551ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3552ebb7c6fdSAlex Wilson 		return (B_FALSE);
3553ebb7c6fdSAlex Wilson 	}
3554ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3555ebb7c6fdSAlex Wilson 
3556ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3557ebb7c6fdSAlex Wilson 	if (ret) {
3558ebb7c6fdSAlex Wilson 		mlwq->mlwq_state &= ~MLXCX_WQ_STARTED;
3559ebb7c6fdSAlex Wilson 	}
3560ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3561ebb7c6fdSAlex Wilson 	return (ret);
3562ebb7c6fdSAlex Wilson }
3563ebb7c6fdSAlex Wilson 
3564ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_sq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)3565ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_sq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
3566ebb7c6fdSAlex Wilson {
3567ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3568ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_sq_in_t in;
3569ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_sq_out_t out;
3570ebb7c6fdSAlex Wilson 	boolean_t ret;
3571ebb7c6fdSAlex Wilson 
3572ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3573ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3574ebb7c6fdSAlex Wilson 
3575ebb7c6fdSAlex Wilson 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
3576ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
3577ebb7c6fdSAlex Wilson 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
3578ebb7c6fdSAlex Wilson 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_STARTED);
3579ebb7c6fdSAlex Wilson 
3580ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3581ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_sq_head,
3582ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_SQ, 0);
3583ebb7c6fdSAlex Wilson 
3584ebb7c6fdSAlex Wilson 	in.mlxi_destroy_sq_sqn = to_be24(mlwq->mlwq_num);
3585ebb7c6fdSAlex Wilson 
3586ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3587ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3588ebb7c6fdSAlex Wilson 		return (B_FALSE);
3589ebb7c6fdSAlex Wilson 	}
3590ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3591ebb7c6fdSAlex Wilson 
3592ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3593ebb7c6fdSAlex Wilson 	if (ret) {
3594ebb7c6fdSAlex Wilson 		mlwq->mlwq_state |= MLXCX_WQ_DESTROYED;
3595ebb7c6fdSAlex Wilson 	}
3596ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3597ebb7c6fdSAlex Wilson 	return (ret);
3598ebb7c6fdSAlex Wilson }
3599ebb7c6fdSAlex Wilson 
3600ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_create_rqt(mlxcx_t * mlxp,mlxcx_rqtable_t * mlrqt)3601ebb7c6fdSAlex Wilson mlxcx_cmd_create_rqt(mlxcx_t *mlxp, mlxcx_rqtable_t *mlrqt)
3602ebb7c6fdSAlex Wilson {
3603ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3604ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_rqt_in_t in;
3605ebb7c6fdSAlex Wilson 	mlxcx_cmd_create_rqt_out_t out;
3606ebb7c6fdSAlex Wilson 	mlxcx_rqtable_ctx_t *ctx;
3607ebb7c6fdSAlex Wilson 	boolean_t ret;
3608ebb7c6fdSAlex Wilson 	uint_t i;
3609ebb7c6fdSAlex Wilson 
3610ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3611ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3612ebb7c6fdSAlex Wilson 
3613ebb7c6fdSAlex Wilson 	VERIFY0(mlrqt->mlrqt_state & MLXCX_RQT_CREATED);
3614ebb7c6fdSAlex Wilson 
3615ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3616ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_rqt_head,
3617ebb7c6fdSAlex Wilson 	    MLXCX_OP_CREATE_RQT, 0);
3618ebb7c6fdSAlex Wilson 
3619ebb7c6fdSAlex Wilson 	ctx = &in.mlxi_create_rqt_context;
3620ebb7c6fdSAlex Wilson 	ASSERT3U(mlrqt->mlrqt_max, <=, MLXCX_RQT_MAX_RQ_REFS);
3621ebb7c6fdSAlex Wilson 	ASSERT3U(mlrqt->mlrqt_max, <=, mlxp->mlx_caps->mlc_max_rqt_size);
3622ebb7c6fdSAlex Wilson 	ctx->mlrqtc_max_size = to_be16(mlrqt->mlrqt_max);
3623ebb7c6fdSAlex Wilson 	ctx->mlrqtc_actual_size = to_be16(mlrqt->mlrqt_used);
3624ebb7c6fdSAlex Wilson 	for (i = 0; i < mlrqt->mlrqt_used; ++i) {
3625ebb7c6fdSAlex Wilson 		ctx->mlrqtc_rqref[i].mlrqtr_rqn = to_be24(
3626ebb7c6fdSAlex Wilson 		    mlrqt->mlrqt_rq[i]->mlwq_num);
3627ebb7c6fdSAlex Wilson 	}
3628ebb7c6fdSAlex Wilson 
3629ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3630ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3631ebb7c6fdSAlex Wilson 		return (B_FALSE);
3632ebb7c6fdSAlex Wilson 	}
3633ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3634ebb7c6fdSAlex Wilson 
3635ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3636ebb7c6fdSAlex Wilson 	if (ret) {
3637ebb7c6fdSAlex Wilson 		mlrqt->mlrqt_num = from_be24(out.mlxo_create_rqt_rqtn);
3638ebb7c6fdSAlex Wilson 		mlrqt->mlrqt_state |= MLXCX_RQT_CREATED;
3639ebb7c6fdSAlex Wilson 		mlrqt->mlrqt_state &= ~MLXCX_RQT_DIRTY;
3640ebb7c6fdSAlex Wilson 	}
3641ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3642ebb7c6fdSAlex Wilson 	return (ret);
3643ebb7c6fdSAlex Wilson }
3644ebb7c6fdSAlex Wilson 
3645ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_destroy_rqt(mlxcx_t * mlxp,mlxcx_rqtable_t * mlrqt)3646ebb7c6fdSAlex Wilson mlxcx_cmd_destroy_rqt(mlxcx_t *mlxp, mlxcx_rqtable_t *mlrqt)
3647ebb7c6fdSAlex Wilson {
3648ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3649ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_rqt_in_t in;
3650ebb7c6fdSAlex Wilson 	mlxcx_cmd_destroy_rqt_out_t out;
3651ebb7c6fdSAlex Wilson 	boolean_t ret;
3652ebb7c6fdSAlex Wilson 
3653ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3654ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3655ebb7c6fdSAlex Wilson 
3656ebb7c6fdSAlex Wilson 	VERIFY(mlrqt->mlrqt_state & MLXCX_RQT_CREATED);
3657ebb7c6fdSAlex Wilson 	VERIFY0(mlrqt->mlrqt_state & MLXCX_RQT_DESTROYED);
3658ebb7c6fdSAlex Wilson 
3659ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3660ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_rqt_head,
3661ebb7c6fdSAlex Wilson 	    MLXCX_OP_DESTROY_RQT, 0);
3662ebb7c6fdSAlex Wilson 
3663ebb7c6fdSAlex Wilson 	in.mlxi_destroy_rqt_rqtn = to_be24(mlrqt->mlrqt_num);
3664ebb7c6fdSAlex Wilson 
3665ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3666ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3667ebb7c6fdSAlex Wilson 		return (B_FALSE);
3668ebb7c6fdSAlex Wilson 	}
3669ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3670ebb7c6fdSAlex Wilson 
3671ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3672ebb7c6fdSAlex Wilson 	if (ret) {
3673ebb7c6fdSAlex Wilson 		mlrqt->mlrqt_state |= MLXCX_RQT_DESTROYED;
3674ebb7c6fdSAlex Wilson 	}
3675ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3676ebb7c6fdSAlex Wilson 	return (ret);
3677ebb7c6fdSAlex Wilson }
3678ebb7c6fdSAlex Wilson 
3679ebb7c6fdSAlex Wilson boolean_t
mlxcx_cmd_set_int_mod(mlxcx_t * mlxp,uint_t intr,uint_t min_delay)3680ebb7c6fdSAlex Wilson mlxcx_cmd_set_int_mod(mlxcx_t *mlxp, uint_t intr, uint_t min_delay)
3681ebb7c6fdSAlex Wilson {
3682ebb7c6fdSAlex Wilson 	mlxcx_cmd_t cmd;
3683ebb7c6fdSAlex Wilson 	mlxcx_cmd_config_int_mod_in_t in;
3684ebb7c6fdSAlex Wilson 	mlxcx_cmd_config_int_mod_out_t out;
3685ebb7c6fdSAlex Wilson 	boolean_t ret;
3686ebb7c6fdSAlex Wilson 
3687ebb7c6fdSAlex Wilson 	bzero(&in, sizeof (in));
3688ebb7c6fdSAlex Wilson 	bzero(&out, sizeof (out));
3689ebb7c6fdSAlex Wilson 
3690ebb7c6fdSAlex Wilson 	mlxcx_cmd_init(mlxp, &cmd);
3691ebb7c6fdSAlex Wilson 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_config_int_mod_head,
3692ebb7c6fdSAlex Wilson 	    MLXCX_OP_CONFIG_INT_MODERATION, MLXCX_CMD_CONFIG_INT_MOD_WRITE);
3693ebb7c6fdSAlex Wilson 
3694ebb7c6fdSAlex Wilson 	in.mlxi_config_int_mod_int_vector = to_be16(intr);
3695ebb7c6fdSAlex Wilson 	in.mlxi_config_int_mod_min_delay = to_be16(min_delay);
3696ebb7c6fdSAlex Wilson 
3697ebb7c6fdSAlex Wilson 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
3698ebb7c6fdSAlex Wilson 		mlxcx_cmd_fini(mlxp, &cmd);
3699ebb7c6fdSAlex Wilson 		return (B_FALSE);
3700ebb7c6fdSAlex Wilson 	}
3701ebb7c6fdSAlex Wilson 	mlxcx_cmd_wait(&cmd);
3702ebb7c6fdSAlex Wilson 
3703ebb7c6fdSAlex Wilson 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
3704ebb7c6fdSAlex Wilson 	mlxcx_cmd_fini(mlxp, &cmd);
3705ebb7c6fdSAlex Wilson 	return (ret);
3706ebb7c6fdSAlex Wilson }
3707ebb7c6fdSAlex Wilson 
3708ebb7c6fdSAlex Wilson /*
3709ebb7c6fdSAlex Wilson  * CTASSERTs here are for the structs in mlxcx_reg.h, to check they match
3710ebb7c6fdSAlex Wilson  * against offsets from the PRM.
3711ebb7c6fdSAlex Wilson  *
3712ebb7c6fdSAlex Wilson  * They're not in the header file, to avoid them being used by multiple .c
3713ebb7c6fdSAlex Wilson  * files.
3714ebb7c6fdSAlex Wilson  */
3715ebb7c6fdSAlex Wilson 
3716ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_eventq_ent_t, mleqe_unknown_data) == 0x20);
3717ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_eventq_ent_t, mleqe_signature) == 0x3c + 2);
3718ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_eventq_ent_t) == 64);
3719ebb7c6fdSAlex Wilson 
3720ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_completionq_error_ent_t, mlcqee_byte_cnt) == 0x2C);
3721ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_completionq_error_ent_t, mlcqee_wqe_opcode) == 0x38);
3722ebb7c6fdSAlex Wilson 
3723ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_completionq_error_ent_t) ==
3724ebb7c6fdSAlex Wilson     sizeof (mlxcx_completionq_ent_t));
3725ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_wqe_control_seg_t) == (1 << 4));
3726ebb7c6fdSAlex Wilson 
3727ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_wqe_eth_seg_t, mles_inline_headers) == 0x0e);
3728ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_wqe_eth_seg_t) == (1 << 5));
3729ebb7c6fdSAlex Wilson 
3730ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_wqe_data_seg_t) == (1 << 4));
3731ebb7c6fdSAlex Wilson 
3732ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_sendq_ent_t) == (1 << MLXCX_SENDQ_STRIDE_SHIFT));
3733ebb7c6fdSAlex Wilson 
3734ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_sendq_bf_t) == (1 << MLXCX_SENDQ_STRIDE_SHIFT));
3735ebb7c6fdSAlex Wilson 
3736ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_sendq_extra_ent_t) == (1 << MLXCX_SENDQ_STRIDE_SHIFT));
3737ebb7c6fdSAlex Wilson 
3738ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_recvq_ent_t) == (1 << MLXCX_RECVQ_STRIDE_SHIFT));
3739ebb7c6fdSAlex Wilson 
3740ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_workq_ctx_t, mlwqc_dbr_addr) == 0x10);
3741ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_workq_ctx_t, mlwqc_pas) == 0xc0);
3742ebb7c6fdSAlex Wilson 
3743ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_rq_ctx_t, mlrqc_cqn) == 0x09);
3744ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_rq_ctx_t, mlrqc_wq) == 0x30);
3745ebb7c6fdSAlex Wilson 
3746ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_sq_ctx_t, mlsqc_cqn) == 0x09);
3747ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_sq_ctx_t, mlsqc_tis_lst_sz) == 0x20);
3748ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_sq_ctx_t, mlsqc_tis_num) == 0x2d);
3749ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_sq_ctx_t, mlsqc_wq) == 0x30);
3750ebb7c6fdSAlex Wilson 
3751ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_tis_ctx_t) == 0xa0);
3752ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_tis_ctx_t, mltisc_transport_domain) == 0x25);
3753ebb7c6fdSAlex Wilson 
3754ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_rqtable_ctx_t, mlrqtc_max_size) == 0x16);
3755ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_rqtable_ctx_t, mlrqtc_rqref) == 0xF0);
3756ebb7c6fdSAlex Wilson 
3757ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_eq_in_t, mlxi_create_eq_event_bitmask) ==
3758ebb7c6fdSAlex Wilson     0x58);
3759ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_eq_in_t, mlxi_create_eq_pas) == 0x110);
3760ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_eq_in_t, mlxi_create_eq_context) == 0x10);
3761ebb7c6fdSAlex Wilson 
3762ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_tir_in_t, mlxi_create_tir_context) == 0x20);
3763ebb7c6fdSAlex Wilson 
3764ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_tis_in_t, mlxi_create_tis_context) == 0x20);
3765ebb7c6fdSAlex Wilson 
3766ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_query_special_ctxs_out_t,
3767ebb7c6fdSAlex Wilson     mlxo_query_special_ctxs_resd_lkey) == 0x0c);
3768ebb7c6fdSAlex Wilson 
3769ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_query_cq_out_t, mlxo_query_cq_context) == 0x10);
3770ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_query_cq_out_t, mlxo_query_cq_pas) == 0x110);
3771ebb7c6fdSAlex Wilson 
3772ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_query_rq_out_t, mlxo_query_rq_context) == 0x20);
3773ebb7c6fdSAlex Wilson 
3774ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_sq_in_t, mlxi_create_sq_context) == 0x20);
3775ebb7c6fdSAlex Wilson 
3776ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_modify_sq_in_t, mlxi_modify_sq_context) == 0x20);
3777ebb7c6fdSAlex Wilson 
3778ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_query_sq_out_t, mlxo_query_sq_context) == 0x20);
3779ebb7c6fdSAlex Wilson 
3780ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_create_rqt_in_t, mlxi_create_rqt_context) == 0x20);
3781ebb7c6fdSAlex Wilson 
3782ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_reg_pmtu_t, mlrd_pmtu_oper_mtu) == 0x0C);
3783ebb7c6fdSAlex Wilson 
3784ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_reg_ptys_t) == 64);
3785*85e4aa97SDan McDonald CTASSERT(offsetof(mlxcx_reg_ptys_t, mlrd_ptys_ext_proto_cap) == 0x08);
3786ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_reg_ptys_t, mlrd_ptys_proto_cap) == 0x0c);
3787*85e4aa97SDan McDonald CTASSERT(offsetof(mlxcx_reg_ptys_t, mlrd_ptys_ext_proto_admin) == 0x14);
3788ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_reg_ptys_t, mlrd_ptys_proto_admin) == 0x18);
3789ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_reg_ptys_t, mlrd_ptys_proto_partner_advert) == 0x30);
3790ebb7c6fdSAlex Wilson 
3791ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_reg_mcia_t, mlrd_mcia_data) == 0x10);
3792ebb7c6fdSAlex Wilson 
3793ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_ppcnt_ieee_802_3_t,
3794ebb7c6fdSAlex Wilson     mlppc_ieee_802_3_in_range_len_err) == 0x50);
3795ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_ppcnt_ieee_802_3_t,
3796ebb7c6fdSAlex Wilson     mlppc_ieee_802_3_pause_tx) == 0x90);
3797ebb7c6fdSAlex Wilson 
3798ebb7c6fdSAlex Wilson CTASSERT(sizeof (mlxcx_reg_ppcnt_t) == 256);
3799ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_reg_ppcnt_t, mlrd_ppcnt_data) == 0x08);
3800ebb7c6fdSAlex Wilson 
3801ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_access_register_in_t,
3802ebb7c6fdSAlex Wilson     mlxi_access_register_argument) == 0x0C);
3803ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_access_register_in_t,
3804ebb7c6fdSAlex Wilson     mlxi_access_register_data) == 0x10);
3805ebb7c6fdSAlex Wilson 
3806ebb7c6fdSAlex Wilson CTASSERT(offsetof(mlxcx_cmd_access_register_out_t,
3807ebb7c6fdSAlex Wilson     mlxo_access_register_data) == 0x10);
38087cbbb9b5SAlex Wilson 
38097cbbb9b5SAlex Wilson CTASSERT(sizeof (mlxcx_cmd_set_flow_table_root_in_t) == 64);
38107cbbb9b5SAlex Wilson CTASSERT(offsetof(mlxcx_cmd_set_flow_table_root_in_t,
38117cbbb9b5SAlex Wilson     mlxi_set_flow_table_root_table_id) == 0x15);
38127cbbb9b5SAlex Wilson CTASSERT(offsetof(mlxcx_cmd_set_flow_table_root_in_t,
38137cbbb9b5SAlex Wilson     mlxi_set_flow_table_root_esw_owner_vhca_id_valid) == 0x1C);
3814