hermon_qp.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_HERMON_QP_H
#define _SYS_IB_ADAPTERS_HERMON_QP_H
/*
* hermon_qp.h
* Contains all of the prototypes, #defines, and structures necessary
* for all of the Queue Pair Processing routines.
* Specifically it contains the various flags, structures used for managing
* Hermon queue pairs, and prototypes for many of the functions consumed by
* other parts of the Hermon driver (including those routines directly
* exposed through the IBTF CI interface).
*
* Most of the values defined below establish default values which,
* where indicated, can be controlled via their related patchable values,
* if 'hermon_alt_config_enable' is set.
*/
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The following defines the default number of Queue Pairs. This value is
* controlled via the "hermon_log_num_qp" configuration variables.
* We also have a define for the minimum size of a QP. QPs allocated
* with size 0, 1, 2, or 3 will always get back a QP of size 4.
*/
#define HERMON_NUM_QP_SHIFT 0x10
#define HERMON_NUM_QPS (1 << HERMON_NUM_QP_SHIFT) /* 65,536 */
#define HERMON_QP_MIN_SIZE 0xf
/*
* The following defines the default number of Hermon RDMA Remote read
* database (RDB) entries per QP. This value is controllable through the
* "hermon_log_num_rdb_per_qp" configuration variable.
*/
#define HERMON_LOG_NUM_RDB_PER_QP 0x4
/*
* This defines the maximum number of SGLs per WQE. This value is
* controllable through the "hermon_wqe_max_sgl" configuration variable
* (but should not be set larger than this value).
*/
#define HERMON_NUM_SGL_PER_WQE 0x10
/*
* Maximum QP number mask (QP number is 24 bits).
* We reserve the most significant bit to indicate an "XRC" QP
* as recommended by the PRM. All XRC QPs will have this bit set.
*/
#define HERMON_QP_MAXNUMBER_MSK 0x7FFFFF
#define HERMON_QP_XRC 0x800000
/*
* This define and the following macro are used to find a schedule queue for
* a new QP based on its queue pair number. Note: This is a rather simple
* method that we use today. We simply choose from the schedule queue based
* on the 4 least significant bits of the QP number.
*/
/*
* The following defines are used to indicate whether a QP is special or
* not (and what type it is). They are used in the "qp_is_special" field
* below in qp_state. If "qp_is_special" == 0 then an ordinary data qp.
*/
/*
* The sl is selected based on the qpnum as it was for Tavor/Arbel, except for
* QP0, which is defined as being 0xF
*/
#define HERMON_QP_SMI 0x1
#define HERMON_QP_GSI 0x2
#define HERMON_DEF_SCHED_POLICY 0x03
#define HERMON_DEF_SCHED_SELECTION 0x0F
#define HERMON_QP_SCHEDQ_GET(port, sl, issmi) \
(HERMON_DEF_SCHED_POLICY \
| (issmi == HERMON_QP_SMI ? (HERMON_DEF_SCHED_SELECTION << 2) : \
((issmi == HERMON_QP_GSI ? 0 : (sl & 0XF)) << 2)) \
| ((port & 0x01) << 6) \
| ((issmi == HERMON_QP_SMI ? 0 : 1) << 7))
/*
* This define determines the frequency with which the AckReq bit will be
* set in outgoing RC packets. By default it is set to five (5) or 2^5 = 32.
* So AckReq will be set once every 32 packets sent. This value is
* controllable through the "hermon_qp_ackreq_freq" configuration variable.
*/
#define HERMON_QP_ACKREQ_FREQ 0x5
/*
* Define the maximum message size (log 2). Note: This value corresponds
* to the maximum allowable message sized as defined by the IBA spec.
*/
#define HERMON_QP_LOG_MAX_MSGSZ 0x1F
/*
* This macro is used to determine if the hermon QP type (qp_serv) is the
* same as the caller passed in IBT type (qp_trans). This is used in QP modify
* to ensure the types match.
*/
#define HERMON_QP_TYPE_VALID(qp_trans, qp_serv) \
((qp_trans == IBT_UD_SRV && qp_serv == HERMON_QP_UD) || \
(qp_trans == IBT_RC_SRV && qp_serv == HERMON_QP_RC) || \
(qp_trans == IBT_UC_SRV && qp_serv == HERMON_QP_UC))
/*
* The following enumerated type is used to capture all the various types
* of Hermon work queue types. It is specifically used as an argument to the
* to the hermon_qp_sgl_to_logwqesz() routine to determine the amount of
* overhead (in WQE header size) consumed by each of the types. This
* information is used to round the WQE size to the next largest power-of-2
* (and to determine the number of SGLs that are supported for the given WQE
* type). There is also a define below used to specify the minimum size for a
* WQE. The minimum size is set to 64 bytes (a single cacheline).
*/
typedef enum {
HERMON_QP_WQ_TYPE_SENDQ_UD,
HERMON_QP_WQ_TYPE_SENDQ_CONN,
HERMON_QP_WQ_TYPE_RECVQ,
HERMON_QP_WQ_TYPE_SENDMLX_QP0,
HERMON_QP_WQ_TYPE_SENDMLX_QP1
} hermon_qp_wq_type_t;
#define HERMON_QP_WQE_MLX_SND_HDRS 0x40
#define HERMON_QP_WQE_MLX_RCV_HDRS 0x00
#define HERMON_QP_WQE_MLX_SRQ_HDRS 0x10
#define HERMON_QP_WQE_MLX_QP0_HDRS 0x40
#define HERMON_QP_WQE_MLX_QP1_HDRS 0x70
#define HERMON_QP_WQE_LOG_MINIMUM 0x6
/*
* The hermon_qp_info_t structure is used internally by the Hermon driver to
* pass information to and from the hermon_qp_alloc() and
* hermon_special_qp_alloc() routines. It contains placeholders for all of the
* potential inputs and outputs that either routine can take.
*/
typedef struct hermon_qp_info_s {
ibt_qp_alloc_attr_t *qpi_attrp;
uint_t qpi_type;
uint_t qpi_port;
ibtl_qp_hdl_t qpi_ibt_qphdl;
ibt_chan_sizes_t *qpi_queueszp;
ib_qpn_t *qpi_qpn;
hermon_qphdl_t qpi_qphdl;
} hermon_qp_info_t;
/*
* The QPN entry which is stored in the AVL tree
*/
typedef struct hermon_qpn_entry_s {
avl_node_t qpn_avlnode;
uint_t qpn_refcnt;
uint_t qpn_counter;
uint_t qpn_indx;
hermon_rsrc_t *qpn_qpc;
} hermon_qpn_entry_t;
#define HERMON_QPN_NOFLAG 0x0
#define HERMON_QPN_RELEASE 0x1
#define HERMON_QPN_FREE_ONLY 0x2
#define HERMON_QP_OH_SIZE 0x0800
/*
* 2KB, fixed per Mnox PRM 0.35c & conversation w/Mnox technical Sep 5, 2007
*/
/*
* The hermon_sw_qp_s structure is also referred to using the "hermon_qphdl_t"
* typedef (see hermon_typedef.h). It encodes all the information necessary
* to track the various resources needed to allocate, query, modify, and
* (later) free both normal QP and special QP.
*
* Specifically, it has a lock to ensure single threaded access to the QP.
* It has QP state, type, and number, pointers to the PD, MR, and CQ handles
* associated with the QP, and pointers to the buffer where the work queues
* come from.
*
* It has two pointers (one per work queue) to the workQ headers for the WRID
* list, as well as pointers to the last WQE on each chain (used when
* connecting a new chain of WQEs to a previously executing chain - see
* hermon_wr.c). It's also got the real WQE size, real number of SGL per WQE,
* and the size of each of the work queues (in number of WQEs).
*
* Additionally, it has pointers to the resources associated with the QP,
* including the obligatory backpointer to the resource for the QP handle
* itself. But it also has some flags, like "qp_forward_sqd_event" and
* "qp_sqd_still_draining" (which are used to indicate whether a Send Queue
* Drained Event should be forwarded to the IBTF) or "qp_is_special",
* "qp_portnum", and "qp_pkeyindx" (which are used by special QP to store
* necessary information about the type of the QP, which port it's connected
* to, and what its current PKey index is set to).
*/
struct hermon_sw_qp_s {
kmutex_t qp_lock;
uint_t qp_state;
uint32_t qp_qpnum;
hermon_pdhdl_t qp_pdhdl;
uint_t qp_serv_type;
uint_t qp_sl; /* service level */
hermon_mrhdl_t qp_mrhdl;
uint_t qp_sq_sigtype;
uint_t qp_is_special;
uint_t qp_is_umap;
uint32_t qp_uarpg;
devmap_cookie_t qp_umap_dhp;
uint_t qp_portnum; /* port 0/1 for HCA */
uint_t qp_portnum_alt; /* port 0/1 for HCA */
uint_t qp_pkeyindx;
uint_t qp_no_prefetch;
/* prefetch == 0, none == 1, for headroom */
uint_t qp_rlky; /* using reserved lkey */
/* Send Work Queue */
kmutex_t qp_sq_lock;
hermon_cqhdl_t qp_sq_cqhdl;
hermon_workq_avl_t qp_sq_wqavl;
hermon_workq_hdr_t *qp_sq_wqhdr;
uint32_t *qp_sq_buf;
uint32_t qp_sq_bufsz;
uint32_t qp_sq_logqsz; /* used to check owner valid */
uint32_t qp_sq_log_wqesz;
uint32_t qp_sq_headroom; /* #bytes needed for headroom */
uint32_t qp_sq_hdrmwqes; /* # wqes needed for headroom */
uint32_t qp_sq_baseaddr;
uint32_t qp_sq_sgl;
uint_t qp_uses_lso;
uint32_t qp_ring;
/* Receive Work Queue - not used when SRQ is used */
kmutex_t qp_rq_lock;
hermon_cqhdl_t qp_rq_cqhdl;
hermon_workq_avl_t qp_rq_wqavl; /* needed for srq */
hermon_workq_hdr_t *qp_rq_wqhdr;
uint32_t *qp_rq_buf;
uint32_t qp_rq_bufsz;
uint32_t qp_rq_logqsz; /* used to check owner valid */
uint32_t qp_rq_log_wqesz;
uint32_t qp_rq_wqecntr;
uint32_t qp_rq_baseaddr;
uint32_t qp_rq_sgl;
/* DoorBell Record information */
ddi_acc_handle_t qp_rq_dbr_acchdl;
hermon_dbr_t *qp_rq_vdbr;
uint64_t qp_rq_pdbr;
uint64_t qp_rdbr_mapoffset; /* user mode access */
uint64_t qp_desc_off;
hermon_rsrc_t *qp_qpcrsrcp;
hermon_rsrc_t *qp_rsrcp;
void *qp_hdlrarg;
uint_t qp_forward_sqd_event;
uint_t qp_sqd_still_draining;
/* Shared Receive Queue */
hermon_srqhdl_t qp_srqhdl;
uint_t qp_srq_en;
/* Refcnt of QP belongs to an MCG */
uint_t qp_mcg_refcnt;
/* save the mtu from init2rtr for future use */
uint_t qp_save_mtu;
hermon_qpn_entry_t *qp_qpn_hdl;
struct hermon_qalloc_info_s qp_wqinfo;
struct hermon_hw_qpc_s qpc;
};
_NOTE(READ_ONLY_DATA(hermon_sw_qp_s::qp_qpnum
hermon_sw_qp_s::qp_sq_buf
hermon_sw_qp_s::qp_sq_log_wqesz
hermon_sw_qp_s::qp_sq_bufsz
hermon_sw_qp_s::qp_sq_sgl
hermon_sw_qp_s::qp_rq_buf
hermon_sw_qp_s::qp_rq_log_wqesz
hermon_sw_qp_s::qp_rq_bufsz
hermon_sw_qp_s::qp_rq_sgl
hermon_sw_qp_s::qp_desc_off
hermon_sw_qp_s::qp_mrhdl
hermon_sw_qp_s::qp_wqinfo
hermon_sw_qp_s::qp_qpcrsrcp
hermon_sw_qp_s::qp_rsrcp
hermon_sw_qp_s::qp_hdlrarg
hermon_sw_qp_s::qp_pdhdl
hermon_sw_qp_s::qp_sq_cqhdl
hermon_sw_qp_s::qp_rq_cqhdl
hermon_sw_qp_s::qp_sq_sigtype
hermon_sw_qp_s::qp_serv_type
hermon_sw_qp_s::qp_is_special
hermon_sw_qp_s::qp_is_umap
hermon_sw_qp_s::qp_uarpg
hermon_sw_qp_s::qp_sq_wqhdr
hermon_sw_qp_s::qp_rq_wqhdr
hermon_sw_qp_s::qp_qpn_hdl))
_NOTE(MUTEX_PROTECTS_DATA(hermon_sw_qp_s::qp_lock,
hermon_sw_qp_s::qp_state
hermon_sw_qp_s::qpc
hermon_sw_qp_s::qp_forward_sqd_event
hermon_sw_qp_s::qp_sqd_still_draining
hermon_sw_qp_s::qp_mcg_refcnt
hermon_sw_qp_s::qp_save_mtu
hermon_sw_qp_s::qp_umap_dhp))
_NOTE(SCHEME_PROTECTS_DATA("safe sharing",
hermon_sw_qp_s::qp_pkeyindx
hermon_sw_qp_s::qp_portnum))
/* Defined in hermon_qp.c */
int hermon_qp_alloc(hermon_state_t *state, hermon_qp_info_t *qpinfo,
uint_t sleepflag);
int hermon_special_qp_alloc(hermon_state_t *state, hermon_qp_info_t *qpinfo,
uint_t sleepflag);
int hermon_qp_free(hermon_state_t *state, hermon_qphdl_t *qphdl,
ibc_free_qp_flags_t free_qp_flags, ibc_qpn_hdl_t *qpnh, uint_t sleepflag);
int hermon_qp_query(hermon_state_t *state, hermon_qphdl_t qphdl,
ibt_qp_query_attr_t *attr_p);
hermon_qphdl_t hermon_qphdl_from_qpnum(hermon_state_t *state, uint_t qpnum);
void hermon_qp_release_qpn(hermon_state_t *state, hermon_qpn_entry_t *entry,
int flags);
void hermon_qpn_avl_init(hermon_state_t *state);
void hermon_qpn_avl_fini(hermon_state_t *state);
/* Defined in hermon_qpmod.c */
int hermon_qp_modify(hermon_state_t *state, hermon_qphdl_t qp,
ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p,
ibt_queue_sizes_t *actual_sz);
int hermon_qp_to_reset(hermon_state_t *state, hermon_qphdl_t qp);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_IB_ADAPTERS_HERMON_QP_H */