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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * ibcm_impl.c
28 *
29 * contains internal functions of IB CM module.
30 *
31 * TBD:
32 * 1. HCA CATASTROPHIC/RECOVERED not handled yet
33 */
34
35 #include <sys/ib/mgt/ibcm/ibcm_impl.h>
36 #include <sys/disp.h>
37
38
39 /* function prototypes */
40 static ibcm_status_t ibcm_init(void);
41 static ibcm_status_t ibcm_fini(void);
42
43 /* Routines to initialize and destroy CM global locks and CVs */
44 static void ibcm_init_locks(void);
45 static void ibcm_fini_locks(void);
46
47 /* Routines that initialize/teardown CM's global hca structures */
48 static void ibcm_init_hcas();
49 static ibcm_status_t ibcm_fini_hcas();
50
51 static void ibcm_init_classportinfo();
52 static void ibcm_stop_timeout_thread();
53
54 /* Routines that handle HCA attach/detach asyncs */
55 static void ibcm_hca_attach(ib_guid_t);
56 static ibcm_status_t ibcm_hca_detach(ibcm_hca_info_t *);
57
58 /* Routines that initialize the HCA's port related fields */
59 static ibt_status_t ibcm_hca_init_port(ibcm_hca_info_t *hcap,
60 uint8_t port_index);
61 static ibcm_status_t ibcm_hca_fini_port(ibcm_hca_info_t *hcap,
62 uint8_t port_index);
63
64 static void ibcm_rc_flow_control_init(void);
65 static void ibcm_rc_flow_control_fini(void);
66
67 /*
68 * Routines that check if hca's avl trees and sidr lists are free of any
69 * active client resources ie., RC or UD state structures in certain states
70 */
71 static ibcm_status_t ibcm_check_avl_clean(ibcm_hca_info_t *hcap);
72 static ibcm_status_t ibcm_check_sidr_clean(ibcm_hca_info_t *hcap);
73
74 /* Add a new hca structure to CM's global hca list */
75 static ibcm_hca_info_t *ibcm_add_hca_entry(ib_guid_t hcaguid, uint_t nports);
76
77 static void ibcm_comm_est_handler(ibt_async_event_t *);
78 void ibcm_async_handler(void *, ibt_hca_hdl_t,
79 ibt_async_code_t, ibt_async_event_t *);
80
81 /* Global variables */
82 char cmlog[] = "ibcm"; /* for debug log messages */
83 ibt_clnt_hdl_t ibcm_ibt_handle; /* IBT handle */
84 kmutex_t ibcm_svc_info_lock; /* list lock */
85 kcondvar_t ibcm_svc_info_cv; /* cv for deregister */
86 kmutex_t ibcm_recv_mutex;
87 avl_tree_t ibcm_svc_avl_tree;
88 taskq_t *ibcm_taskq = NULL;
89 int taskq_dispatch_fail_cnt;
90
91 kmutex_t ibcm_mcglist_lock; /* MCG list lock */
92 kmutex_t ibcm_trace_mutex; /* Trace mutex */
93 kmutex_t ibcm_trace_print_mutex; /* Trace print mutex */
94 int ibcm_conn_max_trcnt = IBCM_MAX_CONN_TRCNT;
95
96 int ibcm_enable_trace = 2; /* Trace level 4 by default */
97 int ibcm_dtrace = 0; /* conditionally enable more dtrace */
98
99 _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_info_s::{svc_bind_list
100 svc_ref_cnt svc_to_delete}))
101
102 _NOTE(MUTEX_PROTECTS_DATA(ibcm_svc_info_lock, ibcm_svc_bind_s::{sbind_link}))
103
104 _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_mutex, ibcm_conn_trace_s))
105
106 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_conn_trace_s))
107
108 _NOTE(MUTEX_PROTECTS_DATA(ibcm_trace_print_mutex, ibcm_debug_buf))
109
110 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_debug_buf))
111
112 /*
113 * Initial state is INIT. All hca dr's return success immediately in this
114 * state, without adding or deleting any hca's to CM.
115 */
116 ibcm_finit_state_t ibcm_finit_state = IBCM_FINIT_INIT;
117
118 /* mutex and cv to manage hca's reference and resource count(s) */
119 kmutex_t ibcm_global_hca_lock;
120 kcondvar_t ibcm_global_hca_cv;
121
122 /* mutex and cv to sa session open */
123 kmutex_t ibcm_sa_open_lock;
124 kcondvar_t ibcm_sa_open_cv;
125 int ibcm_sa_timeout_delay = 1; /* in ticks */
126 _NOTE(MUTEX_PROTECTS_DATA(ibcm_sa_open_lock,
127 ibcm_port_info_s::{port_ibmf_saa_hdl port_saa_open_in_progress}))
128
129 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_port_info_s::{port_ibmf_saa_hdl}))
130
131 /* serialize sm notice callbacks */
132 kmutex_t ibcm_sm_notice_serialize_lock;
133
134 _NOTE(LOCK_ORDER(ibcm_sm_notice_serialize_lock ibcm_global_hca_lock))
135
136 _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock, ibcm_hca_info_s::{hca_state
137 hca_svc_cnt hca_acc_cnt hca_res_cnt hca_next}))
138
139 _NOTE(MUTEX_PROTECTS_DATA(ibcm_global_hca_lock,
140 ibcm_port_info_s::{port_ibmf_hdl}))
141
142 _NOTE(MUTEX_PROTECTS_DATA(ibcm_sm_notice_serialize_lock,
143 ibcm_port_info_s::{port_event_status}))
144
145 _NOTE(DATA_READABLE_WITHOUT_LOCK(ibcm_hca_info_s::{hca_state}))
146 _NOTE(DATA_READABLE_WITHOUT_LOCK(
147 ibcm_hca_info_s::{hca_port_info.port_ibmf_hdl}))
148
149 /* mutex for CM's qp list management */
150 kmutex_t ibcm_qp_list_lock;
151
152 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_port_info_s::{port_qplist}))
153 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s))
154 _NOTE(MUTEX_PROTECTS_DATA(ibcm_qp_list_lock, ibcm_qp_list_s))
155
156 kcondvar_t ibcm_timeout_list_cv;
157 kcondvar_t ibcm_timeout_thread_done_cv;
158 kt_did_t ibcm_timeout_thread_did;
159 ibcm_state_data_t *ibcm_timeout_list_hdr, *ibcm_timeout_list_tail;
160 ibcm_ud_state_data_t *ibcm_ud_timeout_list_hdr, *ibcm_ud_timeout_list_tail;
161 kmutex_t ibcm_timeout_list_lock;
162 uint8_t ibcm_timeout_list_flags = 0;
163 pri_t ibcm_timeout_thread_pri = MINCLSYSPRI;
164
165 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock,
166 ibcm_state_data_s::timeout_next))
167
168 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock,
169 ibcm_ud_state_data_s::ud_timeout_next))
170
171 /*
172 * Flow control logic for open_rc_channel uses the following.
173 */
174
175 struct ibcm_open_s {
176 kmutex_t mutex;
177 kcondvar_t cv;
178 uint8_t task_running;
179 uint_t queued;
180 uint_t exit_deferred;
181 uint_t in_progress;
182 uint_t in_progress_max;
183 uint_t sends;
184 uint_t sends_max;
185 uint_t sends_lowat;
186 uint_t sends_hiwat;
187 ibcm_state_data_t *tail;
188 ibcm_state_data_t head;
189 } ibcm_open;
190
191 /*
192 * Flow control logic for SA access and close_rc_channel calls follows.
193 */
194
195 int ibcm_close_simul_max = 12;
196 int ibcm_lapr_simul_max = 12;
197 int ibcm_saa_simul_max = 8;
198
199 typedef struct ibcm_flow1_s {
200 struct ibcm_flow1_s *link;
201 kcondvar_t cv;
202 uint8_t waiters; /* 1 to IBCM_FLOW_SIMUL_MAX */
203 } ibcm_flow1_t;
204
205 typedef struct ibcm_flow_s {
206 ibcm_flow1_t *list;
207 uint_t simul; /* #requests currently outstanding */
208 uint_t simul_max;
209 uint_t waiters_per_chunk;
210 uint_t lowat;
211 uint_t lowat_default;
212 /* statistics */
213 uint_t total;
214 } ibcm_flow_t;
215
216 ibcm_flow_t ibcm_saa_flow;
217 ibcm_flow_t ibcm_close_flow;
218 ibcm_flow_t ibcm_lapr_flow;
219
220 /* NONBLOCKING close requests are queued */
221 struct ibcm_close_s {
222 kmutex_t mutex;
223 ibcm_state_data_t *tail;
224 ibcm_state_data_t head;
225 } ibcm_close;
226
227 static ibt_clnt_modinfo_t ibcm_ibt_modinfo = { /* Client's modinfop */
228 IBTI_V_CURR,
229 IBT_CM,
230 ibcm_async_handler,
231 NULL,
232 "IBCM"
233 };
234
235 /* IBCM's list of HCAs registered with it */
236 static ibcm_hca_info_t *ibcm_hca_listp = NULL; /* CM's HCA list */
237
238 /* Array of CM state call table functions */
239 ibcm_state_handler_t ibcm_sm_funcs_tbl[] = {
240 ibcm_process_req_msg,
241 ibcm_process_mra_msg,
242 ibcm_process_rej_msg,
243 ibcm_process_rep_msg,
244 ibcm_process_rtu_msg,
245 ibcm_process_dreq_msg,
246 ibcm_process_drep_msg,
247 ibcm_process_sidr_req_msg,
248 ibcm_process_sidr_rep_msg,
249 ibcm_process_lap_msg,
250 ibcm_process_apr_msg
251 };
252
253 /* the following globals are CM tunables */
254 ibt_rnr_nak_time_t ibcm_default_rnr_nak_time = IBT_RNR_NAK_655ms;
255
256 uint8_t ibcm_max_retries = IBCM_MAX_RETRIES;
257 clock_t ibcm_local_processing_time = IBCM_LOCAL_RESPONSE_TIME;
258 clock_t ibcm_remote_response_time = IBCM_REMOTE_RESPONSE_TIME;
259 ib_time_t ibcm_max_sidr_rep_proctime = IBCM_MAX_SIDR_PROCESS_TIME;
260 ib_time_t ibcm_max_sidr_pktlife_time = IBCM_MAX_SIDR_PKT_LIFE_TIME;
261
262 ib_time_t ibcm_max_sidr_rep_store_time = 18;
263 uint32_t ibcm_wait_for_acc_cnt_timeout = 2000000; /* 2 sec */
264
265 ib_time_t ibcm_max_ib_pkt_lt = IBCM_MAX_IB_PKT_LT;
266 ib_time_t ibcm_max_ib_mad_pkt_lt = IBCM_MAX_IB_MAD_PKT_LT;
267
268 /*
269 * This delay accounts for time involved in various activities as follows :
270 *
271 * IBMF delays for posting the MADs in non-blocking mode
272 * IBMF delays for receiving the MADs and delivering to CM
273 * CM delays in processing the MADs before invoking client handlers,
274 * Any other delays associated with HCA driver in processing the MADs and
275 * other subsystems that CM may invoke (ex : SA, HCA driver)
276 */
277 uint32_t ibcm_sw_delay = 1000; /* 1000us / 1ms */
278 uint32_t ibcm_max_sa_retries = IBCM_MAX_SA_RETRIES + 1;
279
280 /* approx boot time */
281 uint32_t ibcm_adj_btime = 4; /* 4 seconds */
282
283 /*
284 * The information in ibcm_clpinfo is kept in wireformat and is setup at
285 * init time, and used read-only after that
286 */
287 ibcm_classportinfo_msg_t ibcm_clpinfo;
288
289 char *event_str[] = {
290 "NEVER SEE THIS ",
291 "SESSION_ID ",
292 "CHAN_HDL ",
293 "LOCAL_COMID/HCA/PORT ",
294 "LOCAL_QPN ",
295 "REMOTE_COMID/HCA ",
296 "REMOTE_QPN ",
297 "BASE_TIME ",
298 "INCOMING_REQ ",
299 "INCOMING_REP ",
300 "INCOMING_RTU ",
301 "INCOMING_COMEST ",
302 "INCOMING_MRA ",
303 "INCOMING_REJ ",
304 "INCOMING_LAP ",
305 "INCOMING_APR ",
306 "INCOMING_DREQ ",
307 "INCOMING_DREP ",
308 "OUTGOING_REQ ",
309 "OUTGOING_REP ",
310 "OUTGOING_RTU ",
311 "OUTGOING_LAP ",
312 "OUTGOING_APR ",
313 "OUTGOING_MRA ",
314 "OUTGOING_REJ ",
315 "OUTGOING_DREQ ",
316 "OUTGOING_DREP ",
317 "REQ_POST_COMPLETE ",
318 "REP_POST_COMPLETE ",
319 "RTU_POST_COMPLETE ",
320 "MRA_POST_COMPLETE ",
321 "REJ_POST_COMPLETE ",
322 "LAP_POST_COMPLETE ",
323 "APR_POST_COMPLETE ",
324 "DREQ_POST_COMPLETE ",
325 "DREP_POST_COMPLETE ",
326 "TIMEOUT_REP ",
327 "CALLED_REQ_RCVD_EVENT ",
328 "RET_REQ_RCVD_EVENT ",
329 "CALLED_REP_RCVD_EVENT ",
330 "RET_REP_RCVD_EVENT ",
331 "CALLED_CONN_EST_EVENT ",
332 "RET_CONN_EST_EVENT ",
333 "CALLED_CONN_FAIL_EVENT ",
334 "RET_CONN_FAIL_EVENT ",
335 "CALLED_CONN_CLOSE_EVENT ",
336 "RET_CONN_CLOSE_EVENT ",
337 "INIT_INIT ",
338 "INIT_INIT_FAIL ",
339 "INIT_RTR ",
340 "INIT_RTR_FAIL ",
341 "RTR_RTS ",
342 "RTR_RTS_FAIL ",
343 "RTS_RTS ",
344 "RTS_RTS_FAIL ",
345 "TO_ERROR ",
346 "ERROR_FAIL ",
347 "SET_ALT ",
348 "SET_ALT_FAIL ",
349 "STALE_DETECT ",
350 "OUTGOING_REQ_RETRY ",
351 "OUTGOING_REP_RETRY ",
352 "OUTGOING_LAP_RETRY ",
353 "OUTGOING_MRA_RETRY ",
354 "OUTGOING_DREQ_RETRY ",
355 "NEVER SEE THIS "
356 };
357
358 char ibcm_debug_buf[IBCM_DEBUG_BUF_SIZE];
359
360 _NOTE(SCHEME_PROTECTS_DATA("used in a localized function consistently",
361 ibcm_debug_buf))
362 _NOTE(READ_ONLY_DATA(ibcm_taskq))
363
364 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_flags))
365 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_timeout_list_hdr))
366 _NOTE(MUTEX_PROTECTS_DATA(ibcm_timeout_list_lock, ibcm_ud_timeout_list_hdr))
367
368 #ifdef DEBUG
369 int ibcm_test_mode = 0; /* set to 1, if running tests */
370 #endif
371
372
373 /* Module Driver Info */
374 static struct modlmisc ibcm_modlmisc = {
375 &mod_miscops,
376 "IB Communication Manager"
377 };
378
379 /* Module Linkage */
380 static struct modlinkage ibcm_modlinkage = {
381 MODREV_1,
382 { &ibcm_modlmisc, NULL }
383 };
384
385
386 int
387 _init(void)
388 {
389 int rval;
390 ibcm_status_t status;
391
392 status = ibcm_init();
393 if (status != IBCM_SUCCESS) {
394 IBTF_DPRINTF_L2(cmlog, "_init: ibcm failed %d", status);
395 return (EINVAL);
396 }
397
398 rval = mod_install(&ibcm_modlinkage);
399 if (rval != 0) {
400 IBTF_DPRINTF_L2(cmlog, "_init: ibcm mod_install failed %d",
401 rval);
402 (void) ibcm_fini();
403 }
404
405 IBTF_DPRINTF_L5(cmlog, "_init: ibcm successful");
406 return (rval);
407
408 }
409
410
411 int
412 _info(struct modinfo *modinfop)
413 {
414 return (mod_info(&ibcm_modlinkage, modinfop));
415 }
416
417
418 int
419 _fini(void)
420 {
421 int status;
422
423 if (ibcm_fini() != IBCM_SUCCESS)
424 return (EBUSY);
425
426 if ((status = mod_remove(&ibcm_modlinkage)) != 0) {
427 IBTF_DPRINTF_L2(cmlog, "_fini: ibcm mod_remove failed %d",
428 status);
429 return (status);
430 }
431
432 IBTF_DPRINTF_L5(cmlog, "_fini: ibcm successful");
433
434 return (status);
435 }
436
437 /* Initializes all global mutex and CV in cm module */
438 static void
439 ibcm_init_locks()
440 {
441
442 /* Verify CM MAD sizes */
443 #ifdef DEBUG
444
445 if (ibcm_test_mode > 1) {
446
447 IBTF_DPRINTF_L1(cmlog, "REQ MAD SIZE %d",
448 sizeof (ibcm_req_msg_t));
449 IBTF_DPRINTF_L1(cmlog, "REP MAD SIZE %d",
450 sizeof (ibcm_rep_msg_t));
451 IBTF_DPRINTF_L1(cmlog, "RTU MAD SIZE %d",
452 sizeof (ibcm_rtu_msg_t));
453 IBTF_DPRINTF_L1(cmlog, "MRA MAD SIZE %d",
454 sizeof (ibcm_mra_msg_t));
455 IBTF_DPRINTF_L1(cmlog, "REJ MAD SIZE %d",
456 sizeof (ibcm_rej_msg_t));
457 IBTF_DPRINTF_L1(cmlog, "LAP MAD SIZE %d",
458 sizeof (ibcm_lap_msg_t));
459 IBTF_DPRINTF_L1(cmlog, "APR MAD SIZE %d",
460 sizeof (ibcm_apr_msg_t));
461 IBTF_DPRINTF_L1(cmlog, "DREQ MAD SIZE %d",
462 sizeof (ibcm_dreq_msg_t));
463 IBTF_DPRINTF_L1(cmlog, "DREP MAD SIZE %d",
464 sizeof (ibcm_drep_msg_t));
465 IBTF_DPRINTF_L1(cmlog, "SIDR REQ MAD SIZE %d",
466 sizeof (ibcm_sidr_req_msg_t));
467 IBTF_DPRINTF_L1(cmlog, "SIDR REP MAD SIZE %d",
468 sizeof (ibcm_sidr_rep_msg_t));
469 }
470
471 #endif
472
473 /* Create all global locks within cm module */
474 mutex_init(&ibcm_svc_info_lock, NULL, MUTEX_DEFAULT, NULL);
475 mutex_init(&ibcm_mcglist_lock, NULL, MUTEX_DEFAULT, NULL);
476 mutex_init(&ibcm_timeout_list_lock, NULL, MUTEX_DEFAULT, NULL);
477 mutex_init(&ibcm_global_hca_lock, NULL, MUTEX_DEFAULT, NULL);
478 mutex_init(&ibcm_sa_open_lock, NULL, MUTEX_DEFAULT, NULL);
479 mutex_init(&ibcm_recv_mutex, NULL, MUTEX_DEFAULT, NULL);
480 mutex_init(&ibcm_sm_notice_serialize_lock, NULL, MUTEX_DEFAULT, NULL);
481 mutex_init(&ibcm_qp_list_lock, NULL, MUTEX_DEFAULT, NULL);
482 mutex_init(&ibcm_trace_mutex, NULL, MUTEX_DEFAULT, NULL);
483 mutex_init(&ibcm_trace_print_mutex, NULL, MUTEX_DEFAULT, NULL);
484 cv_init(&ibcm_svc_info_cv, NULL, CV_DRIVER, NULL);
485 cv_init(&ibcm_timeout_list_cv, NULL, CV_DRIVER, NULL);
486 cv_init(&ibcm_timeout_thread_done_cv, NULL, CV_DRIVER, NULL);
487 cv_init(&ibcm_global_hca_cv, NULL, CV_DRIVER, NULL);
488 cv_init(&ibcm_sa_open_cv, NULL, CV_DRIVER, NULL);
489 avl_create(&ibcm_svc_avl_tree, ibcm_svc_compare,
490 sizeof (ibcm_svc_info_t),
491 offsetof(struct ibcm_svc_info_s, svc_link));
492
493 IBTF_DPRINTF_L5(cmlog, "ibcm_init_locks: done");
494 }
495
496 /* Destroys all global mutex and CV in cm module */
497 static void
498 ibcm_fini_locks()
499 {
500 /* Destroy all global locks within cm module */
501 mutex_destroy(&ibcm_svc_info_lock);
502 mutex_destroy(&ibcm_mcglist_lock);
503 mutex_destroy(&ibcm_timeout_list_lock);
504 mutex_destroy(&ibcm_global_hca_lock);
505 mutex_destroy(&ibcm_sa_open_lock);
506 mutex_destroy(&ibcm_recv_mutex);
507 mutex_destroy(&ibcm_sm_notice_serialize_lock);
508 mutex_destroy(&ibcm_qp_list_lock);
509 mutex_destroy(&ibcm_trace_mutex);
510 mutex_destroy(&ibcm_trace_print_mutex);
511 cv_destroy(&ibcm_svc_info_cv);
512 cv_destroy(&ibcm_timeout_list_cv);
513 cv_destroy(&ibcm_timeout_thread_done_cv);
514 cv_destroy(&ibcm_global_hca_cv);
515 cv_destroy(&ibcm_sa_open_cv);
516 avl_destroy(&ibcm_svc_avl_tree);
517
518 IBTF_DPRINTF_L5(cmlog, "ibcm_fini_locks: done");
519 }
520
521
522 /* Initialize CM's classport info */
523 static void
524 ibcm_init_classportinfo()
525 {
526 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_clpinfo));
527
528 ibcm_clpinfo.BaseVersion = IBCM_MAD_BASE_VERSION;
529 ibcm_clpinfo.ClassVersion = IBCM_MAD_CLASS_VERSION;
530
531 /* For now, CM supports same capabilities at all ports */
532 ibcm_clpinfo.CapabilityMask =
533 h2b16(IBCM_CPINFO_CAP_RC | IBCM_CPINFO_CAP_SIDR);
534
535 /* Bits 0-7 are all 0 for Communication Mgmt Class */
536
537 /* For now, CM has the same respvalue at all ports */
538 ibcm_clpinfo.RespTimeValue_plus =
539 h2b32(ibt_usec2ib(ibcm_local_processing_time) & 0x1f);
540
541 /* For now, redirect fields are set to 0 */
542 /* Trap fields are not applicable to CM, hence set to 0 */
543
544 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_clpinfo));
545 IBTF_DPRINTF_L5(cmlog, "ibcm_init_classportinfo: done");
546 }
547
548 /*
549 * ibcm_init():
550 * - call ibt_attach()
551 * - create AVL trees
552 * - Attach HCA handlers that are already present before
553 * CM got loaded.
554 *
555 * Arguments: NONE
556 *
557 * Return values:
558 * IBCM_SUCCESS - success
559 */
560 static ibcm_status_t
561 ibcm_init(void)
562 {
563 ibt_status_t status;
564 kthread_t *t;
565
566 IBTF_DPRINTF_L3(cmlog, "ibcm_init:");
567
568 ibcm_init_classportinfo();
569
570 if (ibcm_init_ids() != IBCM_SUCCESS) {
571 IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
572 "fatal error: vmem_create() failed");
573 return (IBCM_FAILURE);
574 }
575 ibcm_init_locks();
576
577 if (ibcm_ar_init() != IBCM_SUCCESS) {
578 IBTF_DPRINTF_L1(cmlog, "ibcm_init: "
579 "fatal error: ibcm_ar_init() failed");
580 ibcm_fini_ids();
581 ibcm_fini_locks();
582 return (IBCM_FAILURE);
583 }
584 ibcm_rc_flow_control_init();
585
586 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_taskq))
587 ibcm_taskq = system_taskq;
588 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_taskq))
589
590 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags))
591 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did))
592
593 /* Start the timeout list processing thread */
594 ibcm_timeout_list_flags = 0;
595 t = thread_create(NULL, 0, ibcm_process_tlist, 0, 0, &p0, TS_RUN,
596 ibcm_timeout_thread_pri);
597 ibcm_timeout_thread_did = t->t_did;
598
599 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_flags))
600 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_thread_did))
601
602 /*
603 * NOTE : if ibt_attach is done after ibcm_init_hcas, then some
604 * HCA DR events may be lost. CM could call re-init hca list
605 * again, but it is more complicated. Some HCA's DR's lost may
606 * be HCA detach, which makes hca list re-syncing and locking more
607 * complex
608 */
609 status = ibt_attach(&ibcm_ibt_modinfo, NULL, NULL, &ibcm_ibt_handle);
610 if (status != IBT_SUCCESS) {
611 IBTF_DPRINTF_L2(cmlog, "ibcm_init(): ibt_attach failed %d",
612 status);
613 (void) ibcm_ar_fini();
614 ibcm_stop_timeout_thread();
615 ibcm_fini_ids();
616 ibcm_fini_locks();
617 ibcm_rc_flow_control_fini();
618 return (IBCM_FAILURE);
619 }
620
621 /* Block all HCA attach/detach asyncs */
622 mutex_enter(&ibcm_global_hca_lock);
623
624 ibcm_init_hcas();
625 ibcm_finit_state = IBCM_FINIT_IDLE;
626
627 ibcm_path_cache_init();
628 /*
629 * This callback will be used by IBTL to get the Node record for a
630 * given LID via the speccified HCA and port.
631 */
632 ibtl_cm_set_node_info_cb(ibcm_ibtl_node_info);
633
634 /* Unblock any waiting HCA DR asyncs in CM */
635 mutex_exit(&ibcm_global_hca_lock);
636
637 IBTF_DPRINTF_L4(cmlog, "ibcm_init: done");
638 return (IBCM_SUCCESS);
639 }
640
641 /* Allocates and initializes the "per hca" global data in CM */
642 static void
643 ibcm_init_hcas()
644 {
645 uint_t num_hcas = 0;
646 ib_guid_t *guid_array;
647 int i;
648
649 IBTF_DPRINTF_L5(cmlog, "ibcm_init_hcas:");
650
651 /* Get the number of HCAs */
652 num_hcas = ibt_get_hca_list(&guid_array);
653 IBTF_DPRINTF_L4(cmlog, "ibcm_init_hcas: ibt_get_hca_list() "
654 "returned %d hcas", num_hcas);
655
656 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
657
658 for (i = 0; i < num_hcas; i++)
659 ibcm_hca_attach(guid_array[i]);
660
661 if (num_hcas)
662 ibt_free_hca_list(guid_array, num_hcas);
663
664 IBTF_DPRINTF_L5(cmlog, "ibcm_init_hcas: done");
665 }
666
667
668 /*
669 * ibcm_fini():
670 * - Deregister w/ ibt
671 * - Cleanup IBCM HCA listp
672 * - Destroy mutexes
673 *
674 * Arguments: NONE
675 *
676 * Return values:
677 * IBCM_SUCCESS - success
678 */
679 static ibcm_status_t
680 ibcm_fini(void)
681 {
682 ibt_status_t status;
683
684 IBTF_DPRINTF_L3(cmlog, "ibcm_fini:");
685
686 /*
687 * CM assumes that the all general clients got rid of all the
688 * established connections and service registrations, completed all
689 * pending SIDR operations before a call to ibcm_fini()
690 */
691
692 if (ibcm_ar_fini() != IBCM_SUCCESS) {
693 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: ibcm_ar_fini failed");
694 return (IBCM_FAILURE);
695 }
696
697 /* cleanup the svcinfo list */
698 mutex_enter(&ibcm_svc_info_lock);
699 if (avl_first(&ibcm_svc_avl_tree) != NULL) {
700 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: "
701 "ibcm_svc_avl_tree is not empty");
702 mutex_exit(&ibcm_svc_info_lock);
703 return (IBCM_FAILURE);
704 }
705 mutex_exit(&ibcm_svc_info_lock);
706
707 /* disables any new hca attach/detaches */
708 mutex_enter(&ibcm_global_hca_lock);
709
710 ibcm_finit_state = IBCM_FINIT_BUSY;
711
712 if (ibcm_fini_hcas() != IBCM_SUCCESS) {
713 IBTF_DPRINTF_L2(cmlog, "ibcm_fini: "
714 "some hca's still have client resources");
715
716 /* First, re-initialize the hcas */
717 ibcm_init_hcas();
718 /* and then enable the HCA asyncs */
719 ibcm_finit_state = IBCM_FINIT_IDLE;
720 mutex_exit(&ibcm_global_hca_lock);
721 if (ibcm_ar_init() != IBCM_SUCCESS) {
722 IBTF_DPRINTF_L1(cmlog, "ibcm_fini:ibcm_ar_init failed");
723 }
724 return (IBCM_FAILURE);
725 }
726
727 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr))
728 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr))
729
730 ASSERT(ibcm_timeout_list_hdr == NULL);
731 ASSERT(ibcm_ud_timeout_list_hdr == NULL);
732
733 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_timeout_list_hdr))
734 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibcm_ud_timeout_list_hdr))
735
736 /* Release any pending asyncs on ibcm_global_hca_lock */
737 ibcm_finit_state = IBCM_FINIT_SUCCESS;
738 mutex_exit(&ibcm_global_hca_lock);
739
740 ibcm_stop_timeout_thread();
741
742 ibtl_cm_set_node_info_cb(NULL);
743 /*
744 * Detach from IBTL. Waits until all pending asyncs are complete.
745 * Above cv_broadcast wakes up any waiting hca attach/detach asyncs
746 */
747 status = ibt_detach(ibcm_ibt_handle);
748
749 /* if detach fails, CM didn't free up some resources, so assert */
750 if (status != IBT_SUCCESS)
751 IBTF_DPRINTF_L1(cmlog, "ibcm_fini: ibt_detach failed %d",
752 status);
753
754 ibcm_rc_flow_control_fini();
755
756 ibcm_path_cache_fini();
757
758 ibcm_fini_ids();
759 ibcm_fini_locks();
760 IBTF_DPRINTF_L3(cmlog, "ibcm_fini: done");
761 return (IBCM_SUCCESS);
762 }
763
764 /* This routine exit's the ibcm timeout thread */
765 static void
766 ibcm_stop_timeout_thread()
767 {
768 mutex_enter(&ibcm_timeout_list_lock);
769
770 /* Stop the timeout list processing thread */
771 ibcm_timeout_list_flags =
772 ibcm_timeout_list_flags | IBCM_TIMEOUT_THREAD_EXIT;
773
774 /* Wake up, if the timeout thread is on a cv_wait */
775 cv_signal(&ibcm_timeout_list_cv);
776
777 mutex_exit(&ibcm_timeout_list_lock);
778 thread_join(ibcm_timeout_thread_did);
779
780 IBTF_DPRINTF_L5(cmlog, "ibcm_stop_timeout_thread: done");
781 }
782
783
784 /* Attempts to release all the hca's associated with CM */
785 static ibcm_status_t
786 ibcm_fini_hcas()
787 {
788 ibcm_hca_info_t *hcap, *next;
789
790 IBTF_DPRINTF_L4(cmlog, "ibcm_fini_hcas:");
791
792 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
793
794 hcap = ibcm_hca_listp;
795 while (hcap != NULL) {
796 next = hcap->hca_next;
797 if (ibcm_hca_detach(hcap) != IBCM_SUCCESS) {
798 ibcm_hca_listp = hcap;
799 return (IBCM_FAILURE);
800 }
801 hcap = next;
802 }
803
804 IBTF_DPRINTF_L4(cmlog, "ibcm_fini_hcas: SUCCEEDED");
805 return (IBCM_SUCCESS);
806 }
807
808
809 /*
810 * ibcm_hca_attach():
811 * Called as an asynchronous event to notify CM of an attach of HCA.
812 * Here ibcm_hca_info_t is initialized and all fields are
813 * filled in along with SA Access handles and IBMA handles.
814 * Also called from ibcm_init to initialize ibcm_hca_info_t's for each
815 * hca's
816 *
817 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
818 * hca_guid - HCA's guid
819 *
820 * Return values: NONE
821 */
822 static void
823 ibcm_hca_attach(ib_guid_t hcaguid)
824 {
825 int i;
826 ibt_status_t status;
827 uint8_t nports = 0;
828 ibcm_hca_info_t *hcap;
829 ibt_hca_attr_t hca_attrs;
830
831 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: guid = 0x%llX", hcaguid);
832
833 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
834
835 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*hcap))
836
837 status = ibt_query_hca_byguid(hcaguid, &hca_attrs);
838 if (status != IBT_SUCCESS) {
839 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
840 "ibt_query_hca_byguid failed = %d", status);
841 return;
842 }
843 nports = hca_attrs.hca_nports;
844
845 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_attach: num ports = %x", nports);
846
847 if ((hcap = ibcm_add_hca_entry(hcaguid, nports)) == NULL)
848 return;
849
850 hcap->hca_guid = hcaguid; /* Set GUID */
851 hcap->hca_num_ports = nports; /* Set number of ports */
852
853 if (ibcm_init_hca_ids(hcap) != IBCM_SUCCESS) {
854 ibcm_delete_hca_entry(hcap);
855 return;
856 }
857
858 /* Store the static hca attribute data */
859 hcap->hca_caps = hca_attrs.hca_flags;
860 hcap->hca_vendor_id = hca_attrs.hca_vendor_id;
861 hcap->hca_device_id = hca_attrs.hca_device_id;
862 hcap->hca_ack_delay = hca_attrs.hca_local_ack_delay;
863 hcap->hca_max_rdma_in_qp = hca_attrs.hca_max_rdma_in_qp;
864 hcap->hca_max_rdma_out_qp = hca_attrs.hca_max_rdma_out_qp;
865
866 /* loop thru nports and initialize IBMF handles */
867 for (i = 0; i < hcap->hca_num_ports; i++) {
868 status = ibt_get_port_state_byguid(hcaguid, i + 1, NULL, NULL);
869 if (status != IBT_SUCCESS) {
870 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
871 "port_num %d state DOWN", i + 1);
872 }
873
874 hcap->hca_port_info[i].port_hcap = hcap;
875 hcap->hca_port_info[i].port_num = i+1;
876
877 if (ibcm_hca_init_port(hcap, i) != IBT_SUCCESS)
878 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_attach: "
879 "ibcm_hca_init_port failed %d port_num %d",
880 status, i+1);
881 }
882
883 /* create the "active" CM AVL tree */
884 avl_create(&hcap->hca_active_tree, ibcm_active_node_compare,
885 sizeof (ibcm_state_data_t),
886 offsetof(struct ibcm_state_data_s, avl_active_link));
887
888 /* create the "passive" CM AVL tree */
889 avl_create(&hcap->hca_passive_tree, ibcm_passive_node_compare,
890 sizeof (ibcm_state_data_t),
891 offsetof(struct ibcm_state_data_s, avl_passive_link));
892
893 /* create the "passive comid" CM AVL tree */
894 avl_create(&hcap->hca_passive_comid_tree,
895 ibcm_passive_comid_node_compare,
896 sizeof (ibcm_state_data_t),
897 offsetof(struct ibcm_state_data_s, avl_passive_comid_link));
898
899 /*
900 * Mark the state of the HCA to "attach" only at the end
901 * Now CM starts accepting incoming MADs and client API calls
902 */
903 hcap->hca_state = IBCM_HCA_ACTIVE;
904
905 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*hcap))
906
907 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_attach: ATTACH Done");
908 }
909
910 /*
911 * ibcm_hca_detach():
912 * Called as an asynchronous event to notify CM of a detach of HCA.
913 * Here ibcm_hca_info_t is freed up and all fields that
914 * were initialized earlier are cleaned up
915 *
916 * Arguments: (WILL CHANGE BASED ON ASYNC EVENT CODE)
917 * hca_guid - HCA's guid
918 *
919 * Return values:
920 * IBCM_SUCCESS - able to detach HCA
921 * IBCM_FAILURE - failed to detach HCA
922 */
923 static ibcm_status_t
924 ibcm_hca_detach(ibcm_hca_info_t *hcap)
925 {
926 int port_index, i;
927 ibcm_status_t status = IBCM_SUCCESS;
928 clock_t absolute_time;
929
930 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach: hcap = 0x%p guid = 0x%llX",
931 hcap, hcap->hca_guid);
932
933 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
934
935 /*
936 * Declare hca is going away to all CM clients. Wait until the
937 * access count becomes zero.
938 */
939 hcap->hca_state = IBCM_HCA_NOT_ACTIVE;
940
941 /* wait on response CV */
942 absolute_time = ddi_get_lbolt() +
943 drv_usectohz(ibcm_wait_for_acc_cnt_timeout);
944
945 while (hcap->hca_acc_cnt > 0)
946 if (cv_timedwait(&ibcm_global_hca_cv, &ibcm_global_hca_lock,
947 absolute_time) == -1)
948 break;
949
950 if (hcap->hca_acc_cnt != 0) {
951 /* We got a timeout */
952 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: Aborting due"
953 " to timeout on hca_acc_cnt %u, \n Some CM Clients are "
954 "still active, looks like we need to wait some more time "
955 "(ibcm_wait_for_acc_cnt_timeout).", hcap->hca_acc_cnt);
956 hcap->hca_state = IBCM_HCA_ACTIVE;
957 return (IBCM_FAILURE);
958 }
959
960 /*
961 * First make sure, there are no active users of ibma handles,
962 * and then de-register handles.
963 */
964
965 /* make sure that there are no "Service"s registered w/ this HCA. */
966 if (hcap->hca_svc_cnt != 0) {
967 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
968 "Active services still there %d", hcap->hca_svc_cnt);
969 hcap->hca_state = IBCM_HCA_ACTIVE;
970 return (IBCM_FAILURE);
971 }
972
973 if (ibcm_check_sidr_clean(hcap) != IBCM_SUCCESS) {
974 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach:"
975 "There are active SIDR operations");
976 hcap->hca_state = IBCM_HCA_ACTIVE;
977 return (IBCM_FAILURE);
978 }
979
980 if (ibcm_check_avl_clean(hcap) != IBCM_SUCCESS) {
981 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
982 "There are active RC connections");
983 hcap->hca_state = IBCM_HCA_ACTIVE;
984 return (IBCM_FAILURE);
985 }
986
987 /*
988 * Now, wait until all rc and sidr stateps go away
989 * All these stateps must be short lived ones, waiting to be cleaned
990 * up after some timeout value, based on the current state.
991 */
992 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach:hca_guid = 0x%llX res_cnt = %d",
993 hcap->hca_guid, hcap->hca_res_cnt);
994
995 while (hcap->hca_res_cnt > 0)
996 cv_wait(&ibcm_global_hca_cv, &ibcm_global_hca_lock);
997
998 /* Re-assert the while loop step above */
999 ASSERT(hcap->hca_sidr_list == NULL);
1000 avl_destroy(&hcap->hca_active_tree);
1001 avl_destroy(&hcap->hca_passive_tree);
1002 avl_destroy(&hcap->hca_passive_comid_tree);
1003
1004 /*
1005 * Unregister all ports from IBMA
1006 * If there is a failure, re-initialize any free'd ibma handles. This
1007 * is required to receive the incoming mads
1008 */
1009 status = IBCM_SUCCESS;
1010 for (port_index = 0; port_index < hcap->hca_num_ports; port_index++) {
1011 if ((status = ibcm_hca_fini_port(hcap, port_index)) !=
1012 IBCM_SUCCESS) {
1013 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
1014 "Failed to free IBMA Handle for port_num %d",
1015 port_index + 1);
1016 break;
1017 }
1018 }
1019
1020 /* If detach fails, re-initialize ibma handles for incoming mads */
1021 if (status != IBCM_SUCCESS) {
1022 for (i = 0; i < port_index; i++) {
1023 if (ibcm_hca_init_port(hcap, i) != IBT_SUCCESS)
1024 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_detach: "
1025 "Failed to re-allocate IBMA Handles for"
1026 " port_num %d", port_index + 1);
1027 }
1028 hcap->hca_state = IBCM_HCA_ACTIVE;
1029 return (IBCM_FAILURE);
1030 }
1031
1032 ibcm_fini_hca_ids(hcap);
1033 ibcm_delete_hca_entry(hcap);
1034
1035 IBTF_DPRINTF_L3(cmlog, "ibcm_hca_detach: DETACH succeeded");
1036 return (IBCM_SUCCESS);
1037 }
1038
1039 /* Checks, if there are any active sidr state entries in the specified hca */
1040 static ibcm_status_t
1041 ibcm_check_sidr_clean(ibcm_hca_info_t *hcap)
1042 {
1043 ibcm_ud_state_data_t *usp;
1044 uint32_t transient_cnt = 0;
1045
1046 IBTF_DPRINTF_L5(cmlog, "ibcm_check_sidr_clean:");
1047
1048 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
1049 usp = hcap->hca_sidr_list; /* Point to the list */
1050 while (usp != NULL) {
1051 mutex_enter(&usp->ud_state_mutex);
1052 if ((usp->ud_state != IBCM_STATE_SIDR_REP_SENT) &&
1053 (usp->ud_state != IBCM_STATE_TIMED_OUT) &&
1054 (usp->ud_state != IBCM_STATE_DELETE)) {
1055
1056 IBTF_DPRINTF_L3(cmlog, "ibcm_check_sidr_clean:"
1057 "usp = %p not in transient state = %d", usp,
1058 usp->ud_state);
1059
1060 mutex_exit(&usp->ud_state_mutex);
1061 rw_exit(&hcap->hca_sidr_list_lock);
1062 return (IBCM_FAILURE);
1063 } else {
1064 mutex_exit(&usp->ud_state_mutex);
1065 ++transient_cnt;
1066 }
1067
1068 usp = usp->ud_nextp;
1069 }
1070 rw_exit(&hcap->hca_sidr_list_lock);
1071
1072 IBTF_DPRINTF_L4(cmlog, "ibcm_check_sidr_clean: transient_cnt %d",
1073 transient_cnt);
1074
1075 return (IBCM_SUCCESS);
1076 }
1077
1078 /* Checks, if there are any active rc state entries, in the specified hca */
1079 static ibcm_status_t
1080 ibcm_check_avl_clean(ibcm_hca_info_t *hcap)
1081
1082 {
1083 ibcm_state_data_t *sp;
1084 avl_tree_t *avl_tree;
1085 uint32_t transient_cnt = 0;
1086
1087 IBTF_DPRINTF_L5(cmlog, "ibcm_check_avl_clean:");
1088 /*
1089 * Both the trees ie., active and passive must reference to all
1090 * statep's, so let's use one
1091 */
1092 avl_tree = &hcap->hca_active_tree;
1093
1094 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
1095
1096 for (sp = avl_first(avl_tree); sp != NULL;
1097 sp = avl_walk(avl_tree, sp, AVL_AFTER)) {
1098 mutex_enter(&sp->state_mutex);
1099 if ((sp->state != IBCM_STATE_TIMEWAIT) &&
1100 (sp->state != IBCM_STATE_REJ_SENT) &&
1101 (sp->state != IBCM_STATE_DELETE)) {
1102 IBTF_DPRINTF_L3(cmlog, "ibcm_check_avl_clean: "
1103 "sp = %p not in transient state = %d", sp,
1104 sp->state);
1105 mutex_exit(&sp->state_mutex);
1106 rw_exit(&hcap->hca_state_rwlock);
1107 return (IBCM_FAILURE);
1108 } else {
1109 mutex_exit(&sp->state_mutex);
1110 ++transient_cnt;
1111 }
1112 }
1113
1114 rw_exit(&hcap->hca_state_rwlock);
1115
1116 IBTF_DPRINTF_L4(cmlog, "ibcm_check_avl_clean: transient_cnt %d",
1117 transient_cnt);
1118
1119 return (IBCM_SUCCESS);
1120 }
1121
1122 /* Adds a new entry into CM's global hca list, if hca_guid is not there yet */
1123 static ibcm_hca_info_t *
1124 ibcm_add_hca_entry(ib_guid_t hcaguid, uint_t nports)
1125 {
1126 ibcm_hca_info_t *hcap;
1127
1128 IBTF_DPRINTF_L5(cmlog, "ibcm_add_hca_entry: guid = 0x%llX",
1129 hcaguid);
1130
1131 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
1132
1133 /*
1134 * Check if this hca_guid already in the list
1135 * If yes, then ignore this and return NULL
1136 */
1137
1138 hcap = ibcm_hca_listp;
1139
1140 /* search for this HCA */
1141 while (hcap != NULL) {
1142 if (hcap->hca_guid == hcaguid) {
1143 /* already exists */
1144 IBTF_DPRINTF_L2(cmlog, "ibcm_add_hca_entry: "
1145 "hcap %p guid 0x%llX, entry already exists !!",
1146 hcap, hcap->hca_guid);
1147 return (NULL);
1148 }
1149 hcap = hcap->hca_next;
1150 }
1151
1152 /* Allocate storage for the new HCA entry found */
1153 hcap = kmem_zalloc(sizeof (ibcm_hca_info_t) +
1154 (nports - 1) * sizeof (ibcm_port_info_t), KM_SLEEP);
1155
1156 /* initialize RW lock */
1157 rw_init(&hcap->hca_state_rwlock, NULL, RW_DRIVER, NULL);
1158 /* initialize SIDR list lock */
1159 rw_init(&hcap->hca_sidr_list_lock, NULL, RW_DRIVER, NULL);
1160 /* Insert "hcap" into the global HCA list maintained by CM */
1161 hcap->hca_next = ibcm_hca_listp;
1162 ibcm_hca_listp = hcap;
1163
1164 IBTF_DPRINTF_L5(cmlog, "ibcm_add_hca_entry: done hcap = 0x%p", hcap);
1165
1166 return (hcap);
1167
1168 }
1169
1170 /* deletes the given ibcm_hca_info_t from CM's global hca list */
1171 void
1172 ibcm_delete_hca_entry(ibcm_hca_info_t *hcap)
1173 {
1174 ibcm_hca_info_t *headp, *prevp = NULL;
1175
1176 /* ibcm_hca_global_lock is held */
1177 IBTF_DPRINTF_L5(cmlog, "ibcm_delete_hca_entry: guid = 0x%llX "
1178 "hcap = 0x%p", hcap->hca_guid, hcap);
1179
1180 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
1181
1182 headp = ibcm_hca_listp;
1183 while (headp != NULL) {
1184 if (headp == hcap) {
1185 IBTF_DPRINTF_L3(cmlog, "ibcm_delete_hca_entry: "
1186 "deleting hcap %p hcaguid %llX", hcap,
1187 hcap->hca_guid);
1188 if (prevp) {
1189 prevp->hca_next = headp->hca_next;
1190 } else {
1191 prevp = headp->hca_next;
1192 ibcm_hca_listp = prevp;
1193 }
1194 rw_destroy(&hcap->hca_state_rwlock);
1195 rw_destroy(&hcap->hca_sidr_list_lock);
1196 kmem_free(hcap, sizeof (ibcm_hca_info_t) +
1197 (hcap->hca_num_ports - 1) *
1198 sizeof (ibcm_port_info_t));
1199 return;
1200 }
1201
1202 prevp = headp;
1203 headp = headp->hca_next;
1204 }
1205 }
1206
1207 /*
1208 * ibcm_find_hca_entry:
1209 * Given a HCA's GUID find out ibcm_hca_info_t entry for that HCA
1210 * This entry can be then used to access AVL tree/SIDR list etc.
1211 * If entry exists and in HCA ATTACH state, then hca's ref cnt is
1212 * incremented and entry returned. Else NULL returned.
1213 *
1214 * All functions that use ibcm_find_hca_entry and get a non-NULL
1215 * return values must call ibcm_dec_hca_acc_cnt to decrement the
1216 * respective hca ref cnt. There shouldn't be any usage of
1217 * ibcm_hca_info_t * returned from ibcm_find_hca_entry,
1218 * after decrementing the hca_acc_cnt
1219 *
1220 * INPUTS:
1221 * hca_guid - HCA's guid
1222 *
1223 * RETURN VALUE:
1224 * hcap - if a match is found, else NULL
1225 */
1226 ibcm_hca_info_t *
1227 ibcm_find_hca_entry(ib_guid_t hca_guid)
1228 {
1229 ibcm_hca_info_t *hcap;
1230
1231 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hca_entry: guid = 0x%llX", hca_guid);
1232
1233 mutex_enter(&ibcm_global_hca_lock);
1234
1235 hcap = ibcm_hca_listp;
1236 /* search for this HCA */
1237 while (hcap != NULL) {
1238 if (hcap->hca_guid == hca_guid)
1239 break;
1240 hcap = hcap->hca_next;
1241 }
1242
1243 /* if no hcap for the hca_guid, return NULL */
1244 if (hcap == NULL) {
1245 mutex_exit(&ibcm_global_hca_lock);
1246 return (NULL);
1247 }
1248
1249 /* return hcap, only if it valid to use */
1250 if (hcap->hca_state == IBCM_HCA_ACTIVE) {
1251 ++(hcap->hca_acc_cnt);
1252
1253 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hca_entry: "
1254 "found hcap = 0x%p hca_acc_cnt %u", hcap,
1255 hcap->hca_acc_cnt);
1256
1257 mutex_exit(&ibcm_global_hca_lock);
1258 return (hcap);
1259 } else {
1260 mutex_exit(&ibcm_global_hca_lock);
1261
1262 IBTF_DPRINTF_L2(cmlog, "ibcm_find_hca_entry: "
1263 "found hcap = 0x%p not in active state", hcap);
1264 return (NULL);
1265 }
1266 }
1267
1268 /*
1269 * Searches for ibcm_hca_info_t entry based on hca_guid, but doesn't increment
1270 * the hca's reference count. This function is used, where the calling context
1271 * is attempting to delete hcap itself and hence acc_cnt cannot be incremented
1272 * OR assumes that valid hcap must be available in ibcm's global hca list.
1273 */
1274 ibcm_hca_info_t *
1275 ibcm_find_hcap_entry(ib_guid_t hca_guid)
1276 {
1277 ibcm_hca_info_t *hcap;
1278
1279 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hcap_entry: guid = 0x%llX", hca_guid);
1280
1281 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
1282
1283 hcap = ibcm_hca_listp;
1284 /* search for this HCA */
1285 while (hcap != NULL) {
1286 if (hcap->hca_guid == hca_guid)
1287 break;
1288 hcap = hcap->hca_next;
1289 }
1290
1291 if (hcap == NULL)
1292 IBTF_DPRINTF_L2(cmlog, "ibcm_find_hcap_entry: No hcap found for"
1293 " hca_guid 0x%llX", hca_guid);
1294 else
1295 IBTF_DPRINTF_L5(cmlog, "ibcm_find_hcap_entry: hcap found for"
1296 " hca_guid 0x%llX", hca_guid);
1297
1298 return (hcap);
1299 }
1300
1301 /* increment the hca's temporary reference count */
1302 ibcm_status_t
1303 ibcm_inc_hca_acc_cnt(ibcm_hca_info_t *hcap)
1304 {
1305 mutex_enter(&ibcm_global_hca_lock);
1306 if (hcap->hca_state == IBCM_HCA_ACTIVE) {
1307 ++(hcap->hca_acc_cnt);
1308 IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_acc_cnt: "
1309 "hcap = 0x%p acc_cnt = %d ", hcap, hcap->hca_acc_cnt);
1310 mutex_exit(&ibcm_global_hca_lock);
1311 return (IBCM_SUCCESS);
1312 } else {
1313 IBTF_DPRINTF_L2(cmlog, "ibcm_inc_hca_acc_cnt: "
1314 "hcap INACTIVE 0x%p acc_cnt = %d ", hcap,
1315 hcap->hca_acc_cnt);
1316 mutex_exit(&ibcm_global_hca_lock);
1317 return (IBCM_FAILURE);
1318 }
1319 }
1320
1321 /* decrement the hca's ref count, and wake up any waiting threads */
1322 void
1323 ibcm_dec_hca_acc_cnt(ibcm_hca_info_t *hcap)
1324 {
1325 mutex_enter(&ibcm_global_hca_lock);
1326 ASSERT(hcap->hca_acc_cnt > 0);
1327 --(hcap->hca_acc_cnt);
1328 IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_acc_cnt: hcap = 0x%p "
1329 "acc_cnt = %d", hcap, hcap->hca_acc_cnt);
1330 if ((hcap->hca_state == IBCM_HCA_NOT_ACTIVE) &&
1331 (hcap->hca_acc_cnt == 0)) {
1332 IBTF_DPRINTF_L3(cmlog, "ibcm_dec_hca_acc_cnt: "
1333 "cv_broadcast for hcap = 0x%p", hcap);
1334 cv_broadcast(&ibcm_global_hca_cv);
1335 }
1336 mutex_exit(&ibcm_global_hca_lock);
1337 }
1338
1339 /* increment the hca's resource count */
1340 void
1341 ibcm_inc_hca_res_cnt(ibcm_hca_info_t *hcap)
1342
1343 {
1344 mutex_enter(&ibcm_global_hca_lock);
1345 ++(hcap->hca_res_cnt);
1346 IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_res_cnt: hcap = 0x%p "
1347 "ref_cnt = %d", hcap, hcap->hca_res_cnt);
1348 mutex_exit(&ibcm_global_hca_lock);
1349 }
1350
1351 /* decrement the hca's resource count, and wake up any waiting threads */
1352 void
1353 ibcm_dec_hca_res_cnt(ibcm_hca_info_t *hcap)
1354 {
1355 mutex_enter(&ibcm_global_hca_lock);
1356 ASSERT(hcap->hca_res_cnt > 0);
1357 --(hcap->hca_res_cnt);
1358 IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_res_cnt: hcap = 0x%p "
1359 "ref_cnt = %d", hcap, hcap->hca_res_cnt);
1360 if ((hcap->hca_state == IBCM_HCA_NOT_ACTIVE) &&
1361 (hcap->hca_res_cnt == 0)) {
1362 IBTF_DPRINTF_L3(cmlog, "ibcm_dec_hca_res_cnt: "
1363 "cv_broadcast for hcap = 0x%p", hcap);
1364 cv_broadcast(&ibcm_global_hca_cv);
1365 }
1366 mutex_exit(&ibcm_global_hca_lock);
1367 }
1368
1369 /* increment the hca's service count */
1370 void
1371 ibcm_inc_hca_svc_cnt(ibcm_hca_info_t *hcap)
1372
1373 {
1374 mutex_enter(&ibcm_global_hca_lock);
1375 ++(hcap->hca_svc_cnt);
1376 IBTF_DPRINTF_L5(cmlog, "ibcm_inc_hca_svc_cnt: hcap = 0x%p "
1377 "svc_cnt = %d", hcap, hcap->hca_svc_cnt);
1378 mutex_exit(&ibcm_global_hca_lock);
1379 }
1380
1381 /* decrement the hca's service count */
1382 void
1383 ibcm_dec_hca_svc_cnt(ibcm_hca_info_t *hcap)
1384 {
1385 mutex_enter(&ibcm_global_hca_lock);
1386 ASSERT(hcap->hca_svc_cnt > 0);
1387 --(hcap->hca_svc_cnt);
1388 IBTF_DPRINTF_L5(cmlog, "ibcm_dec_hca_svc_cnt: hcap = 0x%p "
1389 "svc_cnt = %d", hcap, hcap->hca_svc_cnt);
1390 mutex_exit(&ibcm_global_hca_lock);
1391 }
1392
1393 /*
1394 * The following code manages three classes of requests that CM makes to
1395 * the fabric. Those three classes are SA_ACCESS, REQ/REP/RTU, and DREQ/DREP.
1396 * The main issue is that the fabric can become very busy, and the CM
1397 * protocols rely on responses being made based on a predefined timeout
1398 * value. By managing how many simultaneous sessions are allowed, there
1399 * is observed extremely high reliability of CM protocol succeeding when
1400 * it should.
1401 *
1402 * SA_ACCESS and DREQ/DREP are managed at the thread level, whereby the
1403 * thread blocks until there are less than some number of threads doing
1404 * similar requests.
1405 *
1406 * REQ/REP/RTU requests beyond a given limit are added to a list,
1407 * allowing the thread to return immediately to its caller in the
1408 * case where the "mode" is IBT_NONBLOCKING. This is the mode used
1409 * by uDAPL and seems to be an important feature/behavior.
1410 */
1411
1412 static int
1413 ibcm_ok_to_start(struct ibcm_open_s *openp)
1414 {
1415 return (openp->sends < openp->sends_hiwat &&
1416 openp->in_progress < openp->in_progress_max);
1417 }
1418
1419 void
1420 ibcm_open_done(ibcm_state_data_t *statep)
1421 {
1422 int run;
1423 ibcm_state_data_t **linkp, *tmp;
1424
1425 ASSERT(MUTEX_HELD(&statep->state_mutex));
1426 if (statep->open_flow == 1) {
1427 statep->open_flow = 0;
1428 mutex_enter(&ibcm_open.mutex);
1429 if (statep->open_link == NULL) {
1430 ibcm_open.in_progress--;
1431 run = ibcm_ok_to_start(&ibcm_open);
1432 } else {
1433 ibcm_open.queued--;
1434 linkp = &ibcm_open.head.open_link;
1435 while (*linkp != statep)
1436 linkp = &((*linkp)->open_link);
1437 *linkp = statep->open_link;
1438 statep->open_link = NULL;
1439 /*
1440 * If we remove what tail pointed to, we need
1441 * to reassign tail (it is never NULL).
1442 * tail points to head for the empty list.
1443 */
1444 if (ibcm_open.tail == statep) {
1445 tmp = &ibcm_open.head;
1446 while (tmp->open_link != &ibcm_open.head)
1447 tmp = tmp->open_link;
1448 ibcm_open.tail = tmp;
1449 }
1450 run = 0;
1451 }
1452 mutex_exit(&ibcm_open.mutex);
1453 if (run)
1454 ibcm_run_tlist_thread();
1455 }
1456 }
1457
1458 /* dtrace */
1459 void
1460 ibcm_open_wait(hrtime_t delta)
1461 {
1462 if (delta > 1000000)
1463 IBTF_DPRINTF_L2(cmlog, "ibcm_open_wait: flow more %lld", delta);
1464 }
1465
1466 void
1467 ibcm_open_start(ibcm_state_data_t *statep)
1468 {
1469 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REQ);
1470
1471 mutex_enter(&statep->state_mutex);
1472 ibcm_open_wait(gethrtime() - statep->post_time);
1473 mutex_exit(&statep->state_mutex);
1474
1475 ibcm_post_rc_mad(statep, statep->stored_msg, ibcm_post_req_complete,
1476 statep);
1477
1478 mutex_enter(&statep->state_mutex);
1479 IBCM_REF_CNT_DECR(statep);
1480 mutex_exit(&statep->state_mutex);
1481 }
1482
1483 void
1484 ibcm_open_enqueue(ibcm_state_data_t *statep)
1485 {
1486 int run;
1487
1488 mutex_enter(&statep->state_mutex);
1489 statep->post_time = gethrtime();
1490 mutex_exit(&statep->state_mutex);
1491 mutex_enter(&ibcm_open.mutex);
1492 if (ibcm_open.queued == 0 && ibcm_ok_to_start(&ibcm_open)) {
1493 ibcm_open.in_progress++;
1494 mutex_exit(&ibcm_open.mutex);
1495 ibcm_open_start(statep);
1496 } else {
1497 ibcm_open.queued++;
1498 statep->open_link = &ibcm_open.head;
1499 ibcm_open.tail->open_link = statep;
1500 ibcm_open.tail = statep;
1501 run = ibcm_ok_to_start(&ibcm_open);
1502 mutex_exit(&ibcm_open.mutex);
1503 if (run)
1504 ibcm_run_tlist_thread();
1505 }
1506 }
1507
1508 ibcm_state_data_t *
1509 ibcm_open_dequeue(void)
1510 {
1511 ibcm_state_data_t *statep;
1512
1513 ASSERT(MUTEX_HELD(&ibcm_open.mutex));
1514 ibcm_open.queued--;
1515 ibcm_open.in_progress++;
1516 statep = ibcm_open.head.open_link;
1517 ibcm_open.head.open_link = statep->open_link;
1518 statep->open_link = NULL;
1519 /*
1520 * If we remove what tail pointed to, we need
1521 * to reassign tail (it is never NULL).
1522 * tail points to head for the empty list.
1523 */
1524 if (ibcm_open.tail == statep)
1525 ibcm_open.tail = &ibcm_open.head;
1526 return (statep);
1527 }
1528
1529 void
1530 ibcm_check_for_opens(void)
1531 {
1532 ibcm_state_data_t *statep;
1533
1534 mutex_enter(&ibcm_open.mutex);
1535
1536 while (ibcm_open.queued > 0) {
1537 if (ibcm_ok_to_start(&ibcm_open)) {
1538 statep = ibcm_open_dequeue();
1539 mutex_exit(&ibcm_open.mutex);
1540
1541 ibcm_open_start(statep);
1542
1543 mutex_enter(&ibcm_open.mutex);
1544 } else {
1545 break;
1546 }
1547 }
1548 mutex_exit(&ibcm_open.mutex);
1549 }
1550
1551
1552 static void
1553 ibcm_flow_init(ibcm_flow_t *flow, uint_t simul_max)
1554 {
1555 flow->list = NULL;
1556 flow->simul = 0;
1557 flow->waiters_per_chunk = 4;
1558 flow->simul_max = simul_max;
1559 flow->lowat = simul_max - flow->waiters_per_chunk;
1560 flow->lowat_default = flow->lowat;
1561 /* stats */
1562 flow->total = 0;
1563 }
1564
1565 static void
1566 ibcm_rc_flow_control_init(void)
1567 {
1568 mutex_init(&ibcm_open.mutex, NULL, MUTEX_DEFAULT, NULL);
1569 mutex_enter(&ibcm_open.mutex);
1570 ibcm_flow_init(&ibcm_close_flow, ibcm_close_simul_max);
1571 ibcm_flow_init(&ibcm_lapr_flow, ibcm_lapr_simul_max);
1572 ibcm_flow_init(&ibcm_saa_flow, ibcm_saa_simul_max);
1573
1574 ibcm_open.queued = 0;
1575 ibcm_open.exit_deferred = 0;
1576 ibcm_open.in_progress = 0;
1577 ibcm_open.in_progress_max = 16;
1578 ibcm_open.sends = 0;
1579 ibcm_open.sends_max = 0;
1580 ibcm_open.sends_lowat = 8;
1581 ibcm_open.sends_hiwat = 16;
1582 ibcm_open.tail = &ibcm_open.head;
1583 ibcm_open.head.open_link = NULL;
1584 mutex_exit(&ibcm_open.mutex);
1585
1586 mutex_init(&ibcm_close.mutex, NULL, MUTEX_DEFAULT, NULL);
1587 mutex_enter(&ibcm_close.mutex);
1588 ibcm_close.tail = &ibcm_close.head;
1589 ibcm_close.head.close_link = NULL;
1590 mutex_exit(&ibcm_close.mutex);
1591 }
1592
1593 static void
1594 ibcm_rc_flow_control_fini(void)
1595 {
1596 mutex_destroy(&ibcm_open.mutex);
1597 mutex_destroy(&ibcm_close.mutex);
1598 }
1599
1600 static ibcm_flow1_t *
1601 ibcm_flow_find(ibcm_flow_t *flow)
1602 {
1603 ibcm_flow1_t *flow1;
1604 ibcm_flow1_t *f;
1605
1606 f = flow->list;
1607 if (f) { /* most likely code path */
1608 while (f->link != NULL)
1609 f = f->link;
1610 if (f->waiters < flow->waiters_per_chunk)
1611 return (f);
1612 }
1613
1614 /* There was no flow1 list element ready for another waiter */
1615 mutex_exit(&ibcm_open.mutex);
1616 flow1 = kmem_alloc(sizeof (*flow1), KM_SLEEP);
1617 mutex_enter(&ibcm_open.mutex);
1618
1619 f = flow->list;
1620 if (f) {
1621 while (f->link != NULL)
1622 f = f->link;
1623 if (f->waiters < flow->waiters_per_chunk) {
1624 kmem_free(flow1, sizeof (*flow1));
1625 return (f);
1626 }
1627 f->link = flow1;
1628 } else {
1629 flow->list = flow1;
1630 }
1631 cv_init(&flow1->cv, NULL, CV_DRIVER, NULL);
1632 flow1->waiters = 0;
1633 flow1->link = NULL;
1634 return (flow1);
1635 }
1636
1637 static void
1638 ibcm_flow_enter(ibcm_flow_t *flow)
1639 {
1640 mutex_enter(&ibcm_open.mutex);
1641 if (flow->list == NULL && flow->simul < flow->simul_max) {
1642 flow->simul++;
1643 flow->total++;
1644 mutex_exit(&ibcm_open.mutex);
1645 } else {
1646 ibcm_flow1_t *flow1;
1647
1648 flow1 = ibcm_flow_find(flow);
1649 flow1->waiters++;
1650 cv_wait(&flow1->cv, &ibcm_open.mutex);
1651 if (--flow1->waiters == 0) {
1652 cv_destroy(&flow1->cv);
1653 mutex_exit(&ibcm_open.mutex);
1654 kmem_free(flow1, sizeof (*flow1));
1655 } else
1656 mutex_exit(&ibcm_open.mutex);
1657 }
1658 }
1659
1660 static void
1661 ibcm_flow_exit(ibcm_flow_t *flow)
1662 {
1663 mutex_enter(&ibcm_open.mutex);
1664 if (--flow->simul < flow->lowat) {
1665 if (flow->lowat < flow->lowat_default)
1666 flow->lowat++;
1667 if (flow->list) {
1668 ibcm_flow1_t *flow1;
1669
1670 flow1 = flow->list;
1671 flow->list = flow1->link; /* unlink */
1672 flow1->link = NULL; /* be clean */
1673 flow->total += flow1->waiters;
1674 flow->simul += flow1->waiters;
1675 cv_broadcast(&flow1->cv);
1676 }
1677 }
1678 mutex_exit(&ibcm_open.mutex);
1679 }
1680
1681 void
1682 ibcm_flow_inc(void)
1683 {
1684 mutex_enter(&ibcm_open.mutex);
1685 if (++ibcm_open.sends > ibcm_open.sends_max) {
1686 ibcm_open.sends_max = ibcm_open.sends;
1687 IBTF_DPRINTF_L2(cmlog, "ibcm_flow_inc: sends max = %d",
1688 ibcm_open.sends_max);
1689 }
1690 mutex_exit(&ibcm_open.mutex);
1691 }
1692
1693 static void
1694 ibcm_check_send_cmpltn_time(hrtime_t delta, char *event_msg)
1695 {
1696 if (delta > 4000000LL) {
1697 IBTF_DPRINTF_L2(cmlog, "ibcm_check_send_cmpltn_time: "
1698 "%s: %lldns", event_msg, delta);
1699 }
1700 }
1701
1702 void
1703 ibcm_flow_dec(hrtime_t time, char *mad_type)
1704 {
1705 int flow_exit = 0;
1706 int run = 0;
1707
1708 if (ibcm_dtrace)
1709 ibcm_check_send_cmpltn_time(gethrtime() - time, mad_type);
1710 mutex_enter(&ibcm_open.mutex);
1711 ibcm_open.sends--;
1712 if (ibcm_open.sends < ibcm_open.sends_lowat) {
1713 run = ibcm_ok_to_start(&ibcm_open);
1714 if (ibcm_open.exit_deferred) {
1715 ibcm_open.exit_deferred--;
1716 flow_exit = 1;
1717 }
1718 }
1719 mutex_exit(&ibcm_open.mutex);
1720 if (flow_exit)
1721 ibcm_flow_exit(&ibcm_close_flow);
1722 if (run)
1723 ibcm_run_tlist_thread();
1724 }
1725
1726 void
1727 ibcm_close_enqueue(ibcm_state_data_t *statep)
1728 {
1729 mutex_enter(&ibcm_close.mutex);
1730 statep->close_link = NULL;
1731 ibcm_close.tail->close_link = statep;
1732 ibcm_close.tail = statep;
1733 mutex_exit(&ibcm_close.mutex);
1734 ibcm_run_tlist_thread();
1735 }
1736
1737 void
1738 ibcm_check_for_async_close()
1739 {
1740 ibcm_state_data_t *statep;
1741
1742 mutex_enter(&ibcm_close.mutex);
1743
1744 while (ibcm_close.head.close_link) {
1745 statep = ibcm_close.head.close_link;
1746 ibcm_close.head.close_link = statep->close_link;
1747 statep->close_link = NULL;
1748 if (ibcm_close.tail == statep)
1749 ibcm_close.tail = &ibcm_close.head;
1750 mutex_exit(&ibcm_close.mutex);
1751 ibcm_close_start(statep);
1752 mutex_enter(&ibcm_close.mutex);
1753 }
1754 mutex_exit(&ibcm_close.mutex);
1755 }
1756
1757 void
1758 ibcm_close_enter(void)
1759 {
1760 ibcm_flow_enter(&ibcm_close_flow);
1761 }
1762
1763 void
1764 ibcm_close_exit(void)
1765 {
1766 int flow_exit;
1767
1768 mutex_enter(&ibcm_open.mutex);
1769 if (ibcm_open.sends < ibcm_open.sends_lowat ||
1770 ibcm_open.exit_deferred >= 4)
1771 flow_exit = 1;
1772 else {
1773 flow_exit = 0;
1774 ibcm_open.exit_deferred++;
1775 }
1776 mutex_exit(&ibcm_open.mutex);
1777 if (flow_exit)
1778 ibcm_flow_exit(&ibcm_close_flow);
1779 }
1780
1781 /*
1782 * This function needs to be called twice to finish our flow
1783 * control accounting when closing down a connection. One
1784 * call has send_done set to 1, while the other has it set to 0.
1785 * Because of retries, this could get called more than once
1786 * with either 0 or 1, but additional calls have no effect.
1787 */
1788 void
1789 ibcm_close_done(ibcm_state_data_t *statep, int send_done)
1790 {
1791 int flow_exit;
1792
1793 ASSERT(MUTEX_HELD(&statep->state_mutex));
1794 if (statep->close_flow == 1) {
1795 if (send_done)
1796 statep->close_flow = 3;
1797 else
1798 statep->close_flow = 2;
1799 } else if ((send_done && statep->close_flow == 2) ||
1800 (!send_done && statep->close_flow == 3)) {
1801 statep->close_flow = 0;
1802 mutex_enter(&ibcm_open.mutex);
1803 if (ibcm_open.sends < ibcm_open.sends_lowat ||
1804 ibcm_open.exit_deferred >= 4)
1805 flow_exit = 1;
1806 else {
1807 flow_exit = 0;
1808 ibcm_open.exit_deferred++;
1809 }
1810 mutex_exit(&ibcm_open.mutex);
1811 if (flow_exit)
1812 ibcm_flow_exit(&ibcm_close_flow);
1813 }
1814 }
1815
1816 void
1817 ibcm_lapr_enter(void)
1818 {
1819 ibcm_flow_enter(&ibcm_lapr_flow);
1820 }
1821
1822 void
1823 ibcm_lapr_exit(void)
1824 {
1825 ibcm_flow_exit(&ibcm_lapr_flow);
1826 }
1827
1828 void
1829 ibcm_sa_access_enter()
1830 {
1831 ibcm_flow_enter(&ibcm_saa_flow);
1832 }
1833
1834 void
1835 ibcm_sa_access_exit()
1836 {
1837 ibcm_flow_exit(&ibcm_saa_flow);
1838 }
1839
1840 static void
1841 ibcm_sm_notice_handler(ibmf_saa_handle_t saa_handle,
1842 ibmf_saa_subnet_event_t saa_event_code,
1843 ibmf_saa_event_details_t *saa_event_details,
1844 void *callback_arg)
1845 {
1846 ibcm_port_info_t *portp = (ibcm_port_info_t *)callback_arg;
1847 ibt_subnet_event_code_t code;
1848 ibt_subnet_event_t event;
1849 uint8_t event_status;
1850
1851 IBTF_DPRINTF_L3(cmlog, "ibcm_sm_notice_handler: saa_hdl %p, code = %d",
1852 saa_handle, saa_event_code);
1853
1854 mutex_enter(&ibcm_sm_notice_serialize_lock);
1855
1856 switch (saa_event_code) {
1857 case IBMF_SAA_EVENT_MCG_CREATED:
1858 code = IBT_SM_EVENT_MCG_CREATED;
1859 break;
1860 case IBMF_SAA_EVENT_MCG_DELETED:
1861 code = IBT_SM_EVENT_MCG_DELETED;
1862 break;
1863 case IBMF_SAA_EVENT_GID_AVAILABLE:
1864 code = IBT_SM_EVENT_GID_AVAIL;
1865 ibcm_path_cache_purge();
1866 break;
1867 case IBMF_SAA_EVENT_GID_UNAVAILABLE:
1868 code = IBT_SM_EVENT_GID_UNAVAIL;
1869 ibcm_path_cache_purge();
1870 break;
1871 case IBMF_SAA_EVENT_SUBSCRIBER_STATUS_CHG:
1872 event_status =
1873 saa_event_details->ie_producer_event_status_mask &
1874 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM;
1875 if (event_status == (portp->port_event_status &
1876 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)) {
1877 mutex_exit(&ibcm_sm_notice_serialize_lock);
1878 return; /* no change */
1879 }
1880 portp->port_event_status = event_status;
1881 if (event_status == IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM)
1882 code = IBT_SM_EVENT_AVAILABLE;
1883 else
1884 code = IBT_SM_EVENT_UNAVAILABLE;
1885 break;
1886 default:
1887 mutex_exit(&ibcm_sm_notice_serialize_lock);
1888 return;
1889 }
1890
1891 mutex_enter(&ibcm_global_hca_lock);
1892
1893 /* don't send the event if we're tearing down */
1894 if (!IBCM_ACCESS_HCA_OK(portp->port_hcap)) {
1895 mutex_exit(&ibcm_global_hca_lock);
1896 mutex_exit(&ibcm_sm_notice_serialize_lock);
1897 return;
1898 }
1899
1900 ++(portp->port_hcap->hca_acc_cnt);
1901 mutex_exit(&ibcm_global_hca_lock);
1902
1903 event.sm_notice_gid = saa_event_details->ie_gid;
1904 ibtl_cm_sm_notice_handler(portp->port_sgid0, code, &event);
1905
1906 mutex_exit(&ibcm_sm_notice_serialize_lock);
1907
1908 ibcm_dec_hca_acc_cnt(portp->port_hcap);
1909 }
1910
1911 void
1912 ibt_register_subnet_notices(ibt_clnt_hdl_t ibt_hdl,
1913 ibt_sm_notice_handler_t sm_notice_handler, void *private)
1914 {
1915 ibcm_port_info_t *portp;
1916 ibcm_hca_info_t *hcap;
1917 uint8_t port;
1918 int num_failed_sgids;
1919 ibtl_cm_sm_init_fail_t *ifail;
1920 ib_gid_t *sgidp;
1921
1922 IBTF_DPRINTF_L3(cmlog, "ibt_register_subnet_notices(%p, %s)",
1923 ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl));
1924
1925 mutex_enter(&ibcm_sm_notice_serialize_lock);
1926
1927 ibtl_cm_set_sm_notice_handler(ibt_hdl, sm_notice_handler, private);
1928 if (sm_notice_handler == NULL) {
1929 mutex_exit(&ibcm_sm_notice_serialize_lock);
1930 return;
1931 }
1932
1933 /* for each port, if service is not available, make a call */
1934 mutex_enter(&ibcm_global_hca_lock);
1935 num_failed_sgids = 0;
1936 hcap = ibcm_hca_listp;
1937 while (hcap != NULL) {
1938 portp = hcap->hca_port_info;
1939 for (port = 0; port < hcap->hca_num_ports; port++) {
1940 if (!(portp->port_event_status &
1941 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM))
1942 num_failed_sgids++;
1943 portp++;
1944 }
1945 hcap = hcap->hca_next;
1946 }
1947 if (num_failed_sgids != 0) {
1948 ifail = kmem_alloc(sizeof (*ifail) +
1949 (num_failed_sgids - 1) * sizeof (ib_gid_t), KM_SLEEP);
1950 ifail->smf_num_sgids = num_failed_sgids;
1951 ifail->smf_ibt_hdl = ibt_hdl;
1952 sgidp = &ifail->smf_sgid[0];
1953 hcap = ibcm_hca_listp;
1954 while (hcap != NULL) {
1955 portp = hcap->hca_port_info;
1956 for (port = 0; port < hcap->hca_num_ports; port++) {
1957 if (!(portp->port_event_status &
1958 IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM))
1959 *sgidp++ = portp->port_sgid0;
1960 portp++;
1961 }
1962 hcap = hcap->hca_next;
1963 }
1964 }
1965 mutex_exit(&ibcm_global_hca_lock);
1966
1967 if (num_failed_sgids != 0) {
1968 ibtl_cm_sm_notice_init_failure(ifail);
1969 kmem_free(ifail, sizeof (*ifail) +
1970 (num_failed_sgids - 1) * sizeof (ib_gid_t));
1971 }
1972 mutex_exit(&ibcm_sm_notice_serialize_lock);
1973 }
1974
1975 /* The following is run from a taskq because we've seen the stack overflow. */
1976 static void
1977 ibcm_init_saa(void *arg)
1978 {
1979 ibcm_port_info_t *portp = (ibcm_port_info_t *)arg;
1980 int status;
1981 ib_guid_t port_guid;
1982 ibmf_saa_subnet_event_args_t event_args;
1983
1984 port_guid = portp->port_sgid0.gid_guid;
1985
1986 IBTF_DPRINTF_L3(cmlog, "ibcm_init_saa: port guid %llX", port_guid);
1987
1988 event_args.is_event_callback_arg = portp;
1989 event_args.is_event_callback = ibcm_sm_notice_handler;
1990
1991 if ((status = ibmf_sa_session_open(port_guid, 0, &event_args,
1992 IBMF_VERSION, 0, &portp->port_ibmf_saa_hdl)) != IBMF_SUCCESS) {
1993 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa: "
1994 "ibmf_sa_session_open failed for port guid %llX "
1995 "status = %d", port_guid, status);
1996 } else {
1997 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa: "
1998 "registered sa_hdl 0x%p for port guid %llX",
1999 portp->port_ibmf_saa_hdl, port_guid);
2000 }
2001
2002 mutex_enter(&ibcm_sa_open_lock);
2003 portp->port_saa_open_in_progress = 0;
2004 cv_broadcast(&ibcm_sa_open_cv);
2005 mutex_exit(&ibcm_sa_open_lock);
2006 }
2007
2008 void
2009 ibcm_init_saa_handle(ibcm_hca_info_t *hcap, uint8_t port)
2010 {
2011 ibmf_saa_handle_t saa_handle;
2012 uint8_t port_index = port - 1;
2013 ibcm_port_info_t *portp = &hcap->hca_port_info[port_index];
2014 ibt_status_t ibt_status;
2015
2016 if (port_index >= hcap->hca_num_ports)
2017 return;
2018
2019 mutex_enter(&ibcm_sa_open_lock);
2020 if (portp->port_saa_open_in_progress) {
2021 mutex_exit(&ibcm_sa_open_lock);
2022 return;
2023 }
2024
2025 saa_handle = portp->port_ibmf_saa_hdl;
2026 if (saa_handle != NULL) {
2027 mutex_exit(&ibcm_sa_open_lock);
2028 return;
2029 }
2030
2031 portp->port_saa_open_in_progress = 1;
2032 mutex_exit(&ibcm_sa_open_lock);
2033
2034 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(portp->port_event_status))
2035
2036 /* The assumption is that we're getting event notifications */
2037 portp->port_event_status = IBMF_SAA_EVENT_STATUS_MASK_PRODUCER_SM;
2038
2039 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(portp->port_event_status))
2040
2041 ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid,
2042 portp->port_num, &portp->port_sgid0, NULL);
2043 if (ibt_status != IBT_SUCCESS) {
2044 IBTF_DPRINTF_L2(cmlog, "ibcm_init_saa_handle: "
2045 "ibt_get_port_state_byguid failed for guid %llX "
2046 "with status %d", portp->port_hcap->hca_guid, ibt_status);
2047 mutex_enter(&ibcm_sa_open_lock);
2048 portp->port_saa_open_in_progress = 0;
2049 cv_broadcast(&ibcm_sa_open_cv);
2050 mutex_exit(&ibcm_sa_open_lock);
2051 return;
2052 }
2053 /* if the port is UP, try sa_session_open */
2054 (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP);
2055 }
2056
2057
2058 ibmf_saa_handle_t
2059 ibcm_get_saa_handle(ibcm_hca_info_t *hcap, uint8_t port)
2060 {
2061 ibmf_saa_handle_t saa_handle;
2062 uint8_t port_index = port - 1;
2063 ibcm_port_info_t *portp = &hcap->hca_port_info[port_index];
2064 ibt_status_t ibt_status;
2065
2066 if (port_index >= hcap->hca_num_ports)
2067 return (NULL);
2068
2069 mutex_enter(&ibcm_sa_open_lock);
2070 while (portp->port_saa_open_in_progress) {
2071 cv_wait(&ibcm_sa_open_cv, &ibcm_sa_open_lock);
2072 }
2073
2074 saa_handle = portp->port_ibmf_saa_hdl;
2075 if (saa_handle != NULL) {
2076 mutex_exit(&ibcm_sa_open_lock);
2077 return (saa_handle);
2078 }
2079
2080 portp->port_saa_open_in_progress = 1;
2081 mutex_exit(&ibcm_sa_open_lock);
2082
2083 ibt_status = ibt_get_port_state_byguid(portp->port_hcap->hca_guid,
2084 portp->port_num, &portp->port_sgid0, NULL);
2085 if (ibt_status != IBT_SUCCESS) {
2086 IBTF_DPRINTF_L2(cmlog, "ibcm_get_saa_handle: "
2087 "ibt_get_port_state_byguid failed for guid %llX "
2088 "with status %d", portp->port_hcap->hca_guid, ibt_status);
2089 mutex_enter(&ibcm_sa_open_lock);
2090 portp->port_saa_open_in_progress = 0;
2091 cv_broadcast(&ibcm_sa_open_cv);
2092 mutex_exit(&ibcm_sa_open_lock);
2093 return (NULL);
2094 }
2095 /* if the port is UP, try sa_session_open */
2096 (void) taskq_dispatch(ibcm_taskq, ibcm_init_saa, portp, TQ_SLEEP);
2097
2098 mutex_enter(&ibcm_sa_open_lock);
2099 while (portp->port_saa_open_in_progress) {
2100 cv_wait(&ibcm_sa_open_cv, &ibcm_sa_open_lock);
2101 }
2102 saa_handle = portp->port_ibmf_saa_hdl;
2103 mutex_exit(&ibcm_sa_open_lock);
2104 return (saa_handle);
2105 }
2106
2107
2108 /*
2109 * ibcm_hca_init_port():
2110 * - Register port with IBMA
2111 *
2112 * Arguments:
2113 * hcap - HCA's guid
2114 * port_index - port number minus 1
2115 *
2116 * Return values:
2117 * IBCM_SUCCESS - success
2118 */
2119 ibt_status_t
2120 ibcm_hca_init_port(ibcm_hca_info_t *hcap, uint8_t port_index)
2121 {
2122 int status;
2123 ibmf_register_info_t *ibmf_reg;
2124
2125 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_init_port: hcap = 0x%p port_num %d",
2126 hcap, port_index + 1);
2127
2128 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
2129
2130 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcap->hca_port_info))
2131
2132 if (hcap->hca_port_info[port_index].port_ibmf_hdl == NULL) {
2133 /* Register with IBMF */
2134 ibmf_reg = &hcap->hca_port_info[port_index].port_ibmf_reg;
2135 ibmf_reg->ir_ci_guid = hcap->hca_guid;
2136 ibmf_reg->ir_port_num = port_index + 1;
2137 ibmf_reg->ir_client_class = COMM_MGT_MANAGER_AGENT;
2138
2139 /*
2140 * register with management framework
2141 */
2142 status = ibmf_register(ibmf_reg, IBMF_VERSION,
2143 IBMF_REG_FLAG_NO_OFFLOAD, NULL, NULL,
2144 &(hcap->hca_port_info[port_index].port_ibmf_hdl),
2145 &(hcap->hca_port_info[port_index].port_ibmf_caps));
2146
2147 if (status != IBMF_SUCCESS) {
2148 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_init_port: "
2149 "ibmf_register failed for port_num %x, "
2150 "status = %x", port_index + 1, status);
2151 return (ibcm_ibmf_analyze_error(status));
2152 }
2153
2154 hcap->hca_port_info[port_index].port_qp1.qp_cm =
2155 IBMF_QP_HANDLE_DEFAULT;
2156 hcap->hca_port_info[port_index].port_qp1.qp_port =
2157 &(hcap->hca_port_info[port_index]);
2158
2159 /*
2160 * Register the read callback with IBMF.
2161 * Since we just did an ibmf_register, handle is
2162 * valid and ibcm_recv_cb() is valid so we can
2163 * safely assert for success of ibmf_setup_recv_cb()
2164 *
2165 * Depending on the "state" of the HCA,
2166 * CM may drop incoming packets
2167 */
2168 status = ibmf_setup_async_cb(
2169 hcap->hca_port_info[port_index].port_ibmf_hdl,
2170 IBMF_QP_HANDLE_DEFAULT, ibcm_recv_cb,
2171 &(hcap->hca_port_info[port_index].port_qp1), 0);
2172 ASSERT(status == IBMF_SUCCESS);
2173
2174 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_init_port: "
2175 "IBMF hdl[%x] = 0x%p", port_index,
2176 hcap->hca_port_info[port_index].port_ibmf_hdl);
2177
2178 /* Attempt to get the saa_handle for this port */
2179 ibcm_init_saa_handle(hcap, port_index + 1);
2180 }
2181
2182 return (IBT_SUCCESS);
2183 }
2184
2185 /*
2186 * useful, to re attempt to initialize port ibma handles from elsewhere in
2187 * cm code
2188 */
2189 ibt_status_t
2190 ibcm_hca_reinit_port(ibcm_hca_info_t *hcap, uint8_t port_index)
2191 {
2192 ibt_status_t status;
2193
2194 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_reinit_port: hcap 0x%p port_num %d",
2195 hcap, port_index + 1);
2196
2197 mutex_enter(&ibcm_global_hca_lock);
2198 status = ibcm_hca_init_port(hcap, port_index);
2199 mutex_exit(&ibcm_global_hca_lock);
2200 return (status);
2201 }
2202
2203
2204 /*
2205 * ibcm_hca_fini_port():
2206 * - Deregister port with IBMA
2207 *
2208 * Arguments:
2209 * hcap - HCA's guid
2210 * port_index - port number minus 1
2211 *
2212 * Return values:
2213 * IBCM_SUCCESS - success
2214 */
2215 static ibcm_status_t
2216 ibcm_hca_fini_port(ibcm_hca_info_t *hcap, uint8_t port_index)
2217 {
2218 int ibmf_status;
2219 ibcm_status_t ibcm_status;
2220
2221 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_fini_port: hcap = 0x%p port_num %d ",
2222 hcap, port_index + 1);
2223
2224 ASSERT(MUTEX_HELD(&ibcm_global_hca_lock));
2225
2226 if (hcap->hca_port_info[port_index].port_ibmf_saa_hdl != NULL) {
2227 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_fini_port: "
2228 "ibmf_sa_session_close IBMF SAA hdl %p",
2229 hcap->hca_port_info[port_index].port_ibmf_saa_hdl);
2230
2231 ibmf_status = ibmf_sa_session_close(
2232 &hcap->hca_port_info[port_index].port_ibmf_saa_hdl, 0);
2233 if (ibmf_status != IBMF_SUCCESS) {
2234 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
2235 "ibmf_sa_session_close of port %d returned %x",
2236 port_index + 1, ibmf_status);
2237 return (IBCM_FAILURE);
2238 }
2239 }
2240
2241 if (hcap->hca_port_info[port_index].port_ibmf_hdl != NULL) {
2242 IBTF_DPRINTF_L5(cmlog, "ibcm_hca_fini_port: "
2243 "ibmf_unregister IBMF Hdl %p",
2244 hcap->hca_port_info[port_index].port_ibmf_hdl);
2245
2246 /* clean-up all the ibmf qp's allocated on this port */
2247 ibcm_status = ibcm_free_allqps(hcap, port_index + 1);
2248
2249 if (ibcm_status != IBCM_SUCCESS) {
2250
2251 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
2252 "ibcm_free_allqps failed for port_num %d",
2253 port_index + 1);
2254 return (IBCM_FAILURE);
2255 }
2256
2257 /* Tear down the receive callback */
2258 ibmf_status = ibmf_tear_down_async_cb(
2259 hcap->hca_port_info[port_index].port_ibmf_hdl,
2260 IBMF_QP_HANDLE_DEFAULT, 0);
2261
2262 if (ibmf_status != IBMF_SUCCESS) {
2263 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
2264 "ibmf_tear_down_async_cb failed %d port_num %d",
2265 ibmf_status, port_index + 1);
2266 return (IBCM_FAILURE);
2267 }
2268
2269 /* Now, unregister with IBMF */
2270 ibmf_status = ibmf_unregister(
2271 &hcap->hca_port_info[port_index].port_ibmf_hdl, 0);
2272 IBTF_DPRINTF_L4(cmlog, "ibcm_hca_fini_port: "
2273 "ibmf_unregister of port_num %x returned %x",
2274 port_index + 1, ibmf_status);
2275
2276 if (ibmf_status == IBMF_SUCCESS)
2277 hcap->hca_port_info[port_index].port_ibmf_hdl = NULL;
2278 else {
2279 IBTF_DPRINTF_L2(cmlog, "ibcm_hca_fini_port: "
2280 "ibmf_unregister failed %d port_num %d",
2281 ibmf_status, port_index + 1);
2282 return (IBCM_FAILURE);
2283 }
2284 }
2285 return (IBCM_SUCCESS);
2286 }
2287
2288 /*
2289 * ibcm_comm_est_handler():
2290 * Check if the given channel is in ESTABLISHED state or not
2291 *
2292 * Arguments:
2293 * eventp - A pointer to an ibt_async_event_t struct
2294 *
2295 * Return values: NONE
2296 */
2297 static void
2298 ibcm_comm_est_handler(ibt_async_event_t *eventp)
2299 {
2300 ibcm_state_data_t *statep;
2301
2302 IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler:");
2303
2304 /* Both QP and EEC handles can't be NULL */
2305 if (eventp->ev_chan_hdl == NULL) {
2306 IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: "
2307 "both QP and EEC handles are NULL");
2308 return;
2309 }
2310
2311 /* get the "statep" from qp/eec handles */
2312 IBCM_GET_CHAN_PRIVATE(eventp->ev_chan_hdl, statep);
2313 if (statep == NULL) {
2314 IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: statep is NULL");
2315 return;
2316 }
2317
2318 mutex_enter(&statep->state_mutex);
2319
2320 IBCM_RELEASE_CHAN_PRIVATE(eventp->ev_chan_hdl);
2321
2322 IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler: statep = %p", statep);
2323
2324 IBCM_REF_CNT_INCR(statep);
2325
2326 if ((statep->state == IBCM_STATE_REP_SENT) ||
2327 (statep->state == IBCM_STATE_MRA_REP_RCVD)) {
2328 timeout_id_t timer_val = statep->timerid;
2329
2330 statep->state = IBCM_STATE_TRANSIENT_ESTABLISHED;
2331
2332 if (timer_val) {
2333 statep->timerid = 0;
2334 mutex_exit(&statep->state_mutex);
2335 (void) untimeout(timer_val);
2336 } else
2337 mutex_exit(&statep->state_mutex);
2338
2339 /* CM doesn't have RTU message here */
2340 ibcm_cep_state_rtu(statep, NULL);
2341
2342 } else {
2343 if (statep->state == IBCM_STATE_ESTABLISHED ||
2344 statep->state == IBCM_STATE_TRANSIENT_ESTABLISHED) {
2345 IBTF_DPRINTF_L4(cmlog, "ibcm_comm_est_handler: "
2346 "Channel already in ESTABLISHED state");
2347 } else {
2348 /* An unexpected behavior from remote */
2349 IBTF_DPRINTF_L2(cmlog, "ibcm_comm_est_handler: "
2350 "Unexpected in state = %d", statep->state);
2351 }
2352 mutex_exit(&statep->state_mutex);
2353
2354 ibcm_insert_trace(statep, IBCM_TRACE_INCOMING_COMEST);
2355 }
2356
2357 mutex_enter(&statep->state_mutex);
2358 IBCM_REF_CNT_DECR(statep);
2359 mutex_exit(&statep->state_mutex);
2360 }
2361
2362
2363 /*
2364 * ibcm_async_handler():
2365 * CM's Async Handler
2366 * (Handles ATTACH, DETACH, COM_EST events)
2367 *
2368 * Arguments:
2369 * eventp - A pointer to an ibt_async_event_t struct
2370 *
2371 * Return values: None
2372 *
2373 * NOTE : CM assumes that all HCA DR events are delivered sequentially
2374 * i.e., until ibcm_async_handler completes for a given HCA DR, framework
2375 * shall not invoke ibcm_async_handler with another DR event for the same
2376 * HCA
2377 */
2378 /* ARGSUSED */
2379 void
2380 ibcm_async_handler(void *clnt_hdl, ibt_hca_hdl_t hca_hdl,
2381 ibt_async_code_t code, ibt_async_event_t *eventp)
2382 {
2383 ibcm_hca_info_t *hcap;
2384 ibcm_port_up_t *pup;
2385
2386 IBTF_DPRINTF_L3(cmlog, "ibcm_async_handler: "
2387 "clnt_hdl = %p, code = 0x%x, eventp = 0x%p",
2388 clnt_hdl, code, eventp);
2389
2390 mutex_enter(&ibcm_global_hca_lock);
2391
2392 /* If fini is going to complete successfully, then return */
2393 if (ibcm_finit_state != IBCM_FINIT_IDLE) {
2394
2395 /*
2396 * This finit state implies one of the following:
2397 * Init either didn't start or didn't complete OR
2398 * Fini is about to return SUCCESS and release the global lock.
2399 * In all these cases, it is safe to ignore the async.
2400 */
2401
2402 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler: ignoring event %x, "
2403 "as either init didn't complete or fini about to succeed",
2404 code);
2405 mutex_exit(&ibcm_global_hca_lock);
2406 return;
2407 }
2408
2409 switch (code) {
2410 case IBT_PORT_CHANGE_EVENT:
2411 if ((eventp->ev_port_flags & IBT_PORT_CHANGE_SM_LID) == 0)
2412 break;
2413 /* FALLTHROUGH */
2414 case IBT_CLNT_REREG_EVENT:
2415 case IBT_EVENT_PORT_UP:
2416 mutex_exit(&ibcm_global_hca_lock);
2417 pup = kmem_alloc(sizeof (ibcm_port_up_t), KM_SLEEP);
2418 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pup))
2419 pup->pup_hca_guid = eventp->ev_hca_guid;
2420 pup->pup_port = eventp->ev_port;
2421 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*pup))
2422 (void) taskq_dispatch(ibcm_taskq,
2423 ibcm_service_record_rewrite_task, pup, TQ_SLEEP);
2424 ibcm_path_cache_purge();
2425 return;
2426
2427 case IBT_HCA_ATTACH_EVENT:
2428
2429 /* eventp->ev_hcaguid is the HCA GUID of interest */
2430 ibcm_hca_attach(eventp->ev_hca_guid);
2431 break;
2432
2433 case IBT_HCA_DETACH_EVENT:
2434
2435 /* eventp->ev_hca_guid is the HCA GUID of interest */
2436 if ((hcap = ibcm_find_hcap_entry(eventp->ev_hca_guid)) ==
2437 NULL) {
2438 IBTF_DPRINTF_L2(cmlog, "ibcm_async_handler:"
2439 " hca %llX doesn't exist", eventp->ev_hca_guid);
2440 break;
2441 }
2442
2443 (void) ibcm_hca_detach(hcap);
2444 break;
2445
2446 case IBT_EVENT_COM_EST_QP:
2447 /* eventp->ev_qp_hdl is the ibt_qp_hdl_t of interest */
2448 case IBT_EVENT_COM_EST_EEC:
2449 /* eventp->ev_eec_hdl is the ibt_eec_hdl_t of interest */
2450 ibcm_comm_est_handler(eventp);
2451 break;
2452 default:
2453 break;
2454 }
2455
2456 /* Unblock, any blocked fini/init operations */
2457 mutex_exit(&ibcm_global_hca_lock);
2458 }