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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #ifndef _SYS_IB_MGT_IBMF_IBMF_IMPL_H
27 #define _SYS_IB_MGT_IBMF_IBMF_IMPL_H
31 * This file contains the IBMF implementation dependent structures and defines.
38 #include <sys/types.h>
40 #include <sys/modctl.h>
42 #include <sys/ksynch.h>
43 #include <sys/taskq.h>
44 #include <sys/sunddi.h>
46 #include <sys/ib/ibtl/ibvti.h>
47 #include <sys/ib/mgt/ibmf/ibmf.h>
48 #include <sys/ib/mgt/ibmf/ibmf_rmpp.h>
49 #include <sys/ib/mgt/ibmf/ibmf_kstat.h>
50 #include <sys/ib/mgt/ibmf/ibmf_trace.h>
52 #define IBMF_MEM_PER_WQE (IBMF_MAD_SIZE + sizeof (ib_grh_t))
53 #define IBMF_MAX_SQ_WRE 64
54 #define IBMF_MAX_RQ_WRE 64
55 #define IBMF_MAX_POSTED_RQ_PER_QP 512
56 #define IBMF_MAX_POSTED_SQ_PER_QP 512
57 #define IBMF_MAX_SQ_WR_SGL_ELEMENTS 1
58 #define IBMF_MAX_RQ_WR_SGL_ELEMENTS 1
59 #define IBMF_MGMT_Q_KEY 0x80010000
60 #define IBMF_P_KEY_DEF_FULL 0xFFFF
61 #define IBMF_P_KEY_DEF_LIMITED 0x7FFF
62 #define IBMF_P_KEY_BASE_MASK 0x7FFF
63 #define IBMF_PKEY_MEMBERSHIP_MASK 0x8000
65 #define IBMF_TASKQ_1THREAD 1
66 #define IBMF_TASKQ_NTHREADS 128
69 * Work request ID format used for receive requests.
73 #define IBMF_RCV_CQE 0x1
76 * Convenience macro used in the RMPP protocol to obtain R_Method field
77 * of MAD header with Response bit flipped.
79 #define IBMF_FLIP_RESP_BIT(r_method) \
80 (((r_method & 0x80) ^ 0x80) | (r_method & 0x7F))
82 /* Work Request ID macros */
83 #define IBMF_IS_RECV_WR_ID(id) \
84 (((uint64_t)(id) & IBMF_RCV_CQE) ? B_TRUE : B_FALSE)
85 #define IBMF_IS_SEND_WR_ID(id) \
86 (!(IBMF_IS_RECV_WR_ID((id))))
88 /* Decrement IBMF message reference count */
89 #define IBMF_MSG_DECR_REFCNT(msg) { \
90 ASSERT(MUTEX_HELD(&(msg)->im_mutex)); \
91 (msg)->im_ref_count--; \
94 /* Increment IBMF message reference count */
95 #define IBMF_MSG_INCR_REFCNT(msg) \
96 (msg)->im_ref_count++;
98 /* Callback setup/cleanup macros */
99 #define IBMF_RECV_CB_SETUP(clp) { \
100 ASSERT(MUTEX_HELD(&(clp)->ic_mutex)); \
101 (clp)->ic_flags |= IBMF_CLIENT_RECV_CB_ACTIVE; \
102 (clp)->ic_recvs_active++; \
103 mutex_enter(&(clp)->ic_kstat_mutex); \
104 IBMF_ADD32_KSTATS((clp), recvs_active, 1); \
105 mutex_exit(&(clp)->ic_kstat_mutex); \
108 #define IBMF_RECV_CB_CLEANUP(clp) { \
109 ASSERT(MUTEX_HELD(&(clp)->ic_mutex)); \
110 (clp)->ic_recvs_active--; \
111 mutex_enter(&(clp)->ic_kstat_mutex); \
112 IBMF_SUB32_KSTATS((clp), recvs_active, 1); \
113 mutex_exit(&(clp)->ic_kstat_mutex); \
114 if ((clp)->ic_recvs_active == 0) \
115 (clp)->ic_flags &= ~IBMF_CLIENT_RECV_CB_ACTIVE; \
116 if ((((clp)->ic_flags & IBMF_CLIENT_RECV_CB_ACTIVE) == 0) && \
117 (((clp)->ic_flags & IBMF_CLIENT_TEAR_DOWN_CB) != 0)) \
118 cv_signal(&(clp)->ic_recv_cb_teardown_cv); \
121 #define IBMF_ALT_RECV_CB_SETUP(altqp) { \
122 ASSERT(MUTEX_HELD(&(altqp)->isq_mutex)); \
123 (altqp)->isq_flags |= IBMF_CLIENT_RECV_CB_ACTIVE; \
124 (altqp)->isq_recvs_active++; \
125 mutex_enter(&(altqp)->isq_client_hdl->ic_kstat_mutex); \
126 IBMF_ADD32_KSTATS((altqp)->isq_client_hdl, recvs_active, 1); \
127 mutex_exit(&(altqp)->isq_client_hdl->ic_kstat_mutex); \
130 #define IBMF_ALT_RECV_CB_CLEANUP(altqp) { \
131 ASSERT(MUTEX_HELD(&(altqp)->isq_mutex)); \
132 (altqp)->isq_recvs_active--; \
133 mutex_enter(&(altqp)->isq_client_hdl->ic_kstat_mutex); \
134 IBMF_SUB32_KSTATS((altqp)->isq_client_hdl, recvs_active, 1); \
135 mutex_exit(&(altqp)->isq_client_hdl->ic_kstat_mutex); \
136 if ((altqp)->isq_recvs_active == 0) \
137 (altqp)->isq_flags &= ~IBMF_CLIENT_RECV_CB_ACTIVE; \
138 if ((((altqp)->isq_flags & IBMF_CLIENT_RECV_CB_ACTIVE) == 0) && \
139 (((altqp)->isq_flags & IBMF_CLIENT_TEAR_DOWN_CB) != 0)) \
140 cv_signal(&(altqp)->isq_recv_cb_teardown_cv); \
144 * WQE pool management contexts
146 typedef struct _ibmf_wqe_mgt
{
147 struct _ibmf_wqe_mgt
*wqe_mgt_next
; /* next wqe management entry */
148 void *wqes_kmem
; /* kmem allocated for WQEs */
149 uint64_t wqes_kmem_sz
; /* sizeof WQE kmem allocated */
150 ib_vaddr_t wqes_ib_mem
; /* Registered memory */
151 ibt_lkey_t wqes_ib_lkey
; /* Lkey that goes with it */
152 ibt_mr_hdl_t wqes_ib_mem_hdl
; /* IB mem handle */
153 kmutex_t wqes_mutex
; /* WQE mgt context mutex */
155 _NOTE(MUTEX_PROTECTS_DATA(ibmf_wqe_mgt_t::wqes_mutex
,
156 ibmf_wqe_mgt_t::wqes_kmem
157 ibmf_wqe_mgt_t::wqes_kmem_sz
158 ibmf_wqe_mgt_t::wqes_ib_mem
159 ibmf_wqe_mgt_t::wqes_ib_lkey
160 ibmf_wqe_mgt_t::wqes_ib_mem_hdl
))
163 * structure used to keep track of qp handles
165 typedef struct _ibmf_qp_t
{
166 struct _ibmf_qp_t
*iq_next
; /* next in the list */
167 ibt_qp_hdl_t iq_qp_handle
; /* qp handle from IB xport */
168 int iq_port_num
; /* port num for this qp */
169 int iq_qp_num
; /* qp num */
170 int iq_qp_ref
; /* no. of clients using this */
171 uint_t iq_flags
; /* for implementing state m/c */
172 uint_t iq_rwqes_posted
; /* posted receive wqes */
173 kmutex_t iq_mutex
; /* mutex for some fields */
175 _NOTE(READ_ONLY_DATA(ibmf_qp_t::iq_port_num
ibmf_qp_t::iq_qp_handle
))
176 _NOTE(MUTEX_PROTECTS_DATA(ibmf_qp_t::iq_mutex
,
177 ibmf_qp_t::iq_rwqes_posted
))
179 /* defines for iq_flags */
180 #define IBMF_QP_FLAGS_INVALID 0x0001
181 #define IBMF_QP_FLAGS_INITING 0x0002
182 #define IBMF_QP_FLAGS_INITED 0x0004
183 #define IBMF_QP_FLAGS_UNINITING 0x0008
186 * structure used to keep track of qp handles for qps other than
189 typedef struct _ibmf_alt_qp_t
{
190 struct _ibmf_alt_qp_t
*isq_next
; /* next qp ctx on list */
191 ibt_qp_hdl_t isq_qp_handle
; /* qp handle from IB xport */
192 ibt_chan_sizes_t isq_qp_sizes
; /* qp sizes returned by alloc */
193 struct _ibmf_client
*isq_client_hdl
; /* associated client handle */
194 ibmf_msg_cb_t isq_recv_cb
; /* recv callback for this qp */
195 void *isq_recv_cb_arg
; /* arg for recv cb */
196 kcondvar_t isq_recv_cb_teardown_cv
; /* wait on teardown */
197 kmutex_t isq_mutex
; /* qp context mutex */
198 int isq_flags
; /* to keep track of state */
199 int isq_sends_active
; /* outstanding sends */
200 int isq_recvs_active
; /* outstanding recvs */
201 ib_qpn_t isq_qpn
; /* qp number */
202 ib_pkey_t isq_pkey
; /* qp's partition key */
203 ib_qkey_t isq_qkey
; /* qp's queue keye */
204 int isq_port_num
; /* port num for this qp */
205 boolean_t isq_supports_rmpp
; /* qp supports rmpp */
206 kcondvar_t isq_sqd_cv
; /* wait on SQD event */
207 int isq_wqes_alloced
; /* wqes allocated for QP */
208 kcondvar_t isq_wqes_cv
; /* wait on wqes destruction */
209 uint_t isq_rwqes_posted
; /* posted receive wqes */
211 /* Manage Send/Receive WQEs for Special QPs */
212 struct kmem_cache
*isq_send_wqes_cache
; /* Send WQE cache */
213 struct kmem_cache
*isq_recv_wqes_cache
; /* Receive WQE cache */
214 vmem_t
*isq_wqe_ib_vmem
; /* IB virtual address arena */
215 kmutex_t isq_wqe_mutex
; /* WQE management list mutex */
216 ibmf_wqe_mgt_t
*isq_wqe_mgt_list
; /* WQE management list */
218 _NOTE(MUTEX_PROTECTS_DATA(ibmf_alt_qp_t::isq_mutex
,
219 ibmf_alt_qp_t::isq_sends_active
220 ibmf_alt_qp_t::isq_recvs_active
221 ibmf_alt_qp_t::isq_pkey
222 ibmf_alt_qp_t::isq_qkey
223 ibmf_alt_qp_t::isq_recv_cb
224 ibmf_alt_qp_t::isq_recv_cb_arg
225 ibmf_alt_qp_t::isq_flags
226 ibmf_alt_qp_t::isq_rwqes_posted
))
227 _NOTE(MUTEX_PROTECTS_DATA(ibmf_alt_qp_t::isq_wqe_mutex
,
228 ibmf_alt_qp_t::isq_wqe_mgt_list
))
229 _NOTE(READ_ONLY_DATA(ibmf_alt_qp_t::isq_port_num
))
231 #define IBMF_MSG_FLAGS_QUEUED 0x00001000 /* in the ib xport */
232 #define IBMF_MSG_FLAGS_DONE 0x00002000 /* xport done */
233 #define IBMF_MSG_FLAGS_BLOCKING 0x00004000 /* sync command */
236 * This structure is used to keep track of IBT returned ibt_ud_dest_t
239 typedef struct ibmf_ud_dest_s
{
240 ibt_ud_dest_t ud_dest
;
241 struct ibmf_ud_dest_s
*ud_next
;
245 * ibmf_msg_impl definition
246 * The IBMF client initializes various members of the msg while sending
247 * the message. IBMF fills in the various members of the msg when a message
250 typedef struct _ibmf_msg_impl
{
251 ibmf_addr_info_t im_local_addr
; /* local addressing info */
252 ibmf_global_addr_info_t im_global_addr
; /* global addressing info */
253 int32_t im_msg_status
; /* completion status */
254 uint32_t im_msg_flags
; /* flags */
255 size_t im_msg_sz_limit
; /* max. message size */
256 ibmf_msg_bufs_t im_msgbufs_send
; /* input data to ibmf */
257 ibmf_msg_bufs_t im_msgbufs_recv
; /* output data from ibmf */
258 struct _ibmf_msg_impl
*im_msg_next
; /* next message on the list */
259 struct _ibmf_msg_impl
*im_msg_prev
; /* prev message on the list */
260 void *im_client
; /* client that allocd the pkt */
261 ibmf_qp_handle_t im_qp_hdl
; /* qp handle */
262 ibt_ud_dest_t
*im_ud_dest
; /* ptr to the pkt's ud_dest */
263 ibmf_ud_dest_t
*im_ibmf_ud_dest
; /* ptr to the pkt's ud_dest */
264 ibmf_msg_cb_t im_trans_cb
; /* transaction completion cb */
265 void *im_trans_cb_arg
; /* arg for completion cb */
266 uint64_t im_tid
; /* transaction ID */
267 uint8_t im_mgt_class
; /* management class */
268 kmutex_t im_mutex
; /* protects trans context */
269 uint32_t im_state
; /* message state */
270 uint32_t im_transp_op_flags
; /* transaction operation */
271 uint32_t im_flags
; /* message flags */
272 uint32_t im_trans_state_flags
; /* state flags */
273 kcondvar_t im_trans_cv
; /* wait for op completion */
274 ibmf_rmpp_ctx_t im_rmpp_ctx
; /* RMPP context */
275 ibmf_retrans_t im_retrans
; /* retransmission info */
276 timeout_id_t im_rp_timeout_id
; /* response timeout ID */
277 timeout_id_t im_tr_timeout_id
; /* transaction timeout ID */
278 timeout_id_t im_rp_unset_timeout_id
; /* id for untimeout() */
279 timeout_id_t im_tr_unset_timeout_id
; /* id for untimeout() */
280 int im_ref_count
; /* reference count */
281 boolean_t im_unsolicited
; /* msg was unsolicited recv */
282 int im_pending_send_compls
; /* send completions */
284 _NOTE(READ_ONLY_DATA(ibmf_msg_impl_t::im_trans_cb
285 ibmf_msg_impl_t::im_trans_cb_arg
286 ibmf_msg_impl_t::im_transp_op_flags
287 ibmf_msg_impl_t::im_local_addr
288 ibmf_msg_impl_t::im_unsolicited
289 ibmf_msg_impl_t::im_client
))
290 _NOTE(MUTEX_PROTECTS_DATA(ibmf_msg_impl_t::im_mutex
,
291 ibmf_msg_impl_t::im_flags
292 ibmf_msg_impl_t::im_trans_state_flags
293 ibmf_msg_impl_t::im_msgbufs_recv
294 ibmf_msg_impl_t::im_msg_status
295 ibmf_msg_impl_t::im_rmpp_ctx
))
298 #define IBMF_MSG_FLAGS_SEQUENCED 0x1
299 #define IBMF_MSG_FLAGS_SEND_RMPP 0x2
300 #define IBMF_MSG_FLAGS_RECV_RMPP 0x4
301 #define IBMF_MSG_FLAGS_NOT_RMPP 0x8
302 #define IBMF_MSG_FLAGS_BUSY 0x10
303 #define IBMF_MSG_FLAGS_FREE 0x20
304 #define IBMF_MSG_FLAGS_ON_LIST 0x40
305 #define IBMF_MSG_FLAGS_SET_TERMINATION 0x80
306 #define IBMF_MSG_FLAGS_TERMINATION 0x100
308 /* retransmission parameter defaults for im_retrans field */
309 #define IBMF_RETRANS_DEF_RTV 4000000 /* 4 seconds */
310 #define IBMF_RETRANS_DEF_RTTV 100000 /* 100 milliseconds */
311 #define IBMF_RETRANS_DEF_TRANS_TO 40000000 /* 40 seconds */
312 #define IBMF_RETRANS_DEF_RETRIES 0
315 * Transaction state flags (im_trans_state_flags) definitions
316 * Don't use 0x0 as a flag value since clients OR and AND the flags
318 #define IBMF_TRANS_STATE_FLAG_UNINIT 0x1
319 #define IBMF_TRANS_STATE_FLAG_INIT 0x2
320 #define IBMF_TRANS_STATE_FLAG_WAIT 0x4
321 #define IBMF_TRANS_STATE_FLAG_DONE 0x8
322 #define IBMF_TRANS_STATE_FLAG_SIGNALED 0x10
323 #define IBMF_TRANS_STATE_FLAG_TIMEOUT 0x20
324 #define IBMF_TRANS_STATE_FLAG_RECV_ACTIVE 0x40
325 #define IBMF_TRANS_STATE_FLAG_RECV_DONE 0x80
326 #define IBMF_TRANS_STATE_FLAG_SEND_DONE 0x100
329 typedef enum _ibmf_timer_t
{
335 * structure to hold specific client info taken from ibmf_register_info_t
336 * since we can register for more than one client at a time, but each specific
337 * ibmf_client_t only holds one client itself.
339 typedef struct _ibmf_client_info
{
342 ibmf_client_type_t client_class
;
343 } ibmf_client_info_t
;
346 * Defines for the client type (agent/manager/agent+manager)
347 * Bits 16-19 of the client_class specify the client type.
349 #define IBMF_AGENT_ID 0x00010000
350 #define IBMF_MANAGER_ID 0x00020000
351 #define IBMF_AGENT_MANAGER_ID 0x00030000
354 * structure used to keep track of clients
356 typedef struct _ibmf_client
{
357 void *ic_client_sig
; /* set for valid handles */
358 struct _ibmf_ci
*ic_myci
; /* pointer to CI */
359 struct _ibmf_client
*ic_next
; /* next client on list */
360 struct _ibmf_client
*ic_prev
; /* previous client on list */
362 taskq_t
*ic_send_taskq
; /* taskq for send cb */
363 taskq_t
*ic_recv_taskq
; /* taskq for receive cb */
364 uint_t ic_init_state_class
; /* taskq initialization */
366 ibmf_msg_impl_t
*ic_msg_list
; /* protected by ic_mutex */
367 ibmf_msg_impl_t
*ic_msg_last
; /* last message on list */
368 ibmf_msg_impl_t
*ic_term_msg_list
; /* termination loop mesgs */
369 ibmf_msg_impl_t
*ic_term_msg_last
; /* last message on list */
370 kmutex_t ic_msg_mutex
; /* protect the message list */
372 /* IBTL asynchronous event callback (eg. HCA offline) */
373 ibmf_async_event_cb_t ic_async_cb
; /* async/unsolicited handling */
374 void *ic_async_cb_arg
; /* args for async cb */
376 /* Asynchronous/Unsolicited message handler */
377 ibmf_msg_cb_t ic_recv_cb
;
378 void *ic_recv_cb_arg
;
379 kcondvar_t ic_recv_cb_teardown_cv
; /* wait on teardown */
381 ibmf_client_info_t ic_client_info
; /* client registration info */
382 ibmf_qp_t
*ic_qp
; /* special qp context */
383 ibt_hca_hdl_t ic_ci_handle
; /* == ic_myci->ic_ci_handle */
384 kmutex_t ic_mutex
; /* prot the client struct */
385 int ic_flags
; /* to keep track of state */
386 int ic_reg_flags
; /* flags specified during */
390 int ic_msgs_alloced
; /* no. msgs alloced by/for */
391 int ic_msgs_active
; /* no. msgs active */
392 int ic_trans_active
; /* outstanding transacts */
393 int ic_sends_active
; /* outstanding sends */
394 int ic_recvs_active
; /* outstanding recvs */
396 ib_lid_t ic_base_lid
; /* used to calculate pathbits */
397 kmutex_t ic_kstat_mutex
; /* protect the kstat */
398 struct kstat
*ic_kstatp
; /* kstats for client */
400 _NOTE(READ_ONLY_DATA(ibmf_client_t::ic_ci_handle
401 ibmf_client_t::ic_client_info
402 ibmf_client_t::ic_client_sig
))
403 _NOTE(MUTEX_PROTECTS_DATA(ibmf_client_t::ic_msg_mutex
,
404 ibmf_client_t::ic_msg_list
405 ibmf_client_t::ic_msg_last
406 ibmf_client_t::ic_term_msg_list
407 ibmf_client_t::ic_term_msg_last
))
408 _NOTE(MUTEX_PROTECTS_DATA(ibmf_client_t::ic_mutex
,
409 ibmf_client_t::ic_msgs_alloced
410 ibmf_client_t::ic_flags
411 ibmf_client_t::ic_recv_cb
412 ibmf_client_t::ic_recv_cb_arg
))
413 _NOTE(MUTEX_PROTECTS_DATA(ibmf_client_t::ic_kstat_mutex
,
414 ibmf_client_t::ic_kstatp
))
416 #define IBMF_CLIENT_RECV_CB_ACTIVE 0x00000001 /* rcv CB active */
417 #define IBMF_CLIENT_SEND_CB_ACTIVE 0x00000010 /* send CB active */
418 #define IBMF_CLIENT_TEAR_DOWN_CB 0x00000100 /* client wants to */
421 /* IBMF_MAD_ONLY is used by the alternate QP context only (isq_flags) */
422 #define IBMF_MAD_ONLY 0x00002000
423 #define IBMF_RAW_ONLY 0x00004000
425 #define IBMF_REG_MSG_LIST 0
426 #define IBMF_TERM_MSG_LIST 1
431 typedef struct _ibmf_send_wqe
{
432 struct _ibmf_send_wqe
*send_wqe_next
;
433 ibt_send_wr_t send_wr
; /* IBT send work request */
434 ibmf_client_t
*send_client
; /* client that sent this */
435 void *send_mem
; /* memory used in send */
436 ib_vaddr_t send_sg_mem
; /* registered memory */
437 ibt_lkey_t send_sg_lkey
; /* Lkey that goes with it */
438 ibt_mr_hdl_t send_mem_hdl
; /* == ci_send_mr_handle in ci */
439 uint_t send_wqe_flags
;
440 uchar_t send_port_num
; /* port this is posted to */
441 ibt_qp_hdl_t send_qp_handle
; /* qp handle for this wqe */
442 ibmf_qp_handle_t send_ibmf_qp_handle
; /* ibmf qp handle */
443 ibmf_msg_impl_t
*send_msg
; /* message context */
444 uint32_t send_status
; /* completion status */
445 uint32_t send_rmpp_segment
; /* rmpp segment */
449 * Receive WQE context
451 typedef struct _ibmf_recv_wqe
{
452 struct _ibmf_recv_wqe
*recv_wqe_next
;
453 ibt_recv_wr_t recv_wr
;
454 ibmf_client_t
*recv_client
; /* client that received this */
455 void *recv_mem
; /* memory used in WQEs */
456 ibmf_qp_t
*recv_qpp
; /* qp this is posted */
457 ibt_wc_t recv_wc
; /* corresponding cqe */
458 ib_vaddr_t recv_sg_mem
; /* registered mem */
459 ibt_lkey_t recv_sg_lkey
; /* Lkey that goes with it */
460 ibt_mr_hdl_t recv_mem_hdl
; /* == ci_recv_mr_handle in ci */
461 uint_t recv_wqe_flags
;
462 uchar_t recv_port_num
; /* port this is posted to */
463 ibt_qp_hdl_t recv_qp_handle
; /* ibt qp handle for this wqe */
464 ibmf_qp_handle_t recv_ibmf_qp_handle
; /* ibmf qp handle */
465 ibmf_msg_impl_t
*recv_msg
; /* message context */
468 #define IBMF_RECV_WQE_FREE 0x00000001 /* WQE is free */
471 * Struct that keeps track of the underlying IB channel interface. There
472 * is one per CI. Each clients on a given ci gets a reference to the CI.
473 * References are tracked used ci_ref field; when ci_ref drops to 0, the
474 * structure can be freed.
476 typedef struct _ibmf_ci
{
477 struct _ibmf_ci
*ci_next
;
478 kmutex_t ci_mutex
; /* protects the CI struct */
479 ibmf_client_t
*ci_clients
; /* list of clients;head */
480 ibmf_client_t
*ci_clients_last
; /* tail */
481 kmutex_t ci_clients_mutex
; /* protect the client list */
482 ib_guid_t ci_node_guid
; /* node GUID */
483 ibt_hca_hdl_t ci_ci_handle
; /* HCA handle */
484 ibt_pd_hdl_t ci_pd
; /* protection domain */
485 ibmf_qp_t
*ci_qp_list
; /* sp. QP list for all ports */
486 ibmf_qp_t
*ci_qp_list_tail
;
487 kcondvar_t ci_qp_cv
; /* wait for QP valid state */
488 ibt_cq_hdl_t ci_cq_handle
; /* CQ handle for sp. QPs */
489 ibt_cq_hdl_t ci_alt_cq_handle
; /* CQ handle for alt. QPs */
490 ibmf_alt_qp_t
*ci_alt_qp_list
; /* alternate QP list */
492 /* UD destination resources */
493 uint32_t ci_ud_dest_list_count
; /* resources in pool */
494 kmutex_t ci_ud_dest_list_mutex
; /* UD dest list mutex */
495 ibmf_ud_dest_t
*ci_ud_dest_list_head
; /* start of list */
497 /* Send/Receive WQEs for Special QPs */
498 struct kmem_cache
*ci_send_wqes_cache
; /* Send WQE cache */
499 struct kmem_cache
*ci_recv_wqes_cache
; /* Receive WQE cache */
500 vmem_t
*ci_wqe_ib_vmem
; /* IB virtual address arena */
501 kmutex_t ci_wqe_mutex
; /* WQE management list mutex */
502 ibmf_wqe_mgt_t
*ci_wqe_mgt_list
; /* WQE management list */
504 uint_t ci_nports
; /* num ports on the CI */
505 uint32_t ci_vendor_id
:24; /* HCA vendor ID */
506 uint16_t ci_device_id
; /* HCA device ID */
507 uint_t ci_ref
; /* reference count */
508 uint16_t ci_state
; /* CI context state */
509 uint16_t ci_state_flags
; /* CI context state flags */
510 kcondvar_t ci_state_cv
; /* wait on a state change */
511 uint_t ci_init_state
; /* used in cleanup */
513 /* free QP synchronization with WQE completion processing */
514 int ci_wqes_alloced
; /* wqes alloced for sp QPs */
515 kcondvar_t ci_wqes_cv
; /* wait on wqes destruction */
518 struct kstat
*ci_port_kstatp
; /* kstats for client */
520 _NOTE(MUTEX_PROTECTS_DATA(ibmf_ci_t::ci_ud_dest_list_mutex
,
521 ibmf_ci_t::ci_ud_dest_list_count
522 ibmf_ci_t::ci_ud_dest_list_head
))
523 _NOTE(MUTEX_PROTECTS_DATA(ibmf_ci_t::ci_mutex
,
525 ibmf_ci_t::ci_port_kstatp
))
526 _NOTE(MUTEX_PROTECTS_DATA(ibmf_ci_t::ci_clients_mutex
,
527 ibmf_ci_t::ci_clients
528 ibmf_ci_t::ci_clients_last
))
529 _NOTE(MUTEX_PROTECTS_DATA(ibmf_ci_t::ci_mutex
,
531 ibmf_qp_t::iq_flags
))
532 _NOTE(MUTEX_PROTECTS_DATA(ibmf_ci_t::ci_wqe_mutex
,
533 ibmf_ci_t::ci_wqe_mgt_list
))
534 _NOTE(READ_ONLY_DATA(ibmf_ci_t::ci_cq_handle
))
536 #define IBMF_CI_BLOCKED_ON_SEND_WQE 0x00000001 /* blockers on wqe */
538 /* defines for ci_init_state */
539 #define IBMF_CI_INIT_HCA_INITED 0x0001
540 #define IBMF_CI_INIT_MUTEX_CV_INITED 0x0002
541 #define IBMF_CI_INIT_SEND_TASKQ_DONE 0x0004
542 #define IBMF_CI_INIT_RECV_TASKQ_DONE 0x0008
543 #define IBMF_CI_INIT_CQ_INITED 0x0010
544 #define IBMF_CI_INIT_WQES_ALLOCED 0x0020
545 #define IBMF_CI_INIT_HCA_LINKED 0x0040
546 #define IBMF_CI_INIT_QP_LIST_INITED 0x0080
548 /* defines for ci_state */
549 #define IBMF_CI_STATE_PRESENT 0x0001
550 #define IBMF_CI_STATE_INITED 0x0002
551 #define IBMF_CI_STATE_GONE 0x0003
553 /* defines for ci_state_flags */
554 #define IBMF_CI_STATE_INIT_WAIT 0x0001
555 #define IBMF_CI_STATE_UNINIT_WAIT 0x0002
556 #define IBMF_CI_STATE_VALIDATE_WAIT 0x0004
558 #define IBMF_CI_STATE_INVALIDATING 0x0100
559 #define IBMF_CI_STATE_VALIDATING 0x0200
560 #define IBMF_CI_STATE_UNINITING 0x0400
561 #define IBMF_CI_STATE_INITING 0x0800
564 * for keeping track of ibmf state
566 typedef struct _ibmf_state
{
567 struct _ibmf_ci
*ibmf_ci_list
;
568 struct _ibmf_ci
*ibmf_ci_list_tail
;
569 ibt_clnt_hdl_t ibmf_ibt_handle
;
570 ibt_cq_handler_t ibmf_cq_handler
;
572 ibt_clnt_modinfo_t ibmf_ibt_modinfo
;
573 taskq_t
*ibmf_taskq
; /* taskq for MAD processing */
574 /* for classes not registered */
576 _NOTE(MUTEX_PROTECTS_DATA(ibmf_state_t::ibmf_mutex
,
579 /* UD Destination resource cache definitions */
581 * It is preferred that the difference between the hi and lo water
582 * marks be only a few ud_dest resources. The intent is that a
583 * thread that needs to run ibmf_i_populate_ud_dest_list() does not
584 * spend too much time in this ud_dest resource population process
585 * before it returns to its caller. A benefit of a higher lo water
586 * mark is that the larger available pool of resources supports high
587 * stress scenarios better.
589 #define IBMF_UD_DEST_HI_WATER_MARK 512
590 #define IBMF_UD_DEST_LO_WATER_MARK 500
595 /* ci related functions */
596 int ibmf_i_validate_ci_guid_and_port(ib_guid_t hca_guid
, uint8_t port_num
);
597 int ibmf_i_get_ci(ibmf_register_info_t
*client_infop
, ibmf_ci_t
**cipp
);
598 void ibmf_i_release_ci(ibmf_ci_t
*cip
);
600 /* client related functions */
601 int ibmf_i_validate_classes_and_port(ibmf_ci_t
*ibmf_cip
,
602 ibmf_register_info_t
*client_infop
);
603 int ibmf_i_validate_class_mask(ibmf_register_info_t
*client_infop
);
604 int ibmf_i_alloc_client(ibmf_register_info_t
*client_infop
, uint_t flags
,
605 ibmf_client_t
**clientpp
);
606 void ibmf_i_add_client(ibmf_ci_t
*ibmf_ci
, ibmf_client_t
*ibmf_clientp
);
608 void ibmf_i_free_client(ibmf_client_t
*clientp
);
609 void ibmf_i_delete_client(ibmf_ci_t
*ibmf_ci
, ibmf_client_t
*ibmf_clientp
);
610 int ibmf_i_lookup_client_by_mgmt_class(ibmf_ci_t
*ibmf_cip
, int port_num
,
611 ibmf_client_type_t
class, ibmf_client_t
**clientpp
);
613 /* qp related functions */
614 int ibmf_i_get_qp(ibmf_ci_t
*ibmf_cip
, uint_t port_num
,
615 ibmf_client_type_t
class, ibmf_qp_t
**qppp
);
616 void ibmf_i_release_qp(ibmf_ci_t
*ibmf_cip
, ibmf_qp_t
**qpp
);
617 int ibmf_i_alloc_qp(ibmf_client_t
*clientp
, ib_pkey_t p_key
,
618 ib_qkey_t q_key
, uint_t flags
, ibmf_qp_handle_t
*ibmf_qp_handlep
);
619 int ibmf_i_free_qp(ibmf_qp_handle_t ibmf_qp_handle
, uint_t flags
);
620 int ibmf_i_query_qp(ibmf_qp_handle_t ibmf_qp_handle
, uint_t flags
,
621 uint_t
*qp_nump
, ib_pkey_t
*p_keyp
, ib_qkey_t
*q_keyp
, uint8_t *portnump
);
622 int ibmf_i_modify_qp(ibmf_qp_handle_t ibmf_qp_handle
, ib_pkey_t p_key
,
623 ib_qkey_t q_key
, uint_t flags
);
624 int ibmf_i_get_pkeyix(ibt_hca_hdl_t hca_handle
, ib_pkey_t pkey
,
625 uint8_t port
, ib_pkey_t
*pkeyixp
);
626 int ibmf_i_pkey_ix_to_key(ibmf_ci_t
*cip
, uint_t port_num
, uint_t pkey_ix
,
629 /* pkt related functions */
630 int ibmf_i_issue_pkt(ibmf_client_t
*clientp
, ibmf_msg_impl_t
*msgp
,
631 ibmf_qp_handle_t ibmf_qp_handle
, ibmf_send_wqe_t
*send_wqep
);
632 int ibmf_i_alloc_ud_dest(ibmf_client_t
*clientp
,
633 ibmf_msg_impl_t
*msgimplp
, ibt_ud_dest_hdl_t
*ud_dest_p
, boolean_t block
);
634 void ibmf_i_free_ud_dest(ibmf_client_t
*clientp
,
635 ibmf_msg_impl_t
*msgimplp
);
636 void ibmf_i_init_ud_dest(ibmf_ci_t
*cip
);
637 void ibmf_i_fini_ud_dest(ibmf_ci_t
*cip
);
638 ibmf_ud_dest_t
*ibmf_i_get_ud_dest(ibmf_ci_t
*cip
);
639 void ibmf_i_put_ud_dest(ibmf_ci_t
*cip
, ibmf_ud_dest_t
*ud_dest
);
640 void ibmf_i_pop_ud_dest_thread(void *argp
);
641 void ibmf_i_clean_ud_dest_list(ibmf_ci_t
*cip
, boolean_t all
);
642 int ibmf_i_alloc_send_resources(ibmf_ci_t
*cip
, ibmf_msg_impl_t
*msgp
,
643 boolean_t block
, ibmf_send_wqe_t
**swqepp
);
644 void ibmf_i_free_send_resources(ibmf_ci_t
*cip
, ibmf_msg_impl_t
*msgimplp
,
645 ibmf_send_wqe_t
*swqep
);
646 int ibmf_i_post_recv_buffer(ibmf_ci_t
*cip
, ibmf_qp_t
*qpp
, boolean_t block
,
647 ibmf_qp_handle_t ibmf_qp_handle
);
648 int ibmf_i_is_ibmf_handle_valid(ibmf_handle_t ibmf_handle
);
649 int ibmf_i_is_qp_handle_valid(ibmf_handle_t ibmf_handle
,
650 ibmf_qp_handle_t ibmf_qp_handle
);
651 int ibmf_i_check_for_loopback(ibmf_msg_impl_t
*msgimplp
, ibmf_msg_cb_t msgp
,
652 void *msg_cb_args
, ibmf_retrans_t
*retrans
, boolean_t
*loopback
);
653 int ibmf_i_ibt_to_ibmf_status(ibt_status_t ibt_status
);
654 int ibmf_i_ibt_wc_to_ibmf_status(ibt_wc_status_t ibt_wc_status
);
655 int ibmf_i_send_pkt(ibmf_client_t
*clientp
, ibmf_qp_handle_t ibmf_qp_handle
,
656 ibmf_msg_impl_t
*msgimplp
, int block
);
657 int ibmf_i_send_single_pkt(ibmf_client_t
*clientp
,
658 ibmf_qp_handle_t ibmf_qp_handle
, ibmf_msg_impl_t
*msgimplp
, int block
);
660 /* WQE related functions */
661 int ibmf_i_init_wqes(ibmf_ci_t
*cip
);
662 void ibmf_i_fini_wqes(ibmf_ci_t
*cip
);
663 void ibmf_i_init_send_wqe(ibmf_client_t
*clientp
,
664 ibmf_msg_impl_t
*msgimplp
, ibt_wr_ds_t
*sglp
, ibmf_send_wqe_t
*wqep
,
665 ibt_ud_dest_hdl_t ud_dest
, ibt_qp_hdl_t ibt_qp_handle
,
666 ibmf_qp_handle_t ibmf_qp_handle
);
667 void ibmf_i_init_recv_wqe(ibmf_qp_t
*qpp
, ibt_wr_ds_t
*sglp
,
668 ibmf_recv_wqe_t
*wqep
, ibt_qp_hdl_t ibt_qp_handle
,
669 ibmf_qp_handle_t ibmf_qp_handle
);
670 void ibmf_i_mad_completions(ibt_cq_hdl_t cq_handle
, void *arg
);
672 void ibmf_i_dump_wcp(ibmf_ci_t
*cip
, ibt_wc_t
*wcp
, ibmf_recv_wqe_t
*recv_wqep
);
675 void ibmf_ibt_async_handler(void *clnt_private
, ibt_hca_hdl_t hca_hdl
,
676 ibt_async_code_t code
, ibt_async_event_t
*event
);
678 /* msg related functions */
679 void ibmf_i_init_msg(ibmf_msg_impl_t
*msgimplp
, ibmf_msg_cb_t trans_cb
,
680 void *trans_cb_arg
, ibmf_retrans_t
*retrans
, boolean_t block
);
681 void ibmf_i_client_add_msg(ibmf_client_t
*clientp
, ibmf_msg_impl_t
*msgimplp
);
682 void ibmf_i_client_rem_msg(ibmf_client_t
*clientp
, ibmf_msg_impl_t
*msgimplp
,
684 int ibmf_i_alloc_msg(ibmf_client_t
*clientp
, ibmf_msg_impl_t
**msgp
,
686 void ibmf_i_free_msg(ibmf_msg_impl_t
*msgimplp
);
687 int ibmf_i_msg_transport(ibmf_client_t
*clientp
,
688 ibmf_qp_handle_t ibmf_qp_handle
, ibmf_msg_impl_t
*msgimplp
, int blocking
);
689 void ibmf_i_decrement_ref_count(ibmf_msg_impl_t
*msgimplp
);
690 void ibmf_i_handle_send_completion(ibmf_ci_t
*cip
, ibt_wc_t
*wcp
);
691 void ibmf_i_handle_recv_completion(ibmf_ci_t
*cip
, ibt_wc_t
*wcp
);
692 int ibmf_setup_recvbuf_on_error(ibmf_msg_impl_t
*msgimplp
, uchar_t
*mad
);
694 /* transaction related functions */
695 void ibmf_i_terminate_transaction(ibmf_client_t
*clientp
,
696 ibmf_msg_impl_t
*msgimplp
, uint32_t status
);
697 void ibmf_i_notify_client(ibmf_msg_impl_t
*msgimplp
);
698 void ibmf_i_notify_sequence(ibmf_client_t
*clientp
, ibmf_msg_impl_t
*msgimplp
,
701 /* timer related functions */
702 void ibmf_i_set_timer(void (*func
)(void *), ibmf_msg_impl_t
*msgimplp
,
704 void ibmf_i_unset_timer(ibmf_msg_impl_t
*msgimplp
, ibmf_timer_t type
);
705 void ibmf_i_recv_timeout(void *argp
);
706 void ibmf_i_send_timeout(void *argp
);
707 void ibmf_i_err_terminate_timeout(void *msgp
);
709 /* rmpp related functions */
710 boolean_t
ibmf_i_find_msg_client(ibmf_client_t
*cl
, ibmf_msg_impl_t
*msgimplp
,
711 boolean_t inc_refcnt
);
712 boolean_t
ibmf_i_is_rmpp(ibmf_client_t
*clientp
,
713 ibmf_qp_handle_t ibmf_qp_handle
);
714 void ibmf_i_mgt_class_to_hdr_sz_off(uint32_t mgt_class
, uint32_t *szp
,
716 ibmf_msg_impl_t
*ibmf_i_find_msg(ibmf_client_t
*clientp
, uint64_t tid
,
717 uint8_t mgt_class
, uint8_t r_method
, ib_lid_t lid
, ib_gid_t
*gid
,
718 boolean_t gid_pr
, ibmf_rmpp_hdr_t
*rmpp_hdr
, boolean_t msg_list
);
720 ibmf_msg_impl_t
*ibmf_i_find_term_msg(ibmf_client_t
*clientp
, uint64_t tid
,
721 uint8_t mgt_class
, ib_lid_t lid
, ib_gid_t
*gid
, boolean_t gid_pr
,
722 ibmf_rmpp_hdr_t
*rmpp_hd
);
724 void ibmf_i_handle_rmpp(ibmf_client_t
*clientp
, ibmf_qp_handle_t qp_hdl
,
725 ibmf_msg_impl_t
*msgimpl
, uchar_t
*madp
);
726 int ibmf_i_send_rmpp(ibmf_msg_impl_t
*msgimplp
, uint8_t rmpp_type
,
727 uint8_t rmpp_status
, uint32_t segno
, uint32_t nwl
, int block
);
728 int ibmf_i_send_rmpp_pkts(ibmf_client_t
*clientp
,
729 ibmf_qp_handle_t ibmf_qp_handle
, ibmf_msg_impl_t
*msgimplp
, boolean_t isDS
,
731 void ibmf_i_send_rmpp_window(ibmf_msg_impl_t
*msgimplp
, int block
);
732 int ibmf_setup_term_ctx(ibmf_client_t
*clientp
, ibmf_msg_impl_t
*regmsgimplp
);
734 /* Alternate QP WQE cache functions */
735 int ibmf_altqp_send_wqe_cache_constructor(void *buf
, void *cdrarg
,
737 void ibmf_altqp_send_wqe_cache_destructor(void *buf
, void *cdrarg
);
738 int ibmf_altqp_recv_wqe_cache_constructor(void *buf
, void *cdrarg
,
740 void ibmf_altqp_recv_wqe_cache_destructor(void *buf
, void *cdrarg
);
741 int ibmf_i_init_altqp_wqes(ibmf_alt_qp_t
*qp_ctx
);
742 void ibmf_i_fini_altqp_wqes(ibmf_alt_qp_t
*qp_ctx
);
743 int ibmf_i_extend_wqe_cache(ibmf_ci_t
*cip
, ibmf_qp_handle_t ibmf_qp_handle
,
746 /* Receive callback functions */
747 void ibmf_i_recv_cb_setup(ibmf_client_t
*clientp
);
748 void ibmf_i_recv_cb_cleanup(ibmf_client_t
*clientp
);
749 void ibmf_i_alt_recv_cb_setup(ibmf_alt_qp_t
*qpp
);
750 void ibmf_i_alt_recv_cb_cleanup(ibmf_alt_qp_t
*qpp
);
752 /* UD Dest population thread */
753 int ibmf_ud_dest_tq_disp(ibmf_ci_t
*cip
);
759 #endif /* _SYS_IB_MGT_IBMF_IBMF_IMPL_H */