/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_IB_ADAPTERS_HERMON_CMD_H #define _SYS_IB_ADAPTERS_HERMON_CMD_H /* * hermon_cmd.h * Contains all of the prototypes, #defines, and structures necessary * for the Hermon Firmware Command routines. * Specifically it contains the command types, command statuses and flags, * structures used for managing Hermon mailboxes and outstanding commands, * and prototypes for most of the functions consumed by other parts of * the Hermon driver. */ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Defines used hermon_write_hcr() to determine the duration and number of * times (at maximum) to poll while waiting for a Hermon firmware command to * release the HCR resource (i.e. waiting for the command to complete) */ #define HERMON_CMD_POLL_DELAY 1 #define HERMON_CMD_POLL_MAX 3000000 /* * The following defines specify the default number of mailboxes (log 2) of * each type and their size and alignment restrictions. By default the number * of both "In" and "Out" mailboxes is set to 1024 (with each mailbox being * 4KB in size), but both the number and sizes of each are controllable * through the "hermon_log_num_inmbox", "hermon_log_num_outmbox", * "hermon_log_inmbox_size" and "hermon_log_outmbox_size" configuration * variables. Also, we have a define that is used to allocate interrupt * mailboxes (1 in, 1 out). */ #define HERMON_NUM_MAILBOXES_SHIFT 0xA #define HERMON_NUM_INTR_MAILBOXES_SHIFT 0 #define HERMON_MBOX_SIZE_SHIFT 0xC #define HERMON_MBOX_SIZE (1 << HERMON_MBOX_SIZE_SHIFT) #define HERMON_MBOX_ALIGN HERMON_MBOX_SIZE /* * These are the defines for the Hermon command type (opcodes). They are * specified by the Hermon PRM */ /* Init Commands */ #define QUERY_DEV_LIM 0x3 #define QUERY_DEV_CAP 0x3 #define QUERY_FW 0x4 #define QUERY_ADAPTER 0x6 #define INIT_HCA 0x7 #define CLOSE_HCA 0x8 #define INIT_IB 0x9 #define INIT_PORT 0x9 #define CLOSE_IB 0xA #define CLOSE_PORT 0xA #define QUERY_HCA 0xB #define SET_IB 0xC #define SET_PORT 0xC /* added late in tavor for SRQ support */ #define MOD_STAT_CFG 0x34 /* added late in Hermon (PRM 0.35) */ #define QUERY_PORT 0x43 /* TPT Commands */ #define SW2HW_MPT 0xD #define QUERY_MPT 0xE #define HW2SW_MPT 0xF #define READ_MTT 0x10 #define WRITE_MTT 0x11 #define SYNC_TPT 0x2F #define MODIFY_MPT 0x39 /* EQ Commands */ #define MAP_EQ 0x12 #define SW2HW_EQ 0x13 #define HW2SW_EQ 0x14 #define QUERY_EQ 0x15 /* CQ Commands */ #define SW2HW_CQ 0x16 #define HW2SW_CQ 0x17 #define QUERY_CQ 0x18 #define MODIFY_CQ 0x2C /* Modify CQ Command - opcode modifiers */ #define RESIZE_CQ 0x0 #define MODIFY_MODERATION_CQ 0x1 #define MODIFY_EQN 0x2 /* QP Commands */ #define RST2INIT_QP 0x19 #define INIT2INIT_QP 0x2D #define INIT2RTR_QP 0x1A #define RTR2RTS_QP 0x1B #define RTS2RTS_QP 0x1C #define SQERR2RTS_QP 0x1D #define TOERR_QP 0x1E #define RTS2SQD_QP 0x1F #define SQD2SQD_QP 0x38 #define SQD2RTS_QP 0x20 #define TORST_QP 0x21 #define QUERY_QP 0x22 #define SUSPEND_QP 0x32 /* new w/ hermon driver */ #define UNSUSPEND_QP 0x33 /* new w/ hermon driver */ /* SPECIAL QPs Commands */ #define CONF_SPECIAL_QP 0x23 #define MAD_IFC 0x24 /* added late in tavor for SRQ support */ /* SRQ Commands */ #define SW2HW_SRQ 0x35 #define HW2SW_SRQ 0x36 #define QUERY_SRQ 0x37 /* new in hermon, replaces part of modify MPT */ #define RESIZE_SRQ 0X44 /* new in hermon, set limit water mark */ #define ARM_RQ 0X40 /* new in hermon (PRM 0.36) configure interrupt moderation */ #define CONFIG_INT_MOD 0X45 #define HW_HEALTH_CHECK 0X50 /* Multicast Group Commands */ #define READ_MGM 0x25 #define READ_MCG 0x25 #define WRITE_MGM 0x26 #define WRITE_MCG 0x26 #define MGID_HASH 0x27 /* Debug/Diagnostic Commands */ #define QUERY_DEBUG_MSG 0x2A #define SET_DEBUG_MSG 0x2B #define DIAG_RPRT 0x30 #define CMD_NOP 0x31 #define SET_VLAN_FLTR 0x47 #define SET_MCAST_FLTR 0x48 #define CONFIG_FC 0x4A #define QUERY_FC 0x4B #define HEART_BEAT_RQ 0x4C #define SENSE_PORT 0x4D /* ICM and related commands - w/out LAM commands from Arbel */ #define RUN_FW 0xFF6 #define UNMAP_ICM 0xFF9 #define MAP_ICM 0xFFA #define UNMAP_ICM_AUX 0xFFB #define MAP_ICM_AUX 0xFFC #define SET_ICM_SIZE 0xFFD #define UNMAP_FA 0xFFE #define MAP_FA 0xFFF /* * Commands mentioned but not defined in PRM v35 * REL_ICM_AUX * INIT_VM */ /* * These are the defines for the Hermon command completion statuses. They are * also specified (in part) by the Hermon PRM. However, * the HERMON_CMD_INSUFF_RSRC, HERMON_CMD_TIMEOUT and HERMON_CMD_INVALID_STATUS * codes were added for this driver specifically to indicate the conditions * when insufficient resources are available for a command, when a command has * timed out (failure in the Hermon firmware) or when some other invalid result * was received. */ #define HERMON_CMD_TIMEOUT_TOGGLE 0xFFFC /* -4 */ #define HERMON_CMD_INSUFF_RSRC 0xFFFD /* -3 */ #define HERMON_CMD_TIMEOUT_GOBIT 0xFFFE /* -2 */ #define HERMON_CMD_INVALID_STATUS 0xFFFF /* -1 */ #define HERMON_CMD_SUCCESS 0x00 #define HERMON_CMD_INTERNAL_ERR 0x01 #define HERMON_CMD_BAD_OP 0x02 #define HERMON_CMD_BAD_PARAM 0x03 #define HERMON_CMD_BAD_SYS_STATE 0x04 #define HERMON_CMD_BAD_RESOURCE 0x05 #define HERMON_CMD_RESOURCE_BUSY 0x06 #define HERMON_CMD_EXCEED_LIM 0x08 #define HERMON_CMD_BAD_RES_STATE 0x09 #define HERMON_CMD_BAD_INDEX 0x0A #define HERMON_CMD_BAD_NVMEM 0x0B #define HERMON_CMD_ICM_ERROR 0x0C #define HERMON_CMD_BAD_QP_STATE 0x10 #define HERMON_CMD_BAD_SEG_PARAM 0x20 #define HERMON_CMD_REG_BOUND 0x21 #define HERMON_CMD_BAD_PKT 0x30 #define HERMON_CMD_BAD_SIZE 0x40 /* * These defines are used in the "special QP" allocation to indicate the type * of special QP (SMI, GSI, or one of the raw types). These values are * specified by the Hermon PRM */ #define HERMON_CMD_QP_SMI 0 #define HERMON_CMD_QP_GSI 1 #define HERMON_CMD_QP_RAW_IPV6 2 #define HERMON_CMD_QP_RAW_ETH 3 #define HERMON_CMD_SPEC_QP_OPMOD(smi, gsi) \ ((smi & 0x01) | ((gsi & 0x01) << 1)) /* * For certain Hermon QP state transition commands some optional flags are * allowed. These "opmask" flags are defined by the Hermon PRM * as a bitmask. */ #define HERMON_CMD_OP_ALT_PATH (1 << 0) #define HERMON_CMD_OP_RRE (1 << 1) #define HERMON_CMD_OP_RAE (1 << 2) #define HERMON_CMD_OP_RWE (1 << 3) #define HERMON_CMD_OP_PKEYINDX (1 << 4) /* primary path */ #define HERMON_CMD_OP_QKEY (1 << 5) #define HERMON_CMD_OP_MINRNRNAK (1 << 6) #define HERMON_CMD_OP_PRIM_PATH (1 << 7) #define HERMON_CMD_OP_SRA_SET (1 << 8) #define HERMON_CMD_OP_RRA_SET (1 << 9) #define HERMON_CMD_OP_PM_STATE (1 << 10) /* migration */ /* HERMON_CMD_OP_PRIM_PORT is obsolete, instead use HERMON_CMD_OP_SCHEDQUEUE */ #define HERMON_CMD_OP_PRIM_PORT (1 << 11) #define HERMON_CMD_OP_RETRYCNT (1 << 12) /* Global */ #define HERMON_CMD_OP_ALT_RNRRETRY (1 << 13) #define HERMON_CMD_OP_ACKTIMEOUT (1 << 14) /* primary path */ #define HERMON_CMD_OP_PRIM_RNRRETRY (1 << 15) /* reserved in HERMON */ #define HERMON_CMD_OP_SCHEDQUEUE (1 << 16) #define HERMON_CMD_OP_RSSCONTEXT (1 << 17) #define HERMON_CMD_OP_SRQN (1 << 18) /* for rss balancing */ #define HERMON_CMD_OP_CQN_RCV (1 << 19) /* for rss balancing */ /* Bits 20 - 31 RESERVED - per PRM 0.35c */ /* * The Hermon RTS2SQD command can take the following flag as part of its * input modifier to request the Send Queue Drained event */ #define HERMON_CMD_REQ_SQD_EVENT 0x80000000 /* * The Hermon TORST command can take the following flag (as part of a bitmask) * in its opcode modifier to request that the transition to reset should * not go through the Error state (and, hence, should not generate "flushed- * in-error" completions */ #define HERMON_CMD_DIRECT_TO_RESET (1 << 1) /* * Some Hermon commands write an OUT mailbox entry, depending on the value of * the 'opmod' parameter. These defines provide the correct opmod value to * write depending on whether to write an entry or not. */ #define HERMON_CMD_DO_OUTMBOX (0) #define HERMON_CMD_NO_OUTMBOX (1 << 0) /* * The Hermon MAP_EQ command can take the following flags (and use the * HERMON_CMD_UNMAP_EQ_MASK input modifier) to indicate whether the given * event queue should mapped to or unmapped from the given event type. */ #define HERMON_CMD_MAP_EQ_EVT_MAP 0 #define HERMON_CMD_MAP_EQ_EVT_UNMAP 1 #define HERMON_CMD_UNMAP_EQ_MASK 0x80000000 /* * The following defines are used by the MAD_IFC command and the helper * routines that get PortInfo, NodeInfo, GUIDInfo, and PKeyTable entries. * * The first indicates whether of not MKey checking should be enforced. * This is passed in the opcode modifier field for MAD_IFC commands. * * The next set are used to define certain hardcoded management datagram (MAD) * sizes, offsets, and header formats for each of the helper operations. */ #define HERMON_CMD_MKEY_CHECK 0 #define HERMON_CMD_MKEY_DONTCHECK 1 #define HERMON_CMD_BKEY_DONTCHECK 2 #define HERMON_CMD_MAD_IFC_SIZE 0x100 #define HERMON_CMD_MADDATA_OFFSET 0x40 #define HERMON_CMD_MADHDR0 0x01010101 #define HERMON_CMD_MADHDR1 0x00000000 #define HERMON_CMD_MADHDR2 0x00000000 #define HERMON_CMD_MADHDR3 0x00000000 #define HERMON_CMD_PORTINFO 0x00150000 #define HERMON_CMD_NODEINFO 0x00110000 #define HERMON_CMD_NODEDESC 0x00100000 #define HERMON_CMD_GUIDINFO 0x00140000 #define HERMON_CMD_PKEYTBLE 0x00160000 #define HERMON_CMD_PERF_GET 0x01040101 #define HERMON_CMD_PERF_SET 0x01040102 #define HERMON_CMD_CLASSPORTINFO 0x00010000 #define HERMON_CMD_PERFCNTRS 0x00120000 #define HERMON_CMD_EXTPERFCNTRS 0x001D0000 #define HERMON_CMD_PERFATTR 0x00000000 #define HERMON_IS_EXT_WIDTH_SUPPORTED 0x0000020000000000 #define HERMON_IS_EXT_WIDTH_SUPPORTED_NOIETF 0x0000040000000000 /* * The next few defines are used to indicate the size of the "reserved" area * in the WRITE_MTT command, and the respective sizes of the SET_PORT and * MGID_HASH commands */ #define HERMON_CMD_WRITEMTT_RSVD_SZ 0x10 #define HERMON_CMD_SETPORT_SZ 0x8 #define HERMON_CMD_MGIDHASH_SZ 0x10 /* * This last define is used by hermon_cmn_ownership_cmd_post() to keep track * of the direction (from hardware ownership to software, or vice versa) of * the requested operation */ #define HERMON_CMD_RSRC_HW2SW 0 #define HERMON_CMD_RSRC_SW2HW 1 /* * The following macros are used for handling any endianness related issues * that might arise from the Hermon driver's internal use of MADs. * * HERMON_GETPORTINFO_SWAP - All the necessary swapping to handle the * response to a GetPortInfo MAD * HERMON_GETNODEINFO_SWAP - All the necessary swapping to handle the * response to a GetNodeInfo MAD * HERMON_GETGUIDINFO_SWAP - All the necessary swapping to handle the * response to a GetGUIDInfo MAD * HERMON_GETPKEYTABLE_SWAP - All the necessary swapping to handle the * response to a GetPKeyTable MAD */ #ifdef _LITTLE_ENDIAN #define HERMON_GETPORTINFO_SWAP(portinfo) \ { \ (portinfo)->M_Key = ddi_swap64((portinfo)->M_Key); \ (portinfo)->GidPrefix = ddi_swap64((portinfo)->GidPrefix); \ (portinfo)->LID = ddi_swap16((portinfo)->LID); \ (portinfo)->MasterSMLID = ddi_swap16((portinfo)->MasterSMLID); \ (portinfo)->CapabilityMask = \ ddi_swap32((portinfo)->CapabilityMask); \ (portinfo)->DiagCode = ddi_swap16((portinfo)->DiagCode); \ (portinfo)->M_KeyLeasePeriod = \ ddi_swap16((portinfo)->M_KeyLeasePeriod); \ (portinfo)->M_KeyViolations = \ ddi_swap16((portinfo)->M_KeyViolations); \ (portinfo)->P_KeyViolations = \ ddi_swap16((portinfo)->P_KeyViolations); \ (portinfo)->Q_KeyViolations = \ ddi_swap16((portinfo)->Q_KeyViolations); \ } #else #define HERMON_GETPORTINFO_SWAP(portinfo) #endif #ifdef _LITTLE_ENDIAN #define HERMON_GETNODEINFO_SWAP(nodeinfo) \ { \ uint32_t tmp; \ \ tmp = ddi_swap32(((uint32_t *)nodeinfo)[9]); \ (nodeinfo)->VendorID = tmp & 0xFFFFFF; \ (nodeinfo)->LocalPortNum = tmp >> 24; \ (nodeinfo)->Revision = \ ddi_swap32(((uint32_t *)nodeinfo)[8]); \ tmp = ddi_swap32(((uint32_t *)nodeinfo)[7]); \ (nodeinfo)->PartitionCap = tmp >> 16; \ (nodeinfo)->DeviceID = tmp & 0xFFFF; \ (nodeinfo)->PortGUID = ddi_swap64((((uint64_t) \ (((uint32_t *)nodeinfo)[6]) << 32) | \ ((uint32_t *)nodeinfo)[5])); \ (nodeinfo)->NodeGUID = ddi_swap64((((uint64_t) \ (((uint32_t *)nodeinfo)[4]) << 32) | \ ((uint32_t *)nodeinfo)[3])); \ (nodeinfo)->SystemImageGUID = ddi_swap64((((uint64_t) \ (((uint32_t *)nodeinfo)[2]) << 32) | \ ((uint32_t *)nodeinfo)[1])); \ } #else #define HERMON_GETNODEINFO_SWAP(nodeinfo) \ { \ uint32_t tmp; \ \ tmp = ((uint32_t *)nodeinfo)[9]; \ (nodeinfo)->VendorID = tmp & 0xFFFFFF; \ (nodeinfo)->LocalPortNum = tmp >> 24; \ (nodeinfo)->Revision = ((uint32_t *)nodeinfo)[8]; \ tmp = ((uint32_t *)nodeinfo)[7]; \ (nodeinfo)->PartitionCap = tmp >> 16; \ (nodeinfo)->DeviceID = tmp & 0xFFFF; \ (nodeinfo)->PortGUID = (((uint64_t) \ (((uint32_t *)nodeinfo)[5]) << 32) | \ ((uint32_t *)nodeinfo)[6]); \ (nodeinfo)->NodeGUID = (((uint64_t) \ (((uint32_t *)nodeinfo)[3]) << 32) | \ ((uint32_t *)nodeinfo)[4]); \ (nodeinfo)->SystemImageGUID = (((uint64_t) \ (((uint32_t *)nodeinfo)[1]) << 32) | \ ((uint32_t *)nodeinfo)[2]); \ } #endif #ifdef _LITTLE_ENDIAN #define HERMON_GETGUIDINFO_SWAP(guidinfo) \ { \ int i; \ \ for (i = 0; i < 8; i++) { \ (guidinfo)->GUIDBlocks[i] = \ ddi_swap64((guidinfo)->GUIDBlocks[i]); \ } \ } #else #define HERMON_GETGUIDINFO_SWAP(guidinfo) #endif #ifdef _LITTLE_ENDIAN #define HERMON_GETPKEYTABLE_SWAP(pkeytable) \ { \ int i; \ \ for (i = 0; i < 32; i++) { \ (pkeytable)->P_KeyTableBlocks[i] = \ ddi_swap16((pkeytable)->P_KeyTableBlocks[i]); \ } \ } #else #define HERMON_GETPKEYTABLE_SWAP(pkeytable) #endif /* * The Hermon MODIFY_MPT command can take the following opcode modifier * options to specify whether to modify for ResizeSRQ() or to swap the * full MPT entry. */ #define HERMON_CMD_MODIFY_MPT_RESIZESRQ 3 #define HERMON_CMD_MODIFY_MPT_SWAPFULL 5 /* * Hermon MOD_STAT_CFG Opcode Modifier */ #define HERMON_MOD_STAT_CFG_PTR 0x0 #define HERMON_MOD_STAT_CFG_INLINE 0x1 #define HERMON_MOD_STAT_CFG_DEFAULTS 0xF /* * The hermon_mbox_t structure is used internally by the Hermon driver to track * all the information necessary to manage mailboxes for the Hermon command * interface. Specifically, by containing a pointer to the buffer, the * PCI mapped address, the access handle, and a back pointer to the * hermon_rsrc_t structure used to track this resource, it provides enough * information allocate, use, and free any type of mailbox. * * The mb_indx, mb_next, and mb_prev fields are used only by the mailbox * alloc/free routines (see hermon_impl_mbox_alloc/free() for more details) * and are not read or modified by any mailbox consumers. They are used * to implement a fast allocation mechanism. */ typedef struct hermon_mbox_s { void *mb_addr; uint64_t mb_mapaddr; ddi_acc_handle_t mb_acchdl; hermon_rsrc_t *mb_rsrcptr; uint_t mb_indx; uint_t mb_next; uint_t mb_prev; } hermon_mbox_t; /* * The hermon_mboxlist_t structure is used to track all the information * relevant to the pools of Hermon mailboxes. Specifically, it has a pointer * to an array of hermon_mbox_t structures, a lock and cv used for blocking * on alloc when mailboxes are not available, and a head, tail, and entries * free counter to keep track of which (if any) mailboxes are currently free. * This is used (along with the mb_indx, mb_next, and mb_prev fields in the * hermon_mbox_t) to implement the fast allocation mechanism. */ typedef struct hermon_mboxlist_s { kmutex_t mbl_lock; kcondvar_t mbl_cv; hermon_mbox_t *mbl_mbox; uint_t mbl_list_sz; uint_t mbl_num_alloc; uint_t mbl_head_indx; uint_t mbl_tail_indx; uint_t mbl_entries_free; uint_t mbl_waiters; uint_t mbl_pollers; uint_t mbl_signal; } hermon_mboxlist_t; _NOTE(MUTEX_PROTECTS_DATA(hermon_mboxlist_t::mbl_lock, hermon_mboxlist_t::mbl_mbox hermon_mboxlist_t::mbl_list_sz hermon_mboxlist_t::mbl_num_alloc hermon_mboxlist_t::mbl_cv hermon_mboxlist_t::mbl_head_indx hermon_mboxlist_t::mbl_tail_indx hermon_mboxlist_t::mbl_entries_free hermon_mboxlist_t::mbl_waiters hermon_mboxlist_t::mbl_pollers hermon_mboxlist_t::mbl_signal hermon_mbox_t::mb_next hermon_mbox_t::mb_prev)) /* * The hermon_mbox_info_t structure is used by mailbox allocators to specify * the type of mailbox(es) being requested. On a call to hermon_mbox_alloc() * the mbi_alloc_flags may be set to HERMON_ALLOC_INMBOX, HERMON_ALLOC_OUTMBOX, * or both. If it is able to allocate the request type(s) of mailboxes, * hermon_mbox_alloc() will fill in the "mbi_in" and/or "mbi_out" pointers * to point to valid hermon_mbox_t structures from the appropriate * hermon_mboxlist_t (see above). * This same structure is also passed to hermon_mbox_free(). It is the * responsibility of the caller to hermon_mbox_alloc() to return this exact * structure (unmodified) to hermon_mbox_free(). * * Note: If both "In" and "Out" mailboxes are requested, it is assured that * no deadlock can result (from holding one mailbox while attempting to get * the other). This is assured by the fact that the "In" mailbox will always * be allocated first before attempting to allocate the "Out" */ typedef struct hermon_mbox_info_s { uint_t mbi_alloc_flags; uint_t mbi_sleep_context; hermon_mbox_t *mbi_in; hermon_mbox_t *mbi_out; } hermon_mbox_info_t; #define HERMON_ALLOC_INMBOX (1 << 0) #define HERMON_ALLOC_OUTMBOX (1 << 1) /* * The hermon_cmd_t structure is used internally by the Hermon driver to track * all the information necessary to manage outstanding firmware commands on * the Hermon command interface. * * Each hermon_cmd_t structure contains a cv and lock which are used by the * posting thread to block for completion (with cmd_status being overloaded * to indicate the condition variable). The cmd_outparam field is used to * return additional status from those Hermon commands that specifically * require it. * * The cmd_indx, cmd_next, and cmd_prev fields are used by the outstanding * command alloc/free routines (see hermon_outstanding_cmd_alloc/free() for * more details). They are used (in much the same way as the mb_indx, * mb_next, and mb_prev fields in hermon_mbox_t above) to implement a fast * allocation mechanism. */ typedef struct hermon_cmd_s { kmutex_t cmd_comp_lock; kcondvar_t cmd_comp_cv; uint64_t cmd_outparm; uint_t cmd_status; uint_t cmd_indx; uint_t cmd_next; uint_t cmd_prev; } hermon_cmd_t; _NOTE(MUTEX_PROTECTS_DATA(hermon_cmd_t::cmd_comp_lock, hermon_cmd_t::cmd_comp_cv hermon_cmd_t::cmd_status)) /* * The hermon_cmdlist_t structure is used in almost exactly the same way as * the hermon_mboxlist_t above, but instead to track all the information * relevant to the pool of outstanding Hermon commands. Specifically, it has * a pointer to an array of hermon_cmd_t structures, a lock and cv used for * blocking on alloc when outstanding command slots are not available, and a * head, tail, and entries free counter to keep track of which (if any) * command slots are currently free. This is used (along with the cmd_indx, * cmd_next, and cmd_prev fields in the hermon_cmd_t) to implement the fast * allocation mechanism. */ typedef struct hermon_cmdlist_s { kmutex_t cml_lock; kcondvar_t cml_cv; hermon_cmd_t *cml_cmd; uint_t cml_list_sz; uint_t cml_num_alloc; uint_t cml_head_indx; uint_t cml_tail_indx; uint_t cml_entries_free; uint_t cml_waiters; } hermon_cmdlist_t; _NOTE(MUTEX_PROTECTS_DATA(hermon_cmdlist_t::cml_lock, hermon_cmdlist_t::cml_cv hermon_cmdlist_t::cml_cmd hermon_cmdlist_t::cml_list_sz hermon_cmdlist_t::cml_num_alloc hermon_cmdlist_t::cml_head_indx hermon_cmdlist_t::cml_tail_indx hermon_cmdlist_t::cml_entries_free hermon_cmdlist_t::cml_waiters hermon_cmd_t::cmd_next hermon_cmd_t::cmd_prev)) _NOTE(LOCK_ORDER(hermon_cmdlist_t::cml_lock hermon_cmd_t::cmd_comp_lock)) /* * The hermon_cmd_post_t structure is used by all the Hermon Firmware Command * routines to post to Hermon firmware. The fields almost exactly mimic * the fields in the Hermon HCR registers. The notable exception is the * addition of the "cp_flags" field (which can be set to HERMON_CMD_SPIN or * HERMON_CMD_NOSPIN). This flag really controls the value of the "e" bit * in the HCR (i.e. the bit to indicate whether command should complete * "in place" - in the HCR - or whether they should have their completions * written to the command completion event queue. HERMON_CMD_SPIN means * to allow commands to complete "in place" and to poll the "go" bit in * the HCR to determine completion. * * We use HERMON_SLEEP and HERMON_NOSLEEP for our HERMON_CMD_ #defines. This is * to maintain consistency with the rest of the SLEEP flags. Additionally, * because HERMON_SLEEPFLAG_FOR_CONTEXT() in hermon_rsrc.h returns HERMON_SLEEP * or NOSLEEP we must be compatible with this macro. */ typedef struct hermon_cmd_post_s { uint64_t cp_inparm; uint64_t cp_outparm; uint32_t cp_inmod; uint16_t cp_opcode; uint16_t cp_opmod; uint32_t cp_flags; } hermon_cmd_post_t; #define HERMON_CMD_SLEEP_NOSPIN HERMON_SLEEP #define HERMON_CMD_NOSLEEP_SPIN HERMON_NOSLEEP /* * The following are the Hermon Firmware Command routines that accessible * externally (i.e. throughout the rest of the Hermon driver software). * These include the all the alloc/free routines, some initialization * and cleanup routines, and the various specific Hermon firmware commands. */ int hermon_cmd_post(hermon_state_t *state, hermon_cmd_post_t *cmdpost); int hermon_mbox_alloc(hermon_state_t *state, hermon_mbox_info_t *mbox_info, uint_t mbox_wait); void hermon_mbox_free(hermon_state_t *state, hermon_mbox_info_t *mbox_info); int hermon_cmd_complete_handler(hermon_state_t *state, hermon_eqhdl_t eq, hermon_hw_eqe_t *eqe); int hermon_inmbox_list_init(hermon_state_t *state); int hermon_intr_inmbox_list_init(hermon_state_t *state); int hermon_outmbox_list_init(hermon_state_t *state); int hermon_intr_outmbox_list_init(hermon_state_t *state); void hermon_inmbox_list_fini(hermon_state_t *state); void hermon_intr_inmbox_list_fini(hermon_state_t *state); void hermon_outmbox_list_fini(hermon_state_t *state); void hermon_intr_outmbox_list_fini(hermon_state_t *state); int hermon_outstanding_cmdlist_init(hermon_state_t *state); void hermon_outstanding_cmdlist_fini(hermon_state_t *state); /* Added for MemFree */ int hermon_map_cmd_post(hermon_state_t *state, hermon_dma_info_t *dinfo, uint16_t opcode, ddi_dma_cookie_t cookie, uint_t ccount); int hermon_map_fa_cmd_post(hermon_state_t *state); int hermon_run_fw_cmd_post(hermon_state_t *state); int hermon_set_icm_size_cmd_post(hermon_state_t *state); int hermon_map_icm_aux_cmd_post(hermon_state_t *state); int hermon_map_icm_cmd_post(hermon_state_t *state); int hermon_disable_lam_cmd_post(hermon_state_t *state); int hermon_unmap_icm_cmd_post(hermon_state_t *state, hermon_dma_info_t *dma_info); int hermon_unmap_icm_aux_cmd_post(hermon_state_t *state); int hermon_unmap_fa_cmd_post(hermon_state_t *state); /* * INIT_HCA and CLOSE_HCA - used for initialization and teardown of Hermon * device configuration */ int hermon_init_hca_cmd_post(hermon_state_t *state, hermon_hw_initqueryhca_t *inithca, uint_t sleepflag); int hermon_close_hca_cmd_post(hermon_state_t *state, uint_t sleepflag); /* * INIT_PORT, CLOSE_PORT, and SET_PORT - used for bring Hermon ports up and * down, and to set properties of each port (e.g. PortInfo capability mask) * NOTE: New names for the commands in Hermon (previously init_ close_ and * set_ib */ int hermon_set_port_cmd_post(hermon_state_t *state, hermon_hw_set_port_t *initport, uint_t port, uint_t sleepflag); int hermon_init_port_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag); int hermon_close_port_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag); /* * This common function is used to post the following Hermon QP state * transition firmware commands: * RTS2SQD, TOERR, TORST, RST2INIT, INIT2INIT, INIT2RTR, RTR2RTS, RTS2RTS, * SQD2SQD, SQD2RTS, and SQERR2RTS. */ int hermon_cmn_qp_cmd_post(hermon_state_t *state, uint_t opcode, hermon_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask, uint_t sleepflag); /* * This common function is used to post the following Hermon query firmware * commands: * QUERY_DEV_LIM/CAP, QUERY_FW, QUERY_ADAPTER, QUERY_HCA, QUERY_MPT, * QUERY_EQ, QUERY_CQ, and QUERY_QP. * New with FCoIB, QUERY_FC */ int hermon_cmn_query_cmd_post(hermon_state_t *state, uint_t opcode, uint_t opmod, uint_t queryindx, void *query, uint_t size, uint_t sleepflag); /* * This common function is used to post the following Hermon resource ownership * firmware commands: * HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and SW2HW_CQ */ int hermon_cmn_ownership_cmd_post(hermon_state_t *state, uint_t opcode, void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag); /* * MAD_IFC and helper functions - used for posting IB MADs to Hermon firmware. * The helper functions are for the MADs most frequently used by the Hermon * driver (internally). */ int hermon_mad_ifc_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag, uint32_t *mad, uint32_t *resp); int hermon_getportinfo_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag, sm_portinfo_t *portinfo); int hermon_getnodeinfo_cmd_post(hermon_state_t *state, uint_t sleepflag, sm_nodeinfo_t *nodeinfo); int hermon_getnodedesc_cmd_post(hermon_state_t *state, uint_t sleepflag, sm_nodedesc_t *nodedesc); int hermon_getguidinfo_cmd_post(hermon_state_t *state, uint_t port, uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo); int hermon_getpkeytable_cmd_post(hermon_state_t *state, uint_t port, uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable); int hermon_is_ext_port_counters_supported(hermon_state_t *state, uint_t port, uint_t sleepflag, int *ext_width_supported); int hermon_getextperfcntr_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag, hermon_hw_sm_extperfcntr_t *perfinfo); int hermon_getperfcntr_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag, hermon_hw_sm_perfcntr_t *perfinfo, int reset); /* * WRITE_MTT - used for write MTT entries to the Hermon MTT table */ int hermon_write_mtt_cmd_post(hermon_state_t *state, hermon_rsrc_t *mtt, uint64_t start_addr, uint_t nummtt, uint_t sleepflag); /* * SYNC_TPT - used to sync Hermon TPT caches */ int hermon_sync_tpt_cmd_post(hermon_state_t *state, uint_t sleepflag); /* * MAP_EQ - used for map classes of events to Hermon event queues (EQ) */ int hermon_map_eq_cmd_post(hermon_state_t *state, uint_t map, uint_t eqcindx, uint64_t eqmapmask, uint_t sleepflag); /* * RESIZE_CQ - used for resize completion queue (CQ) * opmod 0 is resize cq. opmod 1 is modify interrupt moderation. */ int hermon_resize_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc, uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag); int hermon_modify_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc, uint_t cqcindx, uint_t opmod, uint_t sleepflag); /* * CONF_SPECIAL_QP - used to configure a pair of queue pairs for use as * special QP. Necessary to enable full QP0 and/or QP1 operation. */ int hermon_conf_special_qp_cmd_post(hermon_state_t *state, uint_t qpindx, uint_t qptype, uint_t sleepflag, uint_t opmod); /* * Get FEXCH HEART BEAT */ int hermon_get_heart_beat_rq_cmd_post(hermon_state_t *state, uint_t qpindx, uint64_t *outparm); /* * MGID_HASH, READ_MGM, and WRITE_MGM - used for manipulation of the * hardware resource tables for multicast groups. * NOTE: for intial implementation these functions retain their original * names, though the proper hermon terminology is READ_MCG and * WRITE_MCG - MGID_HASH retains its original name */ int hermon_mgid_hash_cmd_post(hermon_state_t *state, uint64_t mgid_h, uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag); int hermon_read_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg, uint_t mcgindx, uint_t sleepflag); int hermon_write_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg, uint_t mcgindx, uint_t sleepflag); /* * MOD_STAT_CFG - used to configure (override) settings set in NVRAM before * a call to QUERY_DEV_LIM. This is primarily used for SRQ settings in * the firmware. */ int hermon_mod_stat_cfg_cmd_post(hermon_state_t *state); /* * MODIFY_MPT - used to change MPT attributes of a memory region. This * was (Tavor/Arbel) primarily used for Resizing SRQs -- now may be used * to modify MPT paramters */ int hermon_modify_mpt_cmd_post(hermon_state_t *state, hermon_hw_dmpt_t *mpt, uint_t mptindx, uint_t flags, uint_t sleepflag); /* * RESIZE_SRQ is new in hermon, replacing opcodes in modify_mpt. It is used * to resize the SRQ, by passing the new information in the same format as * the original srqc, which the HCA will update appropriately */ int hermon_resize_srq_cmd_post(hermon_state_t *state, hermon_hw_srqc_t *srq, uint_t srqnum, uint_t sleepflag); /* * CMD_NOP - used to test the interrupt/Event Queue mechanism. */ int hermon_nop_post(hermon_state_t *state, uint_t interval, uint_t sleep); int hermon_setdebug_post(hermon_state_t *state); /* * READ_MTT - used to read an mtt entry at address. */ int hermon_read_mtt_cmd_post(hermon_state_t *state, uint64_t mtt_addr, hermon_hw_mtt_t *mtt); /* * SENSE_PORT - used to send protocol running on a port */ int hermon_sense_port_post(hermon_state_t *state, uint_t portnum, uint32_t *protocol); /* * CONFIG_FC - used to do either a basic config passing in * *hermon_hw_config_fc_basic_s, or config the N_Port table. * passing in pointer to an array of 32-bit id's * Note that either one needs to be cast to void * */ int hermon_config_fc_cmd_post(hermon_state_t *state, void *cfginfo, int enable, int selector, int n_ports, int portnum, uint_t sleepflag); /* * CONFIG_INT_MOD - used to configure INTERRUPT moderation */ int hermon_config_int_mod(hermon_state_t *state, uint_t min_delay, uint_t vector); /* * HW_HEALTH_CHECK - tests state of the HCA * if command fails, *health is invalid/undefined */ int hermon_hw_health_check(hermon_state_t *state, int *health); #ifdef __cplusplus } #endif #endif /* _SYS_IB_ADAPTERS_HERMON_CMD_H */