xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_handlers.c (revision 89b2a9fbeabf42fa54594df0e5927bcc50a07cc9)
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 #include <sys/ib/ibtl/impl/ibtl.h>
27 #include <sys/ib/ibtl/impl/ibtl_cm.h>
28 #include <sys/taskq.h>
29 #include <sys/disp.h>
30 #include <sys/callb.h>
31 #include <sys/proc.h>
32 
33 /*
34  * ibtl_handlers.c
35  */
36 
37 /*
38  * What's in this file?
39  *
40  *   This file started as an implementation of Asynchronous Event/Error
41  *   handling and Completion Queue handling.  As the implementation
42  *   evolved, code has been added for other ibc_* interfaces (resume,
43  *   predetach, etc.) that use the same mechanisms as used for asyncs.
44  *
45  * Async and CQ handling at interrupt level.
46  *
47  *   CQ handling is normally done at interrupt level using the CQ callback
48  *   handler to call the appropriate IBT Client (owner of the CQ).  For
49  *   clients that would prefer a fully flexible non-interrupt context to
50  *   do their CQ handling, a CQ can be created so that its handler is
51  *   called from a non-interrupt thread.  CQ handling is done frequently
52  *   whereas Async handling is expected to occur very infrequently.
53  *
54  *   Async handling is done by marking (or'ing in of an async_code of) the
55  *   pertinent IBTL data structure, and then notifying the async_thread(s)
56  *   that the data structure has async work to be done.  The notification
57  *   occurs by linking the data structure through its async_link onto a
58  *   list of like data structures and waking up an async_thread.  This
59  *   list append is not done if there is already async work pending on
60  *   this data structure (IBTL_ASYNC_PENDING).
61  *
62  * Async Mutex and CQ Mutex
63  *
64  *   The global ibtl_async_mutex is "the" mutex used to control access
65  *   to all the data needed by ibc_async_handler.  All the threads that
66  *   use this mutex are written so that the mutex is held for very short
67  *   periods of time, and never held while making calls to functions
68  *   that may block.
69  *
70  *   The global ibtl_cq_mutex is used similarly by ibc_cq_handler and
71  *   the ibtl_cq_thread(s).
72  *
73  * Mutex hierarchy
74  *
75  *   The ibtl_clnt_list_mutex is above the ibtl_async_mutex.
76  *   ibtl_clnt_list_mutex protects all of the various lists.
77  *   The ibtl_async_mutex is below this in the hierarchy.
78  *
79  *   The ibtl_cq_mutex is independent of the above mutexes.
80  *
81  * Threads
82  *
83  *   There are "ibtl_cq_threads" number of threads created for handling
84  *   Completion Queues in threads.  If this feature really gets used,
85  *   then we will want to do some suitable tuning.  Similarly, we may
86  *   want to tune the number of "ibtl_async_thread_init".
87  *
88  *   The function ibtl_cq_thread is the main loop for handling a CQ in a
89  *   thread.  There can be multiple threads executing this same code.
90  *   The code sleeps when there is no work to be done (list is empty),
91  *   otherwise it pulls the first CQ structure off the list and performs
92  *   the CQ handler callback to the client.  After that returns, a check
93  *   is made, and if another ibc_cq_handler call was made for this CQ,
94  *   the client is called again.
95  *
96  *   The function ibtl_async_thread is the main loop for handling async
97  *   events/errors.  There can be multiple threads executing this same code.
98  *   The code sleeps when there is no work to be done (lists are empty),
99  *   otherwise it pulls the first structure off one of the lists and
100  *   performs the async callback(s) to the client(s).  Note that HCA
101  *   async handling is done by calling each of the clients using the HCA.
102  *   When the async handling completes, the data structure having the async
103  *   event/error is checked for more work before it's considered "done".
104  *
105  * Taskq
106  *
107  *   The async_taskq is used here for allowing async handler callbacks to
108  *   occur simultaneously to multiple clients of an HCA.  This taskq could
109  *   be used for other purposes, e.g., if all the async_threads are in
110  *   use, but this is deemed as overkill since asyncs should occur rarely.
111  */
112 
113 /* Globals */
114 static char ibtf_handlers[] = "ibtl_handlers";
115 
116 /* priority for IBTL threads (async, cq, and taskq) */
117 static pri_t ibtl_pri = MAXCLSYSPRI - 1; /* maybe override in /etc/system */
118 
119 /* taskq used for HCA asyncs */
120 #define	ibtl_async_taskq system_taskq
121 
122 /* data for async handling by threads */
123 static kmutex_t ibtl_async_mutex;	/* protects most *_async_* data */
124 static kcondvar_t ibtl_async_cv;	/* async_threads wait on this */
125 static kcondvar_t ibtl_clnt_cv;		/* ibt_detach might wait on this */
126 static void ibtl_dec_clnt_async_cnt(ibtl_clnt_t *clntp);
127 static void ibtl_inc_clnt_async_cnt(ibtl_clnt_t *clntp);
128 
129 static kt_did_t *ibtl_async_did;	/* for thread_join() */
130 int ibtl_async_thread_init = 4;	/* total # of async_threads to create */
131 static int ibtl_async_thread_exit = 0;	/* set if/when thread(s) should exit */
132 
133 /* async lists for various structures */
134 static ibtl_hca_devinfo_t *ibtl_async_hca_list_start, *ibtl_async_hca_list_end;
135 static ibtl_eec_t *ibtl_async_eec_list_start, *ibtl_async_eec_list_end;
136 static ibtl_qp_t *ibtl_async_qp_list_start, *ibtl_async_qp_list_end;
137 static ibtl_cq_t *ibtl_async_cq_list_start, *ibtl_async_cq_list_end;
138 static ibtl_srq_t *ibtl_async_srq_list_start, *ibtl_async_srq_list_end;
139 
140 /* data for CQ completion handling by threads */
141 static kmutex_t ibtl_cq_mutex;	/* protects the cv and the list below */
142 static kcondvar_t ibtl_cq_cv;
143 static ibtl_cq_t *ibtl_cq_list_start, *ibtl_cq_list_end;
144 
145 static int ibtl_cq_threads = 0;		/* total # of cq threads */
146 static int ibtl_cqs_using_threads = 0;	/* total # of cqs using threads */
147 static int ibtl_cq_thread_exit = 0;	/* set if/when thread(s) should exit */
148 
149 /* value used to tell IBTL threads to exit */
150 #define	IBTL_THREAD_EXIT 0x1b7fdead	/* IBTF DEAD */
151 /* Cisco Topspin Vendor ID for Rereg hack */
152 #define	IBT_VENDOR_CISCO 0x05ad
153 
154 int ibtl_eec_not_supported = 1;
155 
156 char *ibtl_last_client_name;	/* may help debugging */
157 typedef ibt_status_t (*ibtl_node_info_cb_t)(ib_guid_t, uint8_t, ib_lid_t,
158     ibt_node_info_t *);
159 
160 ibtl_node_info_cb_t ibtl_node_info_cb;
161 
162 _NOTE(LOCK_ORDER(ibtl_clnt_list_mutex ibtl_async_mutex))
163 
164 void
165 ibtl_cm_set_node_info_cb(ibt_status_t (*node_info_cb)(ib_guid_t, uint8_t,
166     ib_lid_t, ibt_node_info_t *))
167 {
168 	mutex_enter(&ibtl_clnt_list_mutex);
169 	ibtl_node_info_cb = node_info_cb;
170 	mutex_exit(&ibtl_clnt_list_mutex);
171 }
172 
173 /*
174  * ibc_async_handler()
175  *
176  * Asynchronous Event/Error Handler.
177  *
178  *	This is the function called HCA drivers to post various async
179  *	event and errors mention in the IB architecture spec.  See
180  *	ibtl_types.h for additional details of this.
181  *
182  *	This function marks the pertinent IBTF object with the async_code,
183  *	and queues the object for handling by an ibtl_async_thread.  If
184  *	the object is NOT already marked for async processing, it is added
185  *	to the associated list for that type of object, and an
186  *	ibtl_async_thread is signaled to finish the async work.
187  */
188 void
189 ibc_async_handler(ibc_clnt_hdl_t hca_devp, ibt_async_code_t code,
190     ibc_async_event_t *event_p)
191 {
192 	ibtl_qp_t	*ibtl_qp;
193 	ibtl_cq_t	*ibtl_cq;
194 	ibtl_srq_t	*ibtl_srq;
195 	ibtl_eec_t	*ibtl_eec;
196 	uint8_t		port_minus1;
197 
198 	ibtl_async_port_event_t	*portp;
199 
200 	IBTF_DPRINTF_L2(ibtf_handlers, "ibc_async_handler(%p, 0x%x, %p)",
201 	    hca_devp, code, event_p);
202 
203 	mutex_enter(&ibtl_async_mutex);
204 
205 	switch (code) {
206 	case IBT_EVENT_PATH_MIGRATED_QP:
207 	case IBT_EVENT_SQD:
208 	case IBT_ERROR_CATASTROPHIC_QP:
209 	case IBT_ERROR_PATH_MIGRATE_REQ_QP:
210 	case IBT_EVENT_COM_EST_QP:
211 	case IBT_ERROR_INVALID_REQUEST_QP:
212 	case IBT_ERROR_ACCESS_VIOLATION_QP:
213 	case IBT_EVENT_EMPTY_QP:
214 		ibtl_qp = event_p->ev_qp_hdl;
215 		if (ibtl_qp == NULL) {
216 			IBTF_DPRINTF_L2(ibtf_handlers, "ibc_async_handler: "
217 			    "bad qp handle");
218 			break;
219 		}
220 		switch (code) {
221 		case IBT_ERROR_CATASTROPHIC_QP:
222 			ibtl_qp->qp_cat_fma_ena = event_p->ev_fma_ena; break;
223 		case IBT_ERROR_PATH_MIGRATE_REQ_QP:
224 			ibtl_qp->qp_pth_fma_ena = event_p->ev_fma_ena; break;
225 		case IBT_ERROR_INVALID_REQUEST_QP:
226 			ibtl_qp->qp_inv_fma_ena = event_p->ev_fma_ena; break;
227 		case IBT_ERROR_ACCESS_VIOLATION_QP:
228 			ibtl_qp->qp_acc_fma_ena = event_p->ev_fma_ena; break;
229 		}
230 
231 		ibtl_qp->qp_async_codes |= code;
232 		if ((ibtl_qp->qp_async_flags & IBTL_ASYNC_PENDING) == 0) {
233 			ibtl_qp->qp_async_flags |= IBTL_ASYNC_PENDING;
234 			ibtl_qp->qp_async_link = NULL;
235 			if (ibtl_async_qp_list_end == NULL)
236 				ibtl_async_qp_list_start = ibtl_qp;
237 			else
238 				ibtl_async_qp_list_end->qp_async_link = ibtl_qp;
239 			ibtl_async_qp_list_end = ibtl_qp;
240 			cv_signal(&ibtl_async_cv);
241 		}
242 		break;
243 
244 	case IBT_ERROR_CQ:
245 		ibtl_cq = event_p->ev_cq_hdl;
246 		if (ibtl_cq == NULL) {
247 			IBTF_DPRINTF_L2(ibtf_handlers, "ibc_async_handler: "
248 			    "bad cq handle");
249 			break;
250 		}
251 		ibtl_cq->cq_async_codes |= code;
252 		ibtl_cq->cq_fma_ena = event_p->ev_fma_ena;
253 		if ((ibtl_cq->cq_async_flags & IBTL_ASYNC_PENDING) == 0) {
254 			ibtl_cq->cq_async_flags |= IBTL_ASYNC_PENDING;
255 			ibtl_cq->cq_async_link = NULL;
256 			if (ibtl_async_cq_list_end == NULL)
257 				ibtl_async_cq_list_start = ibtl_cq;
258 			else
259 				ibtl_async_cq_list_end->cq_async_link = ibtl_cq;
260 			ibtl_async_cq_list_end = ibtl_cq;
261 			cv_signal(&ibtl_async_cv);
262 		}
263 		break;
264 
265 	case IBT_ERROR_CATASTROPHIC_SRQ:
266 	case IBT_EVENT_LIMIT_REACHED_SRQ:
267 		ibtl_srq = event_p->ev_srq_hdl;
268 		if (ibtl_srq == NULL) {
269 			IBTF_DPRINTF_L2(ibtf_handlers, "ibc_async_handler: "
270 			    "bad srq handle");
271 			break;
272 		}
273 		ibtl_srq->srq_async_codes |= code;
274 		ibtl_srq->srq_fma_ena = event_p->ev_fma_ena;
275 		if ((ibtl_srq->srq_async_flags & IBTL_ASYNC_PENDING) == 0) {
276 			ibtl_srq->srq_async_flags |= IBTL_ASYNC_PENDING;
277 			ibtl_srq->srq_async_link = NULL;
278 			if (ibtl_async_srq_list_end == NULL)
279 				ibtl_async_srq_list_start = ibtl_srq;
280 			else
281 				ibtl_async_srq_list_end->srq_async_link =
282 				    ibtl_srq;
283 			ibtl_async_srq_list_end = ibtl_srq;
284 			cv_signal(&ibtl_async_cv);
285 		}
286 		break;
287 
288 	case IBT_EVENT_PATH_MIGRATED_EEC:
289 	case IBT_ERROR_PATH_MIGRATE_REQ_EEC:
290 	case IBT_ERROR_CATASTROPHIC_EEC:
291 	case IBT_EVENT_COM_EST_EEC:
292 		if (ibtl_eec_not_supported) {
293 			IBTF_DPRINTF_L2(ibtf_handlers, "ibc_async_handler: "
294 			    "EEC events are disabled.");
295 			break;
296 		}
297 		ibtl_eec = event_p->ev_eec_hdl;
298 		if (ibtl_eec == NULL) {
299 			IBTF_DPRINTF_L2(ibtf_handlers, "ibc_async_handler: "
300 			    "bad eec handle");
301 			break;
302 		}
303 		switch (code) {
304 		case IBT_ERROR_PATH_MIGRATE_REQ_EEC:
305 			ibtl_eec->eec_pth_fma_ena = event_p->ev_fma_ena; break;
306 		case IBT_ERROR_CATASTROPHIC_EEC:
307 			ibtl_eec->eec_cat_fma_ena = event_p->ev_fma_ena; break;
308 		}
309 		ibtl_eec->eec_async_codes |= code;
310 		if ((ibtl_eec->eec_async_flags & IBTL_ASYNC_PENDING) == 0) {
311 			ibtl_eec->eec_async_flags |= IBTL_ASYNC_PENDING;
312 			ibtl_eec->eec_async_link = NULL;
313 			if (ibtl_async_eec_list_end == NULL)
314 				ibtl_async_eec_list_start = ibtl_eec;
315 			else
316 				ibtl_async_eec_list_end->eec_async_link =
317 				    ibtl_eec;
318 			ibtl_async_eec_list_end = ibtl_eec;
319 			cv_signal(&ibtl_async_cv);
320 		}
321 		break;
322 
323 	case IBT_ERROR_LOCAL_CATASTROPHIC:
324 		hca_devp->hd_async_codes |= code;
325 		hca_devp->hd_fma_ena = event_p->ev_fma_ena;
326 		/* FALLTHROUGH */
327 
328 	case IBT_EVENT_PORT_UP:
329 	case IBT_PORT_CHANGE_EVENT:
330 	case IBT_CLNT_REREG_EVENT:
331 	case IBT_ERROR_PORT_DOWN:
332 		if ((code & IBT_PORT_EVENTS) != 0) {
333 			if ((port_minus1 = event_p->ev_port - 1) >=
334 			    hca_devp->hd_hca_attr->hca_nports) {
335 				IBTF_DPRINTF_L2(ibtf_handlers,
336 				    "ibc_async_handler: bad port #: %d",
337 				    event_p->ev_port);
338 				break;
339 			}
340 			portp = &hca_devp->hd_async_port[port_minus1];
341 			if (code == IBT_EVENT_PORT_UP) {
342 				/*
343 				 * The port is just coming UP we can't have any
344 				 * valid older events.
345 				 */
346 				portp->status = IBTL_HCA_PORT_UP;
347 			} else if (code == IBT_ERROR_PORT_DOWN) {
348 				/*
349 				 * The port is going DOWN older events don't
350 				 * count.
351 				 */
352 				portp->status = IBTL_HCA_PORT_DOWN;
353 			} else if (code == IBT_PORT_CHANGE_EVENT) {
354 				/*
355 				 * For port UP and DOWN events only the latest
356 				 * event counts. If we get a UP after DOWN it
357 				 * is sufficient to send just UP and vice versa.
358 				 * In the case of port CHANGE event it is valid
359 				 * only when the port is UP already but if we
360 				 * receive it after UP but before UP is
361 				 * delivered we still need to deliver CHANGE
362 				 * after we deliver UP event.
363 				 *
364 				 * We will not get a CHANGE event when the port
365 				 * is down or DOWN event is pending.
366 				 */
367 				portp->flags |= event_p->ev_port_flags;
368 				portp->status |= IBTL_HCA_PORT_CHG;
369 			} else if (code == IBT_CLNT_REREG_EVENT) {
370 				/*
371 				 * SM has requested a re-register of
372 				 * subscription to SM events notification.
373 				 */
374 				portp->status |= IBTL_HCA_PORT_ASYNC_CLNT_REREG;
375 			}
376 
377 			hca_devp->hd_async_codes |= code;
378 		}
379 
380 		if ((hca_devp->hd_async_flags & IBTL_ASYNC_PENDING) == 0) {
381 			hca_devp->hd_async_flags |= IBTL_ASYNC_PENDING;
382 			hca_devp->hd_async_link = NULL;
383 			if (ibtl_async_hca_list_end == NULL)
384 				ibtl_async_hca_list_start = hca_devp;
385 			else
386 				ibtl_async_hca_list_end->hd_async_link =
387 				    hca_devp;
388 			ibtl_async_hca_list_end = hca_devp;
389 			cv_signal(&ibtl_async_cv);
390 		}
391 
392 		break;
393 
394 	default:
395 		IBTF_DPRINTF_L1(ibtf_handlers, "ibc_async_handler: "
396 		    "invalid code (0x%x)", code);
397 	}
398 
399 	mutex_exit(&ibtl_async_mutex);
400 }
401 
402 
403 /* Finally, make the async call to the client. */
404 
405 static void
406 ibtl_async_client_call(ibtl_hca_t *ibt_hca, ibt_async_code_t code,
407     ibt_async_event_t *event_p)
408 {
409 	ibtl_clnt_t		*clntp;
410 	void			*client_private;
411 	ibt_async_handler_t	async_handler;
412 	char			*client_name;
413 
414 	IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_async_client_call(%p, 0x%x, %p)",
415 	    ibt_hca, code, event_p);
416 
417 	clntp = ibt_hca->ha_clnt_devp;
418 
419 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibtl_last_client_name))
420 	/* Record who is being called (just a debugging aid) */
421 	ibtl_last_client_name = client_name = clntp->clnt_name;
422 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibtl_last_client_name))
423 
424 	client_private = clntp->clnt_private;
425 	async_handler = clntp->clnt_modinfop->mi_async_handler;
426 
427 	if (code & (IBT_EVENT_COM_EST_QP | IBT_EVENT_COM_EST_EEC)) {
428 		mutex_enter(&ibtl_clnt_list_mutex);
429 		async_handler = ibtl_cm_async_handler;
430 		client_private = ibtl_cm_clnt_private;
431 		mutex_exit(&ibtl_clnt_list_mutex);
432 		ibt_hca = NULL;
433 		IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_async_client_call: "
434 		    "calling CM for COM_EST");
435 	} else {
436 		IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_async_client_call: "
437 		    "calling client '%s'", client_name);
438 	}
439 	if (async_handler != NULL)
440 		async_handler(client_private, ibt_hca, code, event_p);
441 	else
442 		IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_async_client_call: "
443 		    "client '%s' has no async handler", client_name);
444 }
445 
446 /*
447  * Inform CM or DM about HCA events.
448  *
449  *	We use taskqs to allow simultaneous notification, with sleeping.
450  *	Since taskqs only allow one argument, we define a structure
451  *	because we need to pass in more than one argument.
452  */
453 
454 struct ibtl_mgr_s {
455 	ibtl_hca_devinfo_t	*mgr_hca_devp;
456 	ibt_async_handler_t	mgr_async_handler;
457 	void			*mgr_clnt_private;
458 };
459 
460 /*
461  * Asyncs of HCA level events for CM and DM.  Call CM or DM and tell them
462  * about the HCA for the event recorded in the ibtl_hca_devinfo_t.
463  */
464 static void
465 ibtl_do_mgr_async_task(void *arg)
466 {
467 	struct ibtl_mgr_s	*mgrp = (struct ibtl_mgr_s *)arg;
468 	ibtl_hca_devinfo_t	*hca_devp = mgrp->mgr_hca_devp;
469 
470 	IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_do_mgr_async_task(0x%x)",
471 	    hca_devp->hd_async_code);
472 
473 	mgrp->mgr_async_handler(mgrp->mgr_clnt_private, NULL,
474 	    hca_devp->hd_async_code, &hca_devp->hd_async_event);
475 	kmem_free(mgrp, sizeof (*mgrp));
476 
477 	mutex_enter(&ibtl_clnt_list_mutex);
478 	if (--hca_devp->hd_async_task_cnt == 0)
479 		cv_signal(&hca_devp->hd_async_task_cv);
480 	mutex_exit(&ibtl_clnt_list_mutex);
481 }
482 
483 static void
484 ibt_cisco_embedded_sm_rereg_fix(void *arg)
485 {
486 	struct ibtl_mgr_s *mgrp = arg;
487 	ibtl_hca_devinfo_t *hca_devp;
488 	ibt_node_info_t node_info;
489 	ibt_status_t ibt_status;
490 	ibtl_async_port_event_t *portp;
491 	ib_lid_t sm_lid;
492 	ib_guid_t hca_guid;
493 	ibt_async_event_t *event_p;
494 	ibt_hca_portinfo_t *pinfop;
495 	uint8_t	port;
496 
497 	hca_devp = mgrp->mgr_hca_devp;
498 
499 	mutex_enter(&ibtl_clnt_list_mutex);
500 	event_p = &hca_devp->hd_async_event;
501 	port = event_p->ev_port;
502 	portp = &hca_devp->hd_async_port[port - 1];
503 	pinfop = &hca_devp->hd_portinfop[port - 1];
504 	sm_lid = pinfop->p_sm_lid;
505 	hca_guid = hca_devp->hd_hca_attr->hca_node_guid;
506 	mutex_exit(&ibtl_clnt_list_mutex);
507 
508 	ibt_status = ((ibtl_node_info_cb_t)mgrp->mgr_async_handler)(hca_guid,
509 	    port, sm_lid, &node_info);
510 	if (ibt_status == IBT_SUCCESS) {
511 		if ((node_info.n_vendor_id == IBT_VENDOR_CISCO) &&
512 		    (node_info.n_node_type == IBT_NODE_TYPE_SWITCH)) {
513 			mutex_enter(&ibtl_async_mutex);
514 			portp->status |= IBTL_HCA_PORT_ASYNC_CLNT_REREG;
515 			hca_devp->hd_async_codes |= IBT_CLNT_REREG_EVENT;
516 			mutex_exit(&ibtl_async_mutex);
517 		}
518 	}
519 	kmem_free(mgrp, sizeof (*mgrp));
520 
521 	mutex_enter(&ibtl_clnt_list_mutex);
522 	if (--hca_devp->hd_async_task_cnt == 0)
523 		cv_signal(&hca_devp->hd_async_task_cv);
524 	mutex_exit(&ibtl_clnt_list_mutex);
525 }
526 
527 static void
528 ibtl_cm_get_node_info(ibtl_hca_devinfo_t *hca_devp,
529     ibt_async_handler_t async_handler)
530 {
531 	struct ibtl_mgr_s *mgrp;
532 
533 	if (async_handler == NULL)
534 		return;
535 
536 	_NOTE(NO_COMPETING_THREADS_NOW)
537 	mgrp = kmem_alloc(sizeof (*mgrp), KM_SLEEP);
538 	mgrp->mgr_hca_devp = hca_devp;
539 	mgrp->mgr_async_handler = async_handler;
540 	mgrp->mgr_clnt_private = NULL;
541 	hca_devp->hd_async_task_cnt++;
542 
543 	(void) taskq_dispatch(ibtl_async_taskq,
544 	    ibt_cisco_embedded_sm_rereg_fix, mgrp, TQ_SLEEP);
545 #ifndef lint
546 	_NOTE(COMPETING_THREADS_NOW)
547 #endif
548 }
549 
550 static void
551 ibtl_tell_mgr(ibtl_hca_devinfo_t *hca_devp, ibt_async_handler_t async_handler,
552     void *clnt_private)
553 {
554 	struct ibtl_mgr_s *mgrp;
555 
556 	if (async_handler == NULL)
557 		return;
558 
559 	_NOTE(NO_COMPETING_THREADS_NOW)
560 	mgrp = kmem_alloc(sizeof (*mgrp), KM_SLEEP);
561 	mgrp->mgr_hca_devp = hca_devp;
562 	mgrp->mgr_async_handler = async_handler;
563 	mgrp->mgr_clnt_private = clnt_private;
564 	hca_devp->hd_async_task_cnt++;
565 
566 	(void) taskq_dispatch(ibtl_async_taskq, ibtl_do_mgr_async_task, mgrp,
567 	    TQ_SLEEP);
568 #ifndef lint
569 	_NOTE(COMPETING_THREADS_NOW)
570 #endif
571 }
572 
573 /*
574  * Per client-device asyncs for HCA level events.  Call each client that is
575  * using the HCA for the event recorded in the ibtl_hca_devinfo_t.
576  */
577 static void
578 ibtl_hca_client_async_task(void *arg)
579 {
580 	ibtl_hca_t		*ibt_hca = (ibtl_hca_t *)arg;
581 	ibtl_hca_devinfo_t	*hca_devp = ibt_hca->ha_hca_devp;
582 	ibtl_clnt_t		*clntp = ibt_hca->ha_clnt_devp;
583 	ibt_async_event_t	async_event;
584 
585 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_hca_client_async_task(%p, 0x%x)",
586 	    ibt_hca, hca_devp->hd_async_code);
587 
588 	bcopy(&hca_devp->hd_async_event, &async_event, sizeof (async_event));
589 	ibtl_async_client_call(ibt_hca, hca_devp->hd_async_code, &async_event);
590 
591 	mutex_enter(&ibtl_async_mutex);
592 	if (--ibt_hca->ha_async_cnt == 0 &&
593 	    (ibt_hca->ha_async_flags & IBTL_ASYNC_FREE_OBJECT)) {
594 		mutex_exit(&ibtl_async_mutex);
595 		kmem_free(ibt_hca, sizeof (ibtl_hca_t));
596 	} else
597 		mutex_exit(&ibtl_async_mutex);
598 
599 	mutex_enter(&ibtl_clnt_list_mutex);
600 	if (--hca_devp->hd_async_task_cnt == 0)
601 		cv_signal(&hca_devp->hd_async_task_cv);
602 	if (--clntp->clnt_async_cnt == 0)
603 		cv_broadcast(&ibtl_clnt_cv);
604 
605 	mutex_exit(&ibtl_clnt_list_mutex);
606 }
607 
608 /*
609  * Asyncs for HCA level events.
610  *
611  * The function continues to run until there are no more async
612  * events/errors for this HCA.  An event is chosen for dispatch
613  * to all clients of this HCA.  This thread dispatches them via
614  * the ibtl_async_taskq, then sleeps until all tasks are done.
615  *
616  * This thread records the async_code and async_event in the
617  * ibtl_hca_devinfo_t for all client taskq threads to reference.
618  *
619  * This is called from an async or taskq thread with ibtl_async_mutex held.
620  */
621 static void
622 ibtl_do_hca_asyncs(ibtl_hca_devinfo_t *hca_devp)
623 {
624 	ibtl_hca_t			*ibt_hca;
625 	ibt_async_event_t		*eventp;
626 	ibt_async_code_t		code;
627 	ibtl_async_port_status_t  	temp;
628 	uint8_t				nports;
629 	uint8_t				port_minus1;
630 	ibtl_async_port_event_t		*portp;
631 
632 	mutex_exit(&ibtl_async_mutex);
633 
634 	mutex_enter(&ibtl_clnt_list_mutex);
635 	while (hca_devp->hd_async_busy)
636 		cv_wait(&hca_devp->hd_async_busy_cv, &ibtl_clnt_list_mutex);
637 	hca_devp->hd_async_busy = 1;
638 	mutex_enter(&ibtl_async_mutex);
639 
640 	bzero(&hca_devp->hd_async_event, sizeof (hca_devp->hd_async_event));
641 	for (;;) {
642 
643 		hca_devp->hd_async_event.ev_fma_ena = 0;
644 
645 		code = hca_devp->hd_async_codes;
646 		if (code & IBT_ERROR_LOCAL_CATASTROPHIC) {
647 			code = IBT_ERROR_LOCAL_CATASTROPHIC;
648 			hca_devp->hd_async_event.ev_fma_ena =
649 			    hca_devp->hd_fma_ena;
650 		} else if (code & IBT_ERROR_PORT_DOWN) {
651 			code = IBT_ERROR_PORT_DOWN;
652 			temp = IBTL_HCA_PORT_DOWN;
653 		} else if (code & IBT_EVENT_PORT_UP) {
654 			code = IBT_EVENT_PORT_UP;
655 			temp = IBTL_HCA_PORT_UP;
656 		} else if (code & IBT_PORT_CHANGE_EVENT) {
657 			code = IBT_PORT_CHANGE_EVENT;
658 			temp = IBTL_HCA_PORT_CHG;
659 		} else if (code & IBT_CLNT_REREG_EVENT) {
660 			code = IBT_CLNT_REREG_EVENT;
661 			temp = IBTL_HCA_PORT_ASYNC_CLNT_REREG;
662 		} else {
663 			hca_devp->hd_async_codes = 0;
664 			code = 0;
665 		}
666 
667 		if (code == 0) {
668 			hca_devp->hd_async_flags &= ~IBTL_ASYNC_PENDING;
669 			break;
670 		}
671 		hca_devp->hd_async_codes &= ~code;
672 
673 		/* PORT_UP, PORT_CHANGE, PORT_DOWN or ASYNC_REREG */
674 		if ((code & IBT_PORT_EVENTS) != 0) {
675 			portp = hca_devp->hd_async_port;
676 			nports = hca_devp->hd_hca_attr->hca_nports;
677 			for (port_minus1 = 0; port_minus1 < nports;
678 			    port_minus1++) {
679 				/*
680 				 * Matching event in this port, let's go handle
681 				 * it.
682 				 */
683 				if ((portp[port_minus1].status & temp) != 0)
684 					break;
685 			}
686 			if (port_minus1 >= nports) {
687 				/* we checked again, but found nothing */
688 				continue;
689 			}
690 			IBTF_DPRINTF_L4(ibtf_handlers, "ibtl_do_hca_asyncs: "
691 			    "async: port# %x code %x", port_minus1 + 1, code);
692 			/* mark it to check for other ports after we're done */
693 			hca_devp->hd_async_codes |= code;
694 
695 			/*
696 			 * Copy the event information into hca_devp and clear
697 			 * event information from the per port data.
698 			 */
699 			hca_devp->hd_async_event.ev_port = port_minus1 + 1;
700 			if (temp == IBTL_HCA_PORT_CHG) {
701 				hca_devp->hd_async_event.ev_port_flags =
702 				    hca_devp->hd_async_port[port_minus1].flags;
703 				hca_devp->hd_async_port[port_minus1].flags = 0;
704 			}
705 			hca_devp->hd_async_port[port_minus1].status &= ~temp;
706 
707 			mutex_exit(&ibtl_async_mutex);
708 			ibtl_reinit_hca_portinfo(hca_devp, port_minus1 + 1);
709 			mutex_enter(&ibtl_async_mutex);
710 			eventp = &hca_devp->hd_async_event;
711 			eventp->ev_hca_guid =
712 			    hca_devp->hd_hca_attr->hca_node_guid;
713 		}
714 
715 		hca_devp->hd_async_code = code;
716 		hca_devp->hd_async_event.ev_hca_guid =
717 		    hca_devp->hd_hca_attr->hca_node_guid;
718 		mutex_exit(&ibtl_async_mutex);
719 
720 		/*
721 		 * Make sure to inform CM, DM, and IBMA if we know of them.
722 		 * Also, make sure not to inform them a second time, which
723 		 * would occur if they have the HCA open.
724 		 */
725 
726 		if (ibtl_ibma_async_handler)
727 			ibtl_tell_mgr(hca_devp, ibtl_ibma_async_handler,
728 			    ibtl_ibma_clnt_private);
729 		/* wait for all tasks to complete */
730 		while (hca_devp->hd_async_task_cnt != 0)
731 			cv_wait(&hca_devp->hd_async_task_cv,
732 			    &ibtl_clnt_list_mutex);
733 
734 		/*
735 		 * Hack Alert:
736 		 * The ibmf handler would have updated the Master SM LID if it
737 		 * was SM LID change event. Now lets check if the new Master SM
738 		 * is a Embedded Cisco Topspin SM.
739 		 */
740 		if ((code == IBT_PORT_CHANGE_EVENT) &&
741 		    eventp->ev_port_flags & IBT_PORT_CHANGE_SM_LID)
742 			ibtl_cm_get_node_info(hca_devp,
743 			    (ibt_async_handler_t)ibtl_node_info_cb);
744 		/* wait for node info task to complete */
745 		while (hca_devp->hd_async_task_cnt != 0)
746 			cv_wait(&hca_devp->hd_async_task_cv,
747 			    &ibtl_clnt_list_mutex);
748 
749 		if (ibtl_dm_async_handler)
750 			ibtl_tell_mgr(hca_devp, ibtl_dm_async_handler,
751 			    ibtl_dm_clnt_private);
752 		if (ibtl_cm_async_handler)
753 			ibtl_tell_mgr(hca_devp, ibtl_cm_async_handler,
754 			    ibtl_cm_clnt_private);
755 		/* wait for all tasks to complete */
756 		while (hca_devp->hd_async_task_cnt != 0)
757 			cv_wait(&hca_devp->hd_async_task_cv,
758 			    &ibtl_clnt_list_mutex);
759 
760 		for (ibt_hca = hca_devp->hd_clnt_list;
761 		    ibt_hca != NULL;
762 		    ibt_hca = ibt_hca->ha_clnt_link) {
763 
764 			/* Managers are handled above */
765 			if (IBTL_HCA2MODI_P(ibt_hca)->mi_async_handler ==
766 			    ibtl_cm_async_handler)
767 				continue;
768 			if (IBTL_HCA2MODI_P(ibt_hca)->mi_async_handler ==
769 			    ibtl_dm_async_handler)
770 				continue;
771 			if (IBTL_HCA2MODI_P(ibt_hca)->mi_async_handler ==
772 			    ibtl_ibma_async_handler)
773 				continue;
774 			++ibt_hca->ha_clnt_devp->clnt_async_cnt;
775 
776 			mutex_enter(&ibtl_async_mutex);
777 			ibt_hca->ha_async_cnt++;
778 			mutex_exit(&ibtl_async_mutex);
779 			hca_devp->hd_async_task_cnt++;
780 			(void) taskq_dispatch(ibtl_async_taskq,
781 			    ibtl_hca_client_async_task, ibt_hca, TQ_SLEEP);
782 		}
783 
784 		/* wait for all tasks to complete */
785 		while (hca_devp->hd_async_task_cnt != 0)
786 			cv_wait(&hca_devp->hd_async_task_cv,
787 			    &ibtl_clnt_list_mutex);
788 
789 		mutex_enter(&ibtl_async_mutex);
790 	}
791 	hca_devp->hd_async_code = 0;
792 	hca_devp->hd_async_busy = 0;
793 	cv_broadcast(&hca_devp->hd_async_busy_cv);
794 	mutex_exit(&ibtl_clnt_list_mutex);
795 }
796 
797 /*
798  * Asyncs for QP objects.
799  *
800  * The function continues to run until there are no more async
801  * events/errors for this object.
802  */
803 static void
804 ibtl_do_qp_asyncs(ibtl_qp_t *ibtl_qp)
805 {
806 	ibt_async_code_t	code;
807 	ibt_async_event_t	async_event;
808 
809 	ASSERT(MUTEX_HELD(&ibtl_async_mutex));
810 	bzero(&async_event, sizeof (async_event));
811 	async_event.ev_chan_hdl = IBTL_QP2CHAN(ibtl_qp);
812 
813 	while ((code = ibtl_qp->qp_async_codes) != 0) {
814 		async_event.ev_fma_ena = 0;
815 		if (ibtl_qp->qp_async_flags & IBTL_ASYNC_FREE_OBJECT)
816 			code = 0;	/* fallthrough to "kmem_free" */
817 		else if (code & IBT_ERROR_CATASTROPHIC_QP) {
818 			code = IBT_ERROR_CATASTROPHIC_QP;
819 			async_event.ev_fma_ena = ibtl_qp->qp_cat_fma_ena;
820 		} else if (code & IBT_ERROR_INVALID_REQUEST_QP) {
821 			code = IBT_ERROR_INVALID_REQUEST_QP;
822 			async_event.ev_fma_ena = ibtl_qp->qp_inv_fma_ena;
823 		} else if (code & IBT_ERROR_ACCESS_VIOLATION_QP) {
824 			code = IBT_ERROR_ACCESS_VIOLATION_QP;
825 			async_event.ev_fma_ena = ibtl_qp->qp_acc_fma_ena;
826 		} else if (code & IBT_ERROR_PATH_MIGRATE_REQ_QP) {
827 			code = IBT_ERROR_PATH_MIGRATE_REQ_QP;
828 			async_event.ev_fma_ena = ibtl_qp->qp_pth_fma_ena;
829 		} else if (code & IBT_EVENT_PATH_MIGRATED_QP)
830 			code = IBT_EVENT_PATH_MIGRATED_QP;
831 		else if (code & IBT_EVENT_SQD)
832 			code = IBT_EVENT_SQD;
833 		else if (code & IBT_EVENT_COM_EST_QP)
834 			code = IBT_EVENT_COM_EST_QP;
835 		else if (code & IBT_EVENT_EMPTY_QP)
836 			code = IBT_EVENT_EMPTY_QP;
837 		else {
838 			IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_do_qp_asyncs: "
839 			    "async: unexpected QP async code 0x%x", code);
840 			ibtl_qp->qp_async_codes = 0;
841 			code = 0;
842 		}
843 		ibtl_qp->qp_async_codes &= ~code;
844 
845 		if (code) {
846 			mutex_exit(&ibtl_async_mutex);
847 			ibtl_async_client_call(ibtl_qp->qp_hca,
848 			    code, &async_event);
849 			mutex_enter(&ibtl_async_mutex);
850 		}
851 
852 		if (ibtl_qp->qp_async_flags & IBTL_ASYNC_FREE_OBJECT) {
853 			mutex_exit(&ibtl_async_mutex);
854 			cv_destroy(&(IBTL_QP2CHAN(ibtl_qp))->ch_cm_cv);
855 			mutex_destroy(&(IBTL_QP2CHAN(ibtl_qp))->ch_cm_mutex);
856 			kmem_free(IBTL_QP2CHAN(ibtl_qp),
857 			    sizeof (ibtl_channel_t));
858 			mutex_enter(&ibtl_async_mutex);
859 			return;
860 		}
861 	}
862 	ibtl_qp->qp_async_flags &= ~IBTL_ASYNC_PENDING;
863 }
864 
865 /*
866  * Asyncs for SRQ objects.
867  *
868  * The function continues to run until there are no more async
869  * events/errors for this object.
870  */
871 static void
872 ibtl_do_srq_asyncs(ibtl_srq_t *ibtl_srq)
873 {
874 	ibt_async_code_t	code;
875 	ibt_async_event_t	async_event;
876 
877 	ASSERT(MUTEX_HELD(&ibtl_async_mutex));
878 	bzero(&async_event, sizeof (async_event));
879 	async_event.ev_srq_hdl = ibtl_srq;
880 	async_event.ev_fma_ena = ibtl_srq->srq_fma_ena;
881 
882 	while ((code = ibtl_srq->srq_async_codes) != 0) {
883 		if (ibtl_srq->srq_async_flags & IBTL_ASYNC_FREE_OBJECT)
884 			code = 0;	/* fallthrough to "kmem_free" */
885 		else if (code & IBT_ERROR_CATASTROPHIC_SRQ)
886 			code = IBT_ERROR_CATASTROPHIC_SRQ;
887 		else if (code & IBT_EVENT_LIMIT_REACHED_SRQ)
888 			code = IBT_EVENT_LIMIT_REACHED_SRQ;
889 		else {
890 			IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_do_srq_asyncs: "
891 			    "async: unexpected SRQ async code 0x%x", code);
892 			ibtl_srq->srq_async_codes = 0;
893 			code = 0;
894 		}
895 		ibtl_srq->srq_async_codes &= ~code;
896 
897 		if (code) {
898 			mutex_exit(&ibtl_async_mutex);
899 			ibtl_async_client_call(ibtl_srq->srq_hca,
900 			    code, &async_event);
901 			mutex_enter(&ibtl_async_mutex);
902 		}
903 
904 		if (ibtl_srq->srq_async_flags & IBTL_ASYNC_FREE_OBJECT) {
905 			mutex_exit(&ibtl_async_mutex);
906 			kmem_free(ibtl_srq, sizeof (struct ibtl_srq_s));
907 			mutex_enter(&ibtl_async_mutex);
908 			return;
909 		}
910 	}
911 	ibtl_srq->srq_async_flags &= ~IBTL_ASYNC_PENDING;
912 }
913 
914 /*
915  * Asyncs for CQ objects.
916  *
917  * The function continues to run until there are no more async
918  * events/errors for this object.
919  */
920 static void
921 ibtl_do_cq_asyncs(ibtl_cq_t *ibtl_cq)
922 {
923 	ibt_async_code_t	code;
924 	ibt_async_event_t	async_event;
925 
926 	ASSERT(MUTEX_HELD(&ibtl_async_mutex));
927 	bzero(&async_event, sizeof (async_event));
928 	async_event.ev_cq_hdl = ibtl_cq;
929 	async_event.ev_fma_ena = ibtl_cq->cq_fma_ena;
930 
931 	while ((code = ibtl_cq->cq_async_codes) != 0) {
932 		if (ibtl_cq->cq_async_flags & IBTL_ASYNC_FREE_OBJECT)
933 			code = 0;	/* fallthrough to "kmem_free" */
934 		else if (code & IBT_ERROR_CQ)
935 			code = IBT_ERROR_CQ;
936 		else {
937 			IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_do_cq_asyncs: "
938 			    "async: unexpected CQ async code 0x%x", code);
939 			ibtl_cq->cq_async_codes = 0;
940 			code = 0;
941 		}
942 		ibtl_cq->cq_async_codes &= ~code;
943 
944 		if (code) {
945 			mutex_exit(&ibtl_async_mutex);
946 			ibtl_async_client_call(ibtl_cq->cq_hca,
947 			    code, &async_event);
948 			mutex_enter(&ibtl_async_mutex);
949 		}
950 
951 		if (ibtl_cq->cq_async_flags & IBTL_ASYNC_FREE_OBJECT) {
952 			mutex_exit(&ibtl_async_mutex);
953 			mutex_destroy(&ibtl_cq->cq_mutex);
954 			kmem_free(ibtl_cq, sizeof (struct ibtl_cq_s));
955 			mutex_enter(&ibtl_async_mutex);
956 			return;
957 		}
958 	}
959 	ibtl_cq->cq_async_flags &= ~IBTL_ASYNC_PENDING;
960 }
961 
962 /*
963  * Asyncs for EEC objects.
964  *
965  * The function continues to run until there are no more async
966  * events/errors for this object.
967  */
968 static void
969 ibtl_do_eec_asyncs(ibtl_eec_t *ibtl_eec)
970 {
971 	ibt_async_code_t	code;
972 	ibt_async_event_t	async_event;
973 
974 	ASSERT(MUTEX_HELD(&ibtl_async_mutex));
975 	bzero(&async_event, sizeof (async_event));
976 	async_event.ev_chan_hdl = ibtl_eec->eec_channel;
977 
978 	while ((code = ibtl_eec->eec_async_codes) != 0) {
979 		async_event.ev_fma_ena = 0;
980 		if (ibtl_eec->eec_async_flags & IBTL_ASYNC_FREE_OBJECT)
981 			code = 0;	/* fallthrough to "kmem_free" */
982 		else if (code & IBT_ERROR_CATASTROPHIC_EEC) {
983 			code = IBT_ERROR_CATASTROPHIC_CHAN;
984 			async_event.ev_fma_ena = ibtl_eec->eec_cat_fma_ena;
985 		} else if (code & IBT_ERROR_PATH_MIGRATE_REQ_EEC) {
986 			code = IBT_ERROR_PATH_MIGRATE_REQ;
987 			async_event.ev_fma_ena = ibtl_eec->eec_pth_fma_ena;
988 		} else if (code & IBT_EVENT_PATH_MIGRATED_EEC)
989 			code = IBT_EVENT_PATH_MIGRATED;
990 		else if (code & IBT_EVENT_COM_EST_EEC)
991 			code = IBT_EVENT_COM_EST;
992 		else {
993 			IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_do_eec_asyncs: "
994 			    "async: unexpected code 0x%x", code);
995 			ibtl_eec->eec_async_codes = 0;
996 			code = 0;
997 		}
998 		ibtl_eec->eec_async_codes &= ~code;
999 
1000 		if (code) {
1001 			mutex_exit(&ibtl_async_mutex);
1002 			ibtl_async_client_call(ibtl_eec->eec_hca,
1003 			    code, &async_event);
1004 			mutex_enter(&ibtl_async_mutex);
1005 		}
1006 
1007 		if (ibtl_eec->eec_async_flags & IBTL_ASYNC_FREE_OBJECT) {
1008 			mutex_exit(&ibtl_async_mutex);
1009 			kmem_free(ibtl_eec, sizeof (struct ibtl_eec_s));
1010 			mutex_enter(&ibtl_async_mutex);
1011 			return;
1012 		}
1013 	}
1014 	ibtl_eec->eec_async_flags &= ~IBTL_ASYNC_PENDING;
1015 }
1016 
1017 #ifdef __lock_lint
1018 kmutex_t cpr_mutex;
1019 #endif
1020 
1021 /*
1022  * Loop forever, calling async_handlers until all of the async lists
1023  * are empty.
1024  */
1025 
1026 static void
1027 ibtl_async_thread(void)
1028 {
1029 #ifndef __lock_lint
1030 	kmutex_t cpr_mutex;
1031 #endif
1032 	callb_cpr_t	cprinfo;
1033 
1034 	_NOTE(MUTEX_PROTECTS_DATA(cpr_mutex, cprinfo))
1035 	_NOTE(NO_COMPETING_THREADS_NOW)
1036 	mutex_init(&cpr_mutex, NULL, MUTEX_DRIVER, NULL);
1037 	CALLB_CPR_INIT(&cprinfo, &cpr_mutex, callb_generic_cpr,
1038 	    "ibtl_async_thread");
1039 #ifndef lint
1040 	_NOTE(COMPETING_THREADS_NOW)
1041 #endif
1042 
1043 	mutex_enter(&ibtl_async_mutex);
1044 
1045 	for (;;) {
1046 		if (ibtl_async_hca_list_start) {
1047 			ibtl_hca_devinfo_t *hca_devp;
1048 
1049 			/* remove first entry from list */
1050 			hca_devp = ibtl_async_hca_list_start;
1051 			ibtl_async_hca_list_start = hca_devp->hd_async_link;
1052 			hca_devp->hd_async_link = NULL;
1053 			if (ibtl_async_hca_list_start == NULL)
1054 				ibtl_async_hca_list_end = NULL;
1055 
1056 			ibtl_do_hca_asyncs(hca_devp);
1057 
1058 		} else if (ibtl_async_qp_list_start) {
1059 			ibtl_qp_t *ibtl_qp;
1060 
1061 			/* remove from list */
1062 			ibtl_qp = ibtl_async_qp_list_start;
1063 			ibtl_async_qp_list_start = ibtl_qp->qp_async_link;
1064 			ibtl_qp->qp_async_link = NULL;
1065 			if (ibtl_async_qp_list_start == NULL)
1066 				ibtl_async_qp_list_end = NULL;
1067 
1068 			ibtl_do_qp_asyncs(ibtl_qp);
1069 
1070 		} else if (ibtl_async_srq_list_start) {
1071 			ibtl_srq_t *ibtl_srq;
1072 
1073 			/* remove from list */
1074 			ibtl_srq = ibtl_async_srq_list_start;
1075 			ibtl_async_srq_list_start = ibtl_srq->srq_async_link;
1076 			ibtl_srq->srq_async_link = NULL;
1077 			if (ibtl_async_srq_list_start == NULL)
1078 				ibtl_async_srq_list_end = NULL;
1079 
1080 			ibtl_do_srq_asyncs(ibtl_srq);
1081 
1082 		} else if (ibtl_async_eec_list_start) {
1083 			ibtl_eec_t *ibtl_eec;
1084 
1085 			/* remove from list */
1086 			ibtl_eec = ibtl_async_eec_list_start;
1087 			ibtl_async_eec_list_start = ibtl_eec->eec_async_link;
1088 			ibtl_eec->eec_async_link = NULL;
1089 			if (ibtl_async_eec_list_start == NULL)
1090 				ibtl_async_eec_list_end = NULL;
1091 
1092 			ibtl_do_eec_asyncs(ibtl_eec);
1093 
1094 		} else if (ibtl_async_cq_list_start) {
1095 			ibtl_cq_t *ibtl_cq;
1096 
1097 			/* remove from list */
1098 			ibtl_cq = ibtl_async_cq_list_start;
1099 			ibtl_async_cq_list_start = ibtl_cq->cq_async_link;
1100 			ibtl_cq->cq_async_link = NULL;
1101 			if (ibtl_async_cq_list_start == NULL)
1102 				ibtl_async_cq_list_end = NULL;
1103 
1104 			ibtl_do_cq_asyncs(ibtl_cq);
1105 
1106 		} else {
1107 			if (ibtl_async_thread_exit == IBTL_THREAD_EXIT)
1108 				break;
1109 			mutex_enter(&cpr_mutex);
1110 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
1111 			mutex_exit(&cpr_mutex);
1112 
1113 			cv_wait(&ibtl_async_cv, &ibtl_async_mutex);
1114 
1115 			mutex_exit(&ibtl_async_mutex);
1116 			mutex_enter(&cpr_mutex);
1117 			CALLB_CPR_SAFE_END(&cprinfo, &cpr_mutex);
1118 			mutex_exit(&cpr_mutex);
1119 			mutex_enter(&ibtl_async_mutex);
1120 		}
1121 	}
1122 
1123 	mutex_exit(&ibtl_async_mutex);
1124 
1125 #ifndef __lock_lint
1126 	mutex_enter(&cpr_mutex);
1127 	CALLB_CPR_EXIT(&cprinfo);
1128 #endif
1129 	mutex_destroy(&cpr_mutex);
1130 }
1131 
1132 
1133 void
1134 ibtl_free_qp_async_check(ibtl_qp_t *ibtl_qp)
1135 {
1136 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_free_qp_async_check(%p)", ibtl_qp);
1137 
1138 	mutex_enter(&ibtl_async_mutex);
1139 
1140 	/*
1141 	 * If there is an active async, mark this object to be freed
1142 	 * by the async_thread when it's done.
1143 	 */
1144 	if (ibtl_qp->qp_async_flags & IBTL_ASYNC_PENDING) {
1145 		ibtl_qp->qp_async_flags |= IBTL_ASYNC_FREE_OBJECT;
1146 		mutex_exit(&ibtl_async_mutex);
1147 	} else {	/* free the object now */
1148 		mutex_exit(&ibtl_async_mutex);
1149 		cv_destroy(&(IBTL_QP2CHAN(ibtl_qp))->ch_cm_cv);
1150 		mutex_destroy(&(IBTL_QP2CHAN(ibtl_qp))->ch_cm_mutex);
1151 		kmem_free(IBTL_QP2CHAN(ibtl_qp), sizeof (ibtl_channel_t));
1152 	}
1153 }
1154 
1155 void
1156 ibtl_free_cq_async_check(ibtl_cq_t *ibtl_cq)
1157 {
1158 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_free_cq_async_check(%p)", ibtl_cq);
1159 
1160 	mutex_enter(&ibtl_async_mutex);
1161 
1162 	/* if there is an active async, mark this object to be freed */
1163 	if (ibtl_cq->cq_async_flags & IBTL_ASYNC_PENDING) {
1164 		ibtl_cq->cq_async_flags |= IBTL_ASYNC_FREE_OBJECT;
1165 		mutex_exit(&ibtl_async_mutex);
1166 	} else {	/* free the object now */
1167 		mutex_exit(&ibtl_async_mutex);
1168 		mutex_destroy(&ibtl_cq->cq_mutex);
1169 		kmem_free(ibtl_cq, sizeof (struct ibtl_cq_s));
1170 	}
1171 }
1172 
1173 void
1174 ibtl_free_srq_async_check(ibtl_srq_t *ibtl_srq)
1175 {
1176 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_free_srq_async_check(%p)",
1177 	    ibtl_srq);
1178 
1179 	mutex_enter(&ibtl_async_mutex);
1180 
1181 	/* if there is an active async, mark this object to be freed */
1182 	if (ibtl_srq->srq_async_flags & IBTL_ASYNC_PENDING) {
1183 		ibtl_srq->srq_async_flags |= IBTL_ASYNC_FREE_OBJECT;
1184 		mutex_exit(&ibtl_async_mutex);
1185 	} else {	/* free the object now */
1186 		mutex_exit(&ibtl_async_mutex);
1187 		kmem_free(ibtl_srq, sizeof (struct ibtl_srq_s));
1188 	}
1189 }
1190 
1191 void
1192 ibtl_free_eec_async_check(ibtl_eec_t *ibtl_eec)
1193 {
1194 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_free_eec_async_check(%p)",
1195 	    ibtl_eec);
1196 
1197 	mutex_enter(&ibtl_async_mutex);
1198 
1199 	/* if there is an active async, mark this object to be freed */
1200 	if (ibtl_eec->eec_async_flags & IBTL_ASYNC_PENDING) {
1201 		ibtl_eec->eec_async_flags |= IBTL_ASYNC_FREE_OBJECT;
1202 		mutex_exit(&ibtl_async_mutex);
1203 	} else {	/* free the object now */
1204 		mutex_exit(&ibtl_async_mutex);
1205 		kmem_free(ibtl_eec, sizeof (struct ibtl_eec_s));
1206 	}
1207 }
1208 
1209 /*
1210  * This function differs from above in that we assume this is called
1211  * from non-interrupt context, and never called from the async_thread.
1212  */
1213 
1214 void
1215 ibtl_free_hca_async_check(ibtl_hca_t *ibt_hca)
1216 {
1217 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_free_hca_async_check(%p)",
1218 	    ibt_hca);
1219 
1220 	mutex_enter(&ibtl_async_mutex);
1221 
1222 	/* if there is an active async, mark this object to be freed */
1223 	if (ibt_hca->ha_async_cnt > 0) {
1224 		ibt_hca->ha_async_flags |= IBTL_ASYNC_FREE_OBJECT;
1225 		mutex_exit(&ibtl_async_mutex);
1226 	} else {	/* free the object now */
1227 		mutex_exit(&ibtl_async_mutex);
1228 		kmem_free(ibt_hca, sizeof (ibtl_hca_t));
1229 	}
1230 }
1231 
1232 /*
1233  * Completion Queue Handling.
1234  *
1235  *	A completion queue can be handled through a simple callback
1236  *	at interrupt level, or it may be queued for an ibtl_cq_thread
1237  *	to handle.  The latter is chosen during ibt_alloc_cq when the
1238  *	IBTF_CQ_HANDLER_IN_THREAD is specified.
1239  */
1240 
1241 static void
1242 ibtl_cq_handler_call(ibtl_cq_t *ibtl_cq)
1243 {
1244 	ibt_cq_handler_t	cq_handler;
1245 	void			*arg;
1246 
1247 	IBTF_DPRINTF_L4(ibtf_handlers, "ibtl_cq_handler_call(%p)", ibtl_cq);
1248 
1249 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibtl_cq))
1250 	cq_handler = ibtl_cq->cq_comp_handler;
1251 	arg = ibtl_cq->cq_arg;
1252 	if (cq_handler != NULL)
1253 		cq_handler(ibtl_cq, arg);
1254 	else
1255 		IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_cq_handler_call: "
1256 		    "no cq_handler for cq %p", ibtl_cq);
1257 }
1258 
1259 /*
1260  * Before ibt_free_cq can continue, we need to ensure no more cq_handler
1261  * callbacks can occur.  When we get the mutex, we know there are no
1262  * outstanding cq_handler callbacks.  We set the cq_handler to NULL to
1263  * prohibit future callbacks.
1264  */
1265 void
1266 ibtl_free_cq_check(ibtl_cq_t *ibtl_cq)
1267 {
1268 	mutex_enter(&ibtl_cq->cq_mutex);
1269 	ibtl_cq->cq_comp_handler = NULL;
1270 	mutex_exit(&ibtl_cq->cq_mutex);
1271 	if (ibtl_cq->cq_in_thread) {
1272 		mutex_enter(&ibtl_cq_mutex);
1273 		--ibtl_cqs_using_threads;
1274 		while (ibtl_cq->cq_impl_flags & IBTL_CQ_PENDING) {
1275 			ibtl_cq->cq_impl_flags &= ~IBTL_CQ_CALL_CLIENT;
1276 			ibtl_cq->cq_impl_flags |= IBTL_CQ_FREE;
1277 			cv_wait(&ibtl_cq_cv, &ibtl_cq_mutex);
1278 		}
1279 		mutex_exit(&ibtl_cq_mutex);
1280 	}
1281 }
1282 
1283 /*
1284  * Loop forever, calling cq_handlers until the cq list
1285  * is empty.
1286  */
1287 
1288 static void
1289 ibtl_cq_thread(void)
1290 {
1291 #ifndef __lock_lint
1292 	kmutex_t cpr_mutex;
1293 #endif
1294 	callb_cpr_t	cprinfo;
1295 
1296 	_NOTE(MUTEX_PROTECTS_DATA(cpr_mutex, cprinfo))
1297 	_NOTE(NO_COMPETING_THREADS_NOW)
1298 	mutex_init(&cpr_mutex, NULL, MUTEX_DRIVER, NULL);
1299 	CALLB_CPR_INIT(&cprinfo, &cpr_mutex, callb_generic_cpr,
1300 	    "ibtl_cq_thread");
1301 #ifndef lint
1302 	_NOTE(COMPETING_THREADS_NOW)
1303 #endif
1304 
1305 	mutex_enter(&ibtl_cq_mutex);
1306 
1307 	for (;;) {
1308 		if (ibtl_cq_list_start) {
1309 			ibtl_cq_t *ibtl_cq;
1310 
1311 			ibtl_cq = ibtl_cq_list_start;
1312 			ibtl_cq_list_start = ibtl_cq->cq_link;
1313 			ibtl_cq->cq_link = NULL;
1314 			if (ibtl_cq == ibtl_cq_list_end)
1315 				ibtl_cq_list_end = NULL;
1316 
1317 			while (ibtl_cq->cq_impl_flags & IBTL_CQ_CALL_CLIENT) {
1318 				ibtl_cq->cq_impl_flags &= ~IBTL_CQ_CALL_CLIENT;
1319 				mutex_exit(&ibtl_cq_mutex);
1320 				ibtl_cq_handler_call(ibtl_cq);
1321 				mutex_enter(&ibtl_cq_mutex);
1322 			}
1323 			ibtl_cq->cq_impl_flags &= ~IBTL_CQ_PENDING;
1324 			if (ibtl_cq->cq_impl_flags & IBTL_CQ_FREE)
1325 				cv_broadcast(&ibtl_cq_cv);
1326 		} else {
1327 			if (ibtl_cq_thread_exit == IBTL_THREAD_EXIT)
1328 				break;
1329 			mutex_enter(&cpr_mutex);
1330 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
1331 			mutex_exit(&cpr_mutex);
1332 
1333 			cv_wait(&ibtl_cq_cv, &ibtl_cq_mutex);
1334 
1335 			mutex_exit(&ibtl_cq_mutex);
1336 			mutex_enter(&cpr_mutex);
1337 			CALLB_CPR_SAFE_END(&cprinfo, &cpr_mutex);
1338 			mutex_exit(&cpr_mutex);
1339 			mutex_enter(&ibtl_cq_mutex);
1340 		}
1341 	}
1342 
1343 	mutex_exit(&ibtl_cq_mutex);
1344 #ifndef __lock_lint
1345 	mutex_enter(&cpr_mutex);
1346 	CALLB_CPR_EXIT(&cprinfo);
1347 #endif
1348 	mutex_destroy(&cpr_mutex);
1349 }
1350 
1351 
1352 /*
1353  * ibc_cq_handler()
1354  *
1355  *    Completion Queue Notification Handler.
1356  *
1357  */
1358 /*ARGSUSED*/
1359 void
1360 ibc_cq_handler(ibc_clnt_hdl_t ibc_hdl, ibt_cq_hdl_t ibtl_cq)
1361 {
1362 	IBTF_DPRINTF_L4(ibtf_handlers, "ibc_cq_handler(%p, %p)",
1363 	    ibc_hdl, ibtl_cq);
1364 
1365 	if (ibtl_cq->cq_in_thread) {
1366 		mutex_enter(&ibtl_cq_mutex);
1367 		ibtl_cq->cq_impl_flags |= IBTL_CQ_CALL_CLIENT;
1368 		if ((ibtl_cq->cq_impl_flags & IBTL_CQ_PENDING) == 0) {
1369 			ibtl_cq->cq_impl_flags |= IBTL_CQ_PENDING;
1370 			ibtl_cq->cq_link = NULL;
1371 			if (ibtl_cq_list_end == NULL)
1372 				ibtl_cq_list_start = ibtl_cq;
1373 			else
1374 				ibtl_cq_list_end->cq_link = ibtl_cq;
1375 			ibtl_cq_list_end = ibtl_cq;
1376 			cv_signal(&ibtl_cq_cv);
1377 		}
1378 		mutex_exit(&ibtl_cq_mutex);
1379 		return;
1380 	} else
1381 		ibtl_cq_handler_call(ibtl_cq);
1382 }
1383 
1384 
1385 /*
1386  * ibt_enable_cq_notify()
1387  *      Enable Notification requests on the specified CQ.
1388  *
1389  *      ibt_cq          The CQ handle.
1390  *
1391  *      notify_type     Enable notifications for all (IBT_NEXT_COMPLETION)
1392  *                      completions, or the next Solicited completion
1393  *                      (IBT_NEXT_SOLICITED) only.
1394  *
1395  *	Completion notifications are disabled by setting the completion
1396  *	handler to NULL by calling ibt_set_cq_handler().
1397  */
1398 ibt_status_t
1399 ibt_enable_cq_notify(ibt_cq_hdl_t ibtl_cq, ibt_cq_notify_flags_t notify_type)
1400 {
1401 	IBTF_DPRINTF_L3(ibtf_handlers, "ibt_enable_cq_notify(%p, %d)",
1402 	    ibtl_cq, notify_type);
1403 
1404 	return (IBTL_CQ2CIHCAOPS_P(ibtl_cq)->ibc_notify_cq(
1405 	    IBTL_CQ2CIHCA(ibtl_cq), ibtl_cq->cq_ibc_cq_hdl, notify_type));
1406 }
1407 
1408 
1409 /*
1410  * ibt_set_cq_handler()
1411  *      Register a work request completion handler with the IBTF.
1412  *
1413  *      ibt_cq                  The CQ handle.
1414  *
1415  *      completion_handler      The completion handler.
1416  *
1417  *      arg                     The IBTF client private argument to be passed
1418  *                              back to the client when calling the CQ
1419  *                              completion handler.
1420  *
1421  *	Completion notifications are disabled by setting the completion
1422  *	handler to NULL.  When setting the handler to NULL, no additional
1423  *	calls to the previous CQ handler will be initiated, but there may
1424  *	be one in progress.
1425  *
1426  *      This function does not otherwise change the state of previous
1427  *      calls to ibt_enable_cq_notify().
1428  */
1429 void
1430 ibt_set_cq_handler(ibt_cq_hdl_t ibtl_cq, ibt_cq_handler_t completion_handler,
1431     void *arg)
1432 {
1433 	IBTF_DPRINTF_L3(ibtf_handlers, "ibt_set_cq_handler(%p, %p, %p)",
1434 	    ibtl_cq, completion_handler, arg);
1435 
1436 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibtl_cq))
1437 	ibtl_cq->cq_comp_handler = completion_handler;
1438 	ibtl_cq->cq_arg = arg;
1439 }
1440 
1441 
1442 /*
1443  * Inform IBT clients about New HCAs.
1444  *
1445  *	We use taskqs to allow simultaneous notification, with sleeping.
1446  *	Since taskqs only allow one argument, we define a structure
1447  *	because we need to pass in two arguments.
1448  */
1449 
1450 struct ibtl_new_hca_s {
1451 	ibtl_clnt_t		*nh_clntp;
1452 	ibtl_hca_devinfo_t	*nh_hca_devp;
1453 	ibt_async_code_t	nh_code;
1454 };
1455 
1456 static void
1457 ibtl_tell_client_about_new_hca(void *arg)
1458 {
1459 	struct ibtl_new_hca_s	*new_hcap = (struct ibtl_new_hca_s *)arg;
1460 	ibtl_clnt_t		*clntp = new_hcap->nh_clntp;
1461 	ibt_async_event_t	async_event;
1462 	ibtl_hca_devinfo_t	*hca_devp = new_hcap->nh_hca_devp;
1463 
1464 	bzero(&async_event, sizeof (async_event));
1465 	async_event.ev_hca_guid = hca_devp->hd_hca_attr->hca_node_guid;
1466 	clntp->clnt_modinfop->mi_async_handler(
1467 	    clntp->clnt_private, NULL, new_hcap->nh_code, &async_event);
1468 	kmem_free(new_hcap, sizeof (*new_hcap));
1469 #ifdef __lock_lint
1470 	{
1471 		ibt_hca_hdl_t hca_hdl;
1472 		(void) ibt_open_hca(clntp, 0ULL, &hca_hdl);
1473 	}
1474 #endif
1475 	mutex_enter(&ibtl_clnt_list_mutex);
1476 	if (--hca_devp->hd_async_task_cnt == 0)
1477 		cv_signal(&hca_devp->hd_async_task_cv);
1478 	if (--clntp->clnt_async_cnt == 0)
1479 		cv_broadcast(&ibtl_clnt_cv);
1480 	mutex_exit(&ibtl_clnt_list_mutex);
1481 }
1482 
1483 /*
1484  * ibtl_announce_new_hca:
1485  *
1486  *	o First attach these clients in the given order
1487  *		IBMA
1488  *		IBCM
1489  *
1490  *	o Next attach all other clients in parallel.
1491  *
1492  * NOTE: Use the taskq to simultaneously notify all clients of the new HCA.
1493  * Retval from clients is ignored.
1494  */
1495 void
1496 ibtl_announce_new_hca(ibtl_hca_devinfo_t *hca_devp)
1497 {
1498 	ibtl_clnt_t		*clntp;
1499 	struct ibtl_new_hca_s	*new_hcap;
1500 
1501 	IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_announce_new_hca(%p, %llX)",
1502 	    hca_devp, hca_devp->hd_hca_attr->hca_node_guid);
1503 
1504 	mutex_enter(&ibtl_clnt_list_mutex);
1505 
1506 	clntp = ibtl_clnt_list;
1507 	while (clntp != NULL) {
1508 		if (clntp->clnt_modinfop->mi_clnt_class == IBT_IBMA) {
1509 			IBTF_DPRINTF_L4(ibtf_handlers,
1510 			    "ibtl_announce_new_hca: calling IBMF");
1511 			if (clntp->clnt_modinfop->mi_async_handler) {
1512 				_NOTE(NO_COMPETING_THREADS_NOW)
1513 				new_hcap = kmem_alloc(sizeof (*new_hcap),
1514 				    KM_SLEEP);
1515 				new_hcap->nh_clntp = clntp;
1516 				new_hcap->nh_hca_devp = hca_devp;
1517 				new_hcap->nh_code = IBT_HCA_ATTACH_EVENT;
1518 #ifndef lint
1519 				_NOTE(COMPETING_THREADS_NOW)
1520 #endif
1521 				clntp->clnt_async_cnt++;
1522 				hca_devp->hd_async_task_cnt++;
1523 
1524 				(void) taskq_dispatch(ibtl_async_taskq,
1525 				    ibtl_tell_client_about_new_hca, new_hcap,
1526 				    TQ_SLEEP);
1527 			}
1528 			break;
1529 		}
1530 		clntp = clntp->clnt_list_link;
1531 	}
1532 	if (clntp != NULL)
1533 		while (clntp->clnt_async_cnt > 0)
1534 			cv_wait(&ibtl_clnt_cv, &ibtl_clnt_list_mutex);
1535 	clntp = ibtl_clnt_list;
1536 	while (clntp != NULL) {
1537 		if (clntp->clnt_modinfop->mi_clnt_class == IBT_DM) {
1538 			IBTF_DPRINTF_L4(ibtf_handlers, "ibtl_announce_new_hca: "
1539 			    "calling  %s", clntp->clnt_modinfop->mi_clnt_name);
1540 			if (clntp->clnt_modinfop->mi_async_handler) {
1541 				_NOTE(NO_COMPETING_THREADS_NOW)
1542 				new_hcap = kmem_alloc(sizeof (*new_hcap),
1543 				    KM_SLEEP);
1544 				new_hcap->nh_clntp = clntp;
1545 				new_hcap->nh_hca_devp = hca_devp;
1546 				new_hcap->nh_code = IBT_HCA_ATTACH_EVENT;
1547 #ifndef lint
1548 				_NOTE(COMPETING_THREADS_NOW)
1549 #endif
1550 				clntp->clnt_async_cnt++;
1551 				hca_devp->hd_async_task_cnt++;
1552 
1553 				mutex_exit(&ibtl_clnt_list_mutex);
1554 				(void) ibtl_tell_client_about_new_hca(
1555 				    new_hcap);
1556 				mutex_enter(&ibtl_clnt_list_mutex);
1557 			}
1558 			break;
1559 		}
1560 		clntp = clntp->clnt_list_link;
1561 	}
1562 
1563 	clntp = ibtl_clnt_list;
1564 	while (clntp != NULL) {
1565 		if (clntp->clnt_modinfop->mi_clnt_class == IBT_CM) {
1566 			IBTF_DPRINTF_L4(ibtf_handlers, "ibtl_announce_new_hca: "
1567 			    "calling  %s", clntp->clnt_modinfop->mi_clnt_name);
1568 			if (clntp->clnt_modinfop->mi_async_handler) {
1569 				_NOTE(NO_COMPETING_THREADS_NOW)
1570 				new_hcap = kmem_alloc(sizeof (*new_hcap),
1571 				    KM_SLEEP);
1572 				new_hcap->nh_clntp = clntp;
1573 				new_hcap->nh_hca_devp = hca_devp;
1574 				new_hcap->nh_code = IBT_HCA_ATTACH_EVENT;
1575 #ifndef lint
1576 				_NOTE(COMPETING_THREADS_NOW)
1577 #endif
1578 				clntp->clnt_async_cnt++;
1579 				hca_devp->hd_async_task_cnt++;
1580 
1581 				(void) taskq_dispatch(ibtl_async_taskq,
1582 				    ibtl_tell_client_about_new_hca, new_hcap,
1583 				    TQ_SLEEP);
1584 			}
1585 			break;
1586 		}
1587 		clntp = clntp->clnt_list_link;
1588 	}
1589 	if (clntp != NULL)
1590 		while (clntp->clnt_async_cnt > 0)
1591 			cv_wait(&ibtl_clnt_cv, &ibtl_clnt_list_mutex);
1592 	clntp = ibtl_clnt_list;
1593 	while (clntp != NULL) {
1594 		if ((clntp->clnt_modinfop->mi_clnt_class != IBT_DM) &&
1595 		    (clntp->clnt_modinfop->mi_clnt_class != IBT_CM) &&
1596 		    (clntp->clnt_modinfop->mi_clnt_class != IBT_IBMA)) {
1597 			IBTF_DPRINTF_L4(ibtf_handlers,
1598 			    "ibtl_announce_new_hca: Calling %s ",
1599 			    clntp->clnt_modinfop->mi_clnt_name);
1600 			if (clntp->clnt_modinfop->mi_async_handler) {
1601 				_NOTE(NO_COMPETING_THREADS_NOW)
1602 				new_hcap = kmem_alloc(sizeof (*new_hcap),
1603 				    KM_SLEEP);
1604 				new_hcap->nh_clntp = clntp;
1605 				new_hcap->nh_hca_devp = hca_devp;
1606 				new_hcap->nh_code = IBT_HCA_ATTACH_EVENT;
1607 #ifndef lint
1608 				_NOTE(COMPETING_THREADS_NOW)
1609 #endif
1610 				clntp->clnt_async_cnt++;
1611 				hca_devp->hd_async_task_cnt++;
1612 
1613 				(void) taskq_dispatch(ibtl_async_taskq,
1614 				    ibtl_tell_client_about_new_hca, new_hcap,
1615 				    TQ_SLEEP);
1616 			}
1617 		}
1618 		clntp = clntp->clnt_list_link;
1619 	}
1620 
1621 	/* wait for all tasks to complete */
1622 	while (hca_devp->hd_async_task_cnt != 0)
1623 		cv_wait(&hca_devp->hd_async_task_cv, &ibtl_clnt_list_mutex);
1624 
1625 	/* wakeup thread that may be waiting to send an HCA async */
1626 	ASSERT(hca_devp->hd_async_busy == 1);
1627 	hca_devp->hd_async_busy = 0;
1628 	cv_broadcast(&hca_devp->hd_async_busy_cv);
1629 	mutex_exit(&ibtl_clnt_list_mutex);
1630 }
1631 
1632 /*
1633  * ibtl_detach_all_clients:
1634  *
1635  *	Return value - 0 for Success, 1 for Failure
1636  *
1637  *	o First detach general clients.
1638  *
1639  *	o Next detach these clients
1640  *		IBCM
1641  *		IBDM
1642  *
1643  *	o Finally, detach this client
1644  *		IBMA
1645  */
1646 int
1647 ibtl_detach_all_clients(ibtl_hca_devinfo_t *hca_devp)
1648 {
1649 	ib_guid_t		hcaguid = hca_devp->hd_hca_attr->hca_node_guid;
1650 	ibtl_hca_t		*ibt_hca;
1651 	ibtl_clnt_t		*clntp;
1652 	int			retval;
1653 
1654 	IBTF_DPRINTF_L2(ibtf_handlers, "ibtl_detach_all_clients(%llX)",
1655 	    hcaguid);
1656 
1657 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1658 
1659 	while (hca_devp->hd_async_busy)
1660 		cv_wait(&hca_devp->hd_async_busy_cv, &ibtl_clnt_list_mutex);
1661 	hca_devp->hd_async_busy = 1;
1662 
1663 	/* First inform general clients asynchronously */
1664 	hca_devp->hd_async_event.ev_hca_guid = hcaguid;
1665 	hca_devp->hd_async_event.ev_fma_ena = 0;
1666 	hca_devp->hd_async_event.ev_chan_hdl = NULL;
1667 	hca_devp->hd_async_event.ev_cq_hdl = NULL;
1668 	hca_devp->hd_async_code = IBT_HCA_DETACH_EVENT;
1669 
1670 	ibt_hca = hca_devp->hd_clnt_list;
1671 	while (ibt_hca != NULL) {
1672 		clntp = ibt_hca->ha_clnt_devp;
1673 		if (IBTL_GENERIC_CLIENT(clntp)) {
1674 			++ibt_hca->ha_clnt_devp->clnt_async_cnt;
1675 			mutex_enter(&ibtl_async_mutex);
1676 			ibt_hca->ha_async_cnt++;
1677 			mutex_exit(&ibtl_async_mutex);
1678 			hca_devp->hd_async_task_cnt++;
1679 
1680 			(void) taskq_dispatch(ibtl_async_taskq,
1681 			    ibtl_hca_client_async_task, ibt_hca, TQ_SLEEP);
1682 		}
1683 		ibt_hca = ibt_hca->ha_clnt_link;
1684 	}
1685 
1686 	/* wait for all clients to complete */
1687 	while (hca_devp->hd_async_task_cnt != 0) {
1688 		cv_wait(&hca_devp->hd_async_task_cv, &ibtl_clnt_list_mutex);
1689 	}
1690 	/* Go thru the clients and check if any have not closed this HCA. */
1691 	retval = 0;
1692 	ibt_hca = hca_devp->hd_clnt_list;
1693 	while (ibt_hca != NULL) {
1694 		clntp = ibt_hca->ha_clnt_devp;
1695 		if (IBTL_GENERIC_CLIENT(clntp)) {
1696 			IBTF_DPRINTF_L2(ibtf_handlers,
1697 			    "ibtl_detach_all_clients: "
1698 			    "client '%s' failed to close the HCA.",
1699 			    ibt_hca->ha_clnt_devp->clnt_modinfop->mi_clnt_name);
1700 			retval = 1;
1701 		}
1702 		ibt_hca = ibt_hca->ha_clnt_link;
1703 	}
1704 	if (retval == 1)
1705 		goto bailout;
1706 
1707 	/* Next inform IBDM asynchronously */
1708 	ibt_hca = hca_devp->hd_clnt_list;
1709 	while (ibt_hca != NULL) {
1710 		clntp = ibt_hca->ha_clnt_devp;
1711 		if (clntp->clnt_modinfop->mi_clnt_class == IBT_DM) {
1712 			++ibt_hca->ha_clnt_devp->clnt_async_cnt;
1713 			mutex_enter(&ibtl_async_mutex);
1714 			ibt_hca->ha_async_cnt++;
1715 			mutex_exit(&ibtl_async_mutex);
1716 			hca_devp->hd_async_task_cnt++;
1717 
1718 			mutex_exit(&ibtl_clnt_list_mutex);
1719 			ibtl_hca_client_async_task(ibt_hca);
1720 			mutex_enter(&ibtl_clnt_list_mutex);
1721 			break;
1722 		}
1723 		ibt_hca = ibt_hca->ha_clnt_link;
1724 	}
1725 
1726 	/*
1727 	 * Next inform IBCM.
1728 	 * As IBCM doesn't perform ibt_open_hca(), IBCM will not be
1729 	 * accessible via hca_devp->hd_clnt_list.
1730 	 * ibtl_cm_async_handler will NOT be NULL, if IBCM is registered.
1731 	 */
1732 	if (ibtl_cm_async_handler) {
1733 		ibtl_tell_mgr(hca_devp, ibtl_cm_async_handler,
1734 		    ibtl_cm_clnt_private);
1735 
1736 		/* wait for all tasks to complete */
1737 		while (hca_devp->hd_async_task_cnt != 0)
1738 			cv_wait(&hca_devp->hd_async_task_cv,
1739 			    &ibtl_clnt_list_mutex);
1740 	}
1741 
1742 	/* Go thru the clients and check if any have not closed this HCA. */
1743 	retval = 0;
1744 	ibt_hca = hca_devp->hd_clnt_list;
1745 	while (ibt_hca != NULL) {
1746 		clntp = ibt_hca->ha_clnt_devp;
1747 		if (clntp->clnt_modinfop->mi_clnt_class != IBT_IBMA) {
1748 			IBTF_DPRINTF_L2(ibtf_handlers,
1749 			    "ibtl_detach_all_clients: "
1750 			    "client '%s' failed to close the HCA.",
1751 			    ibt_hca->ha_clnt_devp->clnt_modinfop->mi_clnt_name);
1752 			retval = 1;
1753 		}
1754 		ibt_hca = ibt_hca->ha_clnt_link;
1755 	}
1756 	if (retval == 1)
1757 		goto bailout;
1758 
1759 	/* Finally, inform IBMA */
1760 	ibt_hca = hca_devp->hd_clnt_list;
1761 	while (ibt_hca != NULL) {
1762 		clntp = ibt_hca->ha_clnt_devp;
1763 		if (clntp->clnt_modinfop->mi_clnt_class == IBT_IBMA) {
1764 			++ibt_hca->ha_clnt_devp->clnt_async_cnt;
1765 			mutex_enter(&ibtl_async_mutex);
1766 			ibt_hca->ha_async_cnt++;
1767 			mutex_exit(&ibtl_async_mutex);
1768 			hca_devp->hd_async_task_cnt++;
1769 
1770 			(void) taskq_dispatch(ibtl_async_taskq,
1771 			    ibtl_hca_client_async_task, ibt_hca, TQ_SLEEP);
1772 		} else
1773 			IBTF_DPRINTF_L2(ibtf_handlers,
1774 			    "ibtl_detach_all_clients: "
1775 			    "client '%s' is unexpectedly on the client list",
1776 			    ibt_hca->ha_clnt_devp->clnt_modinfop->mi_clnt_name);
1777 		ibt_hca = ibt_hca->ha_clnt_link;
1778 	}
1779 
1780 	/* wait for IBMA to complete */
1781 	while (hca_devp->hd_async_task_cnt != 0) {
1782 		cv_wait(&hca_devp->hd_async_task_cv, &ibtl_clnt_list_mutex);
1783 	}
1784 
1785 	/* Check if this HCA's client list is empty. */
1786 	ibt_hca = hca_devp->hd_clnt_list;
1787 	if (ibt_hca != NULL) {
1788 		IBTF_DPRINTF_L2(ibtf_handlers,
1789 		    "ibtl_detach_all_clients: "
1790 		    "client '%s' failed to close the HCA.",
1791 		    ibt_hca->ha_clnt_devp->clnt_modinfop->mi_clnt_name);
1792 		retval = 1;
1793 	} else
1794 		retval = 0;
1795 
1796 bailout:
1797 	if (retval) {
1798 		hca_devp->hd_state = IBTL_HCA_DEV_ATTACHED; /* fix hd_state */
1799 		mutex_exit(&ibtl_clnt_list_mutex);
1800 		ibtl_announce_new_hca(hca_devp);
1801 		mutex_enter(&ibtl_clnt_list_mutex);
1802 	} else {
1803 		hca_devp->hd_async_busy = 0;
1804 		cv_broadcast(&hca_devp->hd_async_busy_cv);
1805 	}
1806 
1807 	return (retval);
1808 }
1809 
1810 void
1811 ibtl_free_clnt_async_check(ibtl_clnt_t *clntp)
1812 {
1813 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_free_clnt_async_check(%p)", clntp);
1814 
1815 	ASSERT(MUTEX_HELD(&ibtl_clnt_list_mutex));
1816 
1817 	/* wait for all asyncs based on "ibtl_clnt_list" to complete */
1818 	while (clntp->clnt_async_cnt != 0) {
1819 		cv_wait(&ibtl_clnt_cv, &ibtl_clnt_list_mutex);
1820 	}
1821 }
1822 
1823 static void
1824 ibtl_dec_clnt_async_cnt(ibtl_clnt_t *clntp)
1825 {
1826 	mutex_enter(&ibtl_clnt_list_mutex);
1827 	if (--clntp->clnt_async_cnt == 0) {
1828 		cv_broadcast(&ibtl_clnt_cv);
1829 	}
1830 	mutex_exit(&ibtl_clnt_list_mutex);
1831 }
1832 
1833 static void
1834 ibtl_inc_clnt_async_cnt(ibtl_clnt_t *clntp)
1835 {
1836 	mutex_enter(&ibtl_clnt_list_mutex);
1837 	++clntp->clnt_async_cnt;
1838 	mutex_exit(&ibtl_clnt_list_mutex);
1839 }
1840 
1841 
1842 /*
1843  * Functions and data structures to inform clients that a notification
1844  * has occurred about Multicast Groups that might interest them.
1845  */
1846 struct ibtl_sm_notice {
1847 	ibt_clnt_hdl_t		np_ibt_hdl;
1848 	ib_gid_t		np_sgid;
1849 	ibt_subnet_event_code_t	np_code;
1850 	ibt_subnet_event_t	np_event;
1851 };
1852 
1853 static void
1854 ibtl_sm_notice_task(void *arg)
1855 {
1856 	struct ibtl_sm_notice *noticep = (struct ibtl_sm_notice *)arg;
1857 	ibt_clnt_hdl_t ibt_hdl = noticep->np_ibt_hdl;
1858 	ibt_sm_notice_handler_t sm_notice_handler;
1859 
1860 	sm_notice_handler = ibt_hdl->clnt_sm_trap_handler;
1861 	if (sm_notice_handler != NULL)
1862 		sm_notice_handler(ibt_hdl->clnt_sm_trap_handler_arg,
1863 		    noticep->np_sgid, noticep->np_code, &noticep->np_event);
1864 	kmem_free(noticep, sizeof (*noticep));
1865 	ibtl_dec_clnt_async_cnt(ibt_hdl);
1866 }
1867 
1868 /*
1869  * Inform the client that MCG notices are not working at this time.
1870  */
1871 void
1872 ibtl_cm_sm_notice_init_failure(ibtl_cm_sm_init_fail_t *ifail)
1873 {
1874 	ibt_clnt_hdl_t ibt_hdl = ifail->smf_ibt_hdl;
1875 	struct ibtl_sm_notice *noticep;
1876 	ib_gid_t *sgidp = &ifail->smf_sgid[0];
1877 	int i;
1878 
1879 	for (i = 0; i < ifail->smf_num_sgids; i++) {
1880 		_NOTE(NO_COMPETING_THREADS_NOW)
1881 		noticep = kmem_zalloc(sizeof (*noticep), KM_SLEEP);
1882 		noticep->np_ibt_hdl = ibt_hdl;
1883 		noticep->np_sgid = *sgidp++;
1884 		noticep->np_code = IBT_SM_EVENT_UNAVAILABLE;
1885 #ifndef lint
1886 		_NOTE(COMPETING_THREADS_NOW)
1887 #endif
1888 		ibtl_inc_clnt_async_cnt(ibt_hdl);
1889 		(void) taskq_dispatch(ibtl_async_taskq,
1890 		    ibtl_sm_notice_task, noticep, TQ_SLEEP);
1891 	}
1892 }
1893 
1894 /*
1895  * Inform all clients of the event.
1896  */
1897 void
1898 ibtl_cm_sm_notice_handler(ib_gid_t sgid, ibt_subnet_event_code_t code,
1899     ibt_subnet_event_t *event)
1900 {
1901 	_NOTE(NO_COMPETING_THREADS_NOW)
1902 	struct ibtl_sm_notice	*noticep;
1903 	ibtl_clnt_t		*clntp;
1904 
1905 	mutex_enter(&ibtl_clnt_list_mutex);
1906 	clntp = ibtl_clnt_list;
1907 	while (clntp != NULL) {
1908 		if (clntp->clnt_sm_trap_handler) {
1909 			noticep = kmem_zalloc(sizeof (*noticep), KM_SLEEP);
1910 			noticep->np_ibt_hdl = clntp;
1911 			noticep->np_sgid = sgid;
1912 			noticep->np_code = code;
1913 			noticep->np_event = *event;
1914 			++clntp->clnt_async_cnt;
1915 			(void) taskq_dispatch(ibtl_async_taskq,
1916 			    ibtl_sm_notice_task, noticep, TQ_SLEEP);
1917 		}
1918 		clntp = clntp->clnt_list_link;
1919 	}
1920 	mutex_exit(&ibtl_clnt_list_mutex);
1921 #ifndef lint
1922 	_NOTE(COMPETING_THREADS_NOW)
1923 #endif
1924 }
1925 
1926 /*
1927  * Record the handler for this client.
1928  */
1929 void
1930 ibtl_cm_set_sm_notice_handler(ibt_clnt_hdl_t ibt_hdl,
1931     ibt_sm_notice_handler_t sm_notice_handler, void *private)
1932 {
1933 	_NOTE(NO_COMPETING_THREADS_NOW)
1934 	ibt_hdl->clnt_sm_trap_handler = sm_notice_handler;
1935 	ibt_hdl->clnt_sm_trap_handler_arg = private;
1936 #ifndef lint
1937 	_NOTE(COMPETING_THREADS_NOW)
1938 #endif
1939 }
1940 
1941 
1942 /*
1943  * ibtl_another_cq_handler_in_thread()
1944  *
1945  * Conditionally increase the number of cq_threads.
1946  * The number of threads grows, based on the number of cqs using threads.
1947  *
1948  * The table below controls the number of threads as follows:
1949  *
1950  *	Number of CQs	Number of cq_threads
1951  *		0		0
1952  *		1		1
1953  *		2-3		2
1954  *		4-5		3
1955  *		6-9		4
1956  *		10-15		5
1957  *		16-23		6
1958  *		24-31		7
1959  *		32+		8
1960  */
1961 
1962 #define	IBTL_CQ_MAXTHREADS 8
1963 static uint8_t ibtl_cq_scaling[IBTL_CQ_MAXTHREADS] = {
1964 	1, 2, 4, 6, 10, 16, 24, 32
1965 };
1966 
1967 static kt_did_t ibtl_cq_did[IBTL_CQ_MAXTHREADS];
1968 
1969 void
1970 ibtl_another_cq_handler_in_thread(void)
1971 {
1972 	kthread_t *t;
1973 	int my_idx;
1974 
1975 	mutex_enter(&ibtl_cq_mutex);
1976 	if ((ibtl_cq_threads == IBTL_CQ_MAXTHREADS) ||
1977 	    (++ibtl_cqs_using_threads < ibtl_cq_scaling[ibtl_cq_threads])) {
1978 		mutex_exit(&ibtl_cq_mutex);
1979 		return;
1980 	}
1981 	my_idx = ibtl_cq_threads++;
1982 	mutex_exit(&ibtl_cq_mutex);
1983 	t = thread_create(NULL, 0, ibtl_cq_thread, NULL, 0, &p0, TS_RUN,
1984 	    ibtl_pri - 1);
1985 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibtl_cq_did))
1986 	ibtl_cq_did[my_idx] = t->t_did;	/* save for thread_join() */
1987 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibtl_cq_did))
1988 }
1989 
1990 void
1991 ibtl_thread_init(void)
1992 {
1993 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_thread_init()");
1994 
1995 	mutex_init(&ibtl_async_mutex, NULL, MUTEX_DEFAULT, NULL);
1996 	cv_init(&ibtl_async_cv, NULL, CV_DEFAULT, NULL);
1997 	cv_init(&ibtl_clnt_cv, NULL, CV_DEFAULT, NULL);
1998 
1999 	mutex_init(&ibtl_cq_mutex, NULL, MUTEX_DEFAULT, NULL);
2000 	cv_init(&ibtl_cq_cv, NULL, CV_DEFAULT, NULL);
2001 }
2002 
2003 void
2004 ibtl_thread_init2(void)
2005 {
2006 	int i;
2007 	static int initted = 0;
2008 	kthread_t *t;
2009 
2010 	mutex_enter(&ibtl_async_mutex);
2011 	if (initted == 1) {
2012 		mutex_exit(&ibtl_async_mutex);
2013 		return;
2014 	}
2015 	initted = 1;
2016 	mutex_exit(&ibtl_async_mutex);
2017 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibtl_async_did))
2018 	ibtl_async_did = kmem_zalloc(ibtl_async_thread_init * sizeof (kt_did_t),
2019 	    KM_SLEEP);
2020 
2021 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_thread_init2()");
2022 
2023 	for (i = 0; i < ibtl_async_thread_init; i++) {
2024 		t = thread_create(NULL, 0, ibtl_async_thread, NULL, 0, &p0,
2025 		    TS_RUN, ibtl_pri - 1);
2026 		ibtl_async_did[i] = t->t_did; /* thread_join() */
2027 	}
2028 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibtl_async_did))
2029 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibtl_cq_threads))
2030 	for (i = 0; i < ibtl_cq_threads; i++) {
2031 		t = thread_create(NULL, 0, ibtl_cq_thread, NULL, 0, &p0,
2032 		    TS_RUN, ibtl_pri - 1);
2033 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibtl_cq_did))
2034 		ibtl_cq_did[i] = t->t_did; /* save for thread_join() */
2035 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibtl_cq_did))
2036 	}
2037 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibtl_cq_threads))
2038 }
2039 
2040 void
2041 ibtl_thread_fini(void)
2042 {
2043 	int i;
2044 
2045 	IBTF_DPRINTF_L3(ibtf_handlers, "ibtl_thread_fini()");
2046 
2047 	/* undo the work done by ibtl_thread_init() */
2048 
2049 	mutex_enter(&ibtl_cq_mutex);
2050 	ibtl_cq_thread_exit = IBTL_THREAD_EXIT;
2051 	cv_broadcast(&ibtl_cq_cv);
2052 	mutex_exit(&ibtl_cq_mutex);
2053 
2054 	mutex_enter(&ibtl_async_mutex);
2055 	ibtl_async_thread_exit = IBTL_THREAD_EXIT;
2056 	cv_broadcast(&ibtl_async_cv);
2057 	mutex_exit(&ibtl_async_mutex);
2058 
2059 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibtl_cq_threads))
2060 	for (i = 0; i < ibtl_cq_threads; i++)
2061 		thread_join(ibtl_cq_did[i]);
2062 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibtl_cq_threads))
2063 
2064 	if (ibtl_async_did) {
2065 		for (i = 0; i < ibtl_async_thread_init; i++)
2066 			thread_join(ibtl_async_did[i]);
2067 
2068 		kmem_free(ibtl_async_did,
2069 		    ibtl_async_thread_init * sizeof (kt_did_t));
2070 	}
2071 	mutex_destroy(&ibtl_cq_mutex);
2072 	cv_destroy(&ibtl_cq_cv);
2073 
2074 	mutex_destroy(&ibtl_async_mutex);
2075 	cv_destroy(&ibtl_async_cv);
2076 	cv_destroy(&ibtl_clnt_cv);
2077 }
2078 
2079 /* ARGSUSED */
2080 ibt_status_t ibtl_dummy_node_info_cb(ib_guid_t hca_guid, uint8_t port,
2081     ib_lid_t lid, ibt_node_info_t *node_info)
2082 {
2083 	return (IBT_SUCCESS);
2084 }
2085