1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020, The University of Queensland
14  * Copyright (c) 2018, Joyent, Inc.
15  * Copyright 2020 RackTop Systems, Inc.
16  */
17 
18 /*
19  * Controls the management of commands that are issues to and from the HCA
20  * command queue.
21  */
22 
23 #include <mlxcx.h>
24 
25 #include <sys/debug.h>
26 #include <sys/sysmacros.h>
27 
28 /*
29  * When we start up the command queue, it will undergo some internal
30  * initialization after we set the command queue address. These values allow us
31  * to control how much time we should wait for that to occur.
32  */
33 clock_t mlxcx_cmd_init_delay = 1000 * 10; /* 10 ms in us */
34 uint_t mlxcx_cmd_init_trys = 100; /* Wait at most 1s */
35 
36 clock_t mlxcx_cmd_delay = 1000 * 1; /* 1 ms in us */
37 uint_t mlxcx_cmd_tries = 5000; /* Wait at most 1s */
38 
39 /*
40  * This macro is used to identify that we care about our own function that we're
41  * communicating with. We always use this function.
42  */
43 #define	MLXCX_FUNCTION_SELF	(to_be16(0))
44 
45 static const char *
mlxcx_cmd_response_string(mlxcx_cmd_ret_t ret)46 mlxcx_cmd_response_string(mlxcx_cmd_ret_t ret)
47 {
48 	switch (ret) {
49 	case MLXCX_CMD_R_OK:
50 		return ("MLXCX_CMD_R_OK");
51 	case MLXCX_CMD_R_INTERNAL_ERR:
52 		return ("MLXCX_CMD_R_INTERNAL_ERR");
53 	case MLXCX_CMD_R_BAD_OP:
54 		return ("MLXCX_CMD_R_BAD_OP");
55 	case MLXCX_CMD_R_BAD_PARAM:
56 		return ("MLXCX_CMD_R_BAD_PARAM");
57 	case MLXCX_CMD_R_BAD_SYS_STATE:
58 		return ("MLXCX_CMD_R_BAD_SYS_STATE");
59 	case MLXCX_CMD_R_BAD_RESOURCE:
60 		return ("MLXCX_CMD_R_BAD_RESOURCE");
61 	case MLXCX_CMD_R_RESOURCE_BUSY:
62 		return ("MLXCX_CMD_R_RESOURCE_BUSY");
63 	case MLXCX_CMD_R_EXCEED_LIM:
64 		return ("MLXCX_CMD_R_EXCEED_LIM");
65 	case MLXCX_CMD_R_BAD_RES_STATE:
66 		return ("MLXCX_CMD_R_BAD_RES_STATE");
67 	case MLXCX_CMD_R_BAD_INDEX:
68 		return ("MLXCX_CMD_R_BAD_INDEX");
69 	case MLXCX_CMD_R_NO_RESOURCES:
70 		return ("MLXCX_CMD_R_NO_RESOURCES");
71 	case MLXCX_CMD_R_BAD_INPUT_LEN:
72 		return ("MLXCX_CMD_R_BAD_INPUT_LEN");
73 	case MLXCX_CMD_R_BAD_OUTPUT_LEN:
74 		return ("MLXCX_CMD_R_BAD_OUTPUT_LEN");
75 	case MLXCX_CMD_R_BAD_RESOURCE_STATE:
76 		return ("MLXCX_CMD_R_BAD_RESOURCE_STATE");
77 	case MLXCX_CMD_R_BAD_PKT:
78 		return ("MLXCX_CMD_R_BAD_PKT");
79 	case MLXCX_CMD_R_BAD_SIZE:
80 		return ("MLXCX_CMD_R_BAD_SIZE");
81 	default:
82 		return ("Unknown command");
83 	}
84 }
85 
86 static const char *
mlxcx_cmd_opcode_string(mlxcx_cmd_op_t op)87 mlxcx_cmd_opcode_string(mlxcx_cmd_op_t op)
88 {
89 	switch (op) {
90 	case MLXCX_OP_QUERY_HCA_CAP:
91 		return ("MLXCX_OP_QUERY_HCA_CAP");
92 	case MLXCX_OP_QUERY_ADAPTER:
93 		return ("MLXCX_OP_QUERY_ADAPTER");
94 	case MLXCX_OP_INIT_HCA:
95 		return ("MLXCX_OP_INIT_HCA");
96 	case MLXCX_OP_TEARDOWN_HCA:
97 		return ("MLXCX_OP_TEARDOWN_HCA");
98 	case MLXCX_OP_ENABLE_HCA:
99 		return ("MLXCX_OP_ENABLE_HCA");
100 	case MLXCX_OP_DISABLE_HCA:
101 		return ("MLXCX_OP_DISABLE_HCA");
102 	case MLXCX_OP_QUERY_PAGES:
103 		return ("MLXCX_OP_QUERY_PAGES");
104 	case MLXCX_OP_MANAGE_PAGES:
105 		return ("MLXCX_OP_MANAGE_PAGES");
106 	case MLXCX_OP_SET_HCA_CAP:
107 		return ("MLXCX_OP_SET_HCA_CAP");
108 	case MLXCX_OP_QUERY_ISSI:
109 		return ("MLXCX_OP_QUERY_ISSI");
110 	case MLXCX_OP_SET_ISSI:
111 		return ("MLXCX_OP_SET_ISSI");
112 	case MLXCX_OP_SET_DRIVER_VERSION:
113 		return ("MLXCX_OP_SET_DRIVER_VERSION");
114 	case MLXCX_OP_QUERY_OTHER_HCA_CAP:
115 		return ("MLXCX_OP_QUERY_OTHER_HCA_CAP");
116 	case MLXCX_OP_MODIFY_OTHER_HCA_CAP:
117 		return ("MLXCX_OP_MODIFY_OTHER_HCA_CAP");
118 	case MLXCX_OP_SET_TUNNELED_OPERATIONS:
119 		return ("MLXCX_OP_SET_TUNNELED_OPERATIONS");
120 	case MLXCX_OP_CREATE_MKEY:
121 		return ("MLXCX_OP_CREATE_MKEY");
122 	case MLXCX_OP_QUERY_MKEY:
123 		return ("MLXCX_OP_QUERY_MKEY");
124 	case MLXCX_OP_DESTROY_MKEY:
125 		return ("MLXCX_OP_DESTROY_MKEY");
126 	case MLXCX_OP_QUERY_SPECIAL_CONTEXTS:
127 		return ("MLXCX_OP_QUERY_SPECIAL_CONTEXTS");
128 	case MLXCX_OP_PAGE_FAULT_RESUME:
129 		return ("MLXCX_OP_PAGE_FAULT_RESUME");
130 	case MLXCX_OP_CREATE_EQ:
131 		return ("MLXCX_OP_CREATE_EQ");
132 	case MLXCX_OP_DESTROY_EQ:
133 		return ("MLXCX_OP_DESTROY_EQ");
134 	case MLXCX_OP_QUERY_EQ:
135 		return ("MLXCX_OP_QUERY_EQ");
136 	case MLXCX_OP_GEN_EQE:
137 		return ("MLXCX_OP_GEN_EQE");
138 	case MLXCX_OP_CREATE_CQ:
139 		return ("MLXCX_OP_CREATE_CQ");
140 	case MLXCX_OP_DESTROY_CQ:
141 		return ("MLXCX_OP_DESTROY_CQ");
142 	case MLXCX_OP_QUERY_CQ:
143 		return ("MLXCX_OP_QUERY_CQ");
144 	case MLXCX_OP_MODIFY_CQ:
145 		return ("MLXCX_OP_MODIFY_CQ");
146 	case MLXCX_OP_CREATE_QP:
147 		return ("MLXCX_OP_CREATE_QP");
148 	case MLXCX_OP_DESTROY_QP:
149 		return ("MLXCX_OP_DESTROY_QP");
150 	case MLXCX_OP_RST2INIT_QP:
151 		return ("MLXCX_OP_RST2INIT_QP");
152 	case MLXCX_OP_INIT2RTR_QP:
153 		return ("MLXCX_OP_INIT2RTR_QP");
154 	case MLXCX_OP_RTR2RTS_QP:
155 		return ("MLXCX_OP_RTR2RTS_QP");
156 	case MLXCX_OP_RTS2RTS_QP:
157 		return ("MLXCX_OP_RTS2RTS_QP");
158 	case MLXCX_OP_SQERR2RTS_QP:
159 		return ("MLXCX_OP_SQERR2RTS_QP");
160 	case MLXCX_OP__2ERR_QP:
161 		return ("MLXCX_OP__2ERR_QP");
162 	case MLXCX_OP__2RST_QP:
163 		return ("MLXCX_OP__2RST_QP");
164 	case MLXCX_OP_QUERY_QP:
165 		return ("MLXCX_OP_QUERY_QP");
166 	case MLXCX_OP_SQD_RTS_QP:
167 		return ("MLXCX_OP_SQD_RTS_QP");
168 	case MLXCX_OP_INIT2INIT_QP:
169 		return ("MLXCX_OP_INIT2INIT_QP");
170 	case MLXCX_OP_CREATE_PSV:
171 		return ("MLXCX_OP_CREATE_PSV");
172 	case MLXCX_OP_DESTROY_PSV:
173 		return ("MLXCX_OP_DESTROY_PSV");
174 	case MLXCX_OP_CREATE_SRQ:
175 		return ("MLXCX_OP_CREATE_SRQ");
176 	case MLXCX_OP_DESTROY_SRQ:
177 		return ("MLXCX_OP_DESTROY_SRQ");
178 	case MLXCX_OP_QUERY_SRQ:
179 		return ("MLXCX_OP_QUERY_SRQ");
180 	case MLXCX_OP_ARM_RQ:
181 		return ("MLXCX_OP_ARM_RQ");
182 	case MLXCX_OP_CREATE_XRC_SRQ:
183 		return ("MLXCX_OP_CREATE_XRC_SRQ");
184 	case MLXCX_OP_DESTROY_XRC_SRQ:
185 		return ("MLXCX_OP_DESTROY_XRC_SRQ");
186 	case MLXCX_OP_QUERY_XRC_SRQ:
187 		return ("MLXCX_OP_QUERY_XRC_SRQ");
188 	case MLXCX_OP_ARM_XRC_SRQ:
189 		return ("MLXCX_OP_ARM_XRC_SRQ");
190 	case MLXCX_OP_CREATE_DCT:
191 		return ("MLXCX_OP_CREATE_DCT");
192 	case MLXCX_OP_DESTROY_DCT:
193 		return ("MLXCX_OP_DESTROY_DCT");
194 	case MLXCX_OP_DRAIN_DCT:
195 		return ("MLXCX_OP_DRAIN_DCT");
196 	case MLXCX_OP_QUERY_DCT:
197 		return ("MLXCX_OP_QUERY_DCT");
198 	case MLXCX_OP_ARM_DCT_FOR_KEY_VIOLATION:
199 		return ("MLXCX_OP_ARM_DCT_FOR_KEY_VIOLATION");
200 	case MLXCX_OP_CREATE_XRQ:
201 		return ("MLXCX_OP_CREATE_XRQ");
202 	case MLXCX_OP_DESTROY_XRQ:
203 		return ("MLXCX_OP_DESTROY_XRQ");
204 	case MLXCX_OP_QUERY_XRQ:
205 		return ("MLXCX_OP_QUERY_XRQ");
206 	case MLXCX_OP_CREATE_NVMF_BACKEND_CONTROLLER:
207 		return ("MLXCX_OP_CREATE_NVMF_BACKEND_CONTROLLER");
208 	case MLXCX_OP_DESTROY_NVMF_BACKEND_CONTROLLER:
209 		return ("MLXCX_OP_DESTROY_NVMF_BACKEND_CONTROLLER");
210 	case MLXCX_OP_QUERY_NVMF_BACKEND_CONTROLLER:
211 		return ("MLXCX_OP_QUERY_NVMF_BACKEND_CONTROLLER");
212 	case MLXCX_OP_ATTACH_NVMF_NAMESPACE:
213 		return ("MLXCX_OP_ATTACH_NVMF_NAMESPACE");
214 	case MLXCX_OP_DETACH_NVMF_NAMESPACE:
215 		return ("MLXCX_OP_DETACH_NVMF_NAMESPACE");
216 	case MLXCX_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
217 		return ("MLXCX_OP_QUERY_XRQ_DC_PARAMS_ENTRY");
218 	case MLXCX_OP_SET_XRQ_DC_PARAMS_ENTRY:
219 		return ("MLXCX_OP_SET_XRQ_DC_PARAMS_ENTRY");
220 	case MLXCX_OP_QUERY_XRQ_ERROR_PARAMS:
221 		return ("MLXCX_OP_QUERY_XRQ_ERROR_PARAMS");
222 	case MLXCX_OP_QUERY_VPORT_STATE:
223 		return ("MLXCX_OP_QUERY_VPORT_STATE");
224 	case MLXCX_OP_MODIFY_VPORT_STATE:
225 		return ("MLXCX_OP_MODIFY_VPORT_STATE");
226 	case MLXCX_OP_QUERY_ESW_VPORT_CONTEXT:
227 		return ("MLXCX_OP_QUERY_ESW_VPORT_CONTEXT");
228 	case MLXCX_OP_MODIFY_ESW_VPORT_CONTEXT:
229 		return ("MLXCX_OP_MODIFY_ESW_VPORT_CONTEXT");
230 	case MLXCX_OP_QUERY_NIC_VPORT_CONTEXT:
231 		return ("MLXCX_OP_QUERY_NIC_VPORT_CONTEXT");
232 	case MLXCX_OP_MODIFY_NIC_VPORT_CONTEXT:
233 		return ("MLXCX_OP_MODIFY_NIC_VPORT_CONTEXT");
234 	case MLXCX_OP_QUERY_ROCE_ADDRESS:
235 		return ("MLXCX_OP_QUERY_ROCE_ADDRESS");
236 	case MLXCX_OP_SET_ROCE_ADDRESS:
237 		return ("MLXCX_OP_SET_ROCE_ADDRESS");
238 	case MLXCX_OP_QUERY_HCA_VPORT_CONTEXT:
239 		return ("MLXCX_OP_QUERY_HCA_VPORT_CONTEXT");
240 	case MLXCX_OP_MODIFY_HCA_VPORT_CONTEXT:
241 		return ("MLXCX_OP_MODIFY_HCA_VPORT_CONTEXT");
242 	case MLXCX_OP_QUERY_HCA_VPORT_GID:
243 		return ("MLXCX_OP_QUERY_HCA_VPORT_GID");
244 	case MLXCX_OP_QUERY_HCA_VPORT_PKEY:
245 		return ("MLXCX_OP_QUERY_HCA_VPORT_PKEY");
246 	case MLXCX_OP_QUERY_VPORT_COUNTER:
247 		return ("MLXCX_OP_QUERY_VPORT_COUNTER");
248 	case MLXCX_OP_ALLOC_Q_COUNTER:
249 		return ("MLXCX_OP_ALLOC_Q_COUNTER");
250 	case MLXCX_OP_DEALLOC_Q_COUNTER:
251 		return ("MLXCX_OP_DEALLOC_Q_COUNTER");
252 	case MLXCX_OP_QUERY_Q_COUNTER:
253 		return ("MLXCX_OP_QUERY_Q_COUNTER");
254 	case MLXCX_OP_SET_PP_RATE_LIMIT:
255 		return ("MLXCX_OP_SET_PP_RATE_LIMIT");
256 	case MLXCX_OP_QUERY_PP_RATE_LIMIT:
257 		return ("MLXCX_OP_QUERY_PP_RATE_LIMIT");
258 	case MLXCX_OP_ALLOC_PD:
259 		return ("MLXCX_OP_ALLOC_PD");
260 	case MLXCX_OP_DEALLOC_PD:
261 		return ("MLXCX_OP_DEALLOC_PD");
262 	case MLXCX_OP_ALLOC_UAR:
263 		return ("MLXCX_OP_ALLOC_UAR");
264 	case MLXCX_OP_DEALLOC_UAR:
265 		return ("MLXCX_OP_DEALLOC_UAR");
266 	case MLXCX_OP_CONFIG_INT_MODERATION:
267 		return ("MLXCX_OP_CONFIG_INT_MODERATION");
268 	case MLXCX_OP_ACCESS_REG:
269 		return ("MLXCX_OP_ACCESS_REG");
270 	case MLXCX_OP_ATTACH_TO_MCG:
271 		return ("MLXCX_OP_ATTACH_TO_MCG");
272 	case MLXCX_OP_DETACH_FROM_MCG:
273 		return ("MLXCX_OP_DETACH_FROM_MCG");
274 	case MLXCX_OP_MAD_IFC:
275 		return ("MLXCX_OP_MAD_IFC");
276 	case MLXCX_OP_QUERY_MAD_DEMUX:
277 		return ("MLXCX_OP_QUERY_MAD_DEMUX");
278 	case MLXCX_OP_SET_MAD_DEMUX:
279 		return ("MLXCX_OP_SET_MAD_DEMUX");
280 	case MLXCX_OP_NOP:
281 		return ("MLXCX_OP_NOP");
282 	case MLXCX_OP_ALLOC_XRCD:
283 		return ("MLXCX_OP_ALLOC_XRCD");
284 	case MLXCX_OP_DEALLOC_XRCD:
285 		return ("MLXCX_OP_DEALLOC_XRCD");
286 	case MLXCX_OP_ALLOC_TRANSPORT_DOMAIN:
287 		return ("MLXCX_OP_ALLOC_TRANSPORT_DOMAIN");
288 	case MLXCX_OP_DEALLOC_TRANSPORT_DOMAIN:
289 		return ("MLXCX_OP_DEALLOC_TRANSPORT_DOMAIN");
290 	case MLXCX_OP_QUERY_CONG_STATUS:
291 		return ("MLXCX_OP_QUERY_CONG_STATUS");
292 	case MLXCX_OP_MODIFY_CONG_STATUS:
293 		return ("MLXCX_OP_MODIFY_CONG_STATUS");
294 	case MLXCX_OP_QUERY_CONG_PARAMS:
295 		return ("MLXCX_OP_QUERY_CONG_PARAMS");
296 	case MLXCX_OP_MODIFY_CONG_PARAMS:
297 		return ("MLXCX_OP_MODIFY_CONG_PARAMS");
298 	case MLXCX_OP_QUERY_CONG_STATISTICS:
299 		return ("MLXCX_OP_QUERY_CONG_STATISTICS");
300 	case MLXCX_OP_ADD_VXLAN_UDP_DPORT:
301 		return ("MLXCX_OP_ADD_VXLAN_UDP_DPORT");
302 	case MLXCX_OP_DELETE_VXLAN_UDP_DPORT:
303 		return ("MLXCX_OP_DELETE_VXLAN_UDP_DPORT");
304 	case MLXCX_OP_SET_L2_TABLE_ENTRY:
305 		return ("MLXCX_OP_SET_L2_TABLE_ENTRY");
306 	case MLXCX_OP_QUERY_L2_TABLE_ENTRY:
307 		return ("MLXCX_OP_QUERY_L2_TABLE_ENTRY");
308 	case MLXCX_OP_DELETE_L2_TABLE_ENTRY:
309 		return ("MLXCX_OP_DELETE_L2_TABLE_ENTRY");
310 	case MLXCX_OP_SET_WOL_ROL:
311 		return ("MLXCX_OP_SET_WOL_ROL");
312 	case MLXCX_OP_QUERY_WOL_ROL:
313 		return ("MLXCX_OP_QUERY_WOL_ROL");
314 	case MLXCX_OP_CREATE_TIR:
315 		return ("MLXCX_OP_CREATE_TIR");
316 	case MLXCX_OP_MODIFY_TIR:
317 		return ("MLXCX_OP_MODIFY_TIR");
318 	case MLXCX_OP_DESTROY_TIR:
319 		return ("MLXCX_OP_DESTROY_TIR");
320 	case MLXCX_OP_QUERY_TIR:
321 		return ("MLXCX_OP_QUERY_TIR");
322 	case MLXCX_OP_CREATE_SQ:
323 		return ("MLXCX_OP_CREATE_SQ");
324 	case MLXCX_OP_MODIFY_SQ:
325 		return ("MLXCX_OP_MODIFY_SQ");
326 	case MLXCX_OP_DESTROY_SQ:
327 		return ("MLXCX_OP_DESTROY_SQ");
328 	case MLXCX_OP_QUERY_SQ:
329 		return ("MLXCX_OP_QUERY_SQ");
330 	case MLXCX_OP_CREATE_RQ:
331 		return ("MLXCX_OP_CREATE_RQ");
332 	case MLXCX_OP_MODIFY_RQ:
333 		return ("MLXCX_OP_MODIFY_RQ");
334 	case MLXCX_OP_DESTROY_RQ:
335 		return ("MLXCX_OP_DESTROY_RQ");
336 	case MLXCX_OP_QUERY_RQ:
337 		return ("MLXCX_OP_QUERY_RQ");
338 	case MLXCX_OP_CREATE_RMP:
339 		return ("MLXCX_OP_CREATE_RMP");
340 	case MLXCX_OP_MODIFY_RMP:
341 		return ("MLXCX_OP_MODIFY_RMP");
342 	case MLXCX_OP_DESTROY_RMP:
343 		return ("MLXCX_OP_DESTROY_RMP");
344 	case MLXCX_OP_QUERY_RMP:
345 		return ("MLXCX_OP_QUERY_RMP");
346 	case MLXCX_OP_CREATE_TIS:
347 		return ("MLXCX_OP_CREATE_TIS");
348 	case MLXCX_OP_MODIFY_TIS:
349 		return ("MLXCX_OP_MODIFY_TIS");
350 	case MLXCX_OP_DESTROY_TIS:
351 		return ("MLXCX_OP_DESTROY_TIS");
352 	case MLXCX_OP_QUERY_TIS:
353 		return ("MLXCX_OP_QUERY_TIS");
354 	case MLXCX_OP_CREATE_RQT:
355 		return ("MLXCX_OP_CREATE_RQT");
356 	case MLXCX_OP_MODIFY_RQT:
357 		return ("MLXCX_OP_MODIFY_RQT");
358 	case MLXCX_OP_DESTROY_RQT:
359 		return ("MLXCX_OP_DESTROY_RQT");
360 	case MLXCX_OP_QUERY_RQT:
361 		return ("MLXCX_OP_QUERY_RQT");
362 	case MLXCX_OP_SET_FLOW_TABLE_ROOT:
363 		return ("MLXCX_OP_SET_FLOW_TABLE_ROOT");
364 	case MLXCX_OP_CREATE_FLOW_TABLE:
365 		return ("MLXCX_OP_CREATE_FLOW_TABLE");
366 	case MLXCX_OP_DESTROY_FLOW_TABLE:
367 		return ("MLXCX_OP_DESTROY_FLOW_TABLE");
368 	case MLXCX_OP_QUERY_FLOW_TABLE:
369 		return ("MLXCX_OP_QUERY_FLOW_TABLE");
370 	case MLXCX_OP_CREATE_FLOW_GROUP:
371 		return ("MLXCX_OP_CREATE_FLOW_GROUP");
372 	case MLXCX_OP_DESTROY_FLOW_GROUP:
373 		return ("MLXCX_OP_DESTROY_FLOW_GROUP");
374 	case MLXCX_OP_QUERY_FLOW_GROUP:
375 		return ("MLXCX_OP_QUERY_FLOW_GROUP");
376 	case MLXCX_OP_SET_FLOW_TABLE_ENTRY:
377 		return ("MLXCX_OP_SET_FLOW_TABLE_ENTRY");
378 	case MLXCX_OP_QUERY_FLOW_TABLE_ENTRY:
379 		return ("MLXCX_OP_QUERY_FLOW_TABLE_ENTRY");
380 	case MLXCX_OP_DELETE_FLOW_TABLE_ENTRY:
381 		return ("MLXCX_OP_DELETE_FLOW_TABLE_ENTRY");
382 	case MLXCX_OP_ALLOC_FLOW_COUNTER:
383 		return ("MLXCX_OP_ALLOC_FLOW_COUNTER");
384 	case MLXCX_OP_DEALLOC_FLOW_COUNTER:
385 		return ("MLXCX_OP_DEALLOC_FLOW_COUNTER");
386 	case MLXCX_OP_QUERY_FLOW_COUNTER:
387 		return ("MLXCX_OP_QUERY_FLOW_COUNTER");
388 	case MLXCX_OP_MODIFY_FLOW_TABLE:
389 		return ("MLXCX_OP_MODIFY_FLOW_TABLE");
390 	case MLXCX_OP_ALLOC_ENCAP_HEADER:
391 		return ("MLXCX_OP_ALLOC_ENCAP_HEADER");
392 	case MLXCX_OP_DEALLOC_ENCAP_HEADER:
393 		return ("MLXCX_OP_DEALLOC_ENCAP_HEADER");
394 	case MLXCX_OP_QUERY_ENCAP_HEADER:
395 		return ("MLXCX_OP_QUERY_ENCAP_HEADER");
396 	default:
397 		return ("Unknown Opcode");
398 	}
399 }
400 
401 const char *
mlxcx_port_status_string(mlxcx_port_status_t st)402 mlxcx_port_status_string(mlxcx_port_status_t st)
403 {
404 	switch (st) {
405 	case MLXCX_PORT_STATUS_UP:
406 		return ("UP");
407 	case MLXCX_PORT_STATUS_DOWN:
408 		return ("DOWN");
409 	case MLXCX_PORT_STATUS_UP_ONCE:
410 		return ("UP_ONCE");
411 	case MLXCX_PORT_STATUS_DISABLED:
412 		return ("DISABLED");
413 	default:
414 		return ("UNKNOWN");
415 	}
416 }
417 
418 void
mlxcx_eth_proto_to_string(mlxcx_eth_proto_t p,char * buf,size_t size)419 mlxcx_eth_proto_to_string(mlxcx_eth_proto_t p, char *buf, size_t size)
420 {
421 	if (p & MLXCX_PROTO_SGMII)
422 		(void) strlcat(buf, "SGMII|", size);
423 	if (p & MLXCX_PROTO_1000BASE_KX)
424 		(void) strlcat(buf, "1000BASE_KX|", size);
425 	if (p & MLXCX_PROTO_10GBASE_CX4)
426 		(void) strlcat(buf, "10GBASE_CX4|", size);
427 	if (p & MLXCX_PROTO_10GBASE_KX4)
428 		(void) strlcat(buf, "10GBASE_KX4|", size);
429 	if (p & MLXCX_PROTO_10GBASE_KR)
430 		(void) strlcat(buf, "10GBASE_KR|", size);
431 	if (p & MLXCX_PROTO_40GBASE_CR4)
432 		(void) strlcat(buf, "40GBASE_CR4|", size);
433 	if (p & MLXCX_PROTO_40GBASE_KR4)
434 		(void) strlcat(buf, "40GBASE_KR4|", size);
435 	if (p & MLXCX_PROTO_SGMII_100BASE)
436 		(void) strlcat(buf, "SGMII_100BASE|", size);
437 	if (p & MLXCX_PROTO_10GBASE_CR)
438 		(void) strlcat(buf, "10GBASE_CR|", size);
439 	if (p & MLXCX_PROTO_10GBASE_SR)
440 		(void) strlcat(buf, "10GBASE_SR|", size);
441 	if (p & MLXCX_PROTO_10GBASE_ER_LR)
442 		(void) strlcat(buf, "10GBASE_ER_LR|", size);
443 	if (p & MLXCX_PROTO_40GBASE_SR4)
444 		(void) strlcat(buf, "40GBASE_SR4|", size);
445 	if (p & MLXCX_PROTO_40GBASE_LR4_ER4)
446 		(void) strlcat(buf, "40GBASE_LR4_ER4|", size);
447 	if (p & MLXCX_PROTO_50GBASE_SR2)
448 		(void) strlcat(buf, "50GBASE_SR2|", size);
449 	if (p & MLXCX_PROTO_100GBASE_CR4)
450 		(void) strlcat(buf, "100GBASE_CR4|", size);
451 	if (p & MLXCX_PROTO_100GBASE_SR4)
452 		(void) strlcat(buf, "100GBASE_SR4|", size);
453 	if (p & MLXCX_PROTO_100GBASE_KR4)
454 		(void) strlcat(buf, "100GBASE_KR4|", size);
455 	if (p & MLXCX_PROTO_25GBASE_CR)
456 		(void) strlcat(buf, "25GBASE_CR|", size);
457 	if (p & MLXCX_PROTO_25GBASE_KR)
458 		(void) strlcat(buf, "25GBASE_KR|", size);
459 	if (p & MLXCX_PROTO_25GBASE_SR)
460 		(void) strlcat(buf, "25GBASE_SR|", size);
461 	if (p & MLXCX_PROTO_50GBASE_CR2)
462 		(void) strlcat(buf, "50GBASE_CR2|", size);
463 	/* Chop off the trailing '|' */
464 	if (strlen(buf) > 0)
465 		buf[strlen(buf) - 1] = '\0';
466 }
467 
468 void
mlxcx_cmd_queue_fini(mlxcx_t * mlxp)469 mlxcx_cmd_queue_fini(mlxcx_t *mlxp)
470 {
471 	mlxcx_cmd_queue_t *cmd = &mlxp->mlx_cmd;
472 
473 	if (cmd->mcmd_tokens != NULL) {
474 		id_space_destroy(cmd->mcmd_tokens);
475 		cmd->mcmd_tokens = NULL;
476 	}
477 
478 	if (cmd->mcmd_taskq != NULL) {
479 		ddi_taskq_destroy(cmd->mcmd_taskq);
480 		cmd->mcmd_taskq = NULL;
481 	}
482 
483 	cv_destroy(&cmd->mcmd_cv);
484 	mutex_destroy(&cmd->mcmd_lock);
485 
486 	mlxcx_dma_free(&cmd->mcmd_dma);
487 }
488 
489 boolean_t
mlxcx_cmd_queue_init(mlxcx_t * mlxp)490 mlxcx_cmd_queue_init(mlxcx_t *mlxp)
491 {
492 	uint32_t tmp, cmd_low, cmd_high, i;
493 	mlxcx_cmd_queue_t *cmd = &mlxp->mlx_cmd;
494 	char buf[32];
495 	char tq_name[TASKQ_NAMELEN];
496 	const ddi_dma_cookie_t *ck;
497 
498 	ddi_device_acc_attr_t acc;
499 	ddi_dma_attr_t attr;
500 
501 	tmp = mlxcx_get32(mlxp, MLXCX_ISS_FIRMWARE);
502 	mlxp->mlx_fw_maj = MLXCX_ISS_FW_MAJOR(tmp);
503 	mlxp->mlx_fw_min = MLXCX_ISS_FW_MINOR(tmp);
504 
505 	tmp = mlxcx_get32(mlxp, MLXCX_ISS_FW_CMD);
506 	mlxp->mlx_fw_rev = MLXCX_ISS_FW_REV(tmp);
507 	mlxp->mlx_cmd_rev = MLXCX_ISS_CMD_REV(tmp);
508 
509 	if (mlxp->mlx_cmd_rev != MLXCX_CMD_REVISION) {
510 		mlxcx_warn(mlxp, "found unsupported command revision: %u, "
511 		    "expected %u", mlxp->mlx_cmd_rev, MLXCX_CMD_REVISION);
512 		return (B_FALSE);
513 	}
514 
515 	cmd_low = mlxcx_get32(mlxp, MLXCX_ISS_CMD_LOW);
516 	cmd->mcmd_size_l2 = MLXCX_ISS_CMDQ_SIZE(cmd_low);
517 	cmd->mcmd_stride_l2 = MLXCX_ISS_CMDQ_STRIDE(cmd_low);
518 	cmd->mcmd_size = 1U << cmd->mcmd_size_l2;
519 
520 	if (cmd->mcmd_size > MLXCX_CMD_MAX) {
521 		mlxcx_warn(mlxp, "command queue size %u is too "
522 		    "large. Maximum is %u", cmd->mcmd_size, MLXCX_CMD_MAX);
523 		return (B_FALSE);
524 	}
525 
526 	cmd->mcmd_mask = (uint32_t)((1ULL << cmd->mcmd_size) - 1);
527 
528 	mutex_init(&cmd->mcmd_lock, NULL, MUTEX_DRIVER, NULL);
529 	cv_init(&cmd->mcmd_cv, NULL, CV_DRIVER, NULL);
530 
531 	(void) snprintf(buf, sizeof (buf), "mlxcx_tokens_%d", mlxp->mlx_inst);
532 	if ((cmd->mcmd_tokens = id_space_create(buf, 1, UINT8_MAX)) == NULL) {
533 		mlxcx_warn(mlxp, "failed to allocate token id space");
534 		mlxcx_cmd_queue_fini(mlxp);
535 		return (B_FALSE);
536 	}
537 
538 	(void) snprintf(tq_name, sizeof (tq_name), "cmdq_%d", mlxp->mlx_inst);
539 	if ((cmd->mcmd_taskq = ddi_taskq_create(mlxp->mlx_dip, tq_name, 1,
540 	    TASKQ_DEFAULTPRI, 0)) == NULL) {
541 		mlxcx_warn(mlxp, "failed to create command queue task queue");
542 		mlxcx_cmd_queue_fini(mlxp);
543 		return (B_FALSE);
544 	}
545 
546 	mlxcx_dma_acc_attr(mlxp, &acc);
547 	mlxcx_dma_page_attr(mlxp, &attr);
548 
549 	if (!mlxcx_dma_alloc(mlxp, &cmd->mcmd_dma, &attr, &acc, B_TRUE,
550 	    MLXCX_CMD_DMA_PAGE_SIZE, B_TRUE)) {
551 		mlxcx_warn(mlxp, "failed to allocate command dma buffer");
552 		mlxcx_cmd_queue_fini(mlxp);
553 		return (B_FALSE);
554 	}
555 
556 	ck = mlxcx_dma_cookie_one(&cmd->mcmd_dma);
557 	cmd_high = (uint32_t)(ck->dmac_laddress >> 32);
558 	cmd_low = (uint32_t)(ck->dmac_laddress & UINT32_MAX);
559 
560 	mlxcx_put32(mlxp, MLXCX_ISS_CMD_HIGH, cmd_high);
561 	mlxcx_put32(mlxp, MLXCX_ISS_CMD_LOW, cmd_low);
562 
563 	/*
564 	 * Before this is ready, the initializing bit must become zero.
565 	 */
566 	for (i = 0; i < mlxcx_cmd_init_trys; i++) {
567 		uint32_t init = mlxcx_get32(mlxp, MLXCX_ISS_INIT);
568 
569 		if (MLXCX_ISS_INITIALIZING(init) == 0)
570 			break;
571 		delay(drv_usectohz(mlxcx_cmd_init_delay));
572 	}
573 	if (i == mlxcx_cmd_init_trys) {
574 		mlxcx_warn(mlxp, "timed out initializing command queue");
575 		mlxcx_cmd_queue_fini(mlxp);
576 		return (B_FALSE);
577 	}
578 
579 	/*
580 	 * start in polling mode.
581 	 */
582 	mlxcx_cmd_eq_disable(mlxp);
583 
584 	return (B_TRUE);
585 }
586 
587 void
mlxcx_cmd_eq_enable(mlxcx_t * mlxp)588 mlxcx_cmd_eq_enable(mlxcx_t *mlxp)
589 {
590 	mlxp->mlx_cmd.mcmd_polled = B_FALSE;
591 }
592 
593 void
mlxcx_cmd_eq_disable(mlxcx_t * mlxp)594 mlxcx_cmd_eq_disable(mlxcx_t *mlxp)
595 {
596 	mlxp->mlx_cmd.mcmd_polled = B_TRUE;
597 }
598 
599 static void
mlxcx_cmd_in_header_init(mlxcx_cmd_t * cmd,mlxcx_cmd_in_t * in,mlxcx_cmd_op_t op,uint16_t mod)600 mlxcx_cmd_in_header_init(mlxcx_cmd_t *cmd, mlxcx_cmd_in_t *in,
601     mlxcx_cmd_op_t op, uint16_t mod)
602 {
603 	ASSERT3U(op, <=, UINT16_MAX);
604 	in->mci_opcode = to_be16(op);
605 	in->mci_op_mod = to_be16(mod);
606 	cmd->mlcmd_op = op;
607 }
608 
609 static boolean_t
mlxcx_cmd_mbox_alloc(mlxcx_t * mlxp,list_t * listp,uint8_t nblocks)610 mlxcx_cmd_mbox_alloc(mlxcx_t *mlxp, list_t *listp, uint8_t nblocks)
611 {
612 	uint8_t i;
613 	ddi_device_acc_attr_t acc;
614 	ddi_dma_attr_t attr;
615 
616 	mlxcx_dma_acc_attr(mlxp, &acc);
617 	mlxcx_dma_page_attr(mlxp, &attr);
618 
619 	for (i = 0; i < nblocks; i++) {
620 		mlxcx_cmd_mbox_t *mbox;
621 
622 		mbox = kmem_zalloc(sizeof (*mbox), KM_SLEEP);
623 		if (!mlxcx_dma_alloc(mlxp, &mbox->mlbox_dma, &attr, &acc,
624 		    B_TRUE, sizeof (mlxcx_cmd_mailbox_t), B_TRUE)) {
625 			mlxcx_warn(mlxp, "failed to allocate mailbox dma "
626 			    "buffer");
627 			kmem_free(mbox, sizeof (*mbox));
628 			/*
629 			 * mlxcx_cmd_fini will clean up any mboxes that we
630 			 * already placed onto listp.
631 			 */
632 			return (B_FALSE);
633 		}
634 		mbox->mlbox_data = (void *)mbox->mlbox_dma.mxdb_va;
635 		list_insert_tail(listp, mbox);
636 	}
637 
638 	return (B_TRUE);
639 }
640 
641 static void
mlxcx_cmd_mbox_free(mlxcx_cmd_mbox_t * mbox)642 mlxcx_cmd_mbox_free(mlxcx_cmd_mbox_t *mbox)
643 {
644 	mlxcx_dma_free(&mbox->mlbox_dma);
645 	kmem_free(mbox, sizeof (mlxcx_cmd_mbox_t));
646 }
647 
648 static void
mlxcx_cmd_fini(mlxcx_t * mlxp,mlxcx_cmd_t * cmd)649 mlxcx_cmd_fini(mlxcx_t *mlxp, mlxcx_cmd_t *cmd)
650 {
651 	mlxcx_cmd_mbox_t *mbox;
652 
653 	while ((mbox = list_remove_head(&cmd->mlcmd_mbox_out)) != NULL) {
654 		mlxcx_cmd_mbox_free(mbox);
655 	}
656 	list_destroy(&cmd->mlcmd_mbox_out);
657 	while ((mbox = list_remove_head(&cmd->mlcmd_mbox_in)) != NULL) {
658 		mlxcx_cmd_mbox_free(mbox);
659 	}
660 	list_destroy(&cmd->mlcmd_mbox_in);
661 	id_free(mlxp->mlx_cmd.mcmd_tokens, cmd->mlcmd_token);
662 	cv_destroy(&cmd->mlcmd_cv);
663 	mutex_destroy(&cmd->mlcmd_lock);
664 }
665 
666 static void
mlxcx_cmd_init(mlxcx_t * mlxp,mlxcx_cmd_t * cmd)667 mlxcx_cmd_init(mlxcx_t *mlxp, mlxcx_cmd_t *cmd)
668 {
669 	bzero(cmd, sizeof (*cmd));
670 	mutex_init(&cmd->mlcmd_lock, NULL, MUTEX_DRIVER,
671 	    DDI_INTR_PRI(mlxp->mlx_async_intr_pri));
672 	cv_init(&cmd->mlcmd_cv, NULL, CV_DRIVER, NULL);
673 	cmd->mlcmd_token = id_alloc(mlxp->mlx_cmd.mcmd_tokens);
674 	cmd->mlcmd_poll = mlxp->mlx_cmd.mcmd_polled;
675 	list_create(&cmd->mlcmd_mbox_in, sizeof (mlxcx_cmd_mbox_t),
676 	    offsetof(mlxcx_cmd_mbox_t, mlbox_node));
677 	list_create(&cmd->mlcmd_mbox_out, sizeof (mlxcx_cmd_mbox_t),
678 	    offsetof(mlxcx_cmd_mbox_t, mlbox_node));
679 }
680 
681 static void
mlxcx_cmd_prep_input(mlxcx_cmd_ent_t * ent,mlxcx_cmd_t * cmd)682 mlxcx_cmd_prep_input(mlxcx_cmd_ent_t *ent, mlxcx_cmd_t *cmd)
683 {
684 	uint32_t rem = cmd->mlcmd_inlen;
685 	uint8_t i;
686 	const void *in = cmd->mlcmd_in;
687 	uint32_t copy;
688 	mlxcx_cmd_mbox_t *mbox;
689 	const ddi_dma_cookie_t *ck;
690 
691 	copy = MIN(MLXCX_CMD_INLINE_INPUT_LEN, rem);
692 	bcopy(in, ent->mce_input, copy);
693 
694 	rem -= copy;
695 	in += copy;
696 
697 	if (rem == 0) {
698 		ent->mce_in_mbox = to_be64(0);
699 		VERIFY3U(cmd->mlcmd_nboxes_in, ==, 0);
700 		return;
701 	}
702 
703 	mbox = list_head(&cmd->mlcmd_mbox_in);
704 	ck = mlxcx_dma_cookie_one(&mbox->mlbox_dma);
705 	ent->mce_in_mbox = to_be64(ck->dmac_laddress);
706 	for (i = 0; mbox != NULL;
707 	    mbox = list_next(&cmd->mlcmd_mbox_in, mbox), i++) {
708 		mlxcx_cmd_mbox_t *next;
709 		mlxcx_cmd_mailbox_t *mp = mbox->mlbox_data;
710 
711 		copy = MIN(MLXCX_CMD_MAILBOX_LEN, rem);
712 		bcopy(in, mp->mlxb_data, copy);
713 		rem -= copy;
714 		in += copy;
715 
716 		mp->mlxb_token = cmd->mlcmd_token;
717 		mp->mlxb_blockno = to_be32(i);
718 
719 		next = list_next(&cmd->mlcmd_mbox_in, mbox);
720 		if (next == NULL) {
721 			mp->mlxb_nextp = to_be64(0);
722 		} else {
723 			ck = mlxcx_dma_cookie_one(&next->mlbox_dma);
724 			mp->mlxb_nextp = to_be64(ck->dmac_laddress);
725 		}
726 		MLXCX_DMA_SYNC(mbox->mlbox_dma, DDI_DMA_SYNC_FORDEV);
727 	}
728 	VERIFY3U(i, ==, cmd->mlcmd_nboxes_in);
729 	VERIFY0(rem);
730 }
731 
732 static void
mlxcx_cmd_prep_output(mlxcx_cmd_ent_t * ent,mlxcx_cmd_t * cmd)733 mlxcx_cmd_prep_output(mlxcx_cmd_ent_t *ent, mlxcx_cmd_t *cmd)
734 {
735 	uint8_t i;
736 	mlxcx_cmd_mbox_t *mbox;
737 	const ddi_dma_cookie_t *ck;
738 
739 	if (cmd->mlcmd_nboxes_out == 0) {
740 		ent->mce_out_mbox = to_be64(0);
741 		return;
742 	}
743 
744 	mbox = list_head(&cmd->mlcmd_mbox_out);
745 	ck = mlxcx_dma_cookie_one(&mbox->mlbox_dma);
746 	ent->mce_out_mbox = to_be64(ck->dmac_laddress);
747 	for (i = 0, mbox = list_head(&cmd->mlcmd_mbox_out); mbox != NULL;
748 	    mbox = list_next(&cmd->mlcmd_mbox_out, mbox), i++) {
749 		mlxcx_cmd_mbox_t *next;
750 		mlxcx_cmd_mailbox_t *mp = mbox->mlbox_data;
751 
752 		mp->mlxb_token = cmd->mlcmd_token;
753 		mp->mlxb_blockno = to_be32(i);
754 
755 		next = list_next(&cmd->mlcmd_mbox_out, mbox);
756 		if (next == NULL) {
757 			mp->mlxb_nextp = to_be64(0);
758 		} else {
759 			ck = mlxcx_dma_cookie_one(&next->mlbox_dma);
760 			mp->mlxb_nextp = to_be64(ck->dmac_laddress);
761 		}
762 		MLXCX_DMA_SYNC(mbox->mlbox_dma, DDI_DMA_SYNC_FORDEV);
763 	}
764 	VERIFY3U(i, ==, cmd->mlcmd_nboxes_out);
765 }
766 
767 static void
mlxcx_cmd_copy_output(mlxcx_cmd_ent_t * ent,mlxcx_cmd_t * cmd)768 mlxcx_cmd_copy_output(mlxcx_cmd_ent_t *ent, mlxcx_cmd_t *cmd)
769 {
770 	void *out = cmd->mlcmd_out;
771 	uint32_t rem = cmd->mlcmd_outlen;
772 	uint32_t copy;
773 	mlxcx_cmd_mbox_t *mbox;
774 
775 	copy = MIN(rem, MLXCX_CMD_INLINE_OUTPUT_LEN);
776 	bcopy(ent->mce_output, out, copy);
777 	out += copy;
778 	rem -= copy;
779 
780 	if (rem == 0) {
781 		VERIFY0(cmd->mlcmd_nboxes_out);
782 		return;
783 	}
784 
785 	for (mbox = list_head(&cmd->mlcmd_mbox_out); mbox != NULL;
786 	    mbox = list_next(&cmd->mlcmd_mbox_out, mbox)) {
787 		MLXCX_DMA_SYNC(mbox->mlbox_dma, DDI_DMA_SYNC_FORKERNEL);
788 		copy = MIN(MLXCX_CMD_MAILBOX_LEN, rem);
789 		bcopy(mbox->mlbox_data->mlxb_data, out, copy);
790 		out += copy;
791 		rem -= copy;
792 	}
793 	VERIFY0(rem);
794 }
795 
796 static uint_t
mlxcx_cmd_reserve_slot(mlxcx_cmd_queue_t * cmdq)797 mlxcx_cmd_reserve_slot(mlxcx_cmd_queue_t *cmdq)
798 {
799 	uint_t slot;
800 
801 	mutex_enter(&cmdq->mcmd_lock);
802 	slot = ddi_ffs(cmdq->mcmd_mask);
803 	while (slot == 0) {
804 		cv_wait(&cmdq->mcmd_cv, &cmdq->mcmd_lock);
805 		slot = ddi_ffs(cmdq->mcmd_mask);
806 	}
807 
808 	cmdq->mcmd_mask &= ~(1U << --slot);
809 
810 	ASSERT3P(cmdq->mcmd_active[slot], ==, NULL);
811 
812 	mutex_exit(&cmdq->mcmd_lock);
813 
814 	return (slot);
815 }
816 
817 static void
mlxcx_cmd_release_slot(mlxcx_cmd_queue_t * cmdq,uint_t slot)818 mlxcx_cmd_release_slot(mlxcx_cmd_queue_t *cmdq, uint_t slot)
819 {
820 	mutex_enter(&cmdq->mcmd_lock);
821 	cmdq->mcmd_mask |= 1U << slot;
822 	cv_broadcast(&cmdq->mcmd_cv);
823 	mutex_exit(&cmdq->mcmd_lock);
824 }
825 
826 static void
mlxcx_cmd_done(mlxcx_cmd_t * cmd,uint_t slot)827 mlxcx_cmd_done(mlxcx_cmd_t *cmd, uint_t slot)
828 {
829 	mlxcx_t *mlxp = cmd->mlcmd_mlxp;
830 	mlxcx_cmd_queue_t *cmdq = &mlxp->mlx_cmd;
831 	mlxcx_cmd_ent_t *ent;
832 
833 	/*
834 	 * Command is done. Save relevant data. Once we broadcast on the CV and
835 	 * drop the lock, we must not touch it again.
836 	 */
837 	MLXCX_DMA_SYNC(cmdq->mcmd_dma, DDI_DMA_SYNC_FORKERNEL);
838 
839 	ent = (mlxcx_cmd_ent_t *)(cmdq->mcmd_dma.mxdb_va +
840 	    (slot << cmdq->mcmd_stride_l2));
841 
842 	mutex_enter(&cmd->mlcmd_lock);
843 	cmd->mlcmd_status = MLXCX_CMD_STATUS(ent->mce_status);
844 	if (cmd->mlcmd_status == 0)
845 		mlxcx_cmd_copy_output(ent, cmd);
846 
847 	cmd->mlcmd_state = MLXCX_CMD_S_DONE;
848 	cv_broadcast(&cmd->mlcmd_cv);
849 	mutex_exit(&cmd->mlcmd_lock);
850 
851 	cmdq->mcmd_active[slot] = NULL;
852 	mlxcx_cmd_release_slot(cmdq, slot);
853 }
854 
855 static void
mlxcx_cmd_taskq(void * arg)856 mlxcx_cmd_taskq(void *arg)
857 {
858 	mlxcx_cmd_t *cmd = arg;
859 	mlxcx_t *mlxp = cmd->mlcmd_mlxp;
860 	mlxcx_cmd_queue_t *cmdq = &mlxp->mlx_cmd;
861 	mlxcx_cmd_ent_t *ent;
862 	uint_t poll, slot;
863 
864 	ASSERT3S(cmd->mlcmd_op, !=, 0);
865 
866 	slot = mlxcx_cmd_reserve_slot(cmdq);
867 	ent = (mlxcx_cmd_ent_t *)(cmdq->mcmd_dma.mxdb_va +
868 	    (slot << cmdq->mcmd_stride_l2));
869 
870 	cmdq->mcmd_active[slot] = cmd;
871 
872 	/*
873 	 * Command queue is currently ours as we set busy.
874 	 */
875 	bzero(ent, sizeof (*ent));
876 	ent->mce_type = MLXCX_CMD_TRANSPORT_PCI;
877 	ent->mce_in_length = to_be32(cmd->mlcmd_inlen);
878 	ent->mce_out_length = to_be32(cmd->mlcmd_outlen);
879 	ent->mce_token = cmd->mlcmd_token;
880 	ent->mce_sig = 0;
881 	ent->mce_status = MLXCX_CMD_HW_OWNED;
882 	mlxcx_cmd_prep_input(ent, cmd);
883 	mlxcx_cmd_prep_output(ent, cmd);
884 	MLXCX_DMA_SYNC(cmdq->mcmd_dma, DDI_DMA_SYNC_FORDEV);
885 
886 	mlxcx_put32(mlxp, MLXCX_ISS_CMD_DOORBELL, 1 << slot);
887 
888 	if (!cmd->mlcmd_poll)
889 		return;
890 
891 	for (poll = 0; poll < mlxcx_cmd_tries; poll++) {
892 		delay(drv_usectohz(mlxcx_cmd_delay));
893 		MLXCX_DMA_SYNC(cmdq->mcmd_dma, DDI_DMA_SYNC_FORKERNEL);
894 		if ((ent->mce_status & MLXCX_CMD_HW_OWNED) == 0)
895 			break;
896 	}
897 
898 	/*
899 	 * Command is done (or timed out). Save relevant data. Once we broadcast
900 	 * on the CV and drop the lock, we must not touch the cmd again.
901 	 */
902 
903 	if (poll == mlxcx_cmd_tries) {
904 		mutex_enter(&cmd->mlcmd_lock);
905 		cmd->mlcmd_status = MLXCX_CMD_R_TIMEOUT;
906 		cmd->mlcmd_state = MLXCX_CMD_S_ERROR;
907 		cv_broadcast(&cmd->mlcmd_cv);
908 		mutex_exit(&cmd->mlcmd_lock);
909 
910 		mlxcx_fm_ereport(mlxp, DDI_FM_DEVICE_NO_RESPONSE);
911 
912 		cmdq->mcmd_active[slot] = NULL;
913 		mlxcx_cmd_release_slot(cmdq, slot);
914 
915 		return;
916 	}
917 
918 	mlxcx_cmd_done(cmd, slot);
919 }
920 
921 void
mlxcx_cmd_completion(mlxcx_t * mlxp,mlxcx_eventq_ent_t * ent)922 mlxcx_cmd_completion(mlxcx_t *mlxp, mlxcx_eventq_ent_t *ent)
923 {
924 	mlxcx_cmd_queue_t *cmdq = &mlxp->mlx_cmd;
925 	mlxcx_evdata_cmd_completion_t *eqe_cmd = &ent->mleqe_cmd_completion;
926 	mlxcx_cmd_t *cmd;
927 	uint32_t comp_vec = from_be32(eqe_cmd->mled_cmd_completion_vec);
928 	uint_t slot;
929 
930 	DTRACE_PROBE2(cmd_event, mlxcx_t *, mlxp,
931 	    mlxcx_evdata_cmd_completion_t *, eqe_cmd);
932 
933 	while ((slot = ddi_ffs(comp_vec)) != 0) {
934 		comp_vec &= ~(1U << --slot);
935 
936 		cmd = cmdq->mcmd_active[slot];
937 		if (cmd->mlcmd_poll)
938 			continue;
939 
940 		mlxcx_cmd_done(cmd, slot);
941 	}
942 }
943 
944 static boolean_t
mlxcx_cmd_send(mlxcx_t * mlxp,mlxcx_cmd_t * cmd,const void * in,uint32_t inlen,void * out,uint32_t outlen)945 mlxcx_cmd_send(mlxcx_t *mlxp, mlxcx_cmd_t *cmd, const void *in, uint32_t inlen,
946     void *out, uint32_t outlen)
947 {
948 	if (inlen > MLXCX_CMD_INLINE_INPUT_LEN) {
949 		uint32_t need = inlen - MLXCX_CMD_INLINE_INPUT_LEN;
950 		uint8_t nblocks;
951 
952 		if (need / MLXCX_CMD_MAILBOX_LEN + 1 > UINT8_MAX) {
953 			mlxcx_warn(mlxp, "requested too many input blocks for "
954 			    "%u byte input len", inlen);
955 			return (B_FALSE);
956 		}
957 
958 		nblocks = need / MLXCX_CMD_MAILBOX_LEN + 1;
959 		if (!mlxcx_cmd_mbox_alloc(mlxp, &cmd->mlcmd_mbox_in, nblocks)) {
960 			mlxcx_warn(mlxp, "failed to allocate %u blocks of "
961 			    "input mailbox", nblocks);
962 			return (B_FALSE);
963 		}
964 		cmd->mlcmd_nboxes_in = nblocks;
965 	}
966 
967 	if (outlen > MLXCX_CMD_INLINE_OUTPUT_LEN) {
968 		uint32_t need = outlen - MLXCX_CMD_INLINE_OUTPUT_LEN;
969 		uint8_t nblocks;
970 
971 		if (need / MLXCX_CMD_MAILBOX_LEN + 1 > UINT8_MAX) {
972 			mlxcx_warn(mlxp, "requested too many output blocks for "
973 			    "%u byte output len", outlen);
974 			return (B_FALSE);
975 		}
976 
977 		nblocks = need / MLXCX_CMD_MAILBOX_LEN + 1;
978 		if (!mlxcx_cmd_mbox_alloc(mlxp, &cmd->mlcmd_mbox_out,
979 		    nblocks)) {
980 			mlxcx_warn(mlxp, "failed to allocate %u blocks of "
981 			    "output mailbox", nblocks);
982 			return (B_FALSE);
983 		}
984 		cmd->mlcmd_nboxes_out = nblocks;
985 	}
986 
987 	cmd->mlcmd_in = in;
988 	cmd->mlcmd_inlen = inlen;
989 	cmd->mlcmd_out = out;
990 	cmd->mlcmd_outlen = outlen;
991 	cmd->mlcmd_mlxp = mlxp;
992 
993 	/*
994 	 * Now that all allocations have been done, all that remains is for us
995 	 * to dispatch the request to process this to the taskq for it to be
996 	 * processed.
997 	 */
998 	if (ddi_taskq_dispatch(mlxp->mlx_cmd.mcmd_taskq, mlxcx_cmd_taskq, cmd,
999 	    DDI_SLEEP) != DDI_SUCCESS) {
1000 		mlxcx_warn(mlxp, "failed to submit command to taskq");
1001 		return (B_FALSE);
1002 	}
1003 
1004 	return (B_TRUE);
1005 }
1006 
1007 static void
mlxcx_cmd_wait(mlxcx_cmd_t * cmd)1008 mlxcx_cmd_wait(mlxcx_cmd_t *cmd)
1009 {
1010 	mutex_enter(&cmd->mlcmd_lock);
1011 	while (cmd->mlcmd_state == 0) {
1012 		cv_wait(&cmd->mlcmd_cv, &cmd->mlcmd_lock);
1013 	}
1014 	mutex_exit(&cmd->mlcmd_lock);
1015 }
1016 
1017 static boolean_t
mlxcx_cmd_evaluate(mlxcx_t * mlxp,mlxcx_cmd_t * cmd)1018 mlxcx_cmd_evaluate(mlxcx_t *mlxp, mlxcx_cmd_t *cmd)
1019 {
1020 	mlxcx_cmd_out_t *out;
1021 
1022 	if ((cmd->mlcmd_state & MLXCX_CMD_S_ERROR) != 0) {
1023 		mlxcx_warn(mlxp, "command %s (0x%x) failed due to an internal "
1024 		    "driver error",
1025 		    mlxcx_cmd_opcode_string(cmd->mlcmd_op),
1026 		    cmd->mlcmd_op);
1027 		return (B_FALSE);
1028 	}
1029 
1030 	if (cmd->mlcmd_status != 0) {
1031 		mlxcx_warn(mlxp, "command %s (0x%x) failed with command queue "
1032 		    "error 0x%x",
1033 		    mlxcx_cmd_opcode_string(cmd->mlcmd_op),
1034 		    cmd->mlcmd_op, cmd->mlcmd_status);
1035 		return (B_FALSE);
1036 	}
1037 
1038 	out = cmd->mlcmd_out;
1039 	if (out->mco_status != MLXCX_CMD_R_OK) {
1040 		mlxcx_warn(mlxp, "command %s 0x%x failed with status code %s "
1041 		    "(0x%x)", mlxcx_cmd_opcode_string(cmd->mlcmd_op),
1042 		    cmd->mlcmd_op, mlxcx_cmd_response_string(out->mco_status),
1043 		    out->mco_status);
1044 		return (B_FALSE);
1045 	}
1046 
1047 	return (B_TRUE);
1048 }
1049 
1050 boolean_t
mlxcx_cmd_disable_hca(mlxcx_t * mlxp)1051 mlxcx_cmd_disable_hca(mlxcx_t *mlxp)
1052 {
1053 	mlxcx_cmd_t cmd;
1054 	mlxcx_cmd_disable_hca_in_t in;
1055 	mlxcx_cmd_disable_hca_out_t out;
1056 	boolean_t ret;
1057 
1058 	bzero(&in, sizeof (in));
1059 	bzero(&out, sizeof (out));
1060 
1061 	mlxcx_cmd_init(mlxp, &cmd);
1062 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_disable_hca_head,
1063 	    MLXCX_OP_DISABLE_HCA, 0);
1064 	in.mlxi_disable_hca_func = MLXCX_FUNCTION_SELF;
1065 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1066 		mlxcx_cmd_fini(mlxp, &cmd);
1067 		return (B_FALSE);
1068 	}
1069 	mlxcx_cmd_wait(&cmd);
1070 
1071 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1072 	mlxcx_cmd_fini(mlxp, &cmd);
1073 	return (ret);
1074 }
1075 
1076 boolean_t
mlxcx_cmd_enable_hca(mlxcx_t * mlxp)1077 mlxcx_cmd_enable_hca(mlxcx_t *mlxp)
1078 {
1079 	mlxcx_cmd_t cmd;
1080 	mlxcx_cmd_enable_hca_in_t in;
1081 	mlxcx_cmd_enable_hca_out_t out;
1082 	boolean_t ret;
1083 
1084 	bzero(&in, sizeof (in));
1085 	bzero(&out, sizeof (out));
1086 
1087 	mlxcx_cmd_init(mlxp, &cmd);
1088 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_enable_hca_head,
1089 	    MLXCX_OP_ENABLE_HCA, 0);
1090 	in.mlxi_enable_hca_func = MLXCX_FUNCTION_SELF;
1091 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1092 		mlxcx_cmd_fini(mlxp, &cmd);
1093 		return (B_FALSE);
1094 	}
1095 	mlxcx_cmd_wait(&cmd);
1096 
1097 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1098 	mlxcx_cmd_fini(mlxp, &cmd);
1099 	return (ret);
1100 }
1101 
1102 boolean_t
mlxcx_cmd_query_issi(mlxcx_t * mlxp,uint32_t * issip)1103 mlxcx_cmd_query_issi(mlxcx_t *mlxp, uint32_t *issip)
1104 {
1105 	mlxcx_cmd_t cmd;
1106 	mlxcx_cmd_query_issi_in_t in;
1107 	mlxcx_cmd_query_issi_out_t out;
1108 	boolean_t ret;
1109 
1110 	bzero(&in, sizeof (in));
1111 	bzero(&out, sizeof (out));
1112 
1113 	mlxcx_cmd_init(mlxp, &cmd);
1114 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_issi_head,
1115 	    MLXCX_OP_QUERY_ISSI, 0);
1116 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1117 		mlxcx_cmd_fini(mlxp, &cmd);
1118 		return (B_FALSE);
1119 	}
1120 	mlxcx_cmd_wait(&cmd);
1121 
1122 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1123 	if (ret) {
1124 		*issip = out.mlxo_supported_issi;
1125 	} else if (cmd.mlcmd_status == 0 &&
1126 	    out.mlxo_query_issi_head.mco_status == MLXCX_CMD_R_BAD_OP) {
1127 		/*
1128 		 * The PRM says that if we get a bad operation, that means this
1129 		 * command isn't supported so it only supports version 1 of the
1130 		 * ISSI, which means bit zero should be set.
1131 		 */
1132 		ret = B_TRUE;
1133 		*issip = 1;
1134 	}
1135 	mlxcx_cmd_fini(mlxp, &cmd);
1136 	return (ret);
1137 }
1138 
1139 boolean_t
mlxcx_cmd_set_issi(mlxcx_t * mlxp,uint16_t issi)1140 mlxcx_cmd_set_issi(mlxcx_t *mlxp, uint16_t issi)
1141 {
1142 	mlxcx_cmd_t cmd;
1143 	mlxcx_cmd_set_issi_in_t in;
1144 	mlxcx_cmd_set_issi_out_t out;
1145 	boolean_t ret;
1146 
1147 	bzero(&in, sizeof (in));
1148 	bzero(&out, sizeof (out));
1149 
1150 	mlxcx_cmd_init(mlxp, &cmd);
1151 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_set_issi_head,
1152 	    MLXCX_OP_SET_ISSI, 0);
1153 	in.mlxi_set_issi_current = to_be16(issi);
1154 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1155 		mlxcx_cmd_fini(mlxp, &cmd);
1156 		return (B_FALSE);
1157 	}
1158 	mlxcx_cmd_wait(&cmd);
1159 
1160 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1161 	mlxcx_cmd_fini(mlxp, &cmd);
1162 	return (ret);
1163 }
1164 
1165 boolean_t
mlxcx_cmd_query_pages(mlxcx_t * mlxp,uint_t type,int32_t * npages)1166 mlxcx_cmd_query_pages(mlxcx_t *mlxp, uint_t type, int32_t *npages)
1167 {
1168 	mlxcx_cmd_t cmd;
1169 	mlxcx_cmd_query_pages_in_t in;
1170 	mlxcx_cmd_query_pages_out_t out;
1171 	boolean_t ret;
1172 
1173 	switch (type) {
1174 	case MLXCX_QUERY_PAGES_OPMOD_BOOT:
1175 	case MLXCX_QUERY_PAGES_OPMOD_INIT:
1176 	case MLXCX_QUERY_PAGES_OPMOD_REGULAR:
1177 		break;
1178 	default:
1179 		mlxcx_warn(mlxp, "!passed invalid type to query pages: %u",
1180 		    type);
1181 		return (B_FALSE);
1182 	}
1183 
1184 	bzero(&in, sizeof (in));
1185 	bzero(&out, sizeof (out));
1186 
1187 	mlxcx_cmd_init(mlxp, &cmd);
1188 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_pages_head,
1189 	    MLXCX_OP_QUERY_PAGES, type);
1190 	in.mlxi_query_pages_func = MLXCX_FUNCTION_SELF;
1191 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1192 		mlxcx_cmd_fini(mlxp, &cmd);
1193 		return (B_FALSE);
1194 	}
1195 	mlxcx_cmd_wait(&cmd);
1196 
1197 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1198 	if (ret) {
1199 		*npages = from_be32(out.mlxo_query_pages_npages);
1200 	}
1201 	mlxcx_cmd_fini(mlxp, &cmd);
1202 
1203 	return (ret);
1204 }
1205 
1206 boolean_t
mlxcx_cmd_give_pages(mlxcx_t * mlxp,uint_t type,int32_t npages,mlxcx_dev_page_t ** pages)1207 mlxcx_cmd_give_pages(mlxcx_t *mlxp, uint_t type, int32_t npages,
1208     mlxcx_dev_page_t **pages)
1209 {
1210 	mlxcx_cmd_t cmd;
1211 	mlxcx_cmd_manage_pages_in_t *in;
1212 	mlxcx_cmd_manage_pages_out_t out;
1213 	size_t insize, outsize;
1214 	boolean_t ret;
1215 	uint32_t i;
1216 	uint64_t pa;
1217 	const ddi_dma_cookie_t *ck;
1218 
1219 	switch (type) {
1220 	case MLXCX_MANAGE_PAGES_OPMOD_ALLOC_FAIL:
1221 		if (npages != 0) {
1222 			mlxcx_warn(mlxp, "passed non-zero number of pages (%d) "
1223 			    "but asked to fail page allocation", npages);
1224 			return (B_FALSE);
1225 		}
1226 		break;
1227 	case MLXCX_MANAGE_PAGES_OPMOD_GIVE_PAGES:
1228 		ASSERT3S(npages, <=, MLXCX_MANAGE_PAGES_MAX_PAGES);
1229 		if (npages <= 0) {
1230 			mlxcx_warn(mlxp, "passed invalid number of pages (%d) "
1231 			    "to give pages", npages);
1232 			return (B_FALSE);
1233 		}
1234 		break;
1235 	default:
1236 		mlxcx_warn(mlxp, "!passed invalid type to give pages: %u",
1237 		    type);
1238 		return (B_FALSE);
1239 	}
1240 
1241 	insize = offsetof(mlxcx_cmd_manage_pages_in_t, mlxi_manage_pages_pas) +
1242 	    npages * sizeof (uint64_t);
1243 	outsize = offsetof(mlxcx_cmd_manage_pages_out_t, mlxo_manage_pages_pas);
1244 
1245 	in = kmem_zalloc(insize, KM_SLEEP);
1246 	bzero(&out, sizeof (out));
1247 
1248 	mlxcx_cmd_init(mlxp, &cmd);
1249 	mlxcx_cmd_in_header_init(&cmd, &in->mlxi_manage_pages_head,
1250 	    MLXCX_OP_MANAGE_PAGES, type);
1251 	in->mlxi_manage_pages_func = MLXCX_FUNCTION_SELF;
1252 	in->mlxi_manage_pages_npages = to_be32(npages);
1253 	for (i = 0; i < npages; i++) {
1254 		ck = mlxcx_dma_cookie_one(&pages[i]->mxdp_dma);
1255 		pa = ck->dmac_laddress;
1256 		ASSERT3U(pa & 0xfff, ==, 0);
1257 		ASSERT3U(ck->dmac_size, ==, MLXCX_HW_PAGE_SIZE);
1258 		in->mlxi_manage_pages_pas[i] = to_be64(pa);
1259 	}
1260 
1261 	if ((ret = mlxcx_cmd_send(mlxp, &cmd, in, insize, &out, outsize))) {
1262 		mlxcx_cmd_wait(&cmd);
1263 		ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1264 	}
1265 
1266 	mlxcx_cmd_fini(mlxp, &cmd);
1267 
1268 	kmem_free(in, insize);
1269 	return (ret);
1270 }
1271 
1272 boolean_t
mlxcx_cmd_return_pages(mlxcx_t * mlxp,int32_t nreq,uint64_t * pas,int32_t * nret)1273 mlxcx_cmd_return_pages(mlxcx_t *mlxp, int32_t nreq, uint64_t *pas,
1274     int32_t *nret)
1275 {
1276 	mlxcx_cmd_t cmd;
1277 	mlxcx_cmd_manage_pages_in_t in;
1278 	mlxcx_cmd_manage_pages_out_t *out;
1279 	size_t insize, outsize;
1280 	boolean_t ret;
1281 	uint32_t i;
1282 
1283 	if (nreq <= 0) {
1284 		mlxcx_warn(mlxp, "passed invalid number of pages (%d) "
1285 		    "to return pages", nreq);
1286 		return (B_FALSE);
1287 	}
1288 
1289 	insize = offsetof(mlxcx_cmd_manage_pages_in_t, mlxi_manage_pages_pas);
1290 	outsize = offsetof(mlxcx_cmd_manage_pages_out_t,
1291 	    mlxo_manage_pages_pas) + nreq * sizeof (uint64_t);
1292 
1293 	bzero(&in, sizeof (in));
1294 	out = kmem_alloc(outsize, KM_SLEEP);
1295 
1296 	mlxcx_cmd_init(mlxp, &cmd);
1297 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_manage_pages_head,
1298 	    MLXCX_OP_MANAGE_PAGES, MLXCX_MANAGE_PAGES_OPMOD_RETURN_PAGES);
1299 	in.mlxi_manage_pages_func = MLXCX_FUNCTION_SELF;
1300 	in.mlxi_manage_pages_npages = to_be32(nreq);
1301 
1302 	if ((ret = mlxcx_cmd_send(mlxp, &cmd, &in, insize, out, outsize))) {
1303 		mlxcx_cmd_wait(&cmd);
1304 
1305 		ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1306 		if (ret) {
1307 			*nret = from_be32(out->mlxo_manage_pages_npages);
1308 			for (i = 0; i < *nret; i++) {
1309 				pas[i] =
1310 				    from_be64(out->mlxo_manage_pages_pas[i]);
1311 			}
1312 		}
1313 	}
1314 
1315 	mlxcx_cmd_fini(mlxp, &cmd);
1316 
1317 	kmem_free(out, outsize);
1318 	return (ret);
1319 }
1320 
1321 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)1322 mlxcx_cmd_query_hca_cap(mlxcx_t *mlxp, mlxcx_hca_cap_type_t type,
1323     mlxcx_hca_cap_mode_t mode, mlxcx_hca_cap_t *capp)
1324 {
1325 	mlxcx_cmd_t cmd;
1326 	mlxcx_cmd_query_hca_cap_in_t in;
1327 	mlxcx_cmd_query_hca_cap_out_t *out;
1328 	boolean_t ret;
1329 	uint16_t opmode;
1330 
1331 	bzero(&in, sizeof (in));
1332 	out = kmem_zalloc(sizeof (mlxcx_cmd_query_hca_cap_out_t), KM_SLEEP);
1333 	mlxcx_cmd_init(mlxp, &cmd);
1334 
1335 	opmode = type << 1 | mode;
1336 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_hca_cap_head,
1337 	    MLXCX_OP_QUERY_HCA_CAP, opmode);
1338 
1339 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), out, sizeof (*out))) {
1340 		mlxcx_cmd_fini(mlxp, &cmd);
1341 		kmem_free(out, sizeof (mlxcx_cmd_query_hca_cap_out_t));
1342 		return (B_FALSE);
1343 	}
1344 	mlxcx_cmd_wait(&cmd);
1345 
1346 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1347 	if (ret) {
1348 		capp->mhc_mode = mode;
1349 		capp->mhc_type = type;
1350 		ASSERT3U(sizeof (out->mlxo_query_hca_cap_data), ==,
1351 		    sizeof (capp->mhc_bulk));
1352 		bcopy(out->mlxo_query_hca_cap_data, capp->mhc_bulk,
1353 		    sizeof (capp->mhc_bulk));
1354 	}
1355 	mlxcx_cmd_fini(mlxp, &cmd);
1356 
1357 	kmem_free(out, sizeof (mlxcx_cmd_query_hca_cap_out_t));
1358 	return (B_TRUE);
1359 }
1360 
1361 boolean_t
mlxcx_cmd_init_hca(mlxcx_t * mlxp)1362 mlxcx_cmd_init_hca(mlxcx_t *mlxp)
1363 {
1364 	mlxcx_cmd_t cmd;
1365 	mlxcx_cmd_init_hca_in_t in;
1366 	mlxcx_cmd_init_hca_out_t out;
1367 	boolean_t ret;
1368 
1369 	bzero(&in, sizeof (in));
1370 	bzero(&out, sizeof (out));
1371 
1372 	mlxcx_cmd_init(mlxp, &cmd);
1373 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_init_hca_head,
1374 	    MLXCX_OP_INIT_HCA, 0);
1375 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1376 		mlxcx_cmd_fini(mlxp, &cmd);
1377 		return (B_FALSE);
1378 	}
1379 	mlxcx_cmd_wait(&cmd);
1380 
1381 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1382 	mlxcx_cmd_fini(mlxp, &cmd);
1383 	return (ret);
1384 }
1385 
1386 boolean_t
mlxcx_cmd_set_driver_version(mlxcx_t * mlxp,const char * version)1387 mlxcx_cmd_set_driver_version(mlxcx_t *mlxp, const char *version)
1388 {
1389 	mlxcx_cmd_t cmd;
1390 	mlxcx_cmd_set_driver_version_in_t in;
1391 	mlxcx_cmd_set_driver_version_out_t out;
1392 	boolean_t ret;
1393 
1394 	bzero(&in, sizeof (in));
1395 	bzero(&out, sizeof (out));
1396 
1397 	mlxcx_cmd_init(mlxp, &cmd);
1398 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_set_driver_version_head,
1399 	    MLXCX_OP_SET_DRIVER_VERSION, 0);
1400 	VERIFY3U(strlcpy(in.mlxi_set_driver_version_version, version,
1401 	    sizeof (in.mlxi_set_driver_version_version)), <=,
1402 	    sizeof (in.mlxi_set_driver_version_version));
1403 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1404 		mlxcx_cmd_fini(mlxp, &cmd);
1405 		return (B_FALSE);
1406 	}
1407 	mlxcx_cmd_wait(&cmd);
1408 
1409 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1410 	mlxcx_cmd_fini(mlxp, &cmd);
1411 	return (ret);
1412 }
1413 
1414 boolean_t
mlxcx_cmd_alloc_uar(mlxcx_t * mlxp,mlxcx_uar_t * mlup)1415 mlxcx_cmd_alloc_uar(mlxcx_t *mlxp, mlxcx_uar_t *mlup)
1416 {
1417 	mlxcx_cmd_t cmd;
1418 	mlxcx_cmd_alloc_uar_in_t in;
1419 	mlxcx_cmd_alloc_uar_out_t out;
1420 	boolean_t ret;
1421 	size_t i;
1422 
1423 	bzero(&in, sizeof (in));
1424 	bzero(&out, sizeof (out));
1425 
1426 	mlxcx_cmd_init(mlxp, &cmd);
1427 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_alloc_uar_head,
1428 	    MLXCX_OP_ALLOC_UAR, 0);
1429 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1430 		mlxcx_cmd_fini(mlxp, &cmd);
1431 		return (B_FALSE);
1432 	}
1433 	mlxcx_cmd_wait(&cmd);
1434 
1435 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1436 	if (ret) {
1437 		mlup->mlu_allocated = B_TRUE;
1438 		mlup->mlu_num = from_be24(out.mlxo_alloc_uar_uar);
1439 		VERIFY3U(mlup->mlu_num, >, 0);
1440 		mlup->mlu_base = mlup->mlu_num * MLXCX_HW_PAGE_SIZE;
1441 
1442 		for (i = 0; i < MLXCX_BF_PER_UAR; ++i) {
1443 			mlup->mlu_bf[i].mbf_even = mlup->mlu_base +
1444 			    MLXCX_BF_BASE + MLXCX_BF_SIZE * 2 * i;
1445 			mlup->mlu_bf[i].mbf_odd = mlup->mlu_bf[i].mbf_even +
1446 			    MLXCX_BF_SIZE;
1447 		}
1448 	}
1449 	mlxcx_cmd_fini(mlxp, &cmd);
1450 	return (ret);
1451 }
1452 
1453 boolean_t
mlxcx_cmd_dealloc_uar(mlxcx_t * mlxp,mlxcx_uar_t * mlup)1454 mlxcx_cmd_dealloc_uar(mlxcx_t *mlxp, mlxcx_uar_t *mlup)
1455 {
1456 	mlxcx_cmd_t cmd;
1457 	mlxcx_cmd_dealloc_uar_in_t in;
1458 	mlxcx_cmd_dealloc_uar_out_t out;
1459 	boolean_t ret;
1460 
1461 	bzero(&in, sizeof (in));
1462 	bzero(&out, sizeof (out));
1463 
1464 	mlxcx_cmd_init(mlxp, &cmd);
1465 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_dealloc_uar_head,
1466 	    MLXCX_OP_DEALLOC_UAR, 0);
1467 	VERIFY(mlup->mlu_allocated);
1468 	in.mlxi_dealloc_uar_uar = to_be24(mlup->mlu_num);
1469 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1470 		mlxcx_cmd_fini(mlxp, &cmd);
1471 		return (B_FALSE);
1472 	}
1473 	mlxcx_cmd_wait(&cmd);
1474 
1475 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1476 	if (ret) {
1477 		mlup->mlu_allocated = B_FALSE;
1478 		mlup->mlu_num = 0;
1479 	}
1480 	mlxcx_cmd_fini(mlxp, &cmd);
1481 	return (ret);
1482 }
1483 
1484 boolean_t
mlxcx_cmd_alloc_pd(mlxcx_t * mlxp,mlxcx_pd_t * mlpd)1485 mlxcx_cmd_alloc_pd(mlxcx_t *mlxp, mlxcx_pd_t *mlpd)
1486 {
1487 	mlxcx_cmd_t cmd;
1488 	mlxcx_cmd_alloc_pd_in_t in;
1489 	mlxcx_cmd_alloc_pd_out_t out;
1490 	boolean_t ret;
1491 
1492 	bzero(&in, sizeof (in));
1493 	bzero(&out, sizeof (out));
1494 
1495 	mlxcx_cmd_init(mlxp, &cmd);
1496 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_alloc_pd_head,
1497 	    MLXCX_OP_ALLOC_PD, 0);
1498 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1499 		mlxcx_cmd_fini(mlxp, &cmd);
1500 		return (B_FALSE);
1501 	}
1502 	mlxcx_cmd_wait(&cmd);
1503 
1504 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1505 	if (ret) {
1506 		mlpd->mlpd_allocated = B_TRUE;
1507 		mlpd->mlpd_num = from_be24(out.mlxo_alloc_pd_pdn);
1508 	}
1509 	mlxcx_cmd_fini(mlxp, &cmd);
1510 	return (ret);
1511 }
1512 
1513 boolean_t
mlxcx_cmd_dealloc_pd(mlxcx_t * mlxp,mlxcx_pd_t * mlpd)1514 mlxcx_cmd_dealloc_pd(mlxcx_t *mlxp, mlxcx_pd_t *mlpd)
1515 {
1516 	mlxcx_cmd_t cmd;
1517 	mlxcx_cmd_dealloc_pd_in_t in;
1518 	mlxcx_cmd_dealloc_pd_out_t out;
1519 	boolean_t ret;
1520 
1521 	bzero(&in, sizeof (in));
1522 	bzero(&out, sizeof (out));
1523 
1524 	mlxcx_cmd_init(mlxp, &cmd);
1525 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_dealloc_pd_head,
1526 	    MLXCX_OP_DEALLOC_PD, 0);
1527 	VERIFY(mlpd->mlpd_allocated);
1528 	in.mlxi_dealloc_pd_pdn = to_be24(mlpd->mlpd_num);
1529 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1530 		mlxcx_cmd_fini(mlxp, &cmd);
1531 		return (B_FALSE);
1532 	}
1533 	mlxcx_cmd_wait(&cmd);
1534 
1535 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1536 	if (ret) {
1537 		mlpd->mlpd_allocated = B_FALSE;
1538 		mlpd->mlpd_num = 0;
1539 	}
1540 	mlxcx_cmd_fini(mlxp, &cmd);
1541 	return (ret);
1542 }
1543 
1544 boolean_t
mlxcx_cmd_alloc_tdom(mlxcx_t * mlxp,mlxcx_tdom_t * mltd)1545 mlxcx_cmd_alloc_tdom(mlxcx_t *mlxp, mlxcx_tdom_t *mltd)
1546 {
1547 	mlxcx_cmd_t cmd;
1548 	mlxcx_cmd_alloc_tdom_in_t in;
1549 	mlxcx_cmd_alloc_tdom_out_t out;
1550 	boolean_t ret;
1551 
1552 	bzero(&in, sizeof (in));
1553 	bzero(&out, sizeof (out));
1554 
1555 	mlxcx_cmd_init(mlxp, &cmd);
1556 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_alloc_tdom_head,
1557 	    MLXCX_OP_ALLOC_TRANSPORT_DOMAIN, 0);
1558 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1559 		mlxcx_cmd_fini(mlxp, &cmd);
1560 		return (B_FALSE);
1561 	}
1562 	mlxcx_cmd_wait(&cmd);
1563 
1564 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1565 	if (ret) {
1566 		mltd->mltd_allocated = B_TRUE;
1567 		mltd->mltd_num = from_be24(out.mlxo_alloc_tdom_tdomn);
1568 	}
1569 	mlxcx_cmd_fini(mlxp, &cmd);
1570 	return (ret);
1571 }
1572 
1573 boolean_t
mlxcx_cmd_dealloc_tdom(mlxcx_t * mlxp,mlxcx_tdom_t * mltd)1574 mlxcx_cmd_dealloc_tdom(mlxcx_t *mlxp, mlxcx_tdom_t *mltd)
1575 {
1576 	mlxcx_cmd_t cmd;
1577 	mlxcx_cmd_dealloc_tdom_in_t in;
1578 	mlxcx_cmd_dealloc_tdom_out_t out;
1579 	boolean_t ret;
1580 
1581 	bzero(&in, sizeof (in));
1582 	bzero(&out, sizeof (out));
1583 
1584 	mlxcx_cmd_init(mlxp, &cmd);
1585 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_dealloc_tdom_head,
1586 	    MLXCX_OP_DEALLOC_TRANSPORT_DOMAIN, 0);
1587 	VERIFY(mltd->mltd_allocated);
1588 	in.mlxi_dealloc_tdom_tdomn = to_be24(mltd->mltd_num);
1589 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1590 		mlxcx_cmd_fini(mlxp, &cmd);
1591 		return (B_FALSE);
1592 	}
1593 	mlxcx_cmd_wait(&cmd);
1594 
1595 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1596 	if (ret) {
1597 		mltd->mltd_allocated = B_FALSE;
1598 		mltd->mltd_num = 0;
1599 	}
1600 	mlxcx_cmd_fini(mlxp, &cmd);
1601 	return (ret);
1602 }
1603 
1604 boolean_t
mlxcx_cmd_teardown_hca(mlxcx_t * mlxp)1605 mlxcx_cmd_teardown_hca(mlxcx_t *mlxp)
1606 {
1607 	mlxcx_cmd_t cmd;
1608 	mlxcx_cmd_teardown_hca_in_t in;
1609 	mlxcx_cmd_teardown_hca_out_t out;
1610 	boolean_t ret;
1611 
1612 	bzero(&in, sizeof (in));
1613 	bzero(&out, sizeof (out));
1614 
1615 	mlxcx_cmd_init(mlxp, &cmd);
1616 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_teardown_hca_head,
1617 	    MLXCX_OP_TEARDOWN_HCA, 0);
1618 	in.mlxi_teardown_hca_profile = to_be16(MLXCX_TEARDOWN_HCA_GRACEFUL);
1619 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1620 		mlxcx_cmd_fini(mlxp, &cmd);
1621 		return (B_FALSE);
1622 	}
1623 	mlxcx_cmd_wait(&cmd);
1624 
1625 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1626 	mlxcx_cmd_fini(mlxp, &cmd);
1627 	return (ret);
1628 }
1629 
1630 boolean_t
mlxcx_cmd_query_nic_vport_ctx(mlxcx_t * mlxp,mlxcx_port_t * mlp)1631 mlxcx_cmd_query_nic_vport_ctx(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1632 {
1633 	mlxcx_cmd_t cmd;
1634 	mlxcx_cmd_query_nic_vport_ctx_in_t in;
1635 	mlxcx_cmd_query_nic_vport_ctx_out_t out;
1636 	boolean_t ret;
1637 	const mlxcx_nic_vport_ctx_t *ctx;
1638 
1639 	bzero(&in, sizeof (in));
1640 	bzero(&out, sizeof (out));
1641 
1642 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1643 	mlxcx_cmd_init(mlxp, &cmd);
1644 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_nic_vport_ctx_head,
1645 	    MLXCX_OP_QUERY_NIC_VPORT_CONTEXT, MLXCX_VPORT_TYPE_VNIC);
1646 
1647 	in.mlxi_query_nic_vport_ctx_vport_number = to_be16(mlp->mlp_num);
1648 
1649 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
1650 		mlxcx_cmd_fini(mlxp, &cmd);
1651 		return (B_FALSE);
1652 	}
1653 	mlxcx_cmd_wait(&cmd);
1654 
1655 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1656 	if (ret) {
1657 		ctx = &out.mlxo_query_nic_vport_ctx_context;
1658 		mlp->mlp_guid = from_be64(ctx->mlnvc_port_guid);
1659 		mlp->mlp_mtu = from_be16(ctx->mlnvc_mtu);
1660 		bcopy(ctx->mlnvc_permanent_address, mlp->mlp_mac_address,
1661 		    sizeof (mlp->mlp_mac_address));
1662 		mlp->mlp_wqe_min_inline = get_bits64(ctx->mlnvc_flags,
1663 		    MLXCX_VPORT_CTX_MIN_WQE_INLINE);
1664 	}
1665 	mlxcx_cmd_fini(mlxp, &cmd);
1666 	return (ret);
1667 }
1668 
1669 static const char *
mlxcx_reg_name(mlxcx_register_id_t rid)1670 mlxcx_reg_name(mlxcx_register_id_t rid)
1671 {
1672 	switch (rid) {
1673 	case MLXCX_REG_PMTU:
1674 		return ("PMTU");
1675 	case MLXCX_REG_PAOS:
1676 		return ("PAOS");
1677 	case MLXCX_REG_PTYS:
1678 		return ("PTYS");
1679 	case MLXCX_REG_MSGI:
1680 		return ("MSGI");
1681 	case MLXCX_REG_PMAOS:
1682 		return ("PMAOS");
1683 	case MLXCX_REG_MLCR:
1684 		return ("MLCR");
1685 	case MLXCX_REG_MCIA:
1686 		return ("MCIA");
1687 	case MLXCX_REG_PPCNT:
1688 		return ("PPCNT");
1689 	case MLXCX_REG_PPLM:
1690 		return ("PPLM");
1691 	case MLXCX_REG_MTCAP:
1692 		return ("MTCAP");
1693 	case MLXCX_REG_MTMP:
1694 		return ("MTMP");
1695 	default:
1696 		return ("???");
1697 	}
1698 }
1699 
1700 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)1701 mlxcx_cmd_access_register(mlxcx_t *mlxp, mlxcx_cmd_reg_opmod_t opmod,
1702     mlxcx_register_id_t rid, mlxcx_register_data_t *data)
1703 {
1704 	mlxcx_cmd_t cmd;
1705 	mlxcx_cmd_access_register_in_t in;
1706 	mlxcx_cmd_access_register_out_t out;
1707 	boolean_t ret;
1708 	size_t dsize, insize, outsize;
1709 
1710 	bzero(&in, sizeof (in));
1711 	bzero(&out, sizeof (out));
1712 
1713 	mlxcx_cmd_init(mlxp, &cmd);
1714 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_access_register_head,
1715 	    MLXCX_OP_ACCESS_REG, opmod);
1716 
1717 	in.mlxi_access_register_register_id = to_be16(rid);
1718 
1719 	switch (rid) {
1720 	case MLXCX_REG_PMTU:
1721 		dsize = sizeof (mlxcx_reg_pmtu_t);
1722 		break;
1723 	case MLXCX_REG_PAOS:
1724 		dsize = sizeof (mlxcx_reg_paos_t);
1725 		break;
1726 	case MLXCX_REG_PTYS:
1727 		dsize = sizeof (mlxcx_reg_ptys_t);
1728 		break;
1729 	case MLXCX_REG_MLCR:
1730 		dsize = sizeof (mlxcx_reg_mlcr_t);
1731 		break;
1732 	case MLXCX_REG_PMAOS:
1733 		dsize = sizeof (mlxcx_reg_pmaos_t);
1734 		break;
1735 	case MLXCX_REG_MCIA:
1736 		dsize = sizeof (mlxcx_reg_mcia_t);
1737 		break;
1738 	case MLXCX_REG_PPCNT:
1739 		dsize = sizeof (mlxcx_reg_ppcnt_t);
1740 		break;
1741 	case MLXCX_REG_PPLM:
1742 		dsize = sizeof (mlxcx_reg_pplm_t);
1743 		break;
1744 	case MLXCX_REG_MTCAP:
1745 		dsize = sizeof (mlxcx_reg_mtcap_t);
1746 		break;
1747 	case MLXCX_REG_MTMP:
1748 		dsize = sizeof (mlxcx_reg_mtmp_t);
1749 		break;
1750 	default:
1751 		dsize = 0;
1752 		VERIFY(0);
1753 		return (B_FALSE);
1754 	}
1755 	insize = dsize + offsetof(mlxcx_cmd_access_register_in_t,
1756 	    mlxi_access_register_data);
1757 	outsize = dsize + offsetof(mlxcx_cmd_access_register_out_t,
1758 	    mlxo_access_register_data);
1759 
1760 	bcopy(data, &in.mlxi_access_register_data, dsize);
1761 
1762 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, outsize)) {
1763 		mlxcx_cmd_fini(mlxp, &cmd);
1764 		return (B_FALSE);
1765 	}
1766 	mlxcx_cmd_wait(&cmd);
1767 
1768 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
1769 	if (ret) {
1770 		bcopy(&out.mlxo_access_register_data, data, dsize);
1771 	} else {
1772 		mlxcx_warn(mlxp, "failed OP_ACCESS_REG was for register "
1773 		    "%04x (%s)", rid, mlxcx_reg_name(rid));
1774 	}
1775 	mlxcx_cmd_fini(mlxp, &cmd);
1776 	return (ret);
1777 }
1778 
1779 boolean_t
mlxcx_cmd_query_port_mtu(mlxcx_t * mlxp,mlxcx_port_t * mlp)1780 mlxcx_cmd_query_port_mtu(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1781 {
1782 	mlxcx_register_data_t data;
1783 	boolean_t ret;
1784 
1785 	/*
1786 	 * Since we modify the port here we require that the caller is holding
1787 	 * the port mutex.
1788 	 */
1789 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1790 	bzero(&data, sizeof (data));
1791 	data.mlrd_pmtu.mlrd_pmtu_local_port = mlp->mlp_num + 1;
1792 
1793 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1794 	    MLXCX_REG_PMTU, &data);
1795 
1796 	if (ret) {
1797 		mlp->mlp_mtu = from_be16(data.mlrd_pmtu.mlrd_pmtu_admin_mtu);
1798 		mlp->mlp_max_mtu = from_be16(data.mlrd_pmtu.mlrd_pmtu_max_mtu);
1799 	}
1800 
1801 	return (ret);
1802 }
1803 
1804 boolean_t
mlxcx_cmd_query_module_status(mlxcx_t * mlxp,uint_t id,mlxcx_module_status_t * pstatus,mlxcx_module_error_type_t * perr)1805 mlxcx_cmd_query_module_status(mlxcx_t *mlxp, uint_t id,
1806     mlxcx_module_status_t *pstatus, mlxcx_module_error_type_t *perr)
1807 {
1808 	mlxcx_register_data_t data;
1809 	boolean_t ret;
1810 
1811 	bzero(&data, sizeof (data));
1812 	ASSERT3U(id, <, 0xff);
1813 	data.mlrd_pmaos.mlrd_pmaos_module = (uint8_t)id;
1814 
1815 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1816 	    MLXCX_REG_PMAOS, &data);
1817 
1818 	if (ret) {
1819 		if (pstatus != NULL)
1820 			*pstatus = data.mlrd_pmaos.mlrd_pmaos_oper_status;
1821 		if (perr != NULL)
1822 			*perr = data.mlrd_pmaos.mlrd_pmaos_error_type;
1823 	}
1824 
1825 	return (ret);
1826 }
1827 
1828 boolean_t
mlxcx_cmd_set_port_mtu(mlxcx_t * mlxp,mlxcx_port_t * mlp)1829 mlxcx_cmd_set_port_mtu(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1830 {
1831 	mlxcx_register_data_t data;
1832 	boolean_t ret;
1833 
1834 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1835 	bzero(&data, sizeof (data));
1836 	data.mlrd_pmtu.mlrd_pmtu_local_port = mlp->mlp_num + 1;
1837 	data.mlrd_pmtu.mlrd_pmtu_admin_mtu = to_be16(mlp->mlp_mtu);
1838 
1839 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
1840 	    MLXCX_REG_PMTU, &data);
1841 
1842 	return (ret);
1843 }
1844 
1845 boolean_t
mlxcx_cmd_set_port_led(mlxcx_t * mlxp,mlxcx_port_t * mlp,uint16_t sec)1846 mlxcx_cmd_set_port_led(mlxcx_t *mlxp, mlxcx_port_t *mlp, uint16_t sec)
1847 {
1848 	mlxcx_register_data_t data;
1849 	boolean_t ret;
1850 
1851 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1852 	bzero(&data, sizeof (data));
1853 	data.mlrd_mlcr.mlrd_mlcr_local_port = mlp->mlp_num + 1;
1854 	set_bits8(&data.mlrd_mlcr.mlrd_mlcr_flags, MLXCX_MLCR_LED_TYPE,
1855 	    MLXCX_LED_TYPE_PORT);
1856 	data.mlrd_mlcr.mlrd_mlcr_beacon_duration = to_be16(sec);
1857 
1858 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
1859 	    MLXCX_REG_MLCR, &data);
1860 
1861 	return (ret);
1862 }
1863 
1864 boolean_t
mlxcx_cmd_query_port_status(mlxcx_t * mlxp,mlxcx_port_t * mlp)1865 mlxcx_cmd_query_port_status(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1866 {
1867 	mlxcx_register_data_t data;
1868 	boolean_t ret;
1869 
1870 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1871 	bzero(&data, sizeof (data));
1872 	data.mlrd_paos.mlrd_paos_local_port = mlp->mlp_num + 1;
1873 
1874 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1875 	    MLXCX_REG_PAOS, &data);
1876 
1877 	if (ret) {
1878 		mlp->mlp_admin_status = data.mlrd_paos.mlrd_paos_admin_status;
1879 		mlp->mlp_oper_status = data.mlrd_paos.mlrd_paos_oper_status;
1880 	}
1881 
1882 	return (ret);
1883 }
1884 
1885 boolean_t
mlxcx_cmd_modify_port_status(mlxcx_t * mlxp,mlxcx_port_t * mlp,mlxcx_port_status_t status)1886 mlxcx_cmd_modify_port_status(mlxcx_t *mlxp, mlxcx_port_t *mlp,
1887     mlxcx_port_status_t status)
1888 {
1889 	mlxcx_register_data_t data;
1890 	boolean_t ret;
1891 
1892 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1893 	bzero(&data, sizeof (data));
1894 	data.mlrd_paos.mlrd_paos_local_port = mlp->mlp_num + 1;
1895 	data.mlrd_paos.mlrd_paos_admin_status = status;
1896 	set_bit32(&data.mlrd_paos.mlrd_paos_flags, MLXCX_PAOS_ADMIN_ST_EN);
1897 
1898 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
1899 	    MLXCX_REG_PAOS, &data);
1900 
1901 	return (ret);
1902 }
1903 
1904 boolean_t
mlxcx_cmd_query_port_speed(mlxcx_t * mlxp,mlxcx_port_t * mlp)1905 mlxcx_cmd_query_port_speed(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1906 {
1907 	mlxcx_register_data_t data;
1908 	boolean_t ret;
1909 
1910 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1911 	bzero(&data, sizeof (data));
1912 	data.mlrd_ptys.mlrd_ptys_local_port = mlp->mlp_num + 1;
1913 	set_bit8(&data.mlrd_ptys.mlrd_ptys_proto_mask,
1914 	    MLXCX_PTYS_PROTO_MASK_ETH);
1915 
1916 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1917 	    MLXCX_REG_PTYS, &data);
1918 
1919 	if (ret) {
1920 		if (get_bit8(data.mlrd_ptys.mlrd_ptys_autoneg_flags,
1921 		    MLXCX_AUTONEG_DISABLE)) {
1922 			mlp->mlp_autoneg = B_FALSE;
1923 		} else {
1924 			mlp->mlp_autoneg = B_TRUE;
1925 		}
1926 		mlp->mlp_max_proto =
1927 		    from_bits32(data.mlrd_ptys.mlrd_ptys_proto_cap);
1928 		mlp->mlp_admin_proto =
1929 		    from_bits32(data.mlrd_ptys.mlrd_ptys_proto_admin);
1930 		mlp->mlp_oper_proto =
1931 		    from_bits32(data.mlrd_ptys.mlrd_ptys_proto_oper);
1932 	}
1933 
1934 	return (ret);
1935 }
1936 
1937 boolean_t
mlxcx_cmd_query_port_fec(mlxcx_t * mlxp,mlxcx_port_t * mlp)1938 mlxcx_cmd_query_port_fec(mlxcx_t *mlxp, mlxcx_port_t *mlp)
1939 {
1940 	mlxcx_register_data_t data;
1941 	boolean_t ret;
1942 
1943 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1944 	bzero(&data, sizeof (data));
1945 	data.mlrd_pplm.mlrd_pplm_local_port = mlp->mlp_num + 1;
1946 
1947 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1948 	    MLXCX_REG_PPLM, &data);
1949 
1950 	if (ret) {
1951 		mlp->mlp_fec_active =
1952 		    from_be24(data.mlrd_pplm.mlrd_pplm_fec_mode_active);
1953 	}
1954 
1955 	return (ret);
1956 }
1957 
1958 boolean_t
mlxcx_cmd_modify_port_fec(mlxcx_t * mlxp,mlxcx_port_t * mlp,mlxcx_pplm_fec_caps_t fec)1959 mlxcx_cmd_modify_port_fec(mlxcx_t *mlxp, mlxcx_port_t *mlp,
1960     mlxcx_pplm_fec_caps_t fec)
1961 {
1962 	mlxcx_register_data_t data_in, data_out;
1963 	mlxcx_pplm_fec_caps_t caps;
1964 	mlxcx_reg_pplm_t *pplm_in, *pplm_out;
1965 	boolean_t ret;
1966 
1967 	ASSERT(mutex_owned(&mlp->mlp_mtx));
1968 	bzero(&data_in, sizeof (data_in));
1969 	pplm_in = &data_in.mlrd_pplm;
1970 	pplm_in->mlrd_pplm_local_port = mlp->mlp_num + 1;
1971 
1972 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
1973 	    MLXCX_REG_PPLM, &data_in);
1974 
1975 	if (!ret)
1976 		return (B_FALSE);
1977 
1978 	bzero(&data_out, sizeof (data_out));
1979 	pplm_out = &data_out.mlrd_pplm;
1980 	pplm_out->mlrd_pplm_local_port = mlp->mlp_num + 1;
1981 
1982 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
1983 	    MLXCX_PPLM_CAP_56G);
1984 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
1985 	    MLXCX_PPLM_CAP_56G, fec & caps);
1986 
1987 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
1988 	    MLXCX_PPLM_CAP_100G);
1989 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
1990 	    MLXCX_PPLM_CAP_100G, fec & caps);
1991 
1992 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
1993 	    MLXCX_PPLM_CAP_50G);
1994 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
1995 	    MLXCX_PPLM_CAP_50G, fec & caps);
1996 
1997 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
1998 	    MLXCX_PPLM_CAP_25G);
1999 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2000 	    MLXCX_PPLM_CAP_25G, fec & caps);
2001 
2002 	caps = get_bits32(pplm_in->mlrd_pplm_fec_override_cap,
2003 	    MLXCX_PPLM_CAP_10_40G);
2004 	set_bits32(&pplm_out->mlrd_pplm_fec_override_admin,
2005 	    MLXCX_PPLM_CAP_10_40G, fec & caps);
2006 
2007 	ret = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_WRITE,
2008 	    MLXCX_REG_PPLM, &data_out);
2009 
2010 	return (ret);
2011 }
2012 
2013 boolean_t
mlxcx_cmd_modify_nic_vport_ctx(mlxcx_t * mlxp,mlxcx_port_t * mlp,mlxcx_modify_nic_vport_ctx_fields_t fields)2014 mlxcx_cmd_modify_nic_vport_ctx(mlxcx_t *mlxp, mlxcx_port_t *mlp,
2015     mlxcx_modify_nic_vport_ctx_fields_t fields)
2016 {
2017 	mlxcx_cmd_t cmd;
2018 	mlxcx_cmd_modify_nic_vport_ctx_in_t in;
2019 	mlxcx_cmd_modify_nic_vport_ctx_out_t out;
2020 	boolean_t ret;
2021 	mlxcx_nic_vport_ctx_t *ctx;
2022 
2023 	ASSERT(mutex_owned(&mlp->mlp_mtx));
2024 	bzero(&in, sizeof (in));
2025 	bzero(&out, sizeof (out));
2026 
2027 	mlxcx_cmd_init(mlxp, &cmd);
2028 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_nic_vport_ctx_head,
2029 	    MLXCX_OP_MODIFY_NIC_VPORT_CONTEXT, MLXCX_VPORT_TYPE_VNIC);
2030 
2031 	in.mlxi_modify_nic_vport_ctx_vport_number = to_be16(mlp->mlp_num);
2032 	in.mlxi_modify_nic_vport_ctx_field_select = to_be32(fields);
2033 
2034 	ctx = &in.mlxi_modify_nic_vport_ctx_context;
2035 	if (fields & MLXCX_MODIFY_NIC_VPORT_CTX_PROMISC) {
2036 		set_bit16(&ctx->mlnvc_promisc_list_type,
2037 		    MLXCX_VPORT_PROMISC_ALL);
2038 	}
2039 	if (fields & MLXCX_MODIFY_NIC_VPORT_CTX_MTU) {
2040 		ctx->mlnvc_mtu = to_be16(mlp->mlp_mtu);
2041 	}
2042 
2043 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2044 		mlxcx_cmd_fini(mlxp, &cmd);
2045 		return (B_FALSE);
2046 	}
2047 	mlxcx_cmd_wait(&cmd);
2048 
2049 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2050 	if (ret) {
2051 		if (fields & MLXCX_MODIFY_NIC_VPORT_CTX_PROMISC) {
2052 			mlp->mlp_flags |= MLXCX_PORT_VPORT_PROMISC;
2053 		}
2054 	}
2055 	mlxcx_cmd_fini(mlxp, &cmd);
2056 	return (ret);
2057 }
2058 
2059 boolean_t
mlxcx_cmd_create_eq(mlxcx_t * mlxp,mlxcx_event_queue_t * mleq)2060 mlxcx_cmd_create_eq(mlxcx_t *mlxp, mlxcx_event_queue_t *mleq)
2061 {
2062 	mlxcx_cmd_t cmd;
2063 	mlxcx_cmd_create_eq_in_t in;
2064 	mlxcx_cmd_create_eq_out_t out;
2065 	boolean_t ret;
2066 	mlxcx_eventq_ctx_t *ctx;
2067 	size_t rem, insize;
2068 	const ddi_dma_cookie_t *c;
2069 	uint64_t pa, npages;
2070 
2071 	bzero(&in, sizeof (in));
2072 	bzero(&out, sizeof (out));
2073 
2074 	ASSERT(mutex_owned(&mleq->mleq_mtx));
2075 	VERIFY(mleq->mleq_state & MLXCX_EQ_ALLOC);
2076 	VERIFY0(mleq->mleq_state & MLXCX_EQ_CREATED);
2077 
2078 	mlxcx_cmd_init(mlxp, &cmd);
2079 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_eq_head,
2080 	    MLXCX_OP_CREATE_EQ, 0);
2081 
2082 	ctx = &in.mlxi_create_eq_context;
2083 	ctx->mleqc_uar_page = to_be24(mleq->mleq_uar->mlu_num);
2084 	ctx->mleqc_log_eq_size = mleq->mleq_entshift;
2085 	ctx->mleqc_intr = mleq->mleq_intr_index;
2086 
2087 	in.mlxi_create_eq_event_bitmask = to_be64(mleq->mleq_events);
2088 
2089 	npages = 0;
2090 	c = NULL;
2091 	while ((c = mlxcx_dma_cookie_iter(&mleq->mleq_dma, c)) != NULL) {
2092 		pa = c->dmac_laddress;
2093 		rem = c->dmac_size;
2094 		while (rem > 0) {
2095 			ASSERT3U(pa & 0xfff, ==, 0);
2096 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
2097 			in.mlxi_create_eq_pas[npages++] = to_be64(pa);
2098 			rem -= MLXCX_HW_PAGE_SIZE;
2099 			pa += MLXCX_HW_PAGE_SIZE;
2100 		}
2101 	}
2102 	ASSERT3U(npages, <=, MLXCX_CREATE_QUEUE_MAX_PAGES);
2103 
2104 	insize = offsetof(mlxcx_cmd_create_eq_in_t, mlxi_create_eq_pas) +
2105 	    sizeof (uint64_t) * npages;
2106 
2107 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
2108 		mlxcx_cmd_fini(mlxp, &cmd);
2109 		return (B_FALSE);
2110 	}
2111 	mlxcx_cmd_wait(&cmd);
2112 
2113 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2114 	if (ret) {
2115 		mleq->mleq_state |= MLXCX_EQ_CREATED;
2116 		mleq->mleq_num = out.mlxo_create_eq_eqn;
2117 	}
2118 	mlxcx_cmd_fini(mlxp, &cmd);
2119 	return (ret);
2120 }
2121 
2122 boolean_t
mlxcx_cmd_query_eq(mlxcx_t * mlxp,mlxcx_event_queue_t * mleq,mlxcx_eventq_ctx_t * ctxp)2123 mlxcx_cmd_query_eq(mlxcx_t *mlxp, mlxcx_event_queue_t *mleq,
2124     mlxcx_eventq_ctx_t *ctxp)
2125 {
2126 	mlxcx_cmd_t cmd;
2127 	mlxcx_cmd_query_eq_in_t in;
2128 	mlxcx_cmd_query_eq_out_t out;
2129 	boolean_t ret;
2130 
2131 	bzero(&in, sizeof (in));
2132 	bzero(&out, sizeof (out));
2133 
2134 	VERIFY(mleq->mleq_state & MLXCX_EQ_ALLOC);
2135 	VERIFY(mleq->mleq_state & MLXCX_EQ_CREATED);
2136 
2137 	mlxcx_cmd_init(mlxp, &cmd);
2138 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_eq_head,
2139 	    MLXCX_OP_QUERY_EQ, 0);
2140 
2141 	in.mlxi_query_eq_eqn = mleq->mleq_num;
2142 
2143 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2144 		mlxcx_cmd_fini(mlxp, &cmd);
2145 		return (B_FALSE);
2146 	}
2147 	mlxcx_cmd_wait(&cmd);
2148 
2149 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2150 	if (ret) {
2151 		bcopy(&out.mlxo_query_eq_context, ctxp,
2152 		    sizeof (mlxcx_eventq_ctx_t));
2153 	}
2154 	mlxcx_cmd_fini(mlxp, &cmd);
2155 	return (ret);
2156 }
2157 
2158 boolean_t
mlxcx_cmd_destroy_eq(mlxcx_t * mlxp,mlxcx_event_queue_t * mleq)2159 mlxcx_cmd_destroy_eq(mlxcx_t *mlxp, mlxcx_event_queue_t *mleq)
2160 {
2161 	mlxcx_cmd_t cmd;
2162 	mlxcx_cmd_destroy_eq_in_t in;
2163 	mlxcx_cmd_destroy_eq_out_t out;
2164 	boolean_t ret;
2165 
2166 	bzero(&in, sizeof (in));
2167 	bzero(&out, sizeof (out));
2168 
2169 	ASSERT(mutex_owned(&mleq->mleq_mtx));
2170 	VERIFY(mleq->mleq_state & MLXCX_EQ_ALLOC);
2171 	VERIFY(mleq->mleq_state & MLXCX_EQ_CREATED);
2172 
2173 	mlxcx_cmd_init(mlxp, &cmd);
2174 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_eq_head,
2175 	    MLXCX_OP_DESTROY_EQ, 0);
2176 
2177 	in.mlxi_destroy_eq_eqn = mleq->mleq_num;
2178 
2179 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2180 		mlxcx_cmd_fini(mlxp, &cmd);
2181 		return (B_FALSE);
2182 	}
2183 	mlxcx_cmd_wait(&cmd);
2184 
2185 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2186 	if (ret) {
2187 		mleq->mleq_state |= MLXCX_EQ_DESTROYED;
2188 	}
2189 	mlxcx_cmd_fini(mlxp, &cmd);
2190 	return (ret);
2191 }
2192 
2193 boolean_t
mlxcx_cmd_query_special_ctxs(mlxcx_t * mlxp)2194 mlxcx_cmd_query_special_ctxs(mlxcx_t *mlxp)
2195 {
2196 	mlxcx_cmd_t cmd;
2197 	mlxcx_cmd_query_special_ctxs_in_t in;
2198 	mlxcx_cmd_query_special_ctxs_out_t out;
2199 	boolean_t ret;
2200 
2201 	bzero(&in, sizeof (in));
2202 	bzero(&out, sizeof (out));
2203 
2204 	mlxcx_cmd_init(mlxp, &cmd);
2205 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_special_ctxs_head,
2206 	    MLXCX_OP_QUERY_SPECIAL_CONTEXTS, 0);
2207 
2208 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2209 		mlxcx_cmd_fini(mlxp, &cmd);
2210 		return (B_FALSE);
2211 	}
2212 	mlxcx_cmd_wait(&cmd);
2213 
2214 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2215 	if (ret) {
2216 		mlxp->mlx_rsvd_lkey = from_be32(
2217 		    out.mlxo_query_special_ctxs_resd_lkey);
2218 	}
2219 	mlxcx_cmd_fini(mlxp, &cmd);
2220 	return (ret);
2221 }
2222 
2223 boolean_t
mlxcx_cmd_create_cq(mlxcx_t * mlxp,mlxcx_completion_queue_t * mlcq)2224 mlxcx_cmd_create_cq(mlxcx_t *mlxp, mlxcx_completion_queue_t *mlcq)
2225 {
2226 	mlxcx_cmd_t cmd;
2227 	mlxcx_cmd_create_cq_in_t in;
2228 	mlxcx_cmd_create_cq_out_t out;
2229 	boolean_t ret;
2230 	mlxcx_completionq_ctx_t *ctx;
2231 	size_t rem, insize;
2232 	const ddi_dma_cookie_t *c;
2233 	uint64_t pa, npages;
2234 
2235 	bzero(&in, sizeof (in));
2236 	bzero(&out, sizeof (out));
2237 
2238 	ASSERT(mutex_owned(&mlcq->mlcq_mtx));
2239 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_ALLOC);
2240 	VERIFY0(mlcq->mlcq_state & MLXCX_CQ_CREATED);
2241 
2242 	mlxcx_cmd_init(mlxp, &cmd);
2243 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_cq_head,
2244 	    MLXCX_OP_CREATE_CQ, 0);
2245 
2246 	ctx = &in.mlxi_create_cq_context;
2247 	ctx->mlcqc_uar_page = to_be24(mlcq->mlcq_uar->mlu_num);
2248 	ctx->mlcqc_log_cq_size = mlcq->mlcq_entshift;
2249 	ctx->mlcqc_eqn = mlcq->mlcq_eq->mleq_num;
2250 	ctx->mlcqc_cq_period = to_be16(mlcq->mlcq_cqemod_period_usec);
2251 	ctx->mlcqc_cq_max_count = to_be16(mlcq->mlcq_cqemod_count);
2252 
2253 	c = mlxcx_dma_cookie_one(&mlcq->mlcq_doorbell_dma);
2254 	ctx->mlcqc_dbr_addr = to_be64(c->dmac_laddress);
2255 	ASSERT3U(c->dmac_size, >=, sizeof (mlxcx_completionq_doorbell_t));
2256 
2257 	npages = 0;
2258 	c = NULL;
2259 	while ((c = mlxcx_dma_cookie_iter(&mlcq->mlcq_dma, c)) != NULL) {
2260 		pa = c->dmac_laddress;
2261 		rem = c->dmac_size;
2262 		while (rem > 0) {
2263 			ASSERT3U(pa & 0xfff, ==, 0);
2264 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
2265 			in.mlxi_create_cq_pas[npages++] = to_be64(pa);
2266 			rem -= MLXCX_HW_PAGE_SIZE;
2267 			pa += MLXCX_HW_PAGE_SIZE;
2268 		}
2269 	}
2270 	ASSERT3U(npages, <=, MLXCX_CREATE_QUEUE_MAX_PAGES);
2271 
2272 	insize = offsetof(mlxcx_cmd_create_cq_in_t, mlxi_create_cq_pas) +
2273 	    sizeof (uint64_t) * npages;
2274 
2275 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
2276 		mlxcx_cmd_fini(mlxp, &cmd);
2277 		return (B_FALSE);
2278 	}
2279 	mlxcx_cmd_wait(&cmd);
2280 
2281 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2282 	if (ret) {
2283 		atomic_or_uint(&mlcq->mlcq_state, MLXCX_CQ_CREATED);
2284 		mlcq->mlcq_num = from_be24(out.mlxo_create_cq_cqn);
2285 	}
2286 	mlxcx_cmd_fini(mlxp, &cmd);
2287 	return (ret);
2288 }
2289 
2290 boolean_t
mlxcx_cmd_query_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq,mlxcx_rq_ctx_t * ctxp)2291 mlxcx_cmd_query_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq,
2292     mlxcx_rq_ctx_t *ctxp)
2293 {
2294 	mlxcx_cmd_t cmd;
2295 	mlxcx_cmd_query_rq_in_t in;
2296 	mlxcx_cmd_query_rq_out_t out;
2297 	boolean_t ret;
2298 
2299 	bzero(&in, sizeof (in));
2300 	bzero(&out, sizeof (out));
2301 
2302 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2303 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2304 	ASSERT3S(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_RECVQ);
2305 
2306 	mlxcx_cmd_init(mlxp, &cmd);
2307 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_rq_head,
2308 	    MLXCX_OP_QUERY_RQ, 0);
2309 
2310 	in.mlxi_query_rq_rqn = to_be24(mlwq->mlwq_num);
2311 
2312 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2313 		mlxcx_cmd_fini(mlxp, &cmd);
2314 		return (B_FALSE);
2315 	}
2316 	mlxcx_cmd_wait(&cmd);
2317 
2318 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2319 	if (ret) {
2320 		bcopy(&out.mlxo_query_rq_context, ctxp,
2321 		    sizeof (mlxcx_rq_ctx_t));
2322 	}
2323 	mlxcx_cmd_fini(mlxp, &cmd);
2324 	return (ret);
2325 }
2326 
2327 boolean_t
mlxcx_cmd_query_sq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq,mlxcx_sq_ctx_t * ctxp)2328 mlxcx_cmd_query_sq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq,
2329     mlxcx_sq_ctx_t *ctxp)
2330 {
2331 	mlxcx_cmd_t cmd;
2332 	mlxcx_cmd_query_sq_in_t in;
2333 	mlxcx_cmd_query_sq_out_t out;
2334 	boolean_t ret;
2335 
2336 	bzero(&in, sizeof (in));
2337 	bzero(&out, sizeof (out));
2338 
2339 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2340 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2341 	ASSERT3S(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_SENDQ);
2342 
2343 	mlxcx_cmd_init(mlxp, &cmd);
2344 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_sq_head,
2345 	    MLXCX_OP_QUERY_SQ, 0);
2346 
2347 	in.mlxi_query_sq_sqn = to_be24(mlwq->mlwq_num);
2348 
2349 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2350 		mlxcx_cmd_fini(mlxp, &cmd);
2351 		return (B_FALSE);
2352 	}
2353 	mlxcx_cmd_wait(&cmd);
2354 
2355 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2356 	if (ret) {
2357 		bcopy(&out.mlxo_query_sq_context, ctxp,
2358 		    sizeof (mlxcx_sq_ctx_t));
2359 	}
2360 	mlxcx_cmd_fini(mlxp, &cmd);
2361 	return (ret);
2362 }
2363 
2364 boolean_t
mlxcx_cmd_query_cq(mlxcx_t * mlxp,mlxcx_completion_queue_t * mlcq,mlxcx_completionq_ctx_t * ctxp)2365 mlxcx_cmd_query_cq(mlxcx_t *mlxp, mlxcx_completion_queue_t *mlcq,
2366     mlxcx_completionq_ctx_t *ctxp)
2367 {
2368 	mlxcx_cmd_t cmd;
2369 	mlxcx_cmd_query_cq_in_t in;
2370 	mlxcx_cmd_query_cq_out_t out;
2371 	boolean_t ret;
2372 
2373 	bzero(&in, sizeof (in));
2374 	bzero(&out, sizeof (out));
2375 
2376 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_ALLOC);
2377 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_CREATED);
2378 
2379 	mlxcx_cmd_init(mlxp, &cmd);
2380 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_query_cq_head,
2381 	    MLXCX_OP_QUERY_CQ, 0);
2382 
2383 	in.mlxi_query_cq_cqn = to_be24(mlcq->mlcq_num);
2384 
2385 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2386 		mlxcx_cmd_fini(mlxp, &cmd);
2387 		return (B_FALSE);
2388 	}
2389 	mlxcx_cmd_wait(&cmd);
2390 
2391 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2392 	if (ret) {
2393 		bcopy(&out.mlxo_query_cq_context, ctxp,
2394 		    sizeof (mlxcx_completionq_ctx_t));
2395 	}
2396 	mlxcx_cmd_fini(mlxp, &cmd);
2397 	return (ret);
2398 }
2399 
2400 boolean_t
mlxcx_cmd_destroy_cq(mlxcx_t * mlxp,mlxcx_completion_queue_t * mlcq)2401 mlxcx_cmd_destroy_cq(mlxcx_t *mlxp, mlxcx_completion_queue_t *mlcq)
2402 {
2403 	mlxcx_cmd_t cmd;
2404 	mlxcx_cmd_destroy_cq_in_t in;
2405 	mlxcx_cmd_destroy_cq_out_t out;
2406 	boolean_t ret;
2407 
2408 	bzero(&in, sizeof (in));
2409 	bzero(&out, sizeof (out));
2410 
2411 	ASSERT(mutex_owned(&mlcq->mlcq_mtx));
2412 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_ALLOC);
2413 	VERIFY(mlcq->mlcq_state & MLXCX_CQ_CREATED);
2414 
2415 	mlxcx_cmd_init(mlxp, &cmd);
2416 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_cq_head,
2417 	    MLXCX_OP_DESTROY_CQ, 0);
2418 
2419 	in.mlxi_destroy_cq_cqn = to_be24(mlcq->mlcq_num);
2420 
2421 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2422 		mlxcx_cmd_fini(mlxp, &cmd);
2423 		return (B_FALSE);
2424 	}
2425 	mlxcx_cmd_wait(&cmd);
2426 
2427 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2428 	if (ret) {
2429 		atomic_or_uint(&mlcq->mlcq_state, MLXCX_CQ_DESTROYED);
2430 	}
2431 	mlxcx_cmd_fini(mlxp, &cmd);
2432 	return (ret);
2433 }
2434 
2435 boolean_t
mlxcx_cmd_create_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2436 mlxcx_cmd_create_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2437 {
2438 	mlxcx_cmd_t cmd;
2439 	mlxcx_cmd_create_rq_in_t in;
2440 	mlxcx_cmd_create_rq_out_t out;
2441 	boolean_t ret;
2442 	mlxcx_rq_ctx_t *ctx;
2443 	size_t rem, insize;
2444 	const ddi_dma_cookie_t *c;
2445 	uint64_t pa, npages;
2446 
2447 	bzero(&in, sizeof (in));
2448 	bzero(&out, sizeof (out));
2449 
2450 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2451 	VERIFY3U(mlwq->mlwq_type, ==, MLXCX_WQ_TYPE_RECVQ);
2452 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2453 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2454 
2455 	mlxcx_cmd_init(mlxp, &cmd);
2456 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_rq_head,
2457 	    MLXCX_OP_CREATE_RQ, 0);
2458 
2459 	ctx = &in.mlxi_create_rq_context;
2460 
2461 	set_bit32(&ctx->mlrqc_flags, MLXCX_RQ_FLAGS_RLKEY);
2462 	set_bit32(&ctx->mlrqc_flags, MLXCX_RQ_FLAGS_FLUSH_IN_ERROR);
2463 	set_bit32(&ctx->mlrqc_flags, MLXCX_RQ_FLAGS_VLAN_STRIP_DISABLE);
2464 	ctx->mlrqc_cqn = to_be24(mlwq->mlwq_cq->mlcq_num);
2465 
2466 	set_bits32(&ctx->mlrqc_wq.mlwqc_flags, MLXCX_WORKQ_CTX_TYPE,
2467 	    MLXCX_WORKQ_TYPE_CYCLIC);
2468 	ctx->mlrqc_wq.mlwqc_pd = to_be24(mlwq->mlwq_pd->mlpd_num);
2469 	ctx->mlrqc_wq.mlwqc_log_wq_sz = mlwq->mlwq_entshift;
2470 	ctx->mlrqc_wq.mlwqc_log_wq_stride = MLXCX_RECVQ_STRIDE_SHIFT;
2471 
2472 	c = mlxcx_dma_cookie_one(&mlwq->mlwq_doorbell_dma);
2473 	ctx->mlrqc_wq.mlwqc_dbr_addr = to_be64(c->dmac_laddress);
2474 	ASSERT3U(c->dmac_size, >=, sizeof (mlxcx_workq_doorbell_t));
2475 
2476 	npages = 0;
2477 	c = NULL;
2478 	while ((c = mlxcx_dma_cookie_iter(&mlwq->mlwq_dma, c)) != NULL) {
2479 		pa = c->dmac_laddress;
2480 		rem = c->dmac_size;
2481 		while (rem > 0) {
2482 			ASSERT3U(pa & 0xfff, ==, 0);
2483 			ASSERT3U(rem, >=, MLXCX_HW_PAGE_SIZE);
2484 			ctx->mlrqc_wq.mlwqc_pas[npages++] = to_be64(pa);
2485 			rem -= MLXCX_HW_PAGE_SIZE;
2486 			pa += MLXCX_HW_PAGE_SIZE;
2487 		}
2488 	}
2489 	ASSERT3U(npages, <=, MLXCX_WORKQ_CTX_MAX_ADDRESSES);
2490 
2491 	insize = offsetof(mlxcx_cmd_create_rq_in_t, mlxi_create_rq_context) +
2492 	    offsetof(mlxcx_rq_ctx_t, mlrqc_wq) +
2493 	    offsetof(mlxcx_workq_ctx_t, mlwqc_pas) +
2494 	    sizeof (uint64_t) * npages;
2495 
2496 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, insize, &out, sizeof (out))) {
2497 		mlxcx_cmd_fini(mlxp, &cmd);
2498 		return (B_FALSE);
2499 	}
2500 	mlxcx_cmd_wait(&cmd);
2501 
2502 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2503 	if (ret) {
2504 		mlwq->mlwq_state |= MLXCX_WQ_CREATED;
2505 		mlwq->mlwq_num = from_be24(out.mlxo_create_rq_rqn);
2506 	}
2507 	mlxcx_cmd_fini(mlxp, &cmd);
2508 	return (ret);
2509 }
2510 
2511 boolean_t
mlxcx_cmd_start_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2512 mlxcx_cmd_start_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2513 {
2514 	mlxcx_cmd_t cmd;
2515 	mlxcx_cmd_modify_rq_in_t in;
2516 	mlxcx_cmd_modify_rq_out_t out;
2517 	boolean_t ret;
2518 	ddi_fm_error_t err;
2519 
2520 	bzero(&in, sizeof (in));
2521 	bzero(&out, sizeof (out));
2522 
2523 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2524 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2525 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2526 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_STARTED);
2527 
2528 	/*
2529 	 * Before starting the queue, we have to be sure that it is
2530 	 * empty and the doorbell and counters are set to 0.
2531 	 */
2532 	ASSERT(mutex_owned(&mlwq->mlwq_cq->mlcq_mtx));
2533 	ASSERT(list_is_empty(&mlwq->mlwq_cq->mlcq_buffers));
2534 	ASSERT(list_is_empty(&mlwq->mlwq_cq->mlcq_buffers_b));
2535 
2536 	mlwq->mlwq_doorbell->mlwqd_recv_counter = to_be16(0);
2537 	MLXCX_DMA_SYNC(mlwq->mlwq_doorbell_dma, DDI_DMA_SYNC_FORDEV);
2538 	ddi_fm_dma_err_get(mlwq->mlwq_doorbell_dma.mxdb_dma_handle, &err,
2539 	    DDI_FME_VERSION);
2540 	if (err.fme_status != DDI_FM_OK)
2541 		return (B_FALSE);
2542 	mlwq->mlwq_pc = 0;
2543 
2544 	mlxcx_cmd_init(mlxp, &cmd);
2545 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_rq_head,
2546 	    MLXCX_OP_MODIFY_RQ, 0);
2547 
2548 	in.mlxi_modify_rq_rqn = to_be24(mlwq->mlwq_num);
2549 
2550 	/* From state */
2551 	set_bits8(&in.mlxi_modify_rq_state, MLXCX_CMD_MODIFY_RQ_STATE,
2552 	    MLXCX_RQ_STATE_RST);
2553 	/* To state */
2554 	set_bits32(&in.mlxi_modify_rq_context.mlrqc_flags, MLXCX_RQ_STATE,
2555 	    MLXCX_RQ_STATE_RDY);
2556 
2557 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2558 		mlxcx_cmd_fini(mlxp, &cmd);
2559 		return (B_FALSE);
2560 	}
2561 	mlxcx_cmd_wait(&cmd);
2562 
2563 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2564 	if (ret) {
2565 		mlwq->mlwq_state |= MLXCX_WQ_STARTED;
2566 	}
2567 	mlxcx_cmd_fini(mlxp, &cmd);
2568 	return (ret);
2569 }
2570 
2571 boolean_t
mlxcx_cmd_stop_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2572 mlxcx_cmd_stop_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2573 {
2574 	mlxcx_cmd_t cmd;
2575 	mlxcx_cmd_modify_rq_in_t in;
2576 	mlxcx_cmd_modify_rq_out_t out;
2577 	boolean_t ret;
2578 
2579 	bzero(&in, sizeof (in));
2580 	bzero(&out, sizeof (out));
2581 
2582 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2583 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2584 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2585 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_STARTED);
2586 
2587 	mlxcx_cmd_init(mlxp, &cmd);
2588 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_modify_rq_head,
2589 	    MLXCX_OP_MODIFY_RQ, 0);
2590 
2591 	in.mlxi_modify_rq_rqn = to_be24(mlwq->mlwq_num);
2592 
2593 	/* From state */
2594 	set_bits8(&in.mlxi_modify_rq_state, MLXCX_CMD_MODIFY_RQ_STATE,
2595 	    MLXCX_RQ_STATE_RDY);
2596 	/* To state */
2597 	set_bits32(&in.mlxi_modify_rq_context.mlrqc_flags, MLXCX_RQ_STATE,
2598 	    MLXCX_RQ_STATE_RST);
2599 
2600 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2601 		mlxcx_cmd_fini(mlxp, &cmd);
2602 		return (B_FALSE);
2603 	}
2604 	mlxcx_cmd_wait(&cmd);
2605 
2606 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2607 	if (ret) {
2608 		mlwq->mlwq_state &= ~MLXCX_WQ_STARTED;
2609 	}
2610 	mlxcx_cmd_fini(mlxp, &cmd);
2611 	return (ret);
2612 }
2613 
2614 boolean_t
mlxcx_cmd_destroy_rq(mlxcx_t * mlxp,mlxcx_work_queue_t * mlwq)2615 mlxcx_cmd_destroy_rq(mlxcx_t *mlxp, mlxcx_work_queue_t *mlwq)
2616 {
2617 	mlxcx_cmd_t cmd;
2618 	mlxcx_cmd_destroy_rq_in_t in;
2619 	mlxcx_cmd_destroy_rq_out_t out;
2620 	boolean_t ret;
2621 
2622 	bzero(&in, sizeof (in));
2623 	bzero(&out, sizeof (out));
2624 
2625 	ASSERT(mutex_owned(&mlwq->mlwq_mtx));
2626 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_ALLOC);
2627 	VERIFY(mlwq->mlwq_state & MLXCX_WQ_CREATED);
2628 	VERIFY0(mlwq->mlwq_state & MLXCX_WQ_STARTED);
2629 
2630 	mlxcx_cmd_init(mlxp, &cmd);
2631 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_rq_head,
2632 	    MLXCX_OP_DESTROY_RQ, 0);
2633 
2634 	in.mlxi_destroy_rq_rqn = to_be24(mlwq->mlwq_num);
2635 
2636 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2637 		mlxcx_cmd_fini(mlxp, &cmd);
2638 		return (B_FALSE);
2639 	}
2640 	mlxcx_cmd_wait(&cmd);
2641 
2642 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2643 	if (ret) {
2644 		mlwq->mlwq_state |= MLXCX_WQ_DESTROYED;
2645 	}
2646 	mlxcx_cmd_fini(mlxp, &cmd);
2647 	return (ret);
2648 }
2649 
2650 boolean_t
mlxcx_cmd_create_tir(mlxcx_t * mlxp,mlxcx_tir_t * mltir)2651 mlxcx_cmd_create_tir(mlxcx_t *mlxp, mlxcx_tir_t *mltir)
2652 {
2653 	mlxcx_cmd_t cmd;
2654 	mlxcx_cmd_create_tir_in_t in;
2655 	mlxcx_cmd_create_tir_out_t out;
2656 	mlxcx_tir_ctx_t *ctx;
2657 	boolean_t ret;
2658 
2659 	bzero(&in, sizeof (in));
2660 	bzero(&out, sizeof (out));
2661 
2662 	VERIFY0(mltir->mltir_state & MLXCX_TIR_CREATED);
2663 
2664 	mlxcx_cmd_init(mlxp, &cmd);
2665 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_tir_head,
2666 	    MLXCX_OP_CREATE_TIR, 0);
2667 
2668 	ctx = &in.mlxi_create_tir_context;
2669 	ctx->mltirc_transport_domain = to_be24(mltir->mltir_tdom->mltd_num);
2670 	set_bits8(&ctx->mltirc_disp_type, MLXCX_TIR_CTX_DISP_TYPE,
2671 	    mltir->mltir_type);
2672 	switch (mltir->mltir_type) {
2673 	case MLXCX_TIR_INDIRECT:
2674 		VERIFY(mltir->mltir_rqtable != NULL);
2675 		VERIFY(mltir->mltir_rqtable->mlrqt_state & MLXCX_RQT_CREATED);
2676 		ctx->mltirc_indirect_table =
2677 		    to_be24(mltir->mltir_rqtable->mlrqt_num);
2678 		set_bits8(&ctx->mltirc_hash_lb, MLXCX_TIR_RX_HASH_FN,
2679 		    mltir->mltir_hash_fn);
2680 		bcopy(mltir->mltir_toeplitz_key,
2681 		    ctx->mltirc_rx_hash_toeplitz_key,
2682 		    sizeof (ctx->mltirc_rx_hash_toeplitz_key));
2683 		set_bits32(&ctx->mltirc_rx_hash_fields_outer,
2684 		    MLXCX_RX_HASH_L3_TYPE, mltir->mltir_l3_type);
2685 		set_bits32(&ctx->mltirc_rx_hash_fields_outer,
2686 		    MLXCX_RX_HASH_L4_TYPE, mltir->mltir_l4_type);
2687 		set_bits32(&ctx->mltirc_rx_hash_fields_outer,
2688 		    MLXCX_RX_HASH_FIELDS, mltir->mltir_hash_fields);
2689 		break;
2690 	case MLXCX_TIR_DIRECT:
2691 		VERIFY(mltir->mltir_rq != NULL);
2692 		VERIFY(mltir->mltir_rq->mlwq_state & MLXCX_WQ_CREATED);
2693 		ctx->mltirc_inline_rqn = to_be24(mltir->mltir_rq->mlwq_num);
2694 		break;
2695 	default:
2696 		VERIFY(0);
2697 	}
2698 
2699 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2700 		mlxcx_cmd_fini(mlxp, &cmd);
2701 		return (B_FALSE);
2702 	}
2703 	mlxcx_cmd_wait(&cmd);
2704 
2705 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2706 	if (ret) {
2707 		mltir->mltir_state |= MLXCX_TIR_CREATED;
2708 		mltir->mltir_num = from_be24(out.mlxo_create_tir_tirn);
2709 	}
2710 	mlxcx_cmd_fini(mlxp, &cmd);
2711 	return (ret);
2712 }
2713 
2714 boolean_t
mlxcx_cmd_destroy_tir(mlxcx_t * mlxp,mlxcx_tir_t * mltir)2715 mlxcx_cmd_destroy_tir(mlxcx_t *mlxp, mlxcx_tir_t *mltir)
2716 {
2717 	mlxcx_cmd_t cmd;
2718 	mlxcx_cmd_destroy_tir_in_t in;
2719 	mlxcx_cmd_destroy_tir_out_t out;
2720 	boolean_t ret;
2721 
2722 	bzero(&in, sizeof (in));
2723 	bzero(&out, sizeof (out));
2724 
2725 	VERIFY(mltir->mltir_state & MLXCX_TIR_CREATED);
2726 	VERIFY0(mltir->mltir_state & MLXCX_TIR_DESTROYED);
2727 
2728 	mlxcx_cmd_init(mlxp, &cmd);
2729 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_tir_head,
2730 	    MLXCX_OP_DESTROY_TIR, 0);
2731 
2732 	in.mlxi_destroy_tir_tirn = to_be24(mltir->mltir_num);
2733 
2734 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2735 		mlxcx_cmd_fini(mlxp, &cmd);
2736 		return (B_FALSE);
2737 	}
2738 	mlxcx_cmd_wait(&cmd);
2739 
2740 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2741 	if (ret) {
2742 		mltir->mltir_state |= MLXCX_TIR_DESTROYED;
2743 	}
2744 	mlxcx_cmd_fini(mlxp, &cmd);
2745 	return (ret);
2746 }
2747 
2748 boolean_t
mlxcx_cmd_create_tis(mlxcx_t * mlxp,mlxcx_tis_t * mltis)2749 mlxcx_cmd_create_tis(mlxcx_t *mlxp, mlxcx_tis_t *mltis)
2750 {
2751 	mlxcx_cmd_t cmd;
2752 	mlxcx_cmd_create_tis_in_t in;
2753 	mlxcx_cmd_create_tis_out_t out;
2754 	mlxcx_tis_ctx_t *ctx;
2755 	boolean_t ret;
2756 
2757 	bzero(&in, sizeof (in));
2758 	bzero(&out, sizeof (out));
2759 
2760 	VERIFY0(mltis->mltis_state & MLXCX_TIS_CREATED);
2761 
2762 	mlxcx_cmd_init(mlxp, &cmd);
2763 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_tis_head,
2764 	    MLXCX_OP_CREATE_TIS, 0);
2765 
2766 	ctx = &in.mlxi_create_tis_context;
2767 	ctx->mltisc_transport_domain = to_be24(mltis->mltis_tdom->mltd_num);
2768 
2769 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2770 		mlxcx_cmd_fini(mlxp, &cmd);
2771 		return (B_FALSE);
2772 	}
2773 	mlxcx_cmd_wait(&cmd);
2774 
2775 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2776 	if (ret) {
2777 		mltis->mltis_state |= MLXCX_TIS_CREATED;
2778 		mltis->mltis_num = from_be24(out.mlxo_create_tis_tisn);
2779 	}
2780 	mlxcx_cmd_fini(mlxp, &cmd);
2781 	return (ret);
2782 }
2783 
2784 boolean_t
mlxcx_cmd_destroy_tis(mlxcx_t * mlxp,mlxcx_tis_t * mltis)2785 mlxcx_cmd_destroy_tis(mlxcx_t *mlxp, mlxcx_tis_t *mltis)
2786 {
2787 	mlxcx_cmd_t cmd;
2788 	mlxcx_cmd_destroy_tis_in_t in;
2789 	mlxcx_cmd_destroy_tis_out_t out;
2790 	boolean_t ret;
2791 
2792 	bzero(&in, sizeof (in));
2793 	bzero(&out, sizeof (out));
2794 
2795 	VERIFY(mltis->mltis_state & MLXCX_TIR_CREATED);
2796 	VERIFY0(mltis->mltis_state & MLXCX_TIR_DESTROYED);
2797 
2798 	mlxcx_cmd_init(mlxp, &cmd);
2799 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_destroy_tis_head,
2800 	    MLXCX_OP_DESTROY_TIS, 0);
2801 
2802 	in.mlxi_destroy_tis_tisn = to_be24(mltis->mltis_num);
2803 
2804 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2805 		mlxcx_cmd_fini(mlxp, &cmd);
2806 		return (B_FALSE);
2807 	}
2808 	mlxcx_cmd_wait(&cmd);
2809 
2810 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2811 	if (ret) {
2812 		mltis->mltis_state |= MLXCX_TIS_DESTROYED;
2813 	}
2814 	mlxcx_cmd_fini(mlxp, &cmd);
2815 	return (ret);
2816 }
2817 
2818 boolean_t
mlxcx_cmd_create_flow_table(mlxcx_t * mlxp,mlxcx_flow_table_t * mlft)2819 mlxcx_cmd_create_flow_table(mlxcx_t *mlxp, mlxcx_flow_table_t *mlft)
2820 {
2821 	mlxcx_cmd_t cmd;
2822 	mlxcx_cmd_create_flow_table_in_t in;
2823 	mlxcx_cmd_create_flow_table_out_t out;
2824 	mlxcx_flow_table_ctx_t *ctx;
2825 	boolean_t ret;
2826 
2827 	bzero(&in, sizeof (in));
2828 	bzero(&out, sizeof (out));
2829 
2830 	ASSERT(mutex_owned(&mlft->mlft_mtx));
2831 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
2832 
2833 	mlxcx_cmd_init(mlxp, &cmd);
2834 	mlxcx_cmd_in_header_init(&cmd, &in.mlxi_create_flow_table_head,
2835 	    MLXCX_OP_CREATE_FLOW_TABLE, 0);
2836 
2837 	in.mlxi_create_flow_table_vport_number =
2838 	    to_be16(mlft->mlft_port->mlp_num);
2839 	in.mlxi_create_flow_table_table_type = mlft->mlft_type;
2840 	ctx = &in.mlxi_create_flow_table_context;
2841 	ctx->mlftc_log_size = mlft->mlft_entshift;
2842 	ctx->mlftc_level = mlft->mlft_level;
2843 
2844 	if (!mlxcx_cmd_send(mlxp, &cmd, &in, sizeof (in), &out, sizeof (out))) {
2845 		mlxcx_cmd_fini(mlxp, &cmd);
2846 		return (B_FALSE);
2847 	}
2848 	mlxcx_cmd_wait(&cmd);
2849 
2850 	ret = mlxcx_cmd_evaluate(mlxp, &cmd);
2851 	if (ret) {
2852 		mlft->mlft_num = from_be24(out.mlxo_create_flow_table_table_id);
2853 		mlft->mlft_state |= MLXCX_FLOW_TABLE_CREATED;
2854 	}
2855 	mlxcx_cmd_fini(mlxp, &cmd);
2856 	return (ret);
2857 }
2858 
2859 boolean_t
mlxcx_cmd_destroy_flow_table(mlxcx_t * mlxp,mlxcx_flow_table_t * mlft)2860 mlxcx_cmd_destroy_flow_table(mlxcx_t *mlxp, mlxcx_flow_table_t *mlft)
2861 {
2862 	mlxcx_cmd_t cmd;
2863 	mlxcx_cmd_destroy_flow_table_in_t in;
2864 	mlxcx_cmd_destroy_flow_table_out_t out;
2865 	boolean_t ret;
2866 
2867 	bzero(&in, sizeof (in));
2868 	bzero(&out, sizeof (out));
2869 
2870 	ASSERT(mutex_owned(&mlft->mlft_mtx));
2871 	VERIFY(mlft->mlft_state & MLXCX_FLOW_TABLE_CREATED);
2872 	VERIFY0(mlft->mlft_state & MLXCX_FLOW_TABLE_DESTROYED);
2873 
2874 	mlxcx_cmd_init(mlxp, &