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
* 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 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/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/tnf_probe.h>
#include <sys/taskq.h>
#include <sys/ib/ibtl/ibci.h>
#include <sys/ib/adapters/mlnx_umap.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.
*/
#include <sys/ib/adapters/tavor/tavor_typedef.h>
#include <sys/ib/adapters/tavor/tavor_agents.h>
#include <sys/ib/adapters/tavor/tavor_cfg.h>
#include <sys/ib/adapters/tavor/tavor_cmd.h>
#include <sys/ib/adapters/tavor/tavor_cq.h>
#include <sys/ib/adapters/tavor/tavor_event.h>
#include <sys/ib/adapters/tavor/tavor_hw.h>
#include <sys/ib/adapters/tavor/tavor_ioctl.h>
#include <sys/ib/adapters/tavor/tavor_misc.h>
#include <sys/ib/adapters/tavor/tavor_mr.h>
#include <sys/ib/adapters/tavor/tavor_qp.h>
#include <sys/ib/adapters/tavor/tavor_srq.h>
#include <sys/ib/adapters/tavor/tavor_rsrc.h>
#include <sys/ib/adapters/tavor/tavor_wr.h>
#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) \
TNF_PROBE_0_DEBUG(func##_start, TAVOR_TNF_TRACE, "")
#define TAVOR_TNF_EXIT(func) \
TNF_PROBE_0_DEBUG(func##_end, TAVOR_TNF_TRACE, "")
#define TAVOR_TNF_FAIL(s, e) \
{ \
errormsg = (e); \
status = (s); \
}
#define TAVOR_VPD_HDR_DWSIZE 0x10 /* 16 Dwords */
#define TAVOR_VPD_HDR_BSIZE 0x40 /* 64 Bytes */
/*
* 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
#define TAVOR_DEV_INSTANCE(dev) (getminor((dev)) & \
((1 << TAVOR_MINORNUM_SHIFT) - 1))
/*
* 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_DELAY 100000 /* 100 ms */
#define TAVOR_SW_RESET_POLL_DELAY 100 /* 100 us */
#define TAVOR_SW_RESET_NOTDONE 0xFFFFFFFF
/*
* These defines are used in the Tavor software reset operation. They define
* the total number PCI registers to read/restore during the reset. And they
* 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
* often an indication that the Tavor firmware (and/or hardware) has done
* something unexpected. This warning message means that the driver state
* in unpredictable and that shutdown/restart is suggested.
*/
#define TAVOR_WARNING(state, string) \
cmn_err(CE_WARN, "tavor%d: "string, (state)->ts_instance)
/*
* 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(attach_buf, attach_msg) \
(void) snprintf((attach_buf), TAVOR_ATTACH_MSGSIZE, (attach_msg));
#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).
*/
#define TAVOR_ENABLE_IBTF_CALLB(state, tmp_ibtfpriv) \
(state)->ts_ibtfpriv = (tmp_ibtfpriv);
#define TAVOR_DO_IBTF_ASYNC_CALLB(state, type, event) \
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS((state)->ts_in_evcallb)) \
(state)->ts_in_evcallb = 1; \
ibc_async_handler((state)->ts_ibtfpriv, (type), (event)); \
(state)->ts_in_evcallb = 0;
#define TAVOR_DO_IBTF_CQ_CALLB(state, cq) \
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS((state)->ts_in_evcallb)) \
(state)->ts_in_evcallb = 1; \
ibc_cq_handler((state)->ts_ibtfpriv, (cq)->cq_hdlrarg); \
(state)->ts_in_evcallb = 0;
#define TAVOR_QUIESCE_IBTF_CALLB(state) \
{ \
uint_t count = 0; \
\
state->ts_ibtfpriv = NULL; \
while (((state)->ts_in_evcallb != 0) && \
(count++ < TAVOR_QUIESCE_IBTF_CALLB_POLL_MAX)) { \
drv_usecwait(TAVOR_QUIESCE_IBTF_CALLB_POLL_DELAY); \
} \
}
/*
* 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
* are enabled, but the device's firmware can be updated/flashed (and
* test/debug interfaces should be useable).
* 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
* (and, if necessary, Tavor firmware can be updated/flashed).
*/
#define TAVOR_IS_MAINTENANCE_MODE(dip) \
(((ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"device-id", -1) == 0x5a45) || \
(ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"device-id", -1) == 0x6279)) && \
(ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"vendor-id", -1) == 0x15b3))
#define TAVOR_IS_COMPAT_MODE(dip) \
((ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"device-id", -1) == 0x6278) && \
(ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"vendor-id", -1) == 0x15b3))
#define TAVOR_IS_HCA_MODE(dip) \
((ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"device-id", -1) == 0x5a44) && \
(ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"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) \
(mode == TAVOR_COMPAT_MODE || mode == TAVOR_HCA_MODE)
/*
* Used to determine if parent bridge is a PCI bridge; used in software reset
*/
#define TAVOR_PARENT_IS_BRIDGE(dip) \
((ddi_prop_get_int(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
"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 {
TAVOR_DRV_CLEANUP_LEVEL0,
TAVOR_DRV_CLEANUP_LEVEL1,
TAVOR_DRV_CLEANUP_LEVEL2,
TAVOR_DRV_CLEANUP_LEVEL3,
TAVOR_DRV_CLEANUP_LEVEL4,
TAVOR_DRV_CLEANUP_LEVEL5,
TAVOR_DRV_CLEANUP_LEVEL6,
TAVOR_DRV_CLEANUP_LEVEL7,
TAVOR_DRV_CLEANUP_LEVEL8,
TAVOR_DRV_CLEANUP_LEVEL9,
TAVOR_DRV_CLEANUP_LEVEL10,
TAVOR_DRV_CLEANUP_LEVEL11,
TAVOR_DRV_CLEANUP_LEVEL12,
TAVOR_DRV_CLEANUP_LEVEL13,
TAVOR_DRV_CLEANUP_LEVEL14,
/* No more driver cleanup steps below this point! */
TAVOR_DRV_CLEANUP_ALL
} tavor_drv_cleanup_level_t;
/*
* tavor_mem_alloc_hdl_t structure store DMA handles for the new
* ibc_alloc_io_mem calls
*/
typedef struct tavor_mem_alloc_hdl_s {
ddi_dma_handle_t tavor_dma_hdl;
ddi_acc_handle_t tavor_acc_hdl;
} *tavor_mem_alloc_hdl_t;
/*
* 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 {
tavor_hw_hcr_t *hcr;
kmutex_t hcr_lock;
uint64_t *ecr;
uint64_t *clr_ecr;
uint64_t *clr_int;
uint32_t *sw_reset;
} tavor_cmd_reg_t;
_NOTE(MUTEX_PROTECTS_DATA(tavor_cmd_reg_t::hcr_lock,
tavor_cmd_reg_t::hcr))
/*
* 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 {
dev_info_t *ts_dip;
int ts_instance;
/* Tavor interrupt/MSI information */
int ts_intr_types_avail;
uint_t ts_intr_type_chosen;
int ts_intrmsi_count;
int ts_intrmsi_avail;
int ts_intrmsi_allocd;
ddi_intr_handle_t ts_intrmsi_hdl;
uint_t ts_intrmsi_pri;
int ts_intrmsi_cap;
/* Tavor device operational mode */
int ts_operational_mode;
/* Attach buffer saved per state to store detailed attach errors */
char ts_attach_buf[TAVOR_ATTACH_MSGSIZE];
/*
* Tavor NodeGUID, SystemImageGUID, NodeDescription, HCA name,
* and HCA part number.
*/
uint64_t ts_nodeguid;
uint64_t ts_sysimgguid;
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 */
ibc_hca_info_t ts_ibtfinfo;
ibc_clnt_hdl_t ts_ibtfpriv;
/*
* 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).
*/
ddi_device_acc_attr_t ts_reg_accattr;
caddr_t ts_reg_cmd_baseaddr; /* Tavor CMD BAR */
ddi_acc_handle_t ts_reg_cmdhdl;
caddr_t ts_reg_uar_baseaddr; /* Tavor UAR BAR */
ddi_acc_handle_t ts_reg_uarhdl;
caddr_t ts_reg_ddr_baseaddr; /* Tavor DDR BAR */
ddi_acc_handle_t ts_reg_ddrhdl;
/*
* 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.
*/
uint32_t ts_cfg_data[TAVOR_SW_RESET_NUMREGS];
uint32_t ts_cfg_pdata[TAVOR_SW_RESET_NUMREGS];
/*
* 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).
*/
tavor_rsrc_t *ts_uarpg0_rsrc_rsrvd;
tavor_rsrc_t *ts_uarpg1_rsrc;
tavor_hw_uar_t *ts_uar;
kmutex_t ts_uar_lock;
/*
* 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.
*/
uint_t ts_open_tr_indx;
/*
* 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_cmd_reg_t ts_cmd_regs;
/*
* 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.
*/
vmem_t *ts_ddrvmem;
kmem_cache_t *ts_rsrc_cache;
tavor_rsrc_pool_info_t *ts_rsrc_hdl;
/*
* 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_mboxlist_t ts_in_mblist;
tavor_mboxlist_t ts_out_mblist;
/*
* 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_mboxlist_t ts_in_intr_mblist;
tavor_mboxlist_t ts_out_intr_mblist;
/*
* 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.
*/
tavor_cmdlist_t ts_cmd_list;
/*
* 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.
*/
tavor_cfg_profile_t *ts_cfg_profile;
/*
* 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.
*/
uint32_t ts_cfg_profile_setting;
/*
* 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.
*/
tavor_pdhdl_t ts_pdhdl_internal;
tavor_eqhdl_t ts_eqhdl[TAVOR_NUM_EQ];
tavor_cqhdl_t *ts_cqhdl;
tavor_qphdl_t *ts_qphdl;
tavor_srqhdl_t *ts_srqhdl;
/*
* The AVL tree is used to store information regarding QP number
* allocations. The lock protects access to the AVL tree.
*/
avl_tree_t ts_qpn_avl;
kmutex_t ts_qpn_avl_lock;
/*
* 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
* information), and INIT/QUERY_HCA (which serves the purpose of
* 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.
*/
kmutex_t ts_spec_qplock;
uint_t ts_spec_qpflags;
tavor_rsrc_t *ts_spec_qp0;
tavor_rsrc_t *ts_spec_qp1;
/*
* 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.
*/
tavor_agent_list_t *ts_agents;
ddi_taskq_t *ts_taskq_agents;
uint_t ts_num_agents;
/*
* 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.
*/
kmutex_t ts_mcglock;
tavor_mcghdl_t ts_mcghdl;
tavor_hw_mcg_t *ts_mcgtmp;
/*
* Used for tracking Tavor kstat information
*/
tavor_ks_info_t *ts_ks_info;
/*
* Used for Tavor info ioctl used by VTS
*/
kmutex_t ts_info_lock;
/*
* Used for Tavor FW flash burning. They are used exclusively
* within the ioctl calls for use when accessing the tavor
* flash device.
*/
kmutex_t ts_fw_flashlock;
int ts_fw_flashstarted;
dev_t ts_fw_flashdev;
uint32_t ts_fw_log_sector_sz;
uint32_t ts_fw_device_sz;
uint32_t ts_fw_flashbank;
uint32_t *ts_fw_sector;
uint32_t ts_fw_gpio[4];
ddi_acc_handle_t ts_pci_cfghdl; /* PCI cfg handle */
int ts_fw_cmdset;
/* Tavor fastreboot support */
boolean_t ts_quiescing; /* in fastreboot */
};
_NOTE(MUTEX_PROTECTS_DATA(tavor_state_s::ts_fw_flashlock,
tavor_state_s::ts_fw_flashstarted
tavor_state_s::ts_fw_flashdev
tavor_state_s::ts_fw_log_sector_sz
tavor_state_s::ts_fw_device_sz))
_NOTE(MUTEX_PROTECTS_DATA(tavor_state_s::ts_spec_qplock,
tavor_state_s::ts_spec_qpflags
tavor_state_s::ts_spec_qp0
tavor_state_s::ts_spec_qp1))
_NOTE(MUTEX_PROTECTS_DATA(tavor_state_s::ts_mcglock,
tavor_state_s::ts_mcghdl
tavor_state_s::ts_mcgtmp))
_NOTE(DATA_READABLE_WITHOUT_LOCK(tavor_state_s::ts_in_evcallb
tavor_state_s::ts_fw_log_sector_sz
tavor_state_s::ts_fw_device_sz
tavor_state_s::ts_fw_sector
tavor_state_s::ts_spec_qpflags
tavor_state_s::ts_spec_qp0
tavor_state_s::ts_spec_qp1))
_NOTE(MUTEX_PROTECTS_DATA(tavor_state_s::ts_qpn_avl_lock,
tavor_state_s::ts_qpn_avl))
/*
* 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.
*/
#define TAVOR_IN_FASTREBOOT(state) (state->ts_quiescing == B_TRUE)
/*
* 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)
#define TAVOR_UMAP_DB_IGNORE_INSTANCE (1 << 1)
/*
* 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 {
kmutex_t tdl_umapdb_lock;
avl_tree_t tdl_umapdb_avl;
} tavor_umap_db_t;
/*
* 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;
} tavor_umap_db_priv_t;
/*
* 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 {
uint64_t tdb_key;
uint64_t tdb_value;
uint_t tdb_type;
uint_t tdb_instance;
void *tdb_priv;
} tavor_umap_db_common_t;
/*
* 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 {
avl_node_t tdbe_avlnode;
tavor_umap_db_common_t tdbe_common;
} tavor_umap_db_entry_t;
/*
* 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 {
uint_t tqdb_flags;
tavor_umap_db_common_t tqdb_common;
} tavor_umap_db_query_t;
_NOTE(MUTEX_PROTECTS_DATA(tavor_umap_db_s::tdl_umapdb_lock,
tavor_umap_db_entry_s::tdbe_avlnode
tavor_umap_db_entry_s::tdbe_common.tdb_key
tavor_umap_db_entry_s::tdbe_common.tdb_value
tavor_umap_db_entry_s::tdbe_common.tdb_type
tavor_umap_db_entry_s::tdbe_common.tdb_instance))
/*
* 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 {
tavor_state_t *tdt_state;
uint64_t tdt_offset;
uint_t tdt_size;
int tdt_refcnt;
kmutex_t tdt_lock;
} tavor_devmap_track_t;
/* Defined in tavor_umap.c */
int tavor_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
size_t *maplen, uint_t model);
ibt_status_t tavor_umap_ci_data_in(tavor_state_t *state,
ibt_ci_data_flags_t flags, ibt_object_type_t object, void *hdl,
void *data_p, size_t data_sz);
ibt_status_t tavor_umap_ci_data_out(tavor_state_t *state,
ibt_ci_data_flags_t flags, ibt_object_type_t object, void *hdl,
void *data_p, size_t data_sz);
void tavor_umap_db_init(void);
void tavor_umap_db_fini(void);
tavor_umap_db_entry_t *tavor_umap_db_alloc(uint_t instance, uint64_t key,
uint_t type, uint64_t value);
void tavor_umap_db_free(tavor_umap_db_entry_t *umapdb);
void tavor_umap_db_add(tavor_umap_db_entry_t *umapdb);
void tavor_umap_db_add_nolock(tavor_umap_db_entry_t *umapdb);
int tavor_umap_db_find(uint_t instance, uint64_t key, uint_t type,
uint64_t *value, uint_t flags, tavor_umap_db_entry_t **umapdb);
int tavor_umap_db_find_nolock(uint_t instance, uint64_t key, uint_t type,
uint64_t *value, uint_t flags, tavor_umap_db_entry_t **umapdb);
void tavor_umap_umemlock_cb(ddi_umem_cookie_t *umem_cookie);
int tavor_umap_db_set_onclose_cb(dev_t dev, uint64_t flag,
void (*callback)(void *), void *arg);
int tavor_umap_db_clear_onclose_cb(dev_t dev, uint64_t flag);
void tavor_umap_db_handle_onclose_cb(tavor_umap_db_priv_t *priv);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_IB_ADAPTERS_TAVOR_H */