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