hermon_hw.h revision 71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512d
/*
* 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
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_IB_ADAPTERS_HERMON_HW_H
#define _SYS_IB_ADAPTERS_HERMON_HW_H
/*
* Contains all the structure definitions and #defines for all Hermon
* hardware resources and registers (as defined by the Hermon register
* specification). Wherever possible, the names in the Hermon spec
* have been preserved in the structure and field names below.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* PCI IDs for supported chipsets
*/
#define PCI_VENID_MLX 0x15b3
/*
* Native page size of the adapter
*/
/*
* MACROS to make some page stuff easier
*/
/* given a value, return a value that's the next higher power of 2 */
/*
* given a size in bytes, return the minimum number of
* *HCA PAGES* needed to hold it
*/
#define HERMON_HCA_PAGES(x) \
/*
* given a size in bytes, return the power of two number of
* *HCA PAGES* needed to hold it
*/
/*
* Offsets into the CMD BAR (BAR 0) for many of the more interesting hardware
* registers. These registers include the HCR (more below), and the software
* reset register (SW_RESET).
*/
/*
* Ownership flags used to define hardware or software ownership for
* various Hermon resources
*/
#define HERMON_HW_OWNER 0x1
#define HERMON_SW_OWNER 0x0
/*
* Determines whether or not virtual-to-physical address translation is
* required. Several of the Hermon hardware structures can be optionally
* accessed by Hermon without going through the TPT address translation
* tables.
*/
#define HERMON_VA2PA_XLAT_ENABLED 0x1
#define HERMON_VA2PA_XLAT_DISABLED 0x0
/*
* HCA Command Register (HCR)
* The HCR command interface provides privileged access to the HCA in
* order to query, configure and modify HCA execution. It is the
* primary mechanism through which mailboxes may be posted to Hermon
* firmware. To use this interface software fills the HCR with pointers
* to input and output mailboxes. Some commands support immediate
* parameters, however, and for these commands the HCR will contain the
* input or output parameters. Command execution completion can be
* detected either by the software polling the HCR or by waiting for a
* command completion event.
*/
struct hermon_hw_hcr_s {
};
#define HERMON_HCR_TOKEN_MASK 0xFFFF0000
#define HERMON_HCR_TOKEN_SHIFT 16
#define HERMON_HCR_CMD_STATUS_MASK 0xFF000000
#define HERMON_HCR_CMD_GO_MASK 0x00800000
#define HERMON_HCR_CMD_E_MASK 0x00400000
#define HERMON_HCR_CMD_T_MASK 0x00200000
#define HERMON_HCR_CMD_OPMOD_MASK 0x0000F000
#define HERMON_HCR_CMD_OPCODE_MASK 0x00000FFF
#define HERMON_HCR_CMD_STATUS_SHFT 24
#define HERMON_HCR_CMD_GO_SHFT 23
#define HERMON_HCR_CMD_E_SHFT 22
#define HERMON_HCR_CMD_T_SHFT 21
#define HERMON_HCR_CMD_OPMOD_SHFT 12
/*
* Arbel "QUERY_DEV_LIM" command - Hermon, "QUERY_DEV_CAP" - Same hex code
* The QUERY_DEV_LIM command returns the device limits and capabilities
* supported by the Hermon device. This command must be run before
* running the INIT_HCA command (below) in order to determine the maximum
* capabilities of the device and which optional features are supported.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_querydevlim_s {
uint32_t :4;
uint32_t :2;
uint32_t :7;
uint32_t :3;
uint32_t :4;
uint32_t :4;
uint32_t :4;
uint32_t :2;
uint32_t :3;
uint32_t :4;
uint32_t :8;
uint32_t :32;
uint32_t :2;
uint32_t :4;
uint32_t :4;
uint32_t :2;
uint32_t :2;
uint32_t :10;
uint32_t :10;
uint32_t :12;
uint32_t :11;
uint32_t :31;
uint32_t :4;
uint32_t :12;
uint32_t :4;
uint32_t :12;
uint32_t :8;
uint32_t :3;
uint32_t :5;
uint32_t :2;
uint32_t :6;
uint32_t :32;
uint32_t :2;
uint32_t :2;
uint32_t :10;
uint32_t :8;
uint32_t :6;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :7;
uint32_t :4;
uint32_t :8;
uint32_t :1;
uint32_t :20;
uint32_t :32;
};
#else /* BIG ENDIAN */
struct hermon_hw_querydevlim_s {
uint32_t :4;
uint32_t :3;
uint32_t :7;
uint32_t :2;
uint32_t :4;
uint32_t :8;
uint32_t :4;
uint32_t :3;
uint32_t :2;
uint32_t :4;
uint32_t :4;
uint32_t :4;
uint32_t :4;
uint32_t :2;
uint32_t :32;
uint32_t :10;
uint32_t :10;
uint32_t :2;
uint32_t :2;
uint32_t :31;
uint32_t :11;
/* PRM 0.35, stuff moved to per port info */
uint32_t :12;
uint32_t :3;
uint32_t :8;
uint32_t :12;
uint32_t :4;
uint32_t :12;
uint32_t :4;
uint32_t :32;
uint32_t :6;
uint32_t :2;
uint32_t :5;
uint32_t :6;
uint32_t :8;
uint32_t :10;
uint32_t :2;
uint32_t :2;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :4;
uint32_t :7;
uint32_t :8;
uint32_t :20;
uint32_t :1;
uint32_t :32;
};
#endif
/*
* Hermon "QUERY_FW" command
* The QUERY_FW command retrieves the firmware revision and the Command
* Interface revision. The command also returns the HCA attached local
* memory area (DDR) which is used by the firmware. Below we also
* include some defines which are used to enforce a minimum firmware
* version check (see hermon_fw_version_check() for more details).
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_queryfw_s {
uint32_t :23;
uint32_t :16;
uint32_t :1;
uint32_t :6;
uint32_t :32;
uint32_t :30;
uint32_t :30;
};
#else
struct hermon_hw_queryfw_s {
uint32_t :16;
uint32_t :23;
uint32_t :6;
uint32_t :1;
uint32_t :30;
uint32_t :32;
uint32_t :30;
};
#endif
/*
* need to have min 2.3.0 to include config_spec_qp and SMA in FW
*/
#define HERMON_FW_VER_MINOR 0x0005
#define HERMON_FW_VER_SUBMINOR 0x0000
/*
* Hermon "QUERY_ADAPTER" command
* The QUERY_ADAPTER command retrieves adapter specific parameters. The
* command also retrieves the PCI(X) interrupt pin routing for each of
* the INTx# pins supported by the device. This information is used by
* the driver during interrupt processing in order to clear the appropriate
* interrupt bit.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_queryadapter_s {
uint32_t :32;
uint32_t :24;
uint32_t :16;
uint32_t :32;
};
#else
struct hermon_hw_queryadapter_s {
uint32_t :24;
uint32_t :32;
uint32_t :32;
uint32_t :16;
};
#endif
#define HERMON_REV_A0 0xA0
#define HERMON_REV_A1 0xA1
/*
* Virtual physical mapping structure for: MAP_FA, MAP_ICM_AUX, and
* MAP_ICM commands.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_vpm_s {
uint32_t :12;
uint32_t :7;
};
#else
struct hermon_hw_vpm_s {
uint32_t :12;
uint32_t :7;
};
#endif
/*
* Hermon "INIT_HCA" and "QUERY_HCA" commands
* The INIT_HCA command configures all HCA resources in HCA attached local
* memory and some system relevant information. The same mailbox output
* format is used by the QUERY_HCA command. All parameters, which are
* specifically the output of the QUERY_HCA command are marked as
* "QUERY_HCA only". These parameters are not configurable through the
* INIT_HCA command, but can be retrieved as read-only through the
* QUERY_HCA command.
*
* Below we first define several structures which help make up the whole
* hermon_udav_mem_param_t for "Memory Access Parameters for UDAV Table",
* hermon_multicast_param_t for "Multicast Support Parameters",
* hermon_tpt_param_t for "Translation and Protection Table Parameters",
* and hermon_uar_param_t for Hermon "UAR Parameters".
*/
/*
* need to consider removing any ref to "ee", hermon doesn't support
*/
#ifdef _LITTLE_ENDIAN
typedef struct hermon_hw_qp_ee_cq_eq_rdb_s {
uint32_t :2;
#else
typedef struct hermon_hw_qp_ee_cq_eq_rdb_s {
uint32_t :2;
#endif
#ifdef _LITTLE_ENDIAN
typedef struct hermon_multicast_param_s {
uint32_t :27;
uint32_t :27;
uint32_t :32;
uint32_t :19;
uint32_t :5;
#else
typedef struct hermon_multicast_param_s {
uint32_t :27;
uint32_t :27;
uint32_t :5;
uint32_t :19;
uint32_t :32;
#endif
#define HERMON_MCG_DEFAULT_HASH_FN 0x0
#ifdef _LITTLE_ENDIAN
typedef struct hermon_tpt_param_s {
uint32_t :32;
uint32_t :2;
uint32_t :19;
#else
typedef struct hermon_tpt_param_s {
uint32_t :19;
uint32_t :2;
uint32_t :32;
#endif
#ifdef _LITTLE_ENDIAN
typedef struct hermon_uar_param_s {
uint32_t :32;
uint32_t :20;
#else
typedef struct hermon_uar_param_s {
uint32_t :20;
uint32_t :32;
#endif
/*
* NEW for Hermon
* QP Allocation Params
*
*/
#ifdef _LITTLE_ENDIAN
typedef struct hermon_qp_alloc_param_s {
uint32_t :32;
uint32_t :2;
#else /* BIG ENDIAN */
typedef struct hermon_qp_alloc_param_s {
uint32_t :2;
uint32_t :32;
#endif
#ifdef _LITTLE_ENDIAN
struct hermon_hw_initqueryhca_s {
uint32_t :32;
uint32_t :24;
uint32_t :13;
uint32_t :32;
uint32_t :1;
uint32_t :28;
uint32_t :5;
};
#else /* BIG ENDIAN */
struct hermon_hw_initqueryhca_s {
uint32_t :24;
uint32_t :32;
uint32_t :32;
uint32_t :13;
uint32_t :5;
uint32_t :28;
uint32_t :1;
};
#endif
#define HERMON_UDAV_PROTECT_DISABLED 0x0
#define HERMON_UDAV_PROTECT_ENABLED 0x1
#define HERMON_UDAV_PORTCHK_DISABLED 0x0
#define HERMON_UDAV_PORTCHK_ENABLED 0x1
/*
* Hermon "INIT_IB"/"INIT_PORT" command
* It provides control over the IB port attributes. The capabilities
* requested here should not exceed the device limits, as retrieved by
* the QUERY_DEV_LIM/CAP command (above). To query information about the IB
* port or node, the driver may submit GetPortInfo or GetNodeInfo MADs
* through the Hermon MAD_IFC command.
*
* Changed name to initport, but operates similar to initib - but as of
* PRM v0.35c the initport just does that, and the params set previously
* by initib are now set in SET_PORT
*/
/*
* HERMON query_port and set_port commands. QUERY_PORT is new for hermon,
* doing some of what used to be done in the QUERY_DEV_CAP command. It is
* introduced in PRM v0.35 and will need to be added to the list of
* supported HCA commands
*
* SET_PORT is similar to the SET_IB command from tavor and arbel. Here,
* tho, it's more extensive and will be easier to deal with I suspect by
* making it a structure and filling it in and then doing the copy to the
* mailbox (instead of just writing the minimal information to the mailbox
* directly as was done for the previous HCAs).
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_query_port_s {
/* was max_port_width arbel: long list of values */
uint32_t :4;
uint32_t :4;
/*
* 0x1=2.5G, 0x3=2.5 or 5.0G, 0x5=2.5 or 10G
* 0x7=2.5, 5.0, or 10G, others rsvd
*/
uint32_t :4;
/*
* 0x0 rsvd, 0x1=256, 0x2=512, 0x3=1024, 0x5=2048
* 0x5=4096, others rsvd
*/
uint32_t :4;
uint32_t :32;
/* max vl's supported (not incl vl_15) */
uint32_t :4;
uint32_t :16;
};
#else /* BIG ENDIAN */
struct hermon_hw_query_port_s {
uint32_t :4;
/*
* 0x0 rsvd, 0x1=256, 0x2=512, 0x3=1024, 0x5=2048
* 0x1=256, 0x2=512, 0x3=1024, 0x5=2048
*/
/* 0x5=4096, others rsvd */
uint32_t :4;
/*
* 0x1=2.5G, 0x3=2.5 or 5.0G, 0x5=2.5 or 10G
* 0x7=2.5, 5.0, or 10G, others rsvd
*/
uint32_t :4;
uint32_t :4;
/* was max_port_width arbel: long list of values */
uint32_t :16;
uint32_t :4;
/* max vl's supported (not incl vl_15) */
uint32_t :32;
};
#endif
#ifdef _LITTLE_ENDIAN
struct hermon_hw_set_port_s {
uint32_t :2;
uint32_t :4;
uint32_t :9;
uint32_t :4;
uint32_t :7;
uint32_t :32;
};
#else /* BIG ENDIAN */
struct hermon_hw_set_port_s {
uint32_t :9;
uint32_t :4;
uint32_t :2;
uint32_t :7;
uint32_t :4;
uint32_t :32;
};
#endif
/*
* Hermon Memory Protection Table (MPT) entries
*
* The Memory Protection Table (MPT) contains the information associated
* with all the regions and windows. The MPT table resides in a virtually-
* contiguous area in ICM, and the memory key (R_Key or L_Key) is used to
* calculate the physical address for accessing the entries in the table.
*
*
* The SW2HW_MPT command transfers ownership of an MPT entry from software
* to hardware. The command takes the MPT entry from the input mailbox and
* stores it in the MPT in the hardware. The command will fail if the
* requested MPT entry is already owned by the hardware or if the MPT index
* given in the command is inconsistent with the MPT entry memory key.
* The QUERY_MPT command retrieves a snapshot of an MPT entry. The command
* takes the current state of an MPT entry from the hardware and stores it
* in the output mailbox. The command will fail if the requested MPT entry
* is already owned by software.
* Finally, the HW2SW_MPT command transfers ownership of an MPT entry from
* the hardware to the software. The command takes the MPT entry from the
* hardware, invalidates it, and stores it in the output mailbox. The
* command will fail if the requested entry is already owned by software.
* The command will also fail if the MPT entry in question is a Memory
* Region which has Memory Windows currently bound to it.
*
* The following structure is used in the SW2HW_MPT, QUERY_MPT, and
* HW2SW_MPT commands, and ONLY for the dMPT - for data.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_dmpt_s {
uint32_t :7;
uint32_t :8;
uint32_t :1;
uint32_t :8;
uint32_t :17;
uint32_t :3;
#ifdef HERMON_NOTIMPL
uint32_t :9;
uint32_t :32;
#endif /* HERMON_NOTIMPL */
};
#else /* BIG ENDIAN */
struct hermon_hw_dmpt_s {
uint32_t :8;
uint32_t :1;
uint32_t :1;
uint32_t :8;
uint32_t :8;
uint32_t :17;
uint32_t :24;
uint32_t :11;
uint32_t :11;
#ifdef HERMON_NOTIMPL
uint32_t :9;
uint32_t :16;
uint32_t :16;
uint32_t :32;
#endif /* HERMON_NOTIMPL */
};
#endif
/*
* The following structure is for the CMPTs. This is NEVER actually built and
* passed to the hardware - we use it to track information needed for the
* context entries, and to facilitate the alloc tracking. It differs from
*
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_cmpt_s {
uint32_t :7;
uint32_t :8;
uint32_t :1;
uint32_t :8;
uint32_t :17;
uint32_t :3;
};
#else /* BIG ENDIAN */
struct hermon_hw_cmpt_s {
uint32_t :8;
uint32_t :1;
uint32_t :1;
uint32_t :8;
uint32_t :8;
uint32_t :17;
uint32_t :24;
uint32_t :11;
};
#endif
#define HERMON_MEM_CYCLE_GENERATE 0x1
#define HERMON_IO_CYCLE_GENERATE 0x0
#define HERMON_MPT_IS_WINDOW 0x0
#define HERMON_MPT_IS_REGION 0x1
#define HERMON_MPT_DEFAULT_VERSION 0x0
#define HERMON_UNLIMITED_WIN_BIND 0x0
#define HERMON_PHYSADDR_ENABLED 0x1
#define HERMON_PHYSADDR_DISABLED 0x0
/*
* Hermon Memory Translation Table (MTT) entries
* After accessing the MPT table (above) and validating the access rights
* where it translates the virtual address to a physical address. This
* translation is performed using the Memory Translation Table entries
* (MTT). Note: The MTT in hardware is organized into segments and each
* segment contains multiple address translation pages (MTT entries).
* Each memory region (MPT above) points to the first segment in the MTT
* that corresponds to that region.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_mtt_s {
uint32_t :2;
};
#else /* BIG_ENDIAN */
struct hermon_hw_mtt_s {
uint32_t :2;
};
#endif
#define HERMON_MTT_ENTRY_NOTPRESENT 0x0
#define HERMON_MTT_ENTRY_PRESENT 0x1
/*
* Hermon Event Queue Context Table (EQC) entries
* Hermon supports 512 Event Queues, and the status of Event Queues is stored
* in the Event Queue Context (EQC) table. The EQC table is a virtually-
* contiguous memory structure in the ICM. Each EQC
* table entry contains Event Queue status and information required by
* the hardware in order to access the event queue.
* NOTE that in Hermon (as opposed to earlier HCAs),
* you have to allocate ICM for 2**32 (or about 16 M), even though
* it doesn't support that many. See PRM v35. Also, some set of them
* will be available for each domain in a virtual environment, needing to
* rething the allocation and usage model for EQs - in the future.
*
* The following structure is used in the SW2HW_EQ, QUERY_EQ, and HW2SW_EQ
* commands.
* The SW2HW_EQ command transfers ownership of an EQ context from software
* to hardware. The command takes the EQC entry from the input mailbox and
* stores it in the EQC in the hardware. The command will fail if the
* requested EQC entry is already owned by the hardware. NOTE: the
* initialization of the cMPT for the EQC occurs implicitly as a result
* The QUERY_EQ command retrieves a snapshot of an EQC entry. The command
* stores the snapshot in the output mailbox. The EQC state and its values
* are not affected by the QUERY_EQ command.
* Finally, the HW2SW_EQ command transfers ownership of an EQC entry from
* the hardware to the software. The command takes the EQC entry from the
* hardware and stores it in the output mailbox. The EQC entry will be
* invalidated as a result of the command. It is the responsibility of the
* software to unmap all the events, which might have been previously
* mapped to the EQ, prior to issuing the HW2SW_EQ command.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_eqc_s {
uint32_t :32;
uint32_t :8;
uint32_t :5;
uint32_t :9;
uint32_t :24;
uint32_t :3;
uint32_t :5;
uint32_t :20;
uint32_t :22;
uint32_t :3;
uint32_t :16;
uint32_t :2;
uint32_t :8;
uint32_t :8;
};
#else /* BIG ENDIAN */
struct hermon_hw_eqc_s {
uint32_t :9;
uint32_t :5;
uint32_t :8;
uint32_t :32;
uint32_t :20;
uint32_t :5;
uint32_t :3;
uint32_t :24;
uint32_t :22;
uint32_t :2;
uint32_t :16;
uint32_t :3;
uint32_t :8;
uint32_t :8;
};
#endif
#define HERMON_EQ_STATUS_OK 0x0
#define HERMON_EQ_STATUS_OVERFLOW 0x9
#define HERMON_EQ_STATUS_WRITE_FAILURE 0xA
#define HERMON_EQ_ARMED 0x9
#define HERMON_EQ_FIRED 0xA
#define HERMON_EQ_ALWAYS_ARMED 0xB
/*
* Hermon Event Queue Entries (EQE)
* Each EQE contains enough information for the software to identify the
* source of the event. The following structures are used to define each
* of the various kinds of events that the Hermon hardware will generate.
* Note: The hermon_hw_eqe_t below is the generic "Event Queue Entry". All
* other EQEs differ only in the contents of their "event_data" field.
*
* Below we first define several structures which define the contents of
* the "event_data" fields:
* hermon_hw_eqe_cq_t for "Completion Queue Events"
* hermon_hw_eqe_qp_evt_t for "Queue Pair Events" such as Path Migration
* Succeeded, Path Migration Failed, Communication Established, Send
* Queue Drained, Local WQ Catastrophic Error, Invalid Request Local
* WQ Error, and Local Access Violation WQ Error.
* hermon_hw_eqe_cqerr_t for "Completion Queue Error Events"
* hermon_hw_eqe_portstate_t for "Port State Change Events"
* hermon_hw_eqe_gpio_t for "GPIO State Change Events"
* hermon_hw_eqe_cmdcmpl_t for "Command Interface Completion Events"
* hermon_hw_eqe_operr_t for "Operational and Catastrophic Error Events"
* such as EQ Overflow, Misbehaved UAR page, Internal Parity Error,
* Uplink bus error, and DDR data error.
* hermon_hw_eqe_pgflt_t for "Not-present Page Fault on WQE or Data
* Buffer Access". (Note: Currently, this event is unsupported).
*
* Note also: The following structures are not #define'd with both
* little-endian and big-endian definitions. This is because their
* individual fields are not directly accessed except through the macros
* defined below.
*/
typedef struct hermon_hw_eqe_cq_s {
uint32_t :8;
typedef struct hermon_hw_eqe_qp_evt_s {
uint32_t :8;
typedef struct hermon_hw_eqe_cqerr_s {
uint32_t :8;
uint32_t :32;
uint32_t :24;
#define HERMON_CQERR_OVERFLOW 0x1
#define HERMON_CQERR_ACCESS_VIOLATION 0x2
typedef struct hermon_hw_eqe_portstate_s {
uint32_t :2;
uint32_t :28;
#define HERMON_PORT_LINK_ACTIVE 0x4
#define HERMON_PORT_LINK_DOWN 0x1
typedef struct hermon_hw_eqe_gpio_s {
uint32_t :32;
typedef struct hermon_hw_eqe_cmdcmpl_s {
uint32_t :16;
uint32_t :32;
uint32_t :24;
uint32_t :32;
typedef struct hermon_hw_eqe_operr_s {
uint32_t :24;
#define HERMON_ERREVT_EQ_OVERFLOW 0x1
#define HERMON_ERREVT_BAD_UARPG 0x2
#define HERMON_ERREVT_UPLINK_BUSERR 0x3
#define HERMON_ERREVT_DDR_DATAERR 0x4
#define HERMON_ERREVT_INTERNAL_PARITY 0x5
typedef struct hermon_hw_eqe_pgflt_s {
uint32_t :24;
#define HERMON_PGFLT_PG_NOTPRESENT 0x8
#define HERMON_PGFLT_PG_WRACC_VIOL 0xA
#define HERMON_PGFLT_UNSUP_NOTPRESENT 0xE
#define HERMON_PGFLT_UNSUP_WRACC_VIOL 0xF
#define HERMON_PGFLT_WQE_CAUSED 0x1
#define HERMON_PGFLT_DATA_CAUSED 0x0
#define HERMON_PGFLT_REMOTE_CAUSED 0x1
#define HERMON_PGFLT_LOCAL_CAUSED 0x0
#define HERMON_PGFLT_SEND_CAUSED 0x1
#define HERMON_PGFLT_RECV_CAUSED 0x0
#define HERMON_PGFLT_DESC_CONSUMED 0x1
#define HERMON_PGFLT_DESC_NOTCONSUMED 0x0
struct hermon_hw_eqe_s {
uint32_t :8;
uint32_t :8;
union {
} event_data;
uint32_t :24;
uint32_t :7;
};
/*
* The following macros are used for extracting (and in some cases filling in)
* information from EQEs
*/
#define HERMON_EQE_CQNUM_MASK 0x00FFFFFF
#define HERMON_EQE_CQNUM_SHIFT 0
#define HERMON_EQE_QPNUM_MASK 0x00FFFFFF
#define HERMON_EQE_QPNUM_SHIFT 0
#define HERMON_EQE_PORTNUM_MASK 0x30
#define HERMON_EQE_PORTNUM_SHIFT 4
#define HERMON_EQE_OWNER_MASK 0x00000080
#define HERMON_EQE_OWNER_SHIFT 7
/*
* Hermon does ownership of CQ and EQ differently from Arbel & Tavor.
* Now, you keep track of the TOTAL number of CQE's or EQE's that have been
* processed, and the sense of the ownership bit changes each time through.
* That is, if the size of the queue is 16, so 4 bits [3:0] are the index
* number, then bit [4] is the ownership bit in the count. So you mask that
* bit and compare it to the owner bit in the entry - if the same, then the
* entry is in SW onwership. Otherwise, it's in hardware and the driver
* does not consume it.
*/
/*
* Hermon Completion Queue Context Table (CQC) entries
* The CQC table is a virtually-contiguous memory area residing in HCA's
* ICM. Each CQC table entry contains information
* required by the hardware to access the completion queue to post
* completions (CQE).
*
* The following structure is used in the SW2HW_CQ, QUERY_CQ, RESIZE_CQ,
* and HW2SW_CQ commands.
* The SW2HW_CQ command transfers ownership of an CQ context from software
* to hardware. The command takes the CQC entry from the input mailbox and
* stores it in the CQC in the hardware. The command will fail if the
* requested CQC entry is already owned by the hardware.
* The QUERY_CQ command retrieves a snapshot of a CQC entry. The command
* stores the snapshot in the output mailbox. The CQC state and its values
* are not affected by the QUERY_CQ command.
* Finally, the HW2SW_CQ command transfers ownership of a CQC entry from
* the hardware to the software. The command takes the CQC entry from the
* hardware and stores it in the output mailbox. The CQC entry will be
* invalidated as a result of the command.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_cqc_s {
uint32_t :32;
uint32_t :8;
uint32_t :5;
uint32_t :9;
uint32_t :3;
uint32_t :5;
uint32_t :20;
uint32_t :23;
uint32_t :3;
uint32_t :16;
uint32_t :2;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :3;
};
#else
struct hermon_hw_cqc_s {
uint32_t :9;
uint32_t :5;
uint32_t :8;
uint32_t :32;
uint32_t :20;
uint32_t :5;
uint32_t :3;
uint32_t :23;
uint32_t :2;
uint32_t :16;
uint32_t :3;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :3;
};
#endif
#define HERMON_CQ_STATUS_OK 0x0
#define HERMON_CQ_STATUS_OVERFLOW 0x9
#define HERMON_CQ_STATUS_WRITE_FAILURE 0xA
#define HERMON_CQ_DISARMED 0x0
#define HERMON_CQ_ARMED 0x1
#define HERMON_CQ_ARMED_SOLICITED 0x4
#define HERMON_CQ_FIRED 0xA
/*
* Hermon Completion Queue Entries (CQE)
* Each CQE contains enough information for the software to associate the
* completion with the Work Queue Element (WQE) to which it corresponds.
*
* Note: The following structure is not #define'd with both little-endian
* and big-endian definitions. This is because each CQE's individual
* fields are not directly accessed except through the macros defined below.
*/
struct hermon_hw_cqe_s {
uint32_t :2;
uint32_t :2;
uint32_t :12;
uint32_t :8;
uint32_t :16;
};
#define HERMON_COMPLETION_RECV 0x0
#define HERMON_COMPLETION_SEND 0x1
#define HERMON_CQE_DEFAULT_VERSION 0x0
/*
* The following macros are used for extracting (and in some cases filling in)
* information from CQEs
*/
#define HERMON_CQE_QPNUM_MASK 0x00FFFFFF
#define HERMON_CQE_QPNUM_SHIFT 0
#define HERMON_CQE_DQPN_MASK 0x00FFFFFF
#define HERMON_CQE_DQPN_SHIFT 0
#define HERMON_CQE_SL_SHIFT 4
#define HERMON_CQE_GRH_MASK 0x80
#define HERMON_CQE_PATHBITS_MASK 0x7F
#define HERMON_CQE_SLID_15_8 0xe
#define HERMON_CQE_SLID_7_0 0xf
#define HERMON_CQE_OPCODE_MASK 0x1F
#define HERMON_CQE_SENDRECV_MASK 0x40
#define HERMON_CQE_SENDRECV_SHIFT 6
#define HERMON_CQE_OWNER_MASK 0x80
#define HERMON_CQE_OWNER_SHIFT 7
#define HERMON_CQE_WQECNTR_15_8 0x18
#define HERMON_CQE_WQECNTR_7_0 0x19
/* Byte offsets for IPoIB Checksum Offload fields */
#define HERMON_CQE_CKSUM_15_8 0x1a
#define HERMON_CQE_CKSUM_7_0 0x1b
/* See Comment above for EQE - ownership of CQE is handled the same */
HERMON_CQE_OWNER_SHIFT) == \
/*
* Hermon Shared Receive Queue (SRQ) Context Entry Format
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_srqc_s {
uint32_t :8;
uint32_t :5;
uint32_t :32;
uint32_t :2;
uint32_t :3;
uint32_t :16;
uint32_t :2;
uint32_t :8;
uint32_t :32;
uint32_t :16;
uint32_t :2;
};
#else
struct hermon_hw_srqc_s {
uint32_t :5;
uint32_t :8;
uint32_t :2;
uint32_t :32;
uint32_t :2;
uint32_t :16;
uint32_t :3;
uint32_t :8;
uint32_t :16;
uint32_t :32;
uint32_t :2;
};
#endif
/*
* Hermon MOD_STAT_CFG input mailbox structure
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_mod_stat_cfg_s {
uint32_t :14;
uint32_t :3;
uint32_t :3;
uint32_t :3;
uint32_t :10;
uint32_t :31;
uint32_t :31;
uint32_t :1;
uint32_t :4;
uint32_t :4;
uint32_t :2;
uint32_t :2;
uint32_t :1;
uint32_t :3;
uint32_t :3;
uint32_t :3;
uint32_t :2;
};
#else /* BIG ENDIAN */
struct hermon_hw_mod_stat_cfg_s {
uint32_t :3;
uint32_t :3;
uint32_t :14;
uint32_t :10;
uint32_t :3;
uint32_t :31;
uint32_t :31;
uint32_t :2;
uint32_t :3;
uint32_t :3;
uint32_t :3;
uint32_t :1;
uint32_t :2;
uint32_t :2;
uint32_t :4;
uint32_t :4;
uint32_t :1;
};
#endif
/*
* Hermon MOD_STAT_CFG input modifier structure
*/
struct hermon_hw_msg_in_mod_s {
#ifdef _LITTLE_ENDIAN
uint32_t :8;
#else
uint32_t :8;
#endif
};
/*
* Hermon UD Address Vector (UDAV)
* Hermon UDAV are used in conjunction with Unreliable Datagram (UD) send
* WQEs. Each UD send message contains an address vector in in the datagram
* segment. The verbs consumer must use special verbs to create and modify
* address handles, each of which contains a UDAV structure. When posting
* send WQEs to UD QP, the verbs consumer must supply a valid address
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_udav_s {
uint32_t :8;
uint32_t :5;
uint32_t :4;
uint32_t :9;
};
#else
struct hermon_hw_udav_s {
uint32_t :5;
uint32_t :8;
uint32_t :9;
uint32_t :4;
};
#endif
#define HERMON_UDAV_MODIFY_MASK0 0xFCFFFFFFFF000000ULL
#define HERMON_UDAV_MODIFY_MASK1 0xFF80F00000000000ULL
/*
* Hermon Queue Pair Context Table (QPC) entries
* The QPC table is a virtually-contiguous memory area residing in HCA
* ICM. Each QPC entry is accessed for reads and writes
* by the HCA while executing work requests on the associated QP.
*
* The following structure is used in the RST2INIT_QP, INIT2INIT_QP,
* INIT2RTR_QP, RTR2RTS_QP, RTS2RTS_QP, SQERR2RTS_QP, TOERR_QP, RTS2SQD_QP,
* SQD2RTS_QP, TORST_QP, and QUERY_QP commands.
* With the exception of the QUERY_QP command, each of these commands reads
* from some portion of the QPC in the input mailbox and modified the QPC
* stored in the hardware. The QUERY_QP command retrieves a snapshot of a
* QPC entry. The command stores the snapshot in the output mailbox. The
* QPC state and its values are not affected by the QUERY_QP command.
*
* Below we first define the hermon_hw_addr_path_t or "Hermon Address Path"
* structure. This structure is used to provide address path information
* (both primary and secondary) for each QP context. Note: Since this
* structure is _very_ similar to the hermon_hw_udav_t structure above,
* we are able to leverage the similarity with filling in and reading from
* the two types of structures. See hermon_get_addr_path() and
* hermon_set_addr_path() in hermon_misc.c for more details.
*/
#if (DATAMODEL_NATIVE == DATAMODEL_LP64)
#pragma pack(4)
#endif
#ifdef _LITTLE_ENDIAN
struct hermon_hw_addr_path_s {
uint32_t :22;
uint32_t :4;
uint32_t :4;
uint32_t :4;
uint32_t :3;
uint32_t :7;
uint32_t :1;
uint32_t :32;
};
#else
struct hermon_hw_addr_path_s {
uint32_t :22;
uint32_t :4;
uint32_t :4;
uint32_t :4;
uint32_t :1;
uint32_t :7;
uint32_t :3;
uint32_t :32;
};
#endif /* LITTLE ENDIAN */
#if (DATAMODEL_NATIVE == DATAMODEL_LP64)
#pragma pack()
#endif
#if (DATAMODEL_NATIVE == DATAMODEL_LP64)
#pragma pack(4)
#endif
#ifdef _LITTLE_ENDIAN
struct hermon_hw_qpc_s {
uint32_t :8;
uint32_t :11;
uint32_t :2;
uint32_t :4;
uint32_t :8;
uint32_t :4;
uint32_t :3;
uint32_t :1;
uint32_t :8;
uint32_t :8;
uint32_t :32;
uint32_t :5;
uint32_t :1;
uint32_t :2;
uint32_t :4;
uint32_t :8;
uint32_t :8;
uint32_t :32;
uint32_t :32;
uint32_t :8;
uint32_t :8;
uint32_t :3;
uint32_t :4;
uint32_t :1;
uint32_t :1;
uint32_t :5;
uint32_t :8;
uint32_t :8;
uint32_t :16;
uint32_t :2;
uint32_t :7;
uint32_t :8;
/* new w/ hermon */
uint32_t :1;
uint32_t :3;
uint32_t :16;
uint32_t :2;
};
#else /* BIG ENDIAN */
struct hermon_hw_qpc_s {
uint32_t :4;
uint32_t :2;
uint32_t :11;
uint32_t :8;
uint32_t :1;
uint32_t :3;
uint32_t :4;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :4;
uint32_t :2;
uint32_t :1;
uint32_t :5;
uint32_t :32;
uint32_t :8;
uint32_t :8;
uint32_t :32;
uint32_t :32;
uint32_t :8;
uint32_t :8;
uint32_t :8;
uint32_t :5;
uint32_t :1;
uint32_t :1;
uint32_t :4;
uint32_t :3;
uint32_t :16;
uint32_t :8;
uint32_t :2;
uint32_t :7;
uint32_t :8;
/* new w/ hermon */
uint32_t :1;
uint32_t :2;
uint32_t :16;
uint32_t :3;
};
#endif /* LITTLE ENDIAN */
#if (DATAMODEL_NATIVE == DATAMODEL_LP64)
#pragma pack()
#endif
#define HERMON_QP_RESET 0x0
#define HERMON_QP_INIT 0x1
#define HERMON_QP_RTR 0x2
#define HERMON_QP_RTS 0x3
#define HERMON_QP_SQERR 0x4
#define HERMON_QP_SQD 0x5
#define HERMON_QP_ERR 0x6
#define HERMON_QP_SQDRAINING 0x7
#define HERMON_QP_RC 0x0
#define HERMON_QP_UC 0x1
#define HERMON_QP_UD 0x3
#define HERMON_QP_MLX 0x7
#define HERMON_QP_PMSTATE_MIGRATED 0x3
#define HERMON_QP_PMSTATE_ARMED 0x0
#define HERMON_QP_PMSTATE_REARM 0x1
#define HERMON_QP_DESC_EVT_DISABLED 0x0
#define HERMON_QP_DESC_EVT_ENABLED 0x1
#define HERMON_QP_FLIGHT_LIM_UNLIMITED 0xF
#define HERMON_QP_SQ_ALL_SIGNALED 0x1
#define HERMON_QP_SQ_WR_SIGNALED 0x0
#define HERMON_QP_RQ_ALL_SIGNALED 0x1
#define HERMON_QP_RQ_WR_SIGNALED 0x0
#define HERMON_QP_SRQ_ENABLED 0x1
#define HERMON_QP_SRQ_DISABLED 0x0
#define HERMON_QP_WQE_BASE_SHIFT 0x6
/*
* Hermon Multicast Group Member (MCG)
* Hermon MCG are organized in a virtually-contiguous memory table (the
* Multicast Group Table) in the ICM. This table is
* actually comprised of two consecutive tables: the Multicast Group Hash
* Table (MGHT) and the Additional Multicast Group Members Table (AMGM).
* Each such entry contains an MGID and a list of QPs that are attached to
* the multicast group. Each such entry may also include an index to an
* Additional Multicast Group Member Table (AMGM) entry. The AMGMs are
* used to form a linked list of MCG entries that all map to the same hash
* value. The MCG entry size is configured through the INIT_HCA command.
* Note: An MCG actually consists of a single hermon_hw_mcg_t and some
* number of hermon_hw_mcg_qp_list_t (such that the combined structure is a
* power-of-2).
*
* The following structures are used in the READ_MGM and WRITE_MGM commands.
* The READ_MGM command reads an MCG entry from the multicast table and
* returns it in the output mailbox. Note: This operation does not affect
* the MCG entry state or values.
* The WRITE_MGM command retrieves an MCG entry from the input mailbox and
* stores it in the multicast group table at the index specified in the
* command. Once the command has finished execution, the multicast group
* table is updated. The old entry contents are lost.
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_mcg_s {
uint32_t :8;
uint32_t :6;
uint32_t :32;
uint32_t :32;
};
#else
struct hermon_hw_mcg_s {
uint32_t :6;
uint32_t :8;
uint32_t :32;
uint32_t :32;
};
#endif
/* Multicast Group Member - QP List entries */
#ifdef _LITTLE_ENDIAN
struct hermon_hw_mcg_qp_list_s {
uint32_t :6;
uint32_t :1;
};
#else
struct hermon_hw_mcg_qp_list_s {
uint32_t :1;
uint32_t :6;
};
#endif
#define HERMON_MCG_QPN_BLOCK_LB 0x40000000
/*
* Structure for getting the peformance counters from the HCA
*/
#ifdef _LITTLE_ENDIAN
struct hermon_hw_sm_perfcntr_s {
uint32_t :8;
uint32_t :16;
uint32_t :8;
};
#else /* BIG ENDIAN */
struct hermon_hw_sm_perfcntr_s {
uint32_t :8;
uint32_t :8;
uint32_t :16;
};
#endif
/*
* Hermon User Access Region (UAR)
*
* JBDB : writeup on the UAR for memfree
*
* JBDB : writeup on the structures
* UAR page
* DB register
* DB record
* UCE
*
* [es] and change it even further for hermon
* the whole UAR and doorbell record (dbr) approach is changed again
* from arbel, and needs commenting
*
* -- Tavor comment
*
*
* Tavor doorbells are each rung by writing to the doorbell registers that
* form a User Access Region (UAR). A doorbell is a write-only hardware
* register which enables passing information from software to hardware
* with minimum software latency. A write operation from the host software
* to these doorbell registers passes information about the HCA resources
* and initiates processing of the doorbell data. There are 6 types of
* doorbells in Tavor.
*
* "Send Doorbell" for synchronizing the attachment of a WQE (or a chain
* of WQEs) to the send queue.
* "RD Send Doorbell" (Same as above, except for RD QPs) is not supported.
* "Receive Doorbell" for synchronizing the attachment of a WQE (or a chain
* of WQEs) to the receive queue.
* "CQ Doorbell" for updating the CQ consumer index and requesting
* completion notifications.
* "EQ Doorbell" for updating the EQ consumer index, arming interrupt
* triggering, and disarming CQ notification requests.
* "InfiniBlast" (which would have enabled access to the "InfiniBlast
* buffer") is not supported.
*
* Note: The tavor_hw_uar_t below is the container for all of the various
* doorbell types. Below we first define several structures which make up
* the contents of those doorbell types.
*
* Note also: The following structures are not #define'd with both little-
* endian and big-endian definitions. This is because each doorbell type
* is not directly accessed except through a single ddi_put64() operation
* (see tavor_qp_send_doorbell, tavor_qp_recv_doorbell, tavor_cq_doorbell,
* or tavor_eq_doorbell)
*/
/*
* Send doorbell register structure
*/
typedef struct hermon_hw_send_db_reg_s {
uint32_t :32;
uint32_t :8;
#define HERMON_QPSNDDB_QPN_SHIFT 0x8
/* Max descriptors per Hermon doorbell */
#define HERMON_QP_MAXDESC_PER_DB 256
/*
* CQ doorbell register structure
*/
typedef struct hermon_hw_cq_db_reg_s {
uint32_t :2;
uint32_t :2;
uint32_t :8;
/* consumer cntr of last polled completion */
#define HERMON_CQDB_NOTIFY_CQ 0x02
#define HERMON_CQDB_NOTIFY_CQ_SOLICIT 0x01
/* Default value for use in NOTIFY_CQ doorbell */
#define HERMON_CQDB_DEFAULT_PARAM 0xFFFFFFFF
typedef struct hermon_hw_guest_eq_ci_s { /* guest op eq consumer index */
uint32_t :7;
uint32_t :32;
/*
* UAR page structure, containing all doorbell registers
*/
struct hermon_hw_uar_s {
};
/*
* QP (RQ, SRQ) doorbell record-specific data
* Note that this structure is NOT in ICM, but just kept in host memory
* and managed independently of PRM or other constraints. Also, though
* ease of management. Hermon defines its usage in the QP chapter.
*/
typedef struct hermon_hw_qp_db_s {
uint32_t :16;
uint32_t :32;
/*
* CQ (ARM and SET_CI) doorbell record-specific data
* See comment above re: QP doorbell. This dbr is 8 bytes long, and its
* usage is defined in PRM chapter on Completion Queues
*/
typedef struct hermon_hw_cq_arm_db_s {
uint32_t :8;
uint32_t :2;
/* sequence number of the doorbell ring % 4 */
uint32_t :1;
#define HERMON_CQ_DB_CMD_SOLICTED 0x01
#define HERMON_CQ_DB_CMD_NEXT 0x02
/*
* Hermon Blue Flame (BF)
* Hermon has the ability to do a low-latency write of successive WQEs
* for the HCA. This utilizes part of the memory area behind the
* same BAR as the UAR page (see above) - half the area is devoted to
* UAR pages, the other half to BlueFlame (though in fairness, the return
* information from QUERY_DEV_CAP should be consulted _in case_ they ever
* decide to change it.
*
* We define the structures to access them below.
*/
/*
* Hermon Send Work Queue Element (WQE)
* A Hermon Send WQE is built of the following segments, each of which is a
* multiple of 16 bytes. Note: Each individual WQE may contain only a
* subset of these segments described below (according to the operation type
* and transport type of the QP).
*
* The first 16 bytes of ever WQE are formed from the "Ctrl" segment.
* This segment contains the address of the next WQE to be executed and the
* information required in order to allocate the resources to execute the
* next WQE. The "Ctrl" part of this segment contains the control
* information required to execute the WQE, including the opcode and other
* control information.
* The "Datagram" segment contains address information required in order to
* form a UD message.
* The "Bind" segment contains the parameters required for a Bind Memory
* Window operation.
* The "Remote Address" segment is present only in RDMA or Atomic WQEs and
* specifies remote virtual addresses and RKey, respectively. Length of
* RDMA-write/RDMA-read) or set to eight (for Atomic).
* The "Atomic" segment is present only in Atomic WQEs and specifies
*
* Note: The following structures are not #define'd with both little-endian
* and big-endian definitions. This is because their individual fields are
* not directly accessed except through macros defined below.
*/
struct hermon_hw_snd_wqe_ctrl_s {
uint32_t :26;
/* NOTE: some will be used by enet */
uint32_t :25;
/* WQE size in octowords */
/* SRC remote buffer if impl */
/* set means solicit bit in last packet */
uint32_t s :1;
};
struct hermon_hw_srq_wqe_next_s {
uint32_t :16;
};
#define HERMON_WQE_SEND_FENCE_MASK 0x40
#define HERMON_WQE_SEND_NOPCODE_NOP 0x00
#define HERMON_WQE_SEND_NOPCODE_SND_INV 0x01
#define HERMON_WQE_SEND_NOPCODE_RDMAW 0x8
#define HERMON_WQE_SEND_NOPCODE_RDMAWI 0x9
#define HERMON_WQE_SEND_NOPCODE_SEND 0xA
#define HERMON_WQE_SEND_NOPCODE_SENDI 0xB
#define HERMON_WQE_SEND_NOPCODE_LSO 0xE
#define HERMON_WQE_SEND_NOPCODE_RDMAR 0x10
#define HERMON_WQE_SEND_NOPCODE_ATMCS 0x11
#define HERMON_WQE_SEND_NOPCODE_ATMFA 0x12
#define HERMON_WQE_SEND_NOPCODE_ATMCSE 0x14
#define HERMON_WQE_SEND_NOPCODE_ATMFAE 0x15
#define HERMON_WQE_SEND_NOPCODE_BIND 0x18
#define HERMON_WQE_SEND_NOPCODE_FRWR 0x19
#define HERMON_WQE_SEND_NOPCODE_LCL_INV 0x1B
#define HERMON_WQE_SEND_SIGNALED_MASK 0x0000000C00000000ull
#define HERMON_WQE_SEND_SOLICIT_MASK 0x0000000200000000ull
#define HERMON_WQE_SEND_IMMEDIATE_MASK 0x0000000100000000ull
struct hermon_hw_snd_wqe_ud_s {
struct hermon_hw_udav_s ud_addr_v;
uint32_t :8;
uint32_t :32;
uint32_t :32;
};
#define HERMON_WQE_SENDHDR_UD_AV_MASK 0xFFFFFFFFFFFFFFE0ull
#define HERMON_WQE_SENDHDR_UD_DQPN_MASK 0xFFFFFF
struct hermon_hw_snd_wqe_bind_s {
uint32_t :3;
uint32_t :25;
uint32_t :30;
};
#define HERMON_WQE_SENDHDR_BIND_ATOM 0x8000000000000000ull
#define HERMON_WQE_SENDHDR_BIND_WR 0x4000000000000000ull
#define HERMON_WQE_SENDHDR_BIND_RD 0x2000000000000000ull
struct hermon_hw_snd_wqe_remaddr_s {
uint32_t :32;
};
struct hermon_hw_snd_wqe_atomic_s {
};
struct hermon_hw_snd_wqe_atomic_ext_s {
};
struct hermon_hw_snd_wqe_local_inv_s {
uint32_t :6;
uint32_t :25;
uint32_t :32;
uint32_t :25;
uint32_t :9;
};
struct hermon_hw_snd_wqe_frwr_s {
uint32_t :16;
uint32_t :6;
uint32_t :11;
uint32_t :11;
};
/*
* NOTE: Some hermon-PRM defined Send WQE segments are not defined here
* because they will not be used initially: they should be added and
* used later on:
* FCP-3 init
* FCP-3 Control
* Large Send Offload
*
*/
/*
* Hermon "MLX transport" Work Queue Element (WQE)
* The format of the MLX WQE is similar to that of the Send WQE (above)
* with the following exceptions. MLX WQEs are used for sending MADs on
* (defined below) consists of scatter-gather list entries. The contents
* of these SGLs (also defined below) will be put on the wire exactly as
* they appear in the buffers. In addition, the VCRC and the ICRC of each
* sent packet can be modified by changing values in the following header
* or in the payload of the packet itself.
*/
struct hermon_hw_mlx_wqe_nextctrl_s {
uint32_t :23;
uint32_t :3;
uint32_t :26;
uint32_t :14;
uint32_t :1;
uint32_t :16;
};
#define HERMON_WQE_MLXHDR_VL15_MASK 0x0002000000000000ull
#define HERMON_WQE_MLXHDR_SLR_MASK 0x0001000000000000ull
#define HERMON_WQE_MLXHDR_SRATE_SHIFT 44
#define HERMON_WQE_MLXHDR_SL_SHIFT 40
#define HERMON_WQE_MLXHDR_SIGNALED_MASK 0x0000000800000000ull
#define HERMON_WQE_MLXHDR_RLID_SHIFT 16
/*
* Hermon Receive Work Queue Element (WQE)
* Unlike the Send WQE, the Receive WQE is built ONLY of 16-byte segments. A
* receive queue stride (RQ.STRIDE). It contains just
* some number of scatter list entries for the incoming message.
*
* The format of the scatter-gather list entries is shown below. For
* Receive WQEs the "inline_data" field must be cleared (i.e. data segments
* cannot contain inline data).
*/
struct hermon_hw_wqe_sgl_s {
};
#define HERMON_WQE_SGL_BYTE_CNT_MASK 0x7FFFFFFF
#define HERMON_WQE_SGL_INLINE_MASK 0x80000000
/*
* The following defines are used when building descriptors for special QP
* work requests (i.e. MLX transport WQEs). Note: Because Hermon MLX transport
* requires the driver to build actual IB packet headers, we use these defines
* for the most common fields in those headers.
*/
#define HERMON_MLX_VL15_LVER 0xF0000000
#define HERMON_MLX_VL0_LVER 0x00000000
#define HERMON_MLX_IPVER_TC_FLOW 0x60000000
#define HERMON_MLX_TC_SHIFT 20
#define HERMON_MLX_DEF_PKEY 0xFFFF
#define HERMON_MLX_GSI_QKEY 0x80010000
#define HERMON_MLX_UDSEND_OPCODE 0x64000000
#define HERMON_MLX_DQPN_MASK 0xFFFFFF
/*
* The following macros are used for building each of the individual
* segments that can make up a Hermon WQE. Note: We try not to use the
* structures (with their associated bitfields) here, instead opting to
* build and put 64-bit or 32-bit chunks to the WQEs as appropriate,
* primarily because using the bitfields appears to force more read-modify-
* write operations.
*
* HERMON_WQE_BUILD_UD - Builds Unreliable Datagram Segment
*
* HERMON_WQE_BUILD_REMADDR - Builds Remote Address Segment using
* RDMA info from the work request
* HERMON_WQE_BUILD_RC_ATOMIC_REMADDR - Builds Remote Address Segment
* for RC Atomic work requests
* HERMON_WQE_BUILD_ATOMIC - Builds Atomic Segment using atomic
* info from the work request
* HERMON_WQE_BUILD_BIND - Builds the Bind Memory Window
* Segment using bind info from the
* work request
* HERMON_WQE_BUILD_DATA_SEG - Builds the individual Data Segments
* for Send, Receive, and MLX WQEs
* HERMON_WQE_BUILD_INLINE - Builds an "inline" Data Segment
* (primarily for MLX transport)
* HERMON_WQE_BUILD_INLINE_ICRC - Also builds an "inline" Data Segment
* (but used primarily in the ICRC
* portion of MLX transport WQEs)
* HERMON_WQE_LINKNEXT - Links the current WQE to the
* previous one
* HERMON_WQE_LINKFIRST - Links the first WQE on the current
* chain to the previous WQE
* HERMON_WQE_BUILD_MLX_LRH - Builds the inline LRH header for
* MLX transport MADs
* HERMON_WQE_BUILD_MLX_GRH - Builds the inline GRH header for
* MLX transport MADs
* HERMON_WQE_BUILD_MLX_BTH - Builds the inline BTH header for
* MLX transport MADs
* HERMON_WQE_BUILD_MLX_DETH - Builds the inline DETH header for
* MLX transport MADs
*/
{ \
\
HERMON_WQE_SENDHDR_UD_DQPN_MASK) << 32) | \
tmp[5] = 0; \
}
{ \
\
}
{ \
\
}
{ \
\
}
{ \
\
HERMON_WQE_SENDHDR_BIND_ATOM : 0; \
HERMON_WQE_SENDHDR_BIND_WR : 0; \
HERMON_WQE_SENDHDR_BIND_RD : 0; \
}
{ \
\
}
{ \
membar_producer(); \
}
{ \
\
}
{ \
\
cntr_tmp = 0; \
/*LINTED*/ \
}
{ \
\
cntr_tmp &= 0x80000000; \
if (lid == IB_LID_PERMISSIVE) \
if ((sig) != 0) \
cntr_tmp |= 0xC; \
}
{ \
\
\
} else { \
} \
} else { \
} \
\
lrh_tmp |= IB_LID_PERMISSIVE; \
} else { \
} \
}
/*
* Note: The GRH payload length, calculated below, is the overall packet
* length (in bytes) minus LRH header and GRH headers.
*
* Also note: Filling in the GIDs in the way we do below is helpful because
*/
{ \
\
\
\
sizeof (ib_grh_t))) << 16; \
\
[(udav)->mgid_index]; \
}
{ \
\
\
} \
bth_tmp |= HERMON_MLX_DEF_PKEY; \
} else { \
[(qp)->qp_pkeyindx]; \
} \
}
{ \
\
\
tmp[0] = 0x0; \
} else { \
} \
}
/*
* Flash interface:
* Below we have PCI config space space offsets for flash interface
* access, offsets within Hermon CR space for accessing flash-specific
* information or settings, masks used for flash settings, and
* timeout values for flash operations.
*/
#define HERMON_HW_FLASH_CFG_HWREV 8
#define HERMON_HW_FLASH_CFG_ADDR 88
#define HERMON_HW_FLASH_CFG_DATA 92
#define HERMON_HW_FLASH_RESET_AMD 0xF0
#define HERMON_HW_FLASH_RESET_INTEL 0xFF
#define HERMON_HW_FLASH_CPUMODE 0xF0150
#define HERMON_HW_FLASH_ADDR 0xF01A4
#define HERMON_HW_FLASH_DATA 0xF01A8
#define HERMON_HW_FLASH_GPIO_SEMA 0xF03FC
#define HERMON_HW_FLASH_WRCONF_SEMA 0xF0380
#define HERMON_HW_FLASH_GPIO_DATA 0xF0040
#define HERMON_HW_FLASH_GPIO_MOD1 0xF004C
#define HERMON_HW_FLASH_GPIO_MOD0 0xF0050
#define HERMON_HW_FLASH_GPIO_DATACLEAR 0xF00D4
#define HERMON_HW_FLASH_GPIO_DATASET 0xF00DC
#define HERMON_HW_FLASH_GPIO_LOCK 0xF0048
#define HERMON_HW_FLASH_GPIO_UNLOCK_VAL 0xD42F
#define HERMON_HW_FLASH_GPIO_PIN_ENABLE 0x1E000000
#define HERMON_HW_FLASH_CPU_MASK 0xC0000000
#define HERMON_HW_FLASH_CPU_SHIFT 30
#define HERMON_HW_FLASH_ADDR_MASK 0x0007FFFC
#define HERMON_HW_FLASH_CMD_MASK 0xE0000000
#define HERMON_HW_FLASH_BANK_MASK 0xFFF80000
#define HERMON_HW_FLASH_SPI_BUSY 0x40000000
#define HERMON_HW_FLASH_SPI_WIP 0x01000000
#define HERMON_HW_FLASH_SPI_READ_OP 0x00000001
#define HERMON_HW_FLASH_SPI_USE_INSTR 0x00000040
#define HERMON_HW_FLASH_SPI_NO_ADDR 0x00000020
#define HERMON_HW_FLASH_SPI_NO_DATA 0x00000010
#define HERMON_HW_FLASH_SPI_TRANS_SZ_4B 0x00000200
#define HERMON_HW_FLASH_SPI_SECTOR_ERASE 0xD8
#define HERMON_HW_FLASH_SPI_READ 0x03
#define HERMON_HW_FLASH_SPI_PAGE_PROGRAM 0x02
#define HERMON_HW_FLASH_SPI_READ_STATUS_REG 0x05
#define HERMON_HW_FLASH_SPI_WRITE_ENABLE 0x06
#define HERMON_HW_FLASH_SPI_READ_ESIGNATURE 0xAB
#define HERMON_HW_FLASH_SPI_GW 0xF0400
#define HERMON_HW_FLASH_SPI_ADDR 0xF0404
#define HERMON_HW_FLASH_SPI_DATA 0xF0410
#define HERMON_HW_FLASH_SPI_DATA4 0xF0414
#define HERMON_HW_FLASH_SPI_DATA8 0xF0418
#define HERMON_HW_FLASH_SPI_DATA12 0xF041C
#define HERMON_HW_FLASH_SPI_ADDR_MASK 0x00FFFFFF
#define HERMON_HW_FLASH_SPI_INSTR_PHASE_OFF 0x04
#define HERMON_HW_FLASH_SPI_ADDR_PHASE_OFF 0x08
#define HERMON_HW_FLASH_SPI_DATA_PHASE_OFF 0x10
#define HERMON_HW_FLASH_SPI_ENABLE_OFF 0x2000
#define HERMON_HW_FLASH_SPI_CS_OFF 0x800
#define HERMON_HW_FLASH_SPI_INSTR_OFF 0x10000
#define HERMON_HW_FLASH_SPI_INSTR_SHIFT 0x10
#define HERMON_HW_FLASH_SPI_BOOT_ADDR_REG 0xF0000
#define HERMON_HW_FLASH_TIMEOUT_WRITE 300
#define HERMON_HW_FLASH_TIMEOUT_ERASE 1000000
#define HERMON_HW_FLASH_TIMEOUT_GPIO_SEMA 1000
#define HERMON_HW_FLASH_TIMEOUT_CONFIG 50
#define HERMON_HW_FLASH_ICS_ERASE 0x20
#define HERMON_HW_FLASH_ICS_ERROR 0x3E
#define HERMON_HW_FLASH_ICS_WRITE 0x40
#define HERMON_HW_FLASH_ICS_STATUS 0x70
#define HERMON_HW_FLASH_ICS_READY 0x80
#define HERMON_HW_FLASH_ICS_CONFIRM 0xD0
#define HERMON_HW_FLASH_ICS_READ 0xFF
#ifdef __cplusplus
}
#endif
#endif /* _SYS_IB_ADAPTERS_HERMON_HW_H */