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