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