1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _DAPL_H_ 28 #define _DAPL_H_ 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #define DAPLKA_VERSION (1) 35 #define DAPLKA_TQ_NTHREADS 16 36 #define DAPLKA_STATE_DETACHED 0x0000 37 #define DAPLKA_STATE_ATTACHED 0x0001 38 39 /* 40 * HCA structure 41 */ 42 typedef struct daplka_hca { 43 ib_guid_t hca_guid; 44 ibt_hca_hdl_t hca_hdl; 45 ibt_hca_attr_t hca_attr; 46 uint32_t hca_nports; 47 ibt_hca_portinfo_t *hca_ports; 48 size_t hca_pinfosz; 49 uint32_t hca_qp_count; 50 uint32_t hca_cq_count; 51 uint32_t hca_pd_count; 52 uint32_t hca_mw_count; 53 uint32_t hca_mr_count; 54 uint32_t hca_srq_count; 55 int hca_ref_cnt; 56 struct daplka_hca *hca_next; 57 } daplka_hca_t; 58 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_hca)) 59 60 /* 61 * Per-Device instance state information. 62 */ 63 typedef struct daplka { 64 kmutex_t daplka_mutex; 65 dev_info_t *daplka_dip; 66 ibt_clnt_hdl_t daplka_clnt_hdl; 67 daplka_hca_t *daplka_hca_list_head; 68 uint32_t daplka_status; 69 } daplka_t; 70 71 /* 72 * generic hash table 73 */ 74 typedef struct daplka_hash_entry { 75 uint64_t he_hkey; 76 void *he_objp; 77 struct daplka_hash_entry *he_next; 78 } daplka_hash_entry_t; 79 80 typedef struct daplka_hash_bucket { 81 uint32_t hb_count; 82 daplka_hash_entry_t *hb_entries; 83 } daplka_hash_bucket_t; 84 85 typedef struct daplka_hash_table { 86 boolean_t ht_initialized; 87 uint32_t ht_count; 88 uint32_t ht_nbuckets; 89 uint64_t ht_next_hkey; 90 krwlock_t ht_table_lock; 91 kmutex_t ht_key_lock; 92 daplka_hash_bucket_t *ht_buckets; 93 void (*ht_free_func)(void *); 94 void (*ht_lookup_func)(void *); 95 } daplka_hash_table_t; 96 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_entry)) 97 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_bucket)) 98 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_hash_table)) 99 _NOTE(MUTEX_PROTECTS_DATA(daplka_hash_table::ht_key_lock, 100 daplka_hash_table::ht_next_hkey)) 101 _NOTE(RWLOCK_PROTECTS_DATA(daplka_hash_table::ht_table_lock, 102 daplka_hash_table::ht_buckets 103 daplka_hash_table::ht_count)) 104 105 /* 106 * resource structure header 107 */ 108 typedef struct daplka_resource { 109 uint_t rs_type; 110 minor_t rs_rnum; 111 kmutex_t rs_reflock; 112 uint32_t rs_refcnt; 113 uint32_t rs_charged; 114 int (*rs_free)(struct daplka_resource *); 115 } daplka_resource_t; 116 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_resource)) 117 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_resource::rs_charged)) 118 _NOTE(MUTEX_PROTECTS_DATA(daplka_resource::rs_reflock, 119 daplka_resource::rs_refcnt)) 120 121 #define DAPLKA_EP_HTBL_SZ 128 122 #define DAPLKA_MR_HTBL_SZ 64 123 #define DAPLKA_MW_HTBL_SZ 64 124 #define DAPLKA_PD_HTBL_SZ 32 125 #define DAPLKA_SP_HTBL_SZ 32 126 #define DAPLKA_EVD_HTBL_SZ 32 127 #define DAPLKA_G_SP_HTBL_SZ 512 128 #define DAPLKA_TIMER_HTBL_SZ 512 129 #define DAPLKA_CNO_HTBL_SZ 16 130 #define DAPLKA_SRQ_HTBL_SZ 32 131 132 typedef struct daplka_async_evd_hkey_s { 133 struct daplka_async_evd_hkey_s *aeh_next; 134 uint64_t aeh_evd_hkey; 135 } daplka_async_evd_hkey_t; 136 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_async_evd_hkey_s)) 137 138 /* 139 * Various states IA can be in, this is primarily for handling race 140 * between MW allocation and MR cleanup callback. 141 */ 142 typedef enum daplka_ia_state_e { 143 DAPLKA_IA_INIT = 0, 144 DAPLKA_IA_MW_ALLOC_IN_PROGRESS, 145 DAPLKA_IA_MW_FREEZE_IN_PROGRESS, 146 DAPLKA_IA_MW_FROZEN 147 } daplka_ia_state_t; 148 149 typedef struct daplka_ia_resource { 150 daplka_resource_t header; 151 kmutex_t ia_lock; 152 kcondvar_t ia_cv; 153 daplka_ia_state_t ia_state; 154 ibt_hca_hdl_t ia_hca_hdl; 155 ib_gid_t ia_hca_sgid; 156 daplka_hca_t *ia_hca; 157 uint8_t ia_port_num; 158 uint32_t ia_port_pkey; 159 pid_t ia_pid; 160 uint32_t ia_mw_alloccnt; /* # mw allocs in progress */ 161 daplka_async_evd_hkey_t *ia_async_evd_hkeys; /* hash key of async evd */ 162 daplka_hash_table_t ia_ep_htbl; 163 daplka_hash_table_t ia_mr_htbl; 164 daplka_hash_table_t ia_mw_htbl; 165 daplka_hash_table_t ia_pd_htbl; 166 daplka_hash_table_t ia_evd_htbl; 167 daplka_hash_table_t ia_sp_htbl; 168 daplka_hash_table_t ia_cno_htbl; 169 daplka_hash_table_t ia_srq_htbl; 170 uint8_t ia_sadata[DAPL_ATS_NBYTES]; /* SA data */ 171 boolean_t ia_ar_registered; 172 } daplka_ia_resource_t; 173 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_ia_resource)) 174 _NOTE(MUTEX_PROTECTS_DATA(daplka_ia_resource::ia_lock, 175 daplka_ia_resource::ia_cv 176 daplka_ia_resource::ia_async_evd_hkeys 177 daplka_ia_resource::ia_mw_alloccnt 178 daplka_ia_resource::ia_state 179 daplka_async_evd_hkey_s)) 180 181 typedef struct daplka_pd_resource { 182 daplka_resource_t header; 183 daplka_hca_t *pd_hca; 184 ibt_hca_hdl_t pd_hca_hdl; 185 ibt_pd_hdl_t pd_hdl; 186 } daplka_pd_resource_t; 187 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_pd_resource)) 188 189 /* 190 * Passive side EP cookies - this is generated at the connection request 191 * time and unique for every CR. It gets associated with the EP that 192 * is passed to the CR accept. 193 * 194 * daplka_psep_cookie contains the following information 195 * - 48 bit timestamp (unit = 1/10us) 196 * - 16 bit index in the psp backlog array corr to this CR event 197 * this makes it unique for every CR. 198 */ 199 typedef uint64_t daplka_psep_cookie_t; 200 #define DAPLKA_CREATE_PSEP_COOKIE(index) \ 201 ((uint64_t)((gethrtime()/100)<<16 | (index))) 202 #define DAPLKA_GET_PSEP_INDEX(cookie) \ 203 ((uint16_t)((uint64_t)(cookie) &\ 204 0xffff)) 205 206 /* 207 * daplka_evd_cme_t defines connection manager events that can be 208 * chained to the daplka_evd_cme_list_t. 209 */ 210 typedef struct daplka_evd_cme_s { 211 dapl_ib_cm_event_type_t ec_cm_ev_type; 212 /* ec_cm_cookie is the SP(passive)/EP(active) cookie */ 213 uint64_t ec_cm_cookie; 214 /* ec_cm_ev_session_id is the cookie for DEFER processing */ 215 void *ec_cm_ev_session_id; 216 /* true - passive side event, false - active side event */ 217 boolean_t ec_cm_is_passive; 218 daplka_psep_cookie_t ec_cm_psep_cookie; 219 ib_gid_t ec_cm_req_prim_addr; /* requestor gid */ 220 ibt_priv_data_len_t ec_cm_ev_priv_data_len; 221 void *ec_cm_ev_priv_data; 222 } daplka_evd_cme_t; 223 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_cme_s)) 224 225 typedef enum daplka_evd_event_type_e { 226 DAPLKA_EVD_NO_EVENTS = 0x00, 227 DAPLKA_EVD_ULAND_EVENTS = 0x01, /* userland events ie. CQ or SE */ 228 DAPLKA_EVD_CM_EVENTS = 0x02, 229 DAPLKA_EVD_ASYNC_EVENTS = 0x04 230 } daplka_evd_event_type_t; 231 232 /* 233 * daplka_evd_event_t defines elements in the event list - this is 234 * used for both async as well as connection manager events 235 */ 236 typedef struct daplka_evd_event_s { 237 struct daplka_evd_event_s *ee_next; 238 union { 239 dapl_ib_async_event_t aev; 240 daplka_evd_cme_t cmev; 241 } ee_event; 242 #define ee_aev ee_event.aev 243 #define ee_cmev ee_event.cmev 244 } daplka_evd_event_t; 245 246 typedef struct daplka_evd_event_list_s { 247 daplka_evd_event_type_t eel_event_type; 248 uint32_t eel_num_elements; 249 daplka_evd_event_t *eel_head; 250 daplka_evd_event_t *eel_tail; 251 } daplka_evd_event_list_t; 252 253 typedef struct daplka_evd_resource { 254 daplka_resource_t header; 255 kmutex_t evd_lock; 256 kcondvar_t evd_cv; 257 DAT_EVD_FLAGS evd_flags; 258 daplka_evd_event_type_t evd_newevents; /* DAPLKA_EVD_*_EVENTS */ 259 ibt_cq_hdl_t evd_cq_hdl; 260 uint32_t evd_cq_real_size; 261 daplka_evd_event_list_t evd_cr_events; /* connect request event */ 262 daplka_evd_event_list_t evd_conn_events; /* connection events */ 263 daplka_evd_event_list_t evd_async_events; /* aysnc events list */ 264 ibt_hca_hdl_t evd_hca_hdl; 265 daplka_hca_t *evd_hca; 266 uint32_t evd_waiters; 267 uint64_t evd_cookie; 268 struct daplka_cno_resource *evd_cno_res; 269 } daplka_evd_resource_t; 270 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_event_s)) 271 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_evd_event_s)) 272 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_event_list_s)) 273 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_evd_resource)) 274 _NOTE(MUTEX_PROTECTS_DATA(daplka_evd_resource::evd_lock, 275 daplka_evd_resource::evd_cv 276 daplka_evd_resource::evd_flags 277 daplka_evd_resource::evd_newevents 278 daplka_evd_resource::evd_cr_events 279 daplka_evd_resource::evd_conn_events 280 daplka_evd_resource::evd_async_events 281 daplka_evd_resource::evd_waiters)) 282 283 typedef struct daplka_srq_resource { 284 daplka_resource_t header; 285 kmutex_t srq_lock; 286 daplka_hca_t *srq_hca; 287 ibt_hca_hdl_t srq_hca_hdl; 288 daplka_pd_resource_t *srq_pd_res; 289 ibt_srq_hdl_t srq_hdl; 290 uint32_t srq_real_size; 291 } daplka_srq_resource_t; 292 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_srq_resource)) 293 294 #define DAPLKA_EP_STATE_CLOSED 0x0001 295 #define DAPLKA_EP_STATE_CONNECTING 0x0002 296 #define DAPLKA_EP_STATE_ACCEPTING 0x0003 297 #define DAPLKA_EP_STATE_CONNECTED 0x0004 298 #define DAPLKA_EP_STATE_DISCONNECTING 0x0005 299 #define DAPLKA_EP_STATE_ABORTING 0x0006 300 #define DAPLKA_EP_STATE_DISCONNECTED 0x0007 301 #define DAPLKA_EP_STATE_TRANSITIONING 0x0008 302 #define DAPLKA_EP_STATE_FREED 0x0009 303 304 typedef struct daplka_ep_resource { 305 daplka_resource_t header; 306 kmutex_t ep_lock; 307 kcondvar_t ep_cv; 308 uint64_t ep_cookie; /* userland ep pointer */ 309 daplka_hca_t *ep_hca; 310 ibt_channel_hdl_t ep_chan_hdl; 311 daplka_evd_resource_t *ep_snd_evd; 312 daplka_evd_resource_t *ep_rcv_evd; 313 daplka_evd_resource_t *ep_conn_evd; 314 daplka_evd_resource_t *ep_bind_evd; 315 daplka_pd_resource_t *ep_pd_res; 316 daplka_srq_resource_t *ep_srq_res; 317 uint32_t ep_state; 318 uint64_t ep_timer_hkey; 319 daplka_psep_cookie_t ep_psep_cookie; /* passive side ep cookie */ 320 ibt_priv_data_len_t ep_priv_len; 321 uint8_t ep_priv_data[IBT_REP_PRIV_DATA_SZ]; 322 ib_gid_t ep_sgid; 323 ib_gid_t ep_dgid; 324 } daplka_ep_resource_t; 325 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_ep_resource)) 326 327 typedef struct daplka_timer_info { 328 daplka_ep_resource_t *ti_ep_res; 329 timeout_id_t ti_tmo_id; 330 } daplka_timer_info_t; 331 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_timer_info)) 332 333 typedef struct daplka_mr_resource { 334 daplka_resource_t header; 335 daplka_pd_resource_t *mr_pd_res; 336 daplka_hca_t *mr_hca; 337 ibt_hca_hdl_t mr_hca_hdl; 338 ibt_mr_hdl_t mr_hdl; 339 ibt_mr_attr_t mr_attr; 340 ibt_mr_desc_t mr_desc; 341 kmutex_t mr_lock; 342 struct daplka_mr_resource *mr_next; 343 struct daplka_shared_mr *mr_shared_mr; 344 } daplka_mr_resource_t; 345 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_mr_resource)) 346 _NOTE(MUTEX_PROTECTS_DATA(daplka_mr_resource::mr_lock, 347 daplka_mr_resource::mr_shared_mr)) 348 349 typedef struct daplka_mw_resource { 350 daplka_resource_t header; 351 daplka_pd_resource_t *mw_pd_res; 352 daplka_hca_t *mw_hca; 353 ibt_hca_hdl_t mw_hca_hdl; 354 ibt_mw_hdl_t mw_hdl; 355 kmutex_t mw_lock; 356 } daplka_mw_resource_t; 357 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_mw_resource)) 358 359 /* 360 * This describes the elements in a connection pending list that each SP 361 * maintains. Fields are protected using the sp_lock. 362 */ 363 typedef enum { 364 DAPLKA_SPCP_INIT = 0, 365 DAPLKA_SPCP_PENDING 366 } daplka_spcp_state_t; 367 368 typedef struct daplka_sp_conn_pend_s { 369 daplka_spcp_state_t spcp_state; 370 void *spcp_sid; /* session id for cm_proceed */ 371 uint32_t spcp_req_len; /* used by cr_handoff */ 372 char spcp_req_data[DAPL_MAX_PRIVATE_DATA_SIZE]; 373 uint8_t spcp_rdma_ra_out; 374 uint8_t spcp_rdma_ra_in; 375 } daplka_sp_conn_pend_t; 376 377 #define DAPLKA_DEFAULT_SP_BACKLOG 256 378 typedef struct daplka_sp_resource { 379 daplka_resource_t header; 380 kmutex_t sp_lock; 381 ibt_srv_hdl_t sp_srv_hdl; 382 ibt_sbind_hdl_t sp_bind_hdl; 383 uint64_t sp_cookie; /* userland sp pointer */ 384 int sp_backlog_size; /* # elements backlog */ 385 daplka_sp_conn_pend_t *sp_backlog; /* pending conn backlog array */ 386 daplka_evd_resource_t *sp_evd_res; 387 ib_svc_id_t sp_conn_qual; 388 uint64_t sp_global_hkey; 389 uid_t sp_ruid; 390 } daplka_sp_resource_t; 391 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_sp_resource)) 392 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_sp_conn_pend_s)) 393 _NOTE(MUTEX_PROTECTS_DATA(daplka_sp_resource::sp_lock, 394 daplka_sp_resource::sp_backlog)) 395 396 typedef struct daplka_cno_resource { 397 daplka_resource_t header; 398 kmutex_t cno_lock; 399 kcondvar_t cno_cv; 400 uint64_t cno_evd_cookie; 401 } daplka_cno_resource_t; 402 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_cno_resource)) 403 _NOTE(MUTEX_PROTECTS_DATA(daplka_cno_resource::cno_lock, 404 daplka_cno_resource::cno_cv 405 daplka_cno_resource::cno_evd_cookie)) 406 407 #define DAPLKA_SMR_FREED 0x0000 408 #define DAPLKA_SMR_TRANSITIONING 0x0001 409 #define DAPLKA_SMR_READY 0x0002 410 typedef struct daplka_shared_mr { 411 avl_node_t smr_node; 412 uint32_t smr_refcnt; 413 uint32_t smr_state; 414 daplka_mr_resource_t *smr_mr_list; 415 kcondvar_t smr_cv; 416 dapl_mr_cookie_t smr_cookie; 417 } daplka_shared_mr_t; 418 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_shared_mr)) 419 _NOTE(SCHEME_PROTECTS_DATA("daplka", daplka_shared_mr::smr_mr_list)) 420 421 /* 422 * resource table data structures 423 */ 424 #define DAPLKA_RC_BLKSZ 16 425 #define DAPLKA_RC_RESERVED 0xff 426 typedef struct daplka_resource_blk { 427 int daplka_rcblk_avail; 428 daplka_resource_t *daplka_rcblk_blks[DAPLKA_RC_BLKSZ]; 429 } daplka_resource_blk_t; 430 431 struct daplka_resource_table { 432 krwlock_t daplka_rct_lock; 433 int daplka_rc_len; 434 int daplka_rc_sz; 435 int daplka_rc_cnt; 436 ushort_t daplka_rc_flag; 437 daplka_resource_blk_t **daplka_rc_root; 438 }; 439 _NOTE(DATA_READABLE_WITHOUT_LOCK(daplka_resource_table)) 440 _NOTE(RWLOCK_PROTECTS_DATA(daplka_resource_table::daplka_rct_lock, 441 daplka_resource_table::daplka_rc_root)) 442 443 #ifdef __cplusplus 444 } 445 #endif 446 447 #endif /* _DAPL_H_ */ 448