tavor.h revision 9e39c5ba00a55fa05777cc94b148296af305e135
/*
* 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_TAVOR_H
#define _SYS_IB_ADAPTERS_TAVOR_H
/*
* tavor.h
* Contains the #defines and typedefs necessary for the Tavor softstate
* structure and for proper attach() and detach() processing. Also
* includes all the other Tavor header files (and so is the only header
* file that is directly included by the Tavor source files).
* Additionally, this file contains some defines and macros used by
* Tavor TNF tracing mechanism.
* Lastly, this file includes everything necessary for implementing the
* devmap interface and for maintaining the "mapped resource database".
*/
#include <sys/tnf_probe.h>
/*
* First include all the Tavor typedefs, then include all the other Tavor
* specific headers (many of which depend on the typedefs having already
* been defined.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* The following defines and macros are used for Tavor TNF tracing
* Note: TAVOR_TNF_FAIL is used in routines which has many failure cases.
* It will initialize the "errormsg" and "status" variables (both of which
* must be declared locally in the routines where this macro is used) for use
* in a later TNF probe and return from routine.
*/
#define TAVOR_TNF_ERROR "tavor tavor_error "
#define TAVOR_TNF_TRACE "tavor tavor_trace "
#define TAVOR_TNF_ENTER(func) \
#define TAVOR_TNF_EXIT(func) \
#define TAVOR_TNF_FAIL(s, e) \
{ \
errormsg = (e); \
status = (s); \
}
/*
* Number of initial states to setup. Used in call to ddi_soft_state_init()
*/
#define TAVOR_INITIAL_STATES 3
/*
* Macro and defines used to calculate device instance number from minor
* number (and vice versa).
*/
#define TAVOR_MINORNUM_SHIFT 3
/*
* Locations for the various Tavor hardware PCI BARs (CMD, UAR, DDR)
*/
#define TAVOR_CMD_BAR 1
#define TAVOR_UAR_BAR 2
#define TAVOR_DDR_BAR 3
/*
* Some defines for the software reset. These define the value that should
* be written to begin the reset (TAVOR_SW_RESET_START), the delay before
* beginning to poll for completion (TAVOR_SW_RESET_DELAY), the in-between
* polling delay (TAVOR_SW_RESET_POLL_DELAY), and the value that indicates
* that the reset has not completed (TAVOR_SW_RESET_NOTDONE).
*/
#define TAVOR_SW_RESET_START 0x00000001
#define TAVOR_SW_RESET_NOTDONE 0xFFFFFFFF
/*
* These defines are used in the Tavor software reset operation. They define
* also specify two config registers which should not be read or restored.
*/
#define TAVOR_SW_RESET_NUMREGS 0x40
#define TAVOR_SW_RESET_REG22_RSVD 0x16
#define TAVOR_SW_RESET_REG23_RSVD 0x17
/*
* Macro used to output Tavor warning messages. Note: Tavor warning messages
* are only generated when an unexpected condition has been detected. This
* can be the result of a software bug or some other problem, but it is more
* something unexpected. This warning message means that the driver state
*/
/*
* Macro used to set attach failure messages. Also, the attach message buf
* size is set here.
*/
#define TAVOR_ATTACH_MSGSIZE 80
#define TAVOR_ATTACH_MSG_INIT(attach_buf) \
(attach_buf)[0] = '\0';
/*
* Macros used for controlling whether or not event callbacks will be forwarded
* to the IBTF. This is necessary because there are certain race conditions
* that can occur (e.g. calling IBTF with an asynch event before the IBTF
* registration has successfully completed or handling an event after we've
* detached from the IBTF.)
*
* TAVOR_ENABLE_IBTF_CALLB() initializes the "ts_ibtfpriv" field in the Tavor
* softstate. When "ts_ibtfpriv" is non-NULL, it is OK to forward asynch
* and CQ events to the IBTF.
*
* TAVOR_DO_IBTF_ASYNC_CALLB() and TAVOR_DO_IBTF_CQ_CALLB() both set and clear
* the "ts_in_evcallb" flag, as necessary, to indicate that an IBTF
* callback is currently in progress. This is necessary so that we can
* block on this condition in tavor_detach().
*
* TAVOR_QUIESCE_IBTF_CALLB() is used in tavor_detach() to set the
* "ts_ibtfpriv" to NULL (thereby disabling any further IBTF callbacks)
* and to poll on the "ts_in_evcallb" flag. When this flag is zero, all
* IBTF callbacks have quiesced and it is safe to continue with detach
* (i.e. continue detaching from IBTF).
*/
(state)->ts_in_evcallb = 0;
(state)->ts_in_evcallb = 0;
#define TAVOR_QUIESCE_IBTF_CALLB(state) \
{ \
\
while (((state)->ts_in_evcallb != 0) && \
(count++ < TAVOR_QUIESCE_IBTF_CALLB_POLL_MAX)) { \
} \
}
/*
* Defines used by the TAVOR_QUIESCE_IBTF_CALLB() macro to determine the
* duration and number of times (at maximum) to poll while waiting for IBTF
* callbacks to quiesce.
*/
#define TAVOR_QUIESCE_IBTF_CALLB_POLL_DELAY 1
#define TAVOR_QUIESCE_IBTF_CALLB_POLL_MAX 1000000
/*
* Define used to determine the device mode to which Tavor driver has been
* attached. TAVOR_IS_MAINTENANCE_MODE() returns true when the device has
* come up in the "maintenance mode". In this mode, no InfiniBand interfaces
* TAVOR_IS_HCA_MODE() returns true when the device has come up in the normal
* HCA mode. In this mode, all necessary InfiniBand interfaces are enabled
*/
#define TAVOR_IS_MAINTENANCE_MODE(dip) \
"device-id", -1) == 0x5a45) || \
"device-id", -1) == 0x6279)) && \
"vendor-id", -1) == 0x15b3))
#define TAVOR_IS_COMPAT_MODE(dip) \
"device-id", -1) == 0x6278) && \
"vendor-id", -1) == 0x15b3))
#define TAVOR_IS_HCA_MODE(dip) \
"device-id", -1) == 0x5a44) && \
"vendor-id", -1) == 0x15b3))
#define TAVOR_MAINTENANCE_MODE 1
#define TAVOR_COMPAT_MODE 2
#define TAVOR_HCA_MODE 3
/*
* Used to determine if the device is operational, or not in maintenance mode.
* This means either the driver has attached successfully against an arbel
* device in tavor compatibility mode, or against a tavor device in full HCA
* mode.
*/
#define TAVOR_IS_OPERATIONAL(mode) \
/*
* Used to determine if parent bridge is a PCI bridge; used in software reset
*/
#define TAVOR_PARENT_IS_BRIDGE(dip) \
"device-id", -1) == 0x5a46))
/*
* The following define is used (in tavor_umap_db_set_onclose_cb()) to
* indicate that a cleanup callback is needed to undo initialization done
* by the firmware flash burn code.
*/
#define TAVOR_ONCLOSE_FLASH_INPROGRESS (1 << 0)
/*
* The following enumerated type and structures are used during driver
* initialization. Note: The TAVOR_DRV_CLEANUP_ALL type is used as a marker
* for end of the cleanup steps. No cleanup steps should be added after
* TAVOR_DRV_CLEANUP_ALL. Any addition steps should be added before it.
*/
typedef enum {
/* No more driver cleanup steps below this point! */
/*
* tavor_mem_alloc_hdl_t structure store DMA handles for the new
* ibc_alloc_io_mem calls
*/
typedef struct tavor_mem_alloc_hdl_s {
/*
* The tavor_cmd_reg_t structure is used to hold the address of the each of
* the most frequently accessed hardware registers. Specifically, it holds
* the HCA Command Registers (HCR, used to pass command and mailbox
* information back and forth to Tavor firmware) and the lock used to guarantee
* mutually exclusive access to the registers. It also holds the Event Cause
* Register (ECR) and its related clear register. These are used to indicate
* during interrupt processing which EQs have fired and require servicing.
* Related to this, is the "clr_int" register which is used to clear the
* interrupt once all EQs have been services.
* Finally, there is the software reset register which is used to reinitialize
* the Tavor device and to put it into a known state at driver startup time.
* Below we also have the offsets (into the CMD register space) for each of
* the various registers.
*/
typedef struct tavor_cmd_reg_s {
/*
* The tavor_state_t structure is the Tavor software state structure. It
* contains all the pointers and placeholder for everything that the Tavor
* driver needs to properly operate. One of these structures exists for
* every instance of the Tavor driver.
*/
struct tavor_state_s {
int ts_instance;
int ts_intr_types_avail;
int ts_intrmsi_count;
int ts_intrmsi_avail;
int ts_intrmsi_allocd;
int ts_intrmsi_cap;
/* Tavor device operational mode */
int ts_operational_mode;
/* Attach buffer saved per state to store detailed attach errors */
/*
* Tavor NodeGUID, SystemImageGUID, NodeDescription, HCA name,
* and HCA part number.
*/
char ts_nodedesc[64];
char ts_hca_name[64];
char ts_hca_pn[64];
int ts_hca_pn_len;
/* Info passed to IBTF during registration */
/*
* Tavor register mapping. Holds the device access attributes,
* kernel mapped addresses, and DDI access handles for each of
* Tavor's three types of address register (CMD, UAR, and DDR).
*/
/*
* Tavor PCI config space registers. These two arrays are used to
* save and restore the PCI config registers before and after a
* software reset. Note: We must save away both our own registers
* and our parent's (the "virtual" PCI bridge in the device) because
* the software reset will reset both sets.
*/
/*
* Tavor UAR page resources. Holds the resource pointers for
* UAR page #0 (reserved) and for UAR page #1 (used for kernel
* driver doorbells). In addition, we save a pointer to the
* UAR page #1 doorbells which will be used throughout the driver
* whenever it is necessary to ring one of them. And, in case we
* are unable to do 64-bit writes to the page (because of system
* architecture), we include a lock (to ensure atomic 64-bit access).
*/
/*
* Used during a call to open() if we are in maintenance mode, this
* field serves as a semi-unique rolling count index value, used only
* in the setup of umap_db entries. This is primarily needed to
* firmware device access ioctl operations can still be guaranteed to
* close in the event of an unplanned process exit, even in maintenance
* mode.
*/
/*
* Tavor command registers. This structure contains the addresses
* for each of the most frequently accessed CMD registers. Since
* almost all accesses to the Tavor hardware are through the Tavor
* command interface (i.e. the HCR), we save away the pointer to
* the HCR, as well as pointers to the ECR and INT registers (as
* well as their corresponding "clear" registers) for interrupt
* processing. And we also save away a pointer to the software
* reset register (see above).
*/
/*
* Tavor resource pointers. The following are pointers to the vmem
* arena (created to manage the DDR memory), the kmem cache (from
* which the Tavor resource handles are allocated), and the array
* of "resource pools" (which store all the pertinent information
* necessary to manage each of the various types of resources that
* are used by the Tavor driver. See tavor_rsrc.h for more detail.
*/
/*
* Tavor mailbox lists. These hold the information necessary to
* manage the pools of pre-allocated Tavor mailboxes (both "In" and
* "Out" type). See tavor_cmd.h for more detail.
*/
/*
* Tavor interrupt mailbox lists. We allocate both an "In" mailbox
* and an "Out" type mailbox for the interrupt context. This is in
* order to guarantee that a mailbox entry will always be available in
* the interrupt context, and we can NOSLEEP without having to worry
* about possible failure allocating the mbox. We create this as an
* mboxlist so that we have the potential for having multiple mboxes
* available based on the number of interrupts we can receive at once.
*/
/*
* Tavor outstanding command list. Used to hold all the information
* necessary to manage the Tavor "outstanding command list". See
* tavor_cmd.h for more detail.
*/
/*
* This structure contains the Tavor driver's "configuration profile".
* This is the collected set of configuration information, such as
* number of QPs, CQs, mailboxes and other resources, sizes of
* individual resources, other system level configuration information,
* etc. See tavor_cfg.h for more detail.
*/
/*
* This flag contains the profile setting, selecting which profile the
* driver would use. This is needed in the case where we have to
* fallback to a smaller profile based on some DDR conditions. If we
* don't fallback, then it is set to the size of DDR in the system.
*/
/*
* The following are a collection of resource handles used by the
* Tavor driver (internally). First is the protection domain (PD)
* handle that is used when mapping all kernel memory (work queues,
* completion queues, etc). Next is an array of EQ handles. This
* array is indexed by EQ number and allows the Tavor driver to quickly
* convert an EQ number into the software structure associated with the
* given EQ. Likewise, we have three arrays for CQ, QP and SRQ
* handles. These arrays are also indexed by CQ, QP or SRQ number and
* allow the driver to quickly find the corresponding CQ, QP or SRQ
* software structure. Note: while the EQ table is of fixed size
* (because there are a maximum of 64 EQs), each of the CQ, QP and SRQ
* handle lists must be allocated at driver startup.
*/
/*
* The AVL tree is used to store information regarding QP number
* allocations. The lock protects access to the AVL tree.
*/
/*
* This field is used to indicate whether or not the Tavor driver is
* currently in an IBTF event callback elsewhere in the system. Note:
* It is "volatile" because we intend to poll on this value - in
* tavor_detach() - until we are assured that no further IBTF callbacks
* are currently being processed.
*/
volatile uint32_t ts_in_evcallb;
/*
* The following structures are used to store the results of several
* device query commands passed to the Tavor hardware at startup.
* Specifically, we have hung onto the results of QUERY_DDR (which
* gives information about how much DDR memory is present and where
* it is located), QUERY_FW (which gives information about firmware
* version numbers and the location and extent of firmware's footprint
* in DDR, QUERY_DEVLIM (which gives the device limitations/resource
* maximums), QUERY_ADAPTER (which gives additional miscellaneous
* recording what configuration information was passed to the firmware
* when the HCA was initialized).
*/
struct tavor_hw_queryddr_s ts_ddr;
struct tavor_hw_queryfw_s ts_fw;
struct tavor_hw_querydevlim_s ts_devlim;
struct tavor_hw_queryadapter_s ts_adapter;
struct tavor_hw_initqueryhca_s ts_hcaparams;
/*
* The following are used for managing special QP resources.
* Specifically, we have a lock, a set of flags (in "ts_spec_qpflags")
* used to track the special QP resources, and two Tavor resource
* handle pointers. Each resource handle actually corresponds to two
* consecutive QP contexts (one per port) for each special QP type.
*/
/*
* Related in some ways to the special QP handling above are these
* resources which are used specifically for implementing the Tavor
* agents (SMA, PMA, and BMA). Although, each of these agents does
* little more that intercept the appropriate incoming MAD and forward
* it along to the firmware (see tavor_agents.c for more details), we
* do still use a task queue to queue them up. We can also configure
* the driver to force firmware handling for certain classes of MAD,
* and, therefore, we require the agent list and number of agents
* in order to know what needs to be torn down at detach() time.
*/
/*
* Multicast group lists. These are used to track the "shadow" MCG
* lists that speed up the processing of attach and detach multicast
* group operations. See tavor_misc.h for more details. Note: we
* need the pointer to the "temporary" MCG entry here primarily
* because the size of a given MCG entry is configurable. Therefore,
* it is impossible to put this variable on the stack. And rather
* than allocate and deallocate the entry multiple times, we choose
* instead to preallocate it once and reuse it over and over again.
*/
/*
* Used for tracking Tavor kstat information
*/
/*
* Used for Tavor info ioctl used by VTS
*/
/*
* Used for Tavor FW flash burning. They are used exclusively
* within the ioctl calls for use when accessing the tavor
* flash device.
*/
int ts_fw_flashstarted;
int ts_fw_cmdset;
/* Tavor fastreboot support */
};
/*
* TAVOR_IN_FASTREBOOT() shows if Hermon driver is at fastreboot.
* This macro should be used to check if the mutex lock can be used
* since the lock cannot be used if the driver is in the quiesce mode.
*/
/*
* Bit positions in the "ts_spec_qpflags" field above. The flags are (from
* least significant to most): (QP0,Port1), (QP0,Port2), (QP1,Port1), and
* (QP1,Port2). The masks are there to help with some specific allocation
* and freeing operations
*/
#define TAVOR_SPECIAL_QP0_RSRC 0
#define TAVOR_SPECIAL_QP0_RSRC_MASK 0x3
#define TAVOR_SPECIAL_QP1_RSRC 2
#define TAVOR_SPECIAL_QP1_RSRC_MASK 0xC
/*
* These flags specifies additional behaviors on database access.
* TAVOR_UMAP_DB_REMOVE, for example, specifies that (if found) the database
* entry should be removed from the database. TAVOR_UMAP_DB_IGNORE_INSTANCE
* specifies that a particular database query should ignore value in the
* "tdb_instance" field as a criterion for the search.
*/
#define TAVOR_UMAP_DB_REMOVE (1 << 0)
/*
* The tavor_umap_db_t structure contains what is referred to throughout the
* driver code as the "userland resources database". This structure contains
* all the necessary information to track resources that have been prepared
* for direct-from-userland access. There is an AVL tree ("tdl_umapdb_avl")
* which consists of the "tavor_umap_db_entry_t" (below) and a lock to ensure
* atomic access when adding or removing entries from the database.
*/
typedef struct tavor_umap_db_s {
/*
* The tavor_umap_db_priv_t structure currently contains information necessary
* to provide the "on close" callback to the firmware flash interfaces. It
* is intended that this structure could be extended to enable other "on
* close" callbacks as well.
*/
typedef struct tavor_umap_db_priv_s {
void (*tdp_cb)(void *);
void *tdp_arg;
/*
* The tavor_umap_db_common_t structure contains fields which are common
* between the database entries ("tavor_umap_db_entry_t") and the structure
* used to contain the search criteria ("tavor_umap_db_query_t"). This
* structure contains a key, a resource type (described above), an instance
* (corresponding to the driver instance which inserted the database entry),
* and a "value" field. Typically, "tdb_value" is a pointer to a Tavor
* resource object. Although for memory regions, the value field corresponds
* to the ddi_umem_cookie_t for the pinned userland memory.
* The structure also includes a placeholder for private data ("tdb_priv").
* Currently this data is being used for holding "on close" callback
* information to allow certain kinds of cleanup even if a userland process
* prematurely exits.
*/
typedef struct tavor_umap_db_common_s {
void *tdb_priv;
/*
* The tavor_umap_db_entry_t structure is the entry in "userland resources
* database". As required by the AVL framework, each entry contains an
* "avl_node_t". Then, as required to implement the database, each entry
* contains a "tavor_umap_db_common_t" structure used to contain all of the
* relevant entries.
*/
typedef struct tavor_umap_db_entry_s {
/*
* The tavor_umap_db_query_t structure is used in queries to the "userland
* resources database". In addition to the "tavor_umap_db_common_t" structure
* used to contain the various search criteria, this structure also contains
* a flags field "tqdb_flags" which can be used to specify additional behaviors
* (as described above). Specifically, the flags field can be used to specify
* that an entry should be removed from the database, if found, and to
* specify whether the database lookup should consider "tdb_instance" in the
* search.
*/
typedef struct tavor_umap_db_query_s {
/*
* The tavor_devmap_track_t structure contains all the necessary information
* to track resources that have been mapped through devmap. There is a
* back-pointer to the Tavor softstate, the logical offset corresponding with
* the mapped resource, the size of the mapped resource (zero indicates an
* "invalid mapping"), and a reference count and lock used to determine when
* to free the structure (specifically, this is necessary to handle partial
* unmappings).
*/
typedef struct tavor_devmap_track_s {
int tdt_refcnt;
/* Defined in tavor_umap.c */
void tavor_umap_db_init(void);
void tavor_umap_db_fini(void);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_IB_ADAPTERS_TAVOR_H */