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, ¬icep->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