daplt.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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _DAPL_H_
#define _DAPL_H_
#ifdef __cplusplus
extern "C" {
#endif
#define DAPLKA_VERSION (1)
#define DAPLKA_TQ_NTHREADS 16
#define DAPLKA_STATE_DETACHED 0x0000
#define DAPLKA_STATE_ATTACHED 0x0001
/*
* HCA structure
*/
typedef struct daplka_hca {
ib_guid_t hca_guid;
ibt_hca_hdl_t hca_hdl;
ibt_hca_attr_t hca_attr;
uint32_t hca_nports;
ibt_hca_portinfo_t *hca_ports;
size_t hca_pinfosz;
uint32_t hca_qp_count;
uint32_t hca_cq_count;
uint32_t hca_pd_count;
uint32_t hca_mw_count;
uint32_t hca_mr_count;
uint32_t hca_srq_count;
int hca_ref_cnt;
struct daplka_hca *hca_next;
} daplka_hca_t;
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_hca))
/*
* Per-Device instance state information.
*/
typedef struct daplka {
kmutex_t daplka_mutex;
dev_info_t *daplka_dip;
ibt_clnt_hdl_t daplka_clnt_hdl;
daplka_hca_t *daplka_hca_list_head;
uint32_t daplka_status;
} daplka_t;
/*
* generic hash table
*/
typedef struct daplka_hash_entry {
uint64_t he_hkey;
void *he_objp;
struct daplka_hash_entry *he_next;
} daplka_hash_entry_t;
typedef struct daplka_hash_bucket {
uint32_t hb_count;
daplka_hash_entry_t *hb_entries;
} daplka_hash_bucket_t;
typedef struct daplka_hash_table {
boolean_t ht_initialized;
uint32_t ht_count;
uint32_t ht_nbuckets;
uint64_t ht_next_hkey;
krwlock_t ht_table_lock;
kmutex_t ht_key_lock;
daplka_hash_bucket_t *ht_buckets;
void (*ht_free_func)(void *);
void (*ht_lookup_func)(void *);
} daplka_hash_table_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_entry))
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_bucket))
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_table))
_NOTE(MUTEX_PROTECTS_DATA(daplka_hash_table::ht_key_lock,
daplka_hash_table::ht_next_hkey))
_NOTE(RWLOCK_PROTECTS_DATA(daplka_hash_table::ht_table_lock,
daplka_hash_table::ht_buckets
daplka_hash_table::ht_count))
/*
* resource structure header
*/
typedef struct daplka_resource {
uint_t rs_type;
minor_t rs_rnum;
kmutex_t rs_reflock;
uint32_t rs_refcnt;
uint32_t rs_charged;
int (*rs_free)(struct daplka_resource *);
} daplka_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_resource))
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_resource::rs_charged))
_NOTE(MUTEX_PROTECTS_DATA(daplka_resource::rs_reflock,
daplka_resource::rs_refcnt))
#define DAPLKA_EP_HTBL_SZ 128
#define DAPLKA_MR_HTBL_SZ 64
#define DAPLKA_MW_HTBL_SZ 64
#define DAPLKA_PD_HTBL_SZ 32
#define DAPLKA_SP_HTBL_SZ 32
#define DAPLKA_EVD_HTBL_SZ 32
#define DAPLKA_G_SP_HTBL_SZ 512
#define DAPLKA_TIMER_HTBL_SZ 512
#define DAPLKA_CNO_HTBL_SZ 16
#define DAPLKA_SRQ_HTBL_SZ 32
typedef struct daplka_async_evd_hkey_s {
struct daplka_async_evd_hkey_s *aeh_next;
uint64_t aeh_evd_hkey;
} daplka_async_evd_hkey_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_async_evd_hkey_s))
/*
* Various states IA can be in, this is primarily for handling race
* between MW allocation and MR cleanup callback.
*/
typedef enum daplka_ia_state_e {
DAPLKA_IA_INIT = 0,
DAPLKA_IA_MW_ALLOC_IN_PROGRESS,
DAPLKA_IA_MW_FREEZE_IN_PROGRESS,
DAPLKA_IA_MW_FROZEN
} daplka_ia_state_t;
typedef struct daplka_ia_resource {
daplka_resource_t header;
kmutex_t ia_lock;
kcondvar_t ia_cv;
daplka_ia_state_t ia_state;
ibt_hca_hdl_t ia_hca_hdl;
ib_gid_t ia_hca_sgid;
daplka_hca_t *ia_hca;
uint8_t ia_port_num;
uint32_t ia_port_pkey;
pid_t ia_pid;
uint32_t ia_mw_alloccnt; /* # mw allocs in progress */
daplka_async_evd_hkey_t *ia_async_evd_hkeys; /* hash key of async evd */
daplka_hash_table_t ia_ep_htbl;
daplka_hash_table_t ia_mr_htbl;
daplka_hash_table_t ia_mw_htbl;
daplka_hash_table_t ia_pd_htbl;
daplka_hash_table_t ia_evd_htbl;
daplka_hash_table_t ia_sp_htbl;
daplka_hash_table_t ia_cno_htbl;
daplka_hash_table_t ia_srq_htbl;
uint8_t ia_sadata[DAPL_ATS_NBYTES]; /* SA data */
boolean_t ia_ar_registered;
} daplka_ia_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_ia_resource))
_NOTE(MUTEX_PROTECTS_DATA(daplka_ia_resource::ia_lock,
daplka_ia_resource::ia_cv
daplka_ia_resource::ia_async_evd_hkeys
daplka_ia_resource::ia_mw_alloccnt
daplka_ia_resource::ia_state
daplka_async_evd_hkey_s))
typedef struct daplka_pd_resource {
daplka_resource_t header;
daplka_hca_t *pd_hca;
ibt_hca_hdl_t pd_hca_hdl;
ibt_pd_hdl_t pd_hdl;
} daplka_pd_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_pd_resource))
/*
* Passive side EP cookies - this is generated at the connection request
* time and unique for every CR. It gets associated with the EP that
* is passed to the CR accept.
*
* daplka_psep_cookie contains the following information
* - 48 bit timestamp (unit = 1/10us)
* - 16 bit index in the psp backlog array corr to this CR event
* this makes it unique for every CR.
*/
typedef uint64_t daplka_psep_cookie_t;
#define DAPLKA_CREATE_PSEP_COOKIE(index) \
((uint64_t)((gethrtime()/100)<<16 | (index)))
#define DAPLKA_GET_PSEP_INDEX(cookie) \
((uint16_t)((uint64_t)(cookie) &\
0xffff))
/*
* daplka_evd_cme_t defines connection manager events that can be
* chained to the daplka_evd_cme_list_t.
*/
typedef struct daplka_evd_cme_s {
dapl_ib_cm_event_type_t ec_cm_ev_type;
/* ec_cm_cookie is the SP(passive)/EP(active) cookie */
uint64_t ec_cm_cookie;
/* ec_cm_ev_session_id is the cookie for DEFER processing */
void *ec_cm_ev_session_id;
/* true - passive side event, false - active side event */
boolean_t ec_cm_is_passive;
daplka_psep_cookie_t ec_cm_psep_cookie;
ib_gid_t ec_cm_req_prim_addr; /* requestor gid */
ibt_priv_data_len_t ec_cm_ev_priv_data_len;
void *ec_cm_ev_priv_data;
} daplka_evd_cme_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_cme_s))
typedef enum daplka_evd_event_type_e {
DAPLKA_EVD_NO_EVENTS = 0x00,
DAPLKA_EVD_ULAND_EVENTS = 0x01, /* userland events ie. CQ or SE */
DAPLKA_EVD_CM_EVENTS = 0x02,
DAPLKA_EVD_ASYNC_EVENTS = 0x04
} daplka_evd_event_type_t;
/*
* daplka_evd_event_t defines elements in the event list - this is
* used for both async as well as connection manager events
*/
typedef struct daplka_evd_event_s {
struct daplka_evd_event_s *ee_next;
union {
dapl_ib_async_event_t aev;
daplka_evd_cme_t cmev;
} ee_event;
#define ee_aev ee_event.aev
#define ee_cmev ee_event.cmev
} daplka_evd_event_t;
typedef struct daplka_evd_event_list_s {
daplka_evd_event_type_t eel_event_type;
uint32_t eel_num_elements;
daplka_evd_event_t *eel_head;
daplka_evd_event_t *eel_tail;
} daplka_evd_event_list_t;
typedef struct daplka_evd_resource {
daplka_resource_t header;
kmutex_t evd_lock;
kcondvar_t evd_cv;
DAT_EVD_FLAGS evd_flags;
daplka_evd_event_type_t evd_newevents; /* DAPLKA_EVD_*_EVENTS */
ibt_cq_hdl_t evd_cq_hdl;
uint32_t evd_cq_real_size;
daplka_evd_event_list_t evd_cr_events; /* connect request event */
daplka_evd_event_list_t evd_conn_events; /* connection events */
daplka_evd_event_list_t evd_async_events; /* aysnc events list */
ibt_hca_hdl_t evd_hca_hdl;
daplka_hca_t *evd_hca;
uint32_t evd_waiters;
uint64_t evd_cookie;
struct daplka_cno_resource *evd_cno_res;
} daplka_evd_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_event_s))
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_evd_event_s))
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_event_list_s))
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_resource))
_NOTE(MUTEX_PROTECTS_DATA(daplka_evd_resource::evd_lock,
daplka_evd_resource::evd_cv
daplka_evd_resource::evd_flags
daplka_evd_resource::evd_newevents
daplka_evd_resource::evd_cr_events
daplka_evd_resource::evd_conn_events
daplka_evd_resource::evd_async_events
daplka_evd_resource::evd_waiters))
typedef struct daplka_srq_resource {
daplka_resource_t header;
kmutex_t srq_lock;
daplka_hca_t *srq_hca;
ibt_hca_hdl_t srq_hca_hdl;
daplka_pd_resource_t *srq_pd_res;
ibt_srq_hdl_t srq_hdl;
uint32_t srq_real_size;
} daplka_srq_resource_t;
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_srq_resource))
#define DAPLKA_EP_STATE_CLOSED 0x0001
#define DAPLKA_EP_STATE_CONNECTING 0x0002
#define DAPLKA_EP_STATE_ACCEPTING 0x0003
#define DAPLKA_EP_STATE_CONNECTED 0x0004
#define DAPLKA_EP_STATE_DISCONNECTING 0x0005
#define DAPLKA_EP_STATE_ABORTING 0x0006
#define DAPLKA_EP_STATE_DISCONNECTED 0x0007
#define DAPLKA_EP_STATE_TRANSITIONING 0x0008
#define DAPLKA_EP_STATE_FREED 0x0009
typedef struct daplka_ep_resource {
daplka_resource_t header;
kmutex_t ep_lock;
kcondvar_t ep_cv;
uint64_t ep_cookie; /* userland ep pointer */
daplka_hca_t *ep_hca;
ibt_channel_hdl_t ep_chan_hdl;
daplka_evd_resource_t *ep_snd_evd;
daplka_evd_resource_t *ep_rcv_evd;
daplka_evd_resource_t *ep_conn_evd;
daplka_evd_resource_t *ep_bind_evd;
daplka_pd_resource_t *ep_pd_res;
daplka_srq_resource_t *ep_srq_res;
uint32_t ep_state;
uint64_t ep_timer_hkey;
daplka_psep_cookie_t ep_psep_cookie; /* passive side ep cookie */
ibt_priv_data_len_t ep_priv_len;
uint8_t ep_priv_data[IBT_REP_PRIV_DATA_SZ];
ib_gid_t ep_sgid;
ib_gid_t ep_dgid;
} daplka_ep_resource_t;
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_ep_resource))
typedef struct daplka_timer_info {
daplka_ep_resource_t *ti_ep_res;
timeout_id_t ti_tmo_id;
} daplka_timer_info_t;
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_timer_info))
typedef struct daplka_mr_resource {
daplka_resource_t header;
daplka_pd_resource_t *mr_pd_res;
daplka_hca_t *mr_hca;
ibt_hca_hdl_t mr_hca_hdl;
ibt_mr_hdl_t mr_hdl;
ibt_mr_attr_t mr_attr;
ibt_mr_desc_t mr_desc;
kmutex_t mr_lock;
struct daplka_mr_resource *mr_next;
struct daplka_shared_mr *mr_shared_mr;
} daplka_mr_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_mr_resource))
_NOTE(MUTEX_PROTECTS_DATA(daplka_mr_resource::mr_lock,
daplka_mr_resource::mr_shared_mr))
typedef struct daplka_mw_resource {
daplka_resource_t header;
daplka_pd_resource_t *mw_pd_res;
daplka_hca_t *mw_hca;
ibt_hca_hdl_t mw_hca_hdl;
ibt_mw_hdl_t mw_hdl;
kmutex_t mw_lock;
} daplka_mw_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_mw_resource))
/*
* This describes the elements in a connection pending list that each SP
* maintains. Fields are protected using the sp_lock.
*/
typedef enum {
DAPLKA_SPCP_INIT = 0,
DAPLKA_SPCP_PENDING
} daplka_spcp_state_t;
typedef struct daplka_sp_conn_pend_s {
daplka_spcp_state_t spcp_state;
void *spcp_sid; /* session id for cm_proceed */
uint32_t spcp_req_len; /* used by cr_handoff */
char spcp_req_data[DAPL_MAX_PRIVATE_DATA_SIZE];
} daplka_sp_conn_pend_t;
#define DAPLKA_DEFAULT_SP_BACKLOG 256
typedef struct daplka_sp_resource {
daplka_resource_t header;
kmutex_t sp_lock;
ibt_srv_hdl_t sp_srv_hdl;
ibt_sbind_hdl_t sp_bind_hdl;
uint64_t sp_cookie; /* userland sp pointer */
int sp_backlog_size; /* # elements backlog */
daplka_sp_conn_pend_t *sp_backlog; /* pending conn backlog array */
daplka_evd_resource_t *sp_evd_res;
ib_svc_id_t sp_conn_qual;
uint64_t sp_global_hkey;
uid_t sp_ruid;
} daplka_sp_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_sp_resource))
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_sp_conn_pend_s))
_NOTE(MUTEX_PROTECTS_DATA(daplka_sp_resource::sp_lock,
daplka_sp_resource::sp_backlog))
typedef struct daplka_cno_resource {
daplka_resource_t header;
kmutex_t cno_lock;
kcondvar_t cno_cv;
uint64_t cno_evd_cookie;
} daplka_cno_resource_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_cno_resource))
_NOTE(MUTEX_PROTECTS_DATA(daplka_cno_resource::cno_lock,
daplka_cno_resource::cno_cv
daplka_cno_resource::cno_evd_cookie))
#define DAPLKA_SMR_FREED 0x0000
#define DAPLKA_SMR_TRANSITIONING 0x0001
#define DAPLKA_SMR_READY 0x0002
typedef struct daplka_shared_mr {
avl_node_t smr_node;
uint32_t smr_refcnt;
uint32_t smr_state;
daplka_mr_resource_t *smr_mr_list;
kcondvar_t smr_cv;
dapl_mr_cookie_t smr_cookie;
} daplka_shared_mr_t;
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_shared_mr))
_NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_shared_mr::smr_mr_list))
/*
* resource table data structures
*/
#define DAPLKA_RC_BLKSZ 16
#define DAPLKA_RC_RESERVED 0xff
typedef struct daplka_resource_blk {
int daplka_rcblk_avail;
daplka_resource_t *daplka_rcblk_blks[DAPLKA_RC_BLKSZ];
} daplka_resource_blk_t;
struct daplka_resource_table {
krwlock_t daplka_rct_lock;
int daplka_rc_len;
int daplka_rc_sz;
int daplka_rc_cnt;
ushort_t daplka_rc_flag;
daplka_resource_blk_t **daplka_rc_root;
};
_NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_resource_table))
_NOTE(RWLOCK_PROTECTS_DATA(daplka_resource_table::daplka_rct_lock,
daplka_resource_table::daplka_rc_root))
#ifdef __cplusplus
}
#endif
#endif /* _DAPL_H_ */