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