1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _SYS_IB_ADAPTERS_TAVOR_CMD_H 28 #define _SYS_IB_ADAPTERS_TAVOR_CMD_H 29 30 /* 31 * tavor_cmd.h 32 * Contains all of the prototypes, #defines, and structures necessary 33 * for the Tavor Firmware Command routines. 34 * Specifically it contains the command types, command statuses and flags, 35 * structures used for managing Tavor mailboxes and outstanding commands, 36 * and prototypes for most of the functions consumed by other parts of 37 * the Tavor driver. 38 */ 39 40 #include <sys/types.h> 41 #include <sys/conf.h> 42 #include <sys/ddi.h> 43 #include <sys/sunddi.h> 44 45 #include <sys/ib/mgt/sm_attr.h> 46 47 #ifdef __cplusplus 48 extern "C" { 49 #endif 50 51 52 /* 53 * Defines used tavor_write_hcr() to determine the duration and number of 54 * times (at maximum) to poll while waiting for a Tavor firmware command to 55 * release the HCR resource (i.e. waiting for the command to complete) 56 */ 57 #define TAVOR_CMD_POLL_DELAY 1 58 #define TAVOR_CMD_POLL_MAX 3000000 59 60 /* 61 * The following defines specify the default number of mailboxes (log 2) of 62 * each type and their size and alignment restrictions. By default the number 63 * of both "In" and "Out" mailboxes is set to eight (with each mailbox being 64 * 512 bytes in size), but both the number and sizes of each are controllable 65 * through the "tavor_log_num_inmbox", "tavor_log_num_outmbox", 66 * "tavor_log_inmbox_size" and "tavor_log_outmbox_size" configuration 67 * variables. 68 */ 69 #define TAVOR_NUM_MAILBOXES_SHIFT 8 70 #define TAVOR_NUM_INTR_MAILBOXES_SHIFT 0 71 #define TAVOR_MBOX_SIZE_SHIFT 0x9 72 #define TAVOR_MBOX_SIZE (1 << TAVOR_MBOX_SIZE_SHIFT) 73 #define TAVOR_MBOX_ALIGN TAVOR_MBOX_SIZE 74 75 /* 76 * The following macro determines whether the contents of given mailbox 77 * type need to be sync'd (with ddi_dma_sync()). This decision is based 78 * on whether the mailbox is in DDR memory (no sync) or system memory 79 * (sync required). And it also supports the possibility that if a CQ in 80 * system memory is mapped DDI_DMA_CONSISTENT, it can be configured to not be 81 * sync'd because of the "sync override" parameter in the config profile. 82 */ 83 #define TAVOR_MBOX_IS_SYNC_REQ(state, type) \ 84 ((((((state)->ts_cfg_profile->cp_streaming_consistent) && \ 85 ((state)->ts_cfg_profile->cp_consistent_syncoverride))) || \ 86 ((&((state)->ts_rsrc_hdl[(type)]))->rsrc_loc == TAVOR_IN_DDR)) \ 87 ? 0 : 1) 88 89 /* 90 * These are the defines for the Tavor command type (opcodes). They are 91 * specified by the Tavor register specification 92 */ 93 #define SYS_EN 0x1 94 #define SYS_DIS 0x2 95 #define QUERY_DEV_LIM 0x3 96 #define QUERY_FW 0x4 97 #define QUERY_DDR 0x5 98 #define QUERY_ADAPTER 0x6 99 #define INIT_HCA 0x7 100 #define CLOSE_HCA 0x8 101 #define INIT_IB 0x9 102 #define CLOSE_IB 0xA 103 #define QUERY_HCA 0xB 104 #define SET_IB 0xC 105 #define ACCESS_DDR 0x2E 106 #define SW2HW_MPT 0xD 107 #define QUERY_MPT 0xE 108 #define HW2SW_MPT 0xF 109 #define READ_MTT 0x10 110 #define WRITE_MTT 0x11 111 #define SYNC_TPT 0x2F 112 #define MAP_EQ 0x12 113 #define SW2HW_EQ 0x13 114 #define HW2SW_EQ 0x14 115 #define QUERY_EQ 0x15 116 #define SW2HW_CQ 0x16 117 #define HW2SW_CQ 0x17 118 #define QUERY_CQ 0x18 119 #define RESIZE_CQ 0x2C 120 #define RST2INIT_QP 0x19 121 #define INIT2INIT_QP 0x2D 122 #define INIT2RTR_QP 0x1A 123 #define RTR2RTS_QP 0x1B 124 #define RTS2RTS_QP 0x1C 125 #define SQERR2RTS_QP 0x1D 126 #define TOERR_QP 0x1E 127 #define RTS2SQD_QP 0x1F 128 #define SQD2RTS_QP 0x20 129 #define TORST_QP 0x21 130 #define QUERY_QP 0x22 131 #define CONF_SPECIAL_QP 0x23 132 #define MAD_IFC 0x24 133 #define READ_MGM 0x25 134 #define WRITE_MGM 0x26 135 #define MGID_HASH 0x27 136 #define CONF_NTU 0x28 137 #define QUERY_NTU 0x29 138 #define QUERY_DEBUG_MSG 0x2A 139 #define SET_DEBUG_MSG 0x2B 140 #define DIAG_RPRT 0x30 141 #define MOD_STAT_CFG 0x34 142 #define SW2HW_SRQ 0x35 143 #define HW2SW_SRQ 0x36 144 #define QUERY_SRQ 0x37 145 #define SQD2SQD_QP 0x38 146 #define MODIFY_MPT 0x39 147 148 /* 149 * These are the defines for the Tavor command completion statuses. They are 150 * also specified (in part) by the Tavor register specification. However, 151 * the TAVOR_CMD_INSUFF_RSRC, TAVOR_CMD_TIMEOUT and TAVOR_CMD_INVALID_STATUS 152 * codes were added for this driver specifically to indicate the conditions 153 * when insufficient resources are available for a command, when a command has 154 * timed out (failure in the Tavor firmware) or when some other invalid result 155 * was received. 156 */ 157 #define TAVOR_CMD_INSUFF_RSRC 0xFFFD 158 #define TAVOR_CMD_TIMEOUT 0xFFFE 159 #define TAVOR_CMD_INVALID_STATUS 0xFFFF 160 #define TAVOR_CMD_SUCCESS 0x00 161 #define TAVOR_CMD_INTERNAL_ERR 0x01 162 #define TAVOR_CMD_BAD_OP 0x02 163 #define TAVOR_CMD_BAD_PARAM 0x03 164 #define TAVOR_CMD_BAD_SYS_STATE 0x04 165 #define TAVOR_CMD_BAD_RESOURCE 0x05 166 #define TAVOR_CMD_RESOURCE_BUSY 0x06 167 #define TAVOR_CMD_DDR_MEM_ERR 0x07 168 #define TAVOR_CMD_EXCEED_LIM 0x08 169 #define TAVOR_CMD_BAD_RES_STATE 0x09 170 #define TAVOR_CMD_BAD_INDEX 0x0A 171 #define TAVOR_CMD_BAD_NVMEM 0x0B 172 #define TAVOR_CMD_BAD_QP_STATE 0x10 173 #define TAVOR_CMD_BAD_SEG_PARAM 0x20 174 #define TAVOR_CMD_REG_BOUND 0x21 175 #define TAVOR_CMD_BAD_PKT 0x30 176 #define TAVOR_CMD_BAD_SIZE 0x40 177 178 /* 179 * These defines are used in the "special QP" allocation to indicate the type 180 * of special QP (SMI, GSI, or one of the raw types). These values are 181 * specified by the Tavor register specification 182 */ 183 #define TAVOR_CMD_QP_SMI 0 184 #define TAVOR_CMD_QP_GSI 1 185 #define TAVOR_CMD_QP_RAW_IPV6 2 186 #define TAVOR_CMD_QP_RAW_ETH 3 187 188 /* 189 * For certain Tavor QP state transition commands some optional flags are 190 * allowed. These "opmask" flags are defined by the Tavor register 191 * specification as a bitmask. 192 */ 193 #define TAVOR_CMD_OP_ALT_PATH (1 << 0) 194 #define TAVOR_CMD_OP_RRE (1 << 1) 195 #define TAVOR_CMD_OP_RAE (1 << 2) 196 #define TAVOR_CMD_OP_RWE (1 << 3) 197 #define TAVOR_CMD_OP_PKEYINDX (1 << 4) 198 #define TAVOR_CMD_OP_QKEY (1 << 5) 199 #define TAVOR_CMD_OP_MINRNRNAK (1 << 6) 200 #define TAVOR_CMD_OP_PRIM_PATH (1 << 7) 201 #define TAVOR_CMD_OP_SRA_SET (1 << 8) 202 #define TAVOR_CMD_OP_RRA_SET (1 << 9) 203 #define TAVOR_CMD_OP_PM_STATE (1 << 10) 204 #define TAVOR_CMD_OP_PRIM_PORT (1 << 11) 205 #define TAVOR_CMD_OP_RETRYCNT (1 << 12) 206 #define TAVOR_CMD_OP_ALT_RNRRETRY (1 << 13) 207 #define TAVOR_CMD_OP_ACKTIMEOUT (1 << 14) 208 #define TAVOR_CMD_OP_PRIM_RNRRETRY (1 << 15) 209 #define TAVOR_CMD_OP_SCHEDQUEUE (1 << 16) 210 211 212 /* 213 * The Tavor RTS2SQD command can take the following flag as part of its 214 * input modifier to request the Send Queue Drained event 215 */ 216 #define TAVOR_CMD_REQ_SQD_EVENT 0x80000000 217 218 /* 219 * The Tavor TORST command can take the following flag (as part of a bitmask) 220 * in its opcode modifier to request that the transition to reset should 221 * not go through the Error state (and, hence, should not generate "flushed- 222 * in-error" completions 223 */ 224 #define TAVOR_CMD_DIRECT_TO_RESET (1 << 1) 225 226 /* 227 * Some Tavor commands write an OUT mailbox entry, depending on the value of 228 * the 'opmod' parameter. These defines provide the correct opmod value to 229 * write depending on whether to write an entry or not. 230 */ 231 #define TAVOR_CMD_DO_OUTMBOX (0) 232 #define TAVOR_CMD_NO_OUTMBOX (1 << 0) 233 234 /* 235 * The Tavor SYS_EN command can take the following opcode modifier options 236 * to specify whether certain DDR checks should be performed. 237 */ 238 #define TAVOR_CMD_SYS_EN_NORMAL 0 239 #define TAVOR_CMD_SYS_EN_DDR_MEMCHECK 2 240 #define TAVOR_CMD_SYS_EN_DDR_PRESERVE 3 241 242 /* 243 * The Tavor MAP_EQ command can take the following flags (and use the 244 * TAVOR_CMD_UNMAP_EQ_MASK input modifier) to indicate whether the given 245 * event queue should mapped to or unmapped from the given event type. 246 */ 247 #define TAVOR_CMD_MAP_EQ_EVT_MAP 0 248 #define TAVOR_CMD_MAP_EQ_EVT_UNMAP 1 249 #define TAVOR_CMD_UNMAP_EQ_MASK 0x80000000 250 251 /* 252 * The following defines are used by the MAD_IFC command and the helper 253 * routines that get PortInfo, NodeInfo, GUIDInfo, and PKeyTable entries. 254 * 255 * The first indicates whether of not MKey checking should be enforced. 256 * This is passed in the opcode modifier field for MAD_IFC commands. 257 * 258 * The next set are used to define certain hardcoded management datagram (MAD) 259 * sizes, offsets, and header formats for each of the helper operations. 260 */ 261 #define TAVOR_CMD_MKEY_CHECK 0 262 #define TAVOR_CMD_MKEY_DONTCHECK 1 263 #define TAVOR_CMD_BKEY_DONTCHECK 2 264 265 #define TAVOR_CMD_MAD_IFC_SIZE 0x100 266 #define TAVOR_CMD_MADDATA_OFFSET 0x40 267 #define TAVOR_CMD_MADHDR0 0x01010101 268 #define TAVOR_CMD_MADHDR1 0x00000000 269 #define TAVOR_CMD_MADHDR2 0x00000000 270 #define TAVOR_CMD_MADHDR3 0x00000000 271 #define TAVOR_CMD_PORTINFO 0x00150000 272 #define TAVOR_CMD_NODEINFO 0x00110000 273 #define TAVOR_CMD_NODEDESC 0x00100000 274 #define TAVOR_CMD_GUIDINFO 0x00140000 275 #define TAVOR_CMD_PKEYTBLE 0x00160000 276 277 #define TAVOR_CMD_PERF_GET 0x01040101 278 #define TAVOR_CMD_PERF_SET 0x01040102 279 #define TAVOR_CMD_PERFCNTRS 0x00120000 280 #define TAVOR_CMD_PERFATTR 0x00000000 281 282 /* 283 * The next few defines are used to indicate the size of the "reserved" area 284 * in the WRITE_MTT command, and the respective sizes of the SET_IB and 285 * MGID_HASH commands 286 */ 287 #define TAVOR_CMD_WRITEMTT_RSVD_SZ 0x10 288 #define TAVOR_CMD_SETIB_SZ 0x8 289 #define TAVOR_CMD_MGIDHASH_SZ 0x10 290 291 /* 292 * This last define is used by tavor_cmn_ownership_cmd_post() to keep track 293 * of the direction (from hardware ownership to software, or vice versa) of 294 * the requested operation 295 */ 296 #define TAVOR_CMD_RSRC_HW2SW 0 297 #define TAVOR_CMD_RSRC_SW2HW 1 298 299 /* 300 * The following macros are used for handling any endianness related issues 301 * that might arise from the Tavor driver's internal use of MADs. 302 * 303 * TAVOR_GETPORTINFO_SWAP - All the necessary swapping to handle the 304 * response to a GetPortInfo MAD 305 * TAVOR_GETNODEINFO_SWAP - All the necessary swapping to handle the 306 * response to a GetNodeInfo MAD 307 * TAVOR_GETGUIDINFO_SWAP - All the necessary swapping to handle the 308 * response to a GetGUIDInfo MAD 309 * TAVOR_GETPKEYTABLE_SWAP - All the necessary swapping to handle the 310 * response to a GetPKeyTable MAD 311 */ 312 #ifdef _LITTLE_ENDIAN 313 #define TAVOR_GETPORTINFO_SWAP(portinfo) \ 314 { \ 315 (portinfo)->M_Key = ddi_swap64((portinfo)->M_Key); \ 316 (portinfo)->GidPrefix = ddi_swap64((portinfo)->GidPrefix); \ 317 (portinfo)->LID = ddi_swap16((portinfo)->LID); \ 318 (portinfo)->MasterSMLID = ddi_swap16((portinfo)->MasterSMLID); \ 319 (portinfo)->CapabilityMask = \ 320 ddi_swap32((portinfo)->CapabilityMask); \ 321 (portinfo)->DiagCode = ddi_swap16((portinfo)->DiagCode); \ 322 (portinfo)->M_KeyLeasePeriod = \ 323 ddi_swap16((portinfo)->M_KeyLeasePeriod); \ 324 (portinfo)->M_KeyViolations = \ 325 ddi_swap16((portinfo)->M_KeyViolations); \ 326 (portinfo)->P_KeyViolations = \ 327 ddi_swap16((portinfo)->P_KeyViolations); \ 328 (portinfo)->Q_KeyViolations = \ 329 ddi_swap16((portinfo)->Q_KeyViolations); \ 330 } 331 #else 332 #define TAVOR_GETPORTINFO_SWAP(portinfo) 333 #endif 334 335 #ifdef _LITTLE_ENDIAN 336 #define TAVOR_GETNODEINFO_SWAP(nodeinfo) \ 337 { \ 338 uint32_t tmp; \ 339 \ 340 tmp = ddi_swap32(((uint32_t *)nodeinfo)[9]); \ 341 (nodeinfo)->VendorID = tmp & 0xFFFFFF; \ 342 (nodeinfo)->LocalPortNum = tmp >> 24; \ 343 (nodeinfo)->Revision = \ 344 ddi_swap32(((uint32_t *)nodeinfo)[8]); \ 345 tmp = ddi_swap32(((uint32_t *)nodeinfo)[7]); \ 346 (nodeinfo)->PartitionCap = tmp >> 16; \ 347 (nodeinfo)->DeviceID = tmp & 0xFFFF; \ 348 (nodeinfo)->PortGUID = ddi_swap64((((uint64_t) \ 349 (((uint32_t *)nodeinfo)[6]) << 32) | \ 350 ((uint32_t *)nodeinfo)[5])); \ 351 (nodeinfo)->NodeGUID = ddi_swap64((((uint64_t) \ 352 (((uint32_t *)nodeinfo)[4]) << 32) | \ 353 ((uint32_t *)nodeinfo)[3])); \ 354 (nodeinfo)->SystemImageGUID = ddi_swap64((((uint64_t) \ 355 (((uint32_t *)nodeinfo)[2]) << 32) | \ 356 ((uint32_t *)nodeinfo)[1])); \ 357 } 358 #else 359 #define TAVOR_GETNODEINFO_SWAP(nodeinfo) \ 360 { \ 361 uint32_t tmp; \ 362 \ 363 tmp = ((uint32_t *)nodeinfo)[9]; \ 364 (nodeinfo)->VendorID = tmp & 0xFFFFFF; \ 365 (nodeinfo)->LocalPortNum = tmp >> 24; \ 366 (nodeinfo)->Revision = ((uint32_t *)nodeinfo)[8]; \ 367 tmp = ((uint32_t *)nodeinfo)[7]; \ 368 (nodeinfo)->PartitionCap = tmp >> 16; \ 369 (nodeinfo)->DeviceID = tmp & 0xFFFF; \ 370 (nodeinfo)->PortGUID = (((uint64_t) \ 371 (((uint32_t *)nodeinfo)[5]) << 32) | \ 372 ((uint32_t *)nodeinfo)[6]); \ 373 (nodeinfo)->NodeGUID = (((uint64_t) \ 374 (((uint32_t *)nodeinfo)[3]) << 32) | \ 375 ((uint32_t *)nodeinfo)[4]); \ 376 (nodeinfo)->SystemImageGUID = (((uint64_t) \ 377 (((uint32_t *)nodeinfo)[1]) << 32) | \ 378 ((uint32_t *)nodeinfo)[2]); \ 379 } 380 #endif 381 382 #ifdef _LITTLE_ENDIAN 383 #define TAVOR_GETGUIDINFO_SWAP(guidinfo) \ 384 { \ 385 int i; \ 386 \ 387 for (i = 0; i < 8; i++) { \ 388 (guidinfo)->GUIDBlocks[i] = \ 389 ddi_swap64((guidinfo)->GUIDBlocks[i]); \ 390 } \ 391 } 392 #else 393 #define TAVOR_GETGUIDINFO_SWAP(guidinfo) 394 #endif 395 396 #ifdef _LITTLE_ENDIAN 397 #define TAVOR_GETPKEYTABLE_SWAP(pkeytable) \ 398 { \ 399 int i; \ 400 \ 401 for (i = 0; i < 32; i++) { \ 402 (pkeytable)->P_KeyTableBlocks[i] = \ 403 ddi_swap16((pkeytable)->P_KeyTableBlocks[i]); \ 404 } \ 405 } 406 #else 407 #define TAVOR_GETPKEYTABLE_SWAP(pkeytable) 408 #endif 409 410 /* 411 * The Tavor MODIFY_MPT command can take the following opcode modifier 412 * options to specify whether to modify for ResizeSRQ() or to swap the 413 * full MPT entry. 414 */ 415 #define TAVOR_CMD_MODIFY_MPT_RESIZESRQ 3 416 #define TAVOR_CMD_MODIFY_MPT_SWAPFULL 5 417 418 419 /* 420 * The tavor_mbox_t structure is used internally by the Tavor driver to track 421 * all the information necessary to manage mailboxes for the Tavor command 422 * interface. Specifically, by containing a pointer to the buffer, the 423 * PCI mapped address, the access handle, and a back pointer to the 424 * tavor_rsrc_t structure used to track this resource, it provides enough 425 * information allocate, use, and free any type of mailbox. 426 * 427 * The mb_indx, mb_next, and mb_prev fields are used only by the mailbox 428 * alloc/free routines (see tavor_impl_mbox_alloc/free() for more details) 429 * and are not read or modified by any mailbox consumers. They are used 430 * to implement a fast allocation mechanism. 431 */ 432 typedef struct tavor_mbox_s { 433 void *mb_addr; 434 uint64_t mb_mapaddr; 435 ddi_acc_handle_t mb_acchdl; 436 tavor_rsrc_t *mb_rsrcptr; 437 uint_t mb_sync; 438 uint_t mb_indx; 439 uint_t mb_next; 440 uint_t mb_prev; 441 } tavor_mbox_t; 442 443 /* 444 * The tavor_mboxlist_t structure is used to track all the information 445 * relevant to the pools of Tavor mailboxes. Specifically, it has a pointer 446 * to an array of tavor_mbox_t structures, a lock and cv used for blocking 447 * on alloc when mailboxes are not available, and a head, tail, and entries 448 * free counter to keep track of which (if any) mailboxes are currently free. 449 * This is used (along with the mb_indx, mb_next, and mb_prev fields in the 450 * tavor_mbox_t) to implement the fast allocation mechanism. 451 */ 452 typedef struct tavor_mboxlist_s { 453 kmutex_t mbl_lock; 454 kcondvar_t mbl_cv; 455 tavor_mbox_t *mbl_mbox; 456 uint_t mbl_list_sz; 457 uint_t mbl_num_alloc; 458 uint_t mbl_head_indx; 459 uint_t mbl_tail_indx; 460 uint_t mbl_entries_free; 461 uint_t mbl_waiters; 462 uint_t mbl_pollers; 463 uint_t mbl_signal; 464 } tavor_mboxlist_t; 465 _NOTE(MUTEX_PROTECTS_DATA(tavor_mboxlist_t::mbl_lock, 466 tavor_mboxlist_t::mbl_mbox 467 tavor_mboxlist_t::mbl_list_sz 468 tavor_mboxlist_t::mbl_num_alloc 469 tavor_mboxlist_t::mbl_cv 470 tavor_mboxlist_t::mbl_head_indx 471 tavor_mboxlist_t::mbl_tail_indx 472 tavor_mboxlist_t::mbl_entries_free 473 tavor_mboxlist_t::mbl_waiters 474 tavor_mboxlist_t::mbl_pollers 475 tavor_mboxlist_t::mbl_signal 476 tavor_mbox_t::mb_next 477 tavor_mbox_t::mb_prev)) 478 479 /* 480 * The tavor_mbox_info_t structure is used by mailbox allocators to specify 481 * the type of mailbox(es) being requested. On a call to tavor_mbox_alloc() 482 * the mbi_alloc_flags may be set to TAVOR_ALLOC_INMBOX, TAVOR_ALLOC_OUTMBOX, 483 * or both. If it is able to allocate the request type(s) of mailboxes, 484 * tavor_mbox_alloc() will fill in the "mbi_in" and/or "mbi_out" pointers 485 * to point to valid tavor_mbox_t structures from the appropriate 486 * tavor_mboxlist_t (see above). 487 * This same structure is also passed to tavor_mbox_free(). It is the 488 * responsibility of the caller to tavor_mbox_alloc() to return this exact 489 * structure (unmodified) to tavor_mbox_free(). 490 * 491 * Note: If both "In" and "Out" mailboxes are requested, it is assured that 492 * no deadlock can result (from holding one mailbox while attempting to get 493 * the other). This is assured by the fact that the "In" mailbox will always 494 * be allocated first before attempting to allocate the "Out" 495 */ 496 typedef struct tavor_mbox_info_s { 497 uint_t mbi_alloc_flags; 498 uint_t mbi_sleep_context; 499 tavor_mbox_t *mbi_in; 500 tavor_mbox_t *mbi_out; 501 } tavor_mbox_info_t; 502 #define TAVOR_ALLOC_INMBOX (1 << 0) 503 #define TAVOR_ALLOC_OUTMBOX (1 << 1) 504 505 506 /* 507 * The tavor_cmd_t structure is used internally by the Tavor driver to track 508 * all the information necessary to manage outstanding firmware commands on 509 * the Tavor command interface. 510 * 511 * Each tavor_cmd_t structure contains a cv and lock which are used by the 512 * posting thread to block for completion (with cmd_status being overloaded 513 * to indicate the condition variable). The cmd_outparam field is used to 514 * return additional status from those Tavor commands that specifically 515 * require it. 516 * 517 * The cmd_indx, cmd_next, and cmd_prev fields are used by the outstanding 518 * command alloc/free routines (see tavor_outstanding_cmd_alloc/free() for 519 * more details). They are used (in much the same way as the mb_indx, 520 * mb_next, and mb_prev fields in tavor_mbox_t above) to implement a fast 521 * allocation mechanism. 522 */ 523 typedef struct tavor_cmd_s { 524 kmutex_t cmd_comp_lock; 525 kcondvar_t cmd_comp_cv; 526 uint64_t cmd_outparm; 527 uint_t cmd_status; 528 uint_t cmd_indx; 529 uint_t cmd_next; 530 uint_t cmd_prev; 531 } tavor_cmd_t; 532 _NOTE(MUTEX_PROTECTS_DATA(tavor_cmd_t::cmd_comp_lock, 533 tavor_cmd_t::cmd_comp_cv 534 tavor_cmd_t::cmd_status)) 535 536 /* 537 * The tavor_cmdlist_t structure is used in almost exactly the same way as 538 * the tavor_mboxlist_t above, but instead to track all the information 539 * relevant to the pool of outstanding Tavor commands. Specifically, it has 540 * a pointer to an array of tavor_cmd_t structures, a lock and cv used for 541 * blocking on alloc when outstanding command slots are not available, and a 542 * head, tail, and entries free counter to keep track of which (if any) 543 * command slots are currently free. This is used (along with the cmd_indx, 544 * cmd_next, and cmd_prev fields in the tavor_cmd_t) to implement the fast 545 * allocation mechanism. 546 */ 547 typedef struct tavor_cmdlist_s { 548 kmutex_t cml_lock; 549 kcondvar_t cml_cv; 550 tavor_cmd_t *cml_cmd; 551 uint_t cml_list_sz; 552 uint_t cml_num_alloc; 553 uint_t cml_head_indx; 554 uint_t cml_tail_indx; 555 uint_t cml_entries_free; 556 uint_t cml_waiters; 557 } tavor_cmdlist_t; 558 _NOTE(MUTEX_PROTECTS_DATA(tavor_cmdlist_t::cml_lock, 559 tavor_cmdlist_t::cml_cv 560 tavor_cmdlist_t::cml_cmd 561 tavor_cmdlist_t::cml_list_sz 562 tavor_cmdlist_t::cml_num_alloc 563 tavor_cmdlist_t::cml_head_indx 564 tavor_cmdlist_t::cml_tail_indx 565 tavor_cmdlist_t::cml_entries_free 566 tavor_cmdlist_t::cml_waiters 567 tavor_cmd_t::cmd_next 568 tavor_cmd_t::cmd_prev)) 569 _NOTE(LOCK_ORDER(tavor_cmdlist_t::cml_lock 570 tavor_cmd_t::cmd_comp_lock)) 571 572 /* 573 * The tavor_cmd_post_t structure is used by all the Tavor Firmware Command 574 * routines to post to Tavor firmware. The fields almost exactly mimic 575 * the fields in the Tavor HCR registers. The notable exception is the 576 * addition of the "cp_flags" field (which can be set to TAVOR_CMD_SPIN or 577 * TAVOR_CMD_NOSPIN). This flag really controls the value of the "e" bit 578 * in the HCR (i.e. the bit to indicate whether command should complete 579 * "in place" - in the HCR - or whether they should have their completions 580 * written to the command completion event queue. TAVOR_CMD_SPIN means 581 * to allow commands to complete "in place" and to poll the "go" bit in 582 * the HCR to determine completion. 583 * 584 * We use TAVOR_SLEEP and TAVOR_NOSLEEP for our TAVOR_CMD_ #defines. This is 585 * to maintain consistency with the rest of the SLEEP flags. Additionally, 586 * because TAVOR_SLEEPFLAG_FOR_CONTEXT() in tavor_rsrc.h returns TAVOR_SLEEP or 587 * NOSLEEP we must be compatible with this macro. 588 */ 589 typedef struct tavor_cmd_post_s { 590 uint64_t cp_inparm; 591 uint64_t cp_outparm; 592 uint32_t cp_inmod; 593 uint16_t cp_opcode; 594 uint16_t cp_opmod; 595 uint32_t cp_flags; 596 } tavor_cmd_post_t; 597 #define TAVOR_CMD_SLEEP_NOSPIN TAVOR_SLEEP 598 #define TAVOR_CMD_NOSLEEP_SPIN TAVOR_NOSLEEP 599 600 601 /* 602 * The following are the Tavor Firmware Command routines that accessible 603 * externally (i.e. throughout the rest of the Tavor driver software). 604 * These include the all the alloc/free routines, some initialization 605 * and cleanup routines, and the various specific Tavor firmware commands. 606 */ 607 int tavor_cmd_post(tavor_state_t *state, tavor_cmd_post_t *cmdpost); 608 int tavor_mbox_alloc(tavor_state_t *state, tavor_mbox_info_t *mbox_info, 609 uint_t mbox_wait); 610 void tavor_mbox_free(tavor_state_t *state, tavor_mbox_info_t *mbox_info); 611 int tavor_cmd_complete_handler(tavor_state_t *state, tavor_eqhdl_t eq, 612 tavor_hw_eqe_t *eqe); 613 int tavor_inmbox_list_init(tavor_state_t *state); 614 int tavor_intr_inmbox_list_init(tavor_state_t *state); 615 int tavor_outmbox_list_init(tavor_state_t *state); 616 int tavor_intr_outmbox_list_init(tavor_state_t *state); 617 void tavor_inmbox_list_fini(tavor_state_t *state); 618 void tavor_intr_inmbox_list_fini(tavor_state_t *state); 619 void tavor_outmbox_list_fini(tavor_state_t *state); 620 void tavor_intr_outmbox_list_fini(tavor_state_t *state); 621 int tavor_outstanding_cmdlist_init(tavor_state_t *state); 622 void tavor_outstanding_cmdlist_fini(tavor_state_t *state); 623 624 /* 625 * SYS_EN and SYS_DIS - used for startup and shutdown of Tavor device 626 */ 627 int tavor_sys_en_cmd_post(tavor_state_t *state, uint_t flags, 628 uint64_t *errorcode, uint_t sleepflag); 629 int tavor_sys_dis_cmd_post(tavor_state_t *state, uint_t sleepflag); 630 631 /* 632 * INIT_HCA and CLOSE_HCA - used for initialization and teardown of Tavor 633 * device configuration 634 */ 635 int tavor_init_hca_cmd_post(tavor_state_t *state, 636 tavor_hw_initqueryhca_t *inithca, uint_t sleepflag); 637 int tavor_close_hca_cmd_post(tavor_state_t *state, uint_t sleepflag); 638 639 /* 640 * INIT_IB, CLOSE_IB, and SET_IB - used for bring Tavor ports up and down, 641 * and to set properties of each port (e.g. PortInfo capability mask) 642 */ 643 int tavor_init_ib_cmd_post(tavor_state_t *state, 644 tavor_hw_initib_t *initib, uint_t port, uint_t sleepflag); 645 int tavor_close_ib_cmd_post(tavor_state_t *state, uint_t port, 646 uint_t sleepflag); 647 int tavor_set_ib_cmd_post(tavor_state_t *state, uint32_t capmask, 648 uint_t port, uint_t reset_qkey, uint_t sleepflag); 649 650 /* 651 * This common function is used to post the following Tavor QP state 652 * transition firmware commands: 653 * RTS2SQD, TOERR, TORST, RST2INIT, INIT2INIT, INIT2RTR, RTR2RTS, RTS2RTS, 654 * SQD2SQD, SQD2RTS, and SQERR2RTS. 655 */ 656 int tavor_cmn_qp_cmd_post(tavor_state_t *state, uint_t opcode, 657 tavor_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask, uint_t sleepflag); 658 659 /* 660 * This common function is used to post the following Tavor query firmware 661 * commands: 662 * QUERY_DEV_LIM, QUERY_FW, QUERY_DDR, QUERY_ADAPTER, QUERY_HCA, QUERY_MPT, 663 * QUERY_EQ, QUERY_CQ, and QUERY_QP. 664 */ 665 int tavor_cmn_query_cmd_post(tavor_state_t *state, uint_t opcode, 666 uint_t queryindx, void *query, uint_t size, uint_t sleepflag); 667 668 /* 669 * This common function is used to post the following Tavor resource ownership 670 * firmware commands: 671 * HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and SW2HW_CQ 672 */ 673 int tavor_cmn_ownership_cmd_post(tavor_state_t *state, uint_t opcode, 674 void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag); 675 676 /* 677 * MAD_IFC and helper functions - used for posting IB MADs to Tavor firmware. 678 * The helper functions are for the MADs most frequently used by the Tavor 679 * driver (internally). 680 */ 681 int tavor_mad_ifc_cmd_post(tavor_state_t *state, uint_t port, 682 uint_t sleepflag, uint32_t *mad, uint32_t *resp); 683 int tavor_getportinfo_cmd_post(tavor_state_t *state, uint_t port, 684 uint_t sleepflag, sm_portinfo_t *portinfo); 685 int tavor_getnodeinfo_cmd_post(tavor_state_t *state, uint_t sleepflag, 686 sm_nodeinfo_t *nodeinfo); 687 int tavor_getnodedesc_cmd_post(tavor_state_t *state, uint_t sleepflag, 688 sm_nodedesc_t *nodedesc); 689 int tavor_getguidinfo_cmd_post(tavor_state_t *state, uint_t port, 690 uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo); 691 int tavor_getpkeytable_cmd_post(tavor_state_t *state, uint_t port, 692 uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable); 693 int tavor_getperfcntr_cmd_post(tavor_state_t *state, uint_t port, 694 uint_t sleepflag, tavor_hw_sm_perfcntr_t *perfinfo, int reset); 695 696 /* 697 * WRITE_MTT - used for write MTT entries to the Tavor MTT table 698 */ 699 int tavor_write_mtt_cmd_post(tavor_state_t *state, 700 tavor_mbox_info_t *mbox_info, uint_t num_mtt, uint_t sleepflag); 701 702 /* 703 * SYNC_TPT - used to sync Tavor TPT caches 704 */ 705 int tavor_sync_tpt_cmd_post(tavor_state_t *state, uint_t sleepflag); 706 707 /* 708 * MAP_EQ - used for map classes of events to Tavor event queues (EQ) 709 */ 710 int tavor_map_eq_cmd_post(tavor_state_t *state, uint_t map, 711 uint_t eqcindx, uint64_t eqmapmask, uint_t sleepflag); 712 713 /* 714 * RESIZE_CQ - used for resize completion queue (CQ) 715 */ 716 int tavor_resize_cq_cmd_post(tavor_state_t *state, tavor_hw_cqc_t *cqc, 717 uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag); 718 719 /* 720 * CONF_SPECIAL_QP - used to configure a pair of queue pairs for use as 721 * special QP. Necessary to enable full QP0 and/or QP1 operation. 722 */ 723 int tavor_conf_special_qp_cmd_post(tavor_state_t *state, uint_t qpindx, 724 uint_t qptype, uint_t sleepflag); 725 726 /* 727 * MGID_HASH, READ_MGM, and WRITE_MGM - used for manipulation of the 728 * hardware resource tables for multicast groups. 729 */ 730 int tavor_mgid_hash_cmd_post(tavor_state_t *state, uint64_t mgid_h, 731 uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag); 732 int tavor_read_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg, 733 uint_t mcgindx, uint_t sleepflag); 734 int tavor_write_mgm_cmd_post(tavor_state_t *state, tavor_hw_mcg_t *mcg, 735 uint_t mcgindx, uint_t sleepflag); 736 737 /* 738 * MOD_STAT_CFG - used to configure (override) settings set in NVRAM before 739 * a call to QUERY_DEV_LIM. This is primarily used for SRQ settings in 740 * the firmware. 741 */ 742 int tavor_mod_stat_cfg_cmd_post(tavor_state_t *state); 743 744 /* 745 * MODIFY_MPT - used to change MPT attributes of a memory region. This 746 * is primarily used for Resizing SRQs. 747 */ 748 int tavor_modify_mpt_cmd_post(tavor_state_t *state, tavor_hw_mpt_t *mpt, 749 uint_t mptindx, uint_t flags, uint_t sleepflag); 750 751 #ifdef __cplusplus 752 } 753 #endif 754 755 #endif /* _SYS_IB_ADAPTERS_TAVOR_CMD_H */ 756