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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file implements the client interfaces of the IBMF. 31 */ 32 33 #include <sys/ib/mgt/ibmf/ibmf_impl.h> 34 #include <sys/ib/mgt/ib_mad.h> 35 36 extern ibmf_state_t *ibmf_statep; 37 38 /* global settable */ 39 int ibmf_send_wqes_per_port = IBMF_MAX_SQ_WRE; 40 int ibmf_recv_wqes_per_port = IBMF_MAX_RQ_WRE; 41 int ibmf_send_wqes_posted_per_qp = IBMF_MAX_POSTED_SQ_PER_QP; 42 int ibmf_recv_wqes_posted_per_qp = IBMF_MAX_POSTED_RQ_PER_QP; 43 44 int ibmf_taskq_max_tasks = 1024; 45 46 int ibmf_trace_level = DPRINT_L0; 47 48 #define IBMF_MAD_CL_HDR_OFF_1 0 49 #define IBMF_MAD_CL_HDR_OFF_2 12 50 #define IBMF_MAD_CL_HDR_SZ_1 40 51 #define IBMF_MAD_CL_HDR_SZ_2 20 52 #define IBMF_MAD_CL_HDR_SZ_3 0 53 #define IBMF_MAD_CL_HDR_SZ_4 4 54 55 #define IBMF_VALID_CLIENT_TYPE(client_type) \ 56 ((client_type) == SUBN_AGENT || \ 57 (client_type) == SUBN_MANAGER || \ 58 (client_type) == SUBN_ADM_AGENT || \ 59 (client_type) == SUBN_ADM_MANAGER || \ 60 (client_type) == PERF_AGENT || \ 61 (client_type) == PERF_MANAGER || \ 62 (client_type) == BM_AGENT || \ 63 (client_type) == BM_MANAGER || \ 64 (client_type) == DEV_MGT_AGENT || \ 65 (client_type) == DEV_MGT_MANAGER || \ 66 (client_type) == COMM_MGT_MANAGER_AGENT || \ 67 (client_type) == SNMP_MANAGER_AGENT || \ 68 (client_type) == VENDOR_09_MANAGER_AGENT || \ 69 (client_type) == VENDOR_0A_MANAGER_AGENT || \ 70 (client_type) == VENDOR_0B_MANAGER_AGENT || \ 71 (client_type) == VENDOR_0C_MANAGER_AGENT || \ 72 (client_type) == VENDOR_0D_MANAGER_AGENT || \ 73 (client_type) == VENDOR_0E_MANAGER_AGENT || \ 74 (client_type) == VENDOR_0F_MANAGER_AGENT || \ 75 (client_type) == VENDOR_30_MANAGER_AGENT || \ 76 (client_type) == VENDOR_31_MANAGER_AGENT || \ 77 (client_type) == VENDOR_32_MANAGER_AGENT || \ 78 (client_type) == VENDOR_33_MANAGER_AGENT || \ 79 (client_type) == VENDOR_34_MANAGER_AGENT || \ 80 (client_type) == VENDOR_35_MANAGER_AGENT || \ 81 (client_type) == VENDOR_36_MANAGER_AGENT || \ 82 (client_type) == VENDOR_37_MANAGER_AGENT || \ 83 (client_type) == VENDOR_38_MANAGER_AGENT || \ 84 (client_type) == VENDOR_39_MANAGER_AGENT || \ 85 (client_type) == VENDOR_3A_MANAGER_AGENT || \ 86 (client_type) == VENDOR_3B_MANAGER_AGENT || \ 87 (client_type) == VENDOR_3C_MANAGER_AGENT || \ 88 (client_type) == VENDOR_3D_MANAGER_AGENT || \ 89 (client_type) == VENDOR_3E_MANAGER_AGENT || \ 90 (client_type) == VENDOR_3F_MANAGER_AGENT || \ 91 (client_type) == VENDOR_40_MANAGER_AGENT || \ 92 (client_type) == VENDOR_41_MANAGER_AGENT || \ 93 (client_type) == VENDOR_42_MANAGER_AGENT || \ 94 (client_type) == VENDOR_43_MANAGER_AGENT || \ 95 (client_type) == VENDOR_44_MANAGER_AGENT || \ 96 (client_type) == VENDOR_45_MANAGER_AGENT || \ 97 (client_type) == VENDOR_46_MANAGER_AGENT || \ 98 (client_type) == VENDOR_47_MANAGER_AGENT || \ 99 (client_type) == VENDOR_48_MANAGER_AGENT || \ 100 (client_type) == VENDOR_49_MANAGER_AGENT || \ 101 (client_type) == VENDOR_4A_MANAGER_AGENT || \ 102 (client_type) == VENDOR_4B_MANAGER_AGENT || \ 103 (client_type) == VENDOR_4C_MANAGER_AGENT || \ 104 (client_type) == VENDOR_4D_MANAGER_AGENT || \ 105 (client_type) == VENDOR_4E_MANAGER_AGENT || \ 106 (client_type) == VENDOR_4F_MANAGER_AGENT || \ 107 (client_type) == APPLICATION_10_MANAGER_AGENT || \ 108 (client_type) == APPLICATION_11_MANAGER_AGENT || \ 109 (client_type) == APPLICATION_12_MANAGER_AGENT || \ 110 (client_type) == APPLICATION_13_MANAGER_AGENT || \ 111 (client_type) == APPLICATION_14_MANAGER_AGENT || \ 112 (client_type) == APPLICATION_15_MANAGER_AGENT || \ 113 (client_type) == APPLICATION_16_MANAGER_AGENT || \ 114 (client_type) == APPLICATION_17_MANAGER_AGENT || \ 115 (client_type) == APPLICATION_18_MANAGER_AGENT || \ 116 (client_type) == APPLICATION_19_MANAGER_AGENT || \ 117 (client_type) == APPLICATION_1A_MANAGER_AGENT || \ 118 (client_type) == APPLICATION_1B_MANAGER_AGENT || \ 119 (client_type) == APPLICATION_1C_MANAGER_AGENT || \ 120 (client_type) == APPLICATION_1D_MANAGER_AGENT || \ 121 (client_type) == APPLICATION_1E_MANAGER_AGENT || \ 122 (client_type) == APPLICATION_1F_MANAGER_AGENT || \ 123 (client_type) == APPLICATION_20_MANAGER_AGENT || \ 124 (client_type) == APPLICATION_21_MANAGER_AGENT || \ 125 (client_type) == APPLICATION_22_MANAGER_AGENT || \ 126 (client_type) == APPLICATION_23_MANAGER_AGENT || \ 127 (client_type) == APPLICATION_24_MANAGER_AGENT || \ 128 (client_type) == APPLICATION_25_MANAGER_AGENT || \ 129 (client_type) == APPLICATION_26_MANAGER_AGENT || \ 130 (client_type) == APPLICATION_27_MANAGER_AGENT || \ 131 (client_type) == APPLICATION_28_MANAGER_AGENT || \ 132 (client_type) == APPLICATION_29_MANAGER_AGENT || \ 133 (client_type) == APPLICATION_2A_MANAGER_AGENT || \ 134 (client_type) == APPLICATION_2B_MANAGER_AGENT || \ 135 (client_type) == APPLICATION_2C_MANAGER_AGENT || \ 136 (client_type) == APPLICATION_2D_MANAGER_AGENT || \ 137 (client_type) == APPLICATION_2E_MANAGER_AGENT || \ 138 (client_type) == APPLICATION_2F_MANAGER_AGENT || \ 139 (client_type) == UNIVERSAL_CLASS) 140 141 static ibmf_ci_t *ibmf_i_lookup_ci(ib_guid_t ci_guid); 142 static int ibmf_i_init_ci(ibmf_register_info_t *client_infop, 143 ibmf_ci_t *cip); 144 static void ibmf_i_uninit_ci(ibmf_ci_t *cip); 145 static void ibmf_i_init_ci_done(ibmf_ci_t *cip); 146 static void ibmf_i_uninit_ci_done(ibmf_ci_t *cip); 147 static int ibmf_i_init_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp); 148 static void ibmf_i_uninit_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp); 149 static int ibmf_i_init_cqs(ibmf_ci_t *cip); 150 static void ibmf_i_fini_cqs(ibmf_ci_t *cip); 151 static void ibmf_i_init_qplist(ibmf_ci_t *ibmf_cip); 152 static void ibmf_i_fini_qplist(ibmf_ci_t *ibmf_cip); 153 static int ibmf_i_lookup_client_by_info(ibmf_ci_t *ibmf_cip, 154 ibmf_register_info_t *ir_client, ibmf_client_t **clientpp); 155 156 /* 157 * ibmf_init(): 158 * Initializes module state and registers with the IBT framework. 159 * Returns 0 if initialization was successful, else returns non-zero. 160 */ 161 int 162 ibmf_init(void) 163 { 164 ibt_status_t status; 165 ibt_clnt_hdl_t ibmf_ibt_handle; 166 167 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_start, 168 IBMF_TNF_TRACE, "", "ibmf_init() enter\n"); 169 170 /* setup the IBT module information */ 171 ibmf_statep->ibmf_ibt_modinfo.mi_ibt_version = IBTI_V1; 172 ibmf_statep->ibmf_ibt_modinfo.mi_clnt_class = IBT_IBMA; 173 ibmf_statep->ibmf_ibt_modinfo.mi_async_handler 174 = ibmf_ibt_async_handler; 175 ibmf_statep->ibmf_ibt_modinfo.mi_reserved = NULL; 176 ibmf_statep->ibmf_ibt_modinfo.mi_clnt_name = "ibmf"; 177 178 /* setup a connection to IB transport layer (IBTF) */ 179 status = ibt_attach(&ibmf_statep->ibmf_ibt_modinfo, (void *)NULL, 180 (void *)NULL, (void *)&ibmf_ibt_handle); 181 if (status != IBT_SUCCESS) { 182 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_init_err, 183 IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg, 184 "ibt attach failed", tnf_uint, status, status); 185 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_end, 186 IBMF_TNF_TRACE, "", "ibmf_init() exit\n"); 187 return (1); 188 } 189 190 /* initialize the IBMF state context */ 191 ibmf_statep->ibmf_ibt_handle = ibmf_ibt_handle; 192 ibmf_statep->ibmf_ci_list = (ibmf_ci_t *)NULL; 193 ibmf_statep->ibmf_ci_list_tail = (ibmf_ci_t *)NULL; 194 mutex_init(&ibmf_statep->ibmf_mutex, NULL, MUTEX_DRIVER, NULL); 195 ibmf_statep->ibmf_cq_handler = ibmf_i_mad_completions; 196 197 ibmf_statep->ibmf_taskq = taskq_create("ibmf_taskq", IBMF_TASKQ_1THREAD, 198 MINCLSYSPRI, 1, ibmf_taskq_max_tasks, TASKQ_PREPOPULATE); 199 200 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_init_end, 201 IBMF_TNF_TRACE, "", "ibmf_init() exit\n"); 202 203 return (0); 204 } 205 206 /* 207 * ibmf_fini(): 208 * Cleans up module state resources and unregisters from IBT framework. 209 */ 210 int 211 ibmf_fini(void) 212 { 213 ibmf_ci_t *cip; 214 ibmf_ci_t *tcip; 215 ibt_status_t status; 216 217 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_start, 218 IBMF_TNF_TRACE, "", "ibmf_fini() enter\n"); 219 220 ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex)); 221 222 mutex_enter(&ibmf_statep->ibmf_mutex); 223 224 /* free all the Channel Interface (CI) context structures */ 225 cip = ibmf_statep->ibmf_ci_list; 226 tcip = NULL; 227 while (cip != (ibmf_ci_t *)NULL) { 228 229 mutex_enter(&cip->ci_mutex); 230 ASSERT((cip->ci_state == IBMF_CI_STATE_PRESENT && cip->ci_ref == 231 0) || (cip->ci_state == IBMF_CI_STATE_GONE)); 232 ASSERT(cip->ci_init_state == IBMF_CI_INIT_HCA_LINKED); 233 ASSERT(cip->ci_qp_list == NULL && cip->ci_qp_list_tail == NULL); 234 if (tcip != (ibmf_ci_t *)NULL) 235 tcip->ci_next = cip->ci_next; 236 if (ibmf_statep->ibmf_ci_list_tail == cip) 237 ibmf_statep->ibmf_ci_list_tail = NULL; 238 if (ibmf_statep->ibmf_ci_list == cip) 239 ibmf_statep->ibmf_ci_list = cip->ci_next; 240 tcip = cip->ci_next; 241 mutex_exit(&cip->ci_mutex); 242 /* free up the ci structure */ 243 if (cip->ci_port_kstatp != NULL) { 244 kstat_delete(cip->ci_port_kstatp); 245 } 246 mutex_destroy(&cip->ci_mutex); 247 mutex_destroy(&cip->ci_clients_mutex); 248 mutex_destroy(&cip->ci_wqe_mutex); 249 cv_destroy(&cip->ci_state_cv); 250 cv_destroy(&cip->ci_wqes_cv); 251 kmem_free((void *) cip, sizeof (ibmf_ci_t)); 252 cip = tcip; 253 } 254 255 ASSERT(ibmf_statep->ibmf_ci_list == NULL); 256 ASSERT(ibmf_statep->ibmf_ci_list_tail == NULL); 257 258 taskq_destroy(ibmf_statep->ibmf_taskq); 259 260 mutex_exit(&ibmf_statep->ibmf_mutex); 261 262 /* detach from IBTF */ 263 status = ibt_detach(ibmf_statep->ibmf_ibt_handle); 264 if (status != IBT_SUCCESS) { 265 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_fini_err, 266 IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg, 267 "ibt detach error", tnf_uint, status, status); 268 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_end, 269 IBMF_TNF_TRACE, "", "ibmf_fini() exit\n"); 270 return (1); 271 } 272 273 mutex_destroy(&ibmf_statep->ibmf_mutex); 274 275 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_fini_end, 276 IBMF_TNF_TRACE, "", "ibmf_fini() exit\n"); 277 278 return (0); 279 } 280 281 /* 282 * ibmf_i_validate_class_mask(): 283 * Checks client type value in client information structure. 284 */ 285 int 286 ibmf_i_validate_class_mask(ibmf_register_info_t *client_infop) 287 { 288 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 289 ibmf_i_validate_class_mask_start, IBMF_TNF_TRACE, "", 290 "ibmf_i_validate_class_mask() enter, client_infop = %p\n", 291 tnf_opaque, client_infop, client_infop); 292 293 if (IBMF_VALID_CLIENT_TYPE(client_infop->ir_client_class) == B_FALSE) { 294 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 295 ibmf_i_validate_class_mask_err, IBMF_TNF_ERROR, "", 296 "%s, class = %x\n", tnf_string, msg, 297 "invalid class", tnf_uint, class, 298 client_infop->ir_client_class); 299 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 300 ibmf_i_validate_class_mask_end, IBMF_TNF_TRACE, "", 301 "ibmf_i_validate_class_mask() exit\n"); 302 return (IBMF_BAD_CLASS); 303 } 304 305 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_validate_class_mask_end, 306 IBMF_TNF_TRACE, "", "ibmf_i_validate_class_mask() exit\n"); 307 return (IBMF_SUCCESS); 308 } 309 310 /* 311 * ibmf_i_validate_ci_guid_and_port(): 312 * Checks validity of port number and HCA GUID at client 313 * registration time. 314 */ 315 int 316 ibmf_i_validate_ci_guid_and_port(ib_guid_t hca_guid, uint8_t port_num) 317 { 318 ibt_status_t status; 319 ibt_hca_attr_t hca_attrs; 320 321 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 322 ibmf_i_validate_ci_guid_and_port_start, IBMF_TNF_TRACE, "", 323 "ibmf_i_validate_ci_guid_and_port() enter, hca_guid = %x, " 324 "port_num = %d\n", tnf_opaque, hca_guid, hca_guid, 325 tnf_uint, port_num, port_num); 326 327 /* check for incorrect port number specification */ 328 if (port_num == 0) { 329 IBMF_TRACE_1(IBMF_TNF_NODEBUG, 1, 330 ibmf_i_validate_ci_guid_and_port_err, IBMF_TNF_ERROR, "", 331 "%s\n", tnf_string, msg, "port num is 0"); 332 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 333 ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "", 334 "ibmf_i_validate_ci_guid_and_port() exit\n"); 335 return (IBMF_BAD_PORT); 336 } 337 338 /* call IB transport layer for HCA attributes */ 339 status = ibt_query_hca_byguid(hca_guid, &hca_attrs); 340 if (status != IBT_SUCCESS) { 341 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 342 ibmf_i_validate_ci_guid_and_port_err, 343 IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg, 344 "query_hca_guid failed", tnf_uint, status, status); 345 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 346 ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "", 347 "ibmf_i_validate_ci_guid_and_port() exit\n"); 348 return (IBMF_BAD_NODE); 349 } 350 351 /* check if the specified port number is within the HCAs range */ 352 if (port_num > hca_attrs.hca_nports) { 353 IBMF_TRACE_3(IBMF_TNF_NODEBUG, 1, 354 ibmf_i_validate_ci_guid_and_port_err, IBMF_TNF_ERROR, "", 355 "%s, num = %d, hca_ports = %d\n", 356 tnf_string, msg, "port num > valid ports", 357 tnf_uint, num, port_num, tnf_uint, hca_nports, 358 hca_attrs.hca_nports); 359 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 360 ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "", 361 "ibmf_i_validate_ci_guid_and_port() exit\n"); 362 return (IBMF_BAD_PORT); 363 } 364 365 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 366 ibmf_i_validate_ci_guid_and_port_end, IBMF_TNF_TRACE, "", 367 "ibmf_i_validate_ci_guid_and_port() exit\n"); 368 return (IBMF_SUCCESS); 369 } 370 371 /* 372 * ibmf_i_lookup_ci(): 373 * Lookup the ci and return if found. If the CI is not found, returns 374 * NULL. 375 */ 376 static ibmf_ci_t * 377 ibmf_i_lookup_ci(ib_guid_t ci_guid) 378 { 379 ibmf_ci_t *cip = NULL; 380 381 ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex)); 382 383 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_lookup_ci_start, 384 IBMF_TNF_TRACE, "", "ibmf_i_lookup_ci(): enter, guid = 0x%x\n", 385 tnf_uint64, guid, ci_guid); 386 387 /* walk the CI list looking for one that matches the provided GUID */ 388 mutex_enter(&ibmf_statep->ibmf_mutex); 389 cip = ibmf_statep->ibmf_ci_list; 390 while (cip != (ibmf_ci_t *)NULL) { 391 if (ci_guid == cip->ci_node_guid) { 392 /* found it in our list */ 393 break; 394 } 395 cip = cip->ci_next; 396 } 397 mutex_exit(&ibmf_statep->ibmf_mutex); 398 399 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_lookup_ci_end, 400 IBMF_TNF_TRACE, "", "ibmf_i_lookup_ci() exit\n"); 401 402 return (cip); 403 } 404 405 /* 406 * ibmf_i_get_ci(): 407 * Get the CI structure based on the HCA GUID from a list if it exists. 408 * If the CI structure does not exist, and the HCA GUID is valid, 409 * create a new CI structure and add it to the list. 410 */ 411 int 412 ibmf_i_get_ci(ibmf_register_info_t *client_infop, ibmf_ci_t **cipp) 413 { 414 ibmf_ci_t *cip; 415 ibt_status_t status; 416 boolean_t invalid = B_FALSE; 417 ibt_hca_attr_t hca_attrs; 418 ibmf_port_kstat_t *ksp; 419 420 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_start, 421 IBMF_TNF_TRACE, "", "ibmf_i_get_ci() enter, clinfop = %p\n", 422 tnf_opaque, client_infop, client_infop); 423 424 /* look for a CI context with a matching GUID */ 425 cip = ibmf_i_lookup_ci(client_infop->ir_ci_guid); 426 427 if (cip == NULL) { 428 429 /* 430 * attempt to create the ci. First, verify the ci exists. 431 * If it exists, allocate ci memory and insert in the ci list. 432 * It is possible that some other thread raced with us 433 * and inserted created ci while we are blocked in 434 * allocating memory. Check for that case and if that is indeed 435 * the case, free up what we allocated and try to get a 436 * reference count on the ci that the other thread added. 437 */ 438 status = ibt_query_hca_byguid(client_infop->ir_ci_guid, 439 &hca_attrs); 440 if (status == IBT_SUCCESS) { 441 442 ibmf_ci_t *tcip; 443 char buf[128]; 444 445 /* allocate memory for the CI structure */ 446 cip = (ibmf_ci_t *)kmem_zalloc(sizeof (ibmf_ci_t), 447 KM_SLEEP); 448 449 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cip)) 450 451 mutex_init(&cip->ci_mutex, NULL, MUTEX_DRIVER, NULL); 452 mutex_init(&cip->ci_clients_mutex, NULL, MUTEX_DRIVER, 453 NULL); 454 mutex_init(&cip->ci_wqe_mutex, NULL, MUTEX_DRIVER, 455 NULL); 456 cv_init(&cip->ci_state_cv, NULL, CV_DRIVER, NULL); 457 cv_init(&cip->ci_wqes_cv, NULL, CV_DRIVER, NULL); 458 459 (void) sprintf(buf, "r%08X", 460 (uint32_t)client_infop->ir_ci_guid); 461 mutex_enter(&cip->ci_mutex); 462 463 cip->ci_state = IBMF_CI_STATE_PRESENT; 464 cip->ci_node_guid = client_infop->ir_ci_guid; 465 466 /* set up per CI kstats */ 467 (void) sprintf(buf, "ibmf_%016" PRIx64 "_%d_stat", 468 client_infop->ir_ci_guid, 469 client_infop->ir_port_num); 470 if ((cip->ci_port_kstatp = kstat_create("ibmf", 0, buf, 471 "misc", KSTAT_TYPE_NAMED, 472 sizeof (ibmf_port_kstat_t) / sizeof (kstat_named_t), 473 KSTAT_FLAG_WRITABLE)) == NULL) { 474 mutex_exit(&cip->ci_mutex); 475 mutex_destroy(&cip->ci_mutex); 476 mutex_destroy(&cip->ci_clients_mutex); 477 mutex_destroy(&cip->ci_wqe_mutex); 478 cv_destroy(&cip->ci_state_cv); 479 cv_destroy(&cip->ci_wqes_cv); 480 kmem_free((void *)cip, sizeof (ibmf_ci_t)); 481 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 482 ibmf_i_get_ci_err, IBMF_TNF_ERROR, "", 483 "%s\n", tnf_string, msg, 484 "kstat create failed"); 485 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 486 ibmf_i_get_ci_end, IBMF_TNF_TRACE, "", 487 "ibmf_i_get_ci() exit\n"); 488 return (IBMF_NO_RESOURCES); 489 } 490 ksp = (ibmf_port_kstat_t *)cip->ci_port_kstatp->ks_data; 491 kstat_named_init(&ksp->clients_registered, 492 "clients_registered", KSTAT_DATA_UINT32); 493 kstat_named_init(&ksp->client_regs_failed, 494 "client_registrations_failed", KSTAT_DATA_UINT32); 495 kstat_named_init(&ksp->send_wqes_alloced, 496 "send_wqes_allocated", KSTAT_DATA_UINT32); 497 kstat_named_init(&ksp->recv_wqes_alloced, 498 "receive_wqes_allocated", KSTAT_DATA_UINT32); 499 kstat_named_init(&ksp->swqe_allocs_failed, 500 "send_wqe_allocs_failed", KSTAT_DATA_UINT32); 501 kstat_named_init(&ksp->rwqe_allocs_failed, 502 "recv_wqe_allocs_failed", KSTAT_DATA_UINT32); 503 kstat_install(cip->ci_port_kstatp); 504 505 mutex_exit(&cip->ci_mutex); 506 507 mutex_enter(&ibmf_statep->ibmf_mutex); 508 509 tcip = ibmf_statep->ibmf_ci_list; 510 while (tcip != (ibmf_ci_t *)NULL) { 511 if (client_infop->ir_ci_guid == 512 tcip->ci_node_guid) { 513 /* found it in our list */ 514 break; 515 } 516 tcip = tcip->ci_next; 517 } 518 519 /* if the ci isn't on the list, add it */ 520 if (tcip == NULL) { 521 cip->ci_next = NULL; 522 523 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip)) 524 525 if (ibmf_statep->ibmf_ci_list_tail != NULL) 526 ibmf_statep->ibmf_ci_list_tail-> 527 ci_next = cip; 528 if (ibmf_statep->ibmf_ci_list == NULL) 529 ibmf_statep->ibmf_ci_list = cip; 530 ibmf_statep->ibmf_ci_list_tail = cip; 531 532 mutex_enter(&cip->ci_mutex); 533 cip->ci_init_state |= IBMF_CI_INIT_HCA_LINKED; 534 mutex_exit(&cip->ci_mutex); 535 536 } else { 537 /* free cip and set it to the one on the list */ 538 kstat_delete(cip->ci_port_kstatp); 539 mutex_destroy(&cip->ci_mutex); 540 mutex_destroy(&cip->ci_clients_mutex); 541 mutex_destroy(&cip->ci_wqe_mutex); 542 cv_destroy(&cip->ci_state_cv); 543 cv_destroy(&cip->ci_wqes_cv); 544 kmem_free((void *)cip, sizeof (ibmf_ci_t)); 545 546 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip)) 547 548 cip = tcip; 549 } 550 mutex_exit(&ibmf_statep->ibmf_mutex); 551 } else { 552 /* we didn't find it and the CI doesn't exist */ 553 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1, 554 ibmf_i_get_ci_err, IBMF_TNF_ERROR, "", "%s\n", 555 tnf_string, msg, "GUID doesn't exist"); 556 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 557 ibmf_i_get_ci_end, IBMF_TNF_TRACE, "", 558 "ibmf_i_get_ci() exit\n"); 559 return (IBMF_TRANSPORT_FAILURE); 560 } 561 } 562 563 ASSERT(cip != NULL); 564 565 /* 566 * We now have a CI context structure, either found it on the list, 567 * or created it. 568 * We now proceed to intialize the CI context. 569 */ 570 for (;;) { 571 mutex_enter(&cip->ci_mutex); 572 573 /* CI is INITED & no state change in progress; we are all set */ 574 if (cip->ci_state == IBMF_CI_STATE_INITED && (cip-> 575 ci_state_flags & (IBMF_CI_STATE_INVALIDATING | 576 IBMF_CI_STATE_UNINITING)) == 0) { 577 578 cip->ci_ref++; 579 mutex_exit(&cip->ci_mutex); 580 581 break; 582 } 583 584 /* CI is PRESENT; transition it to INITED */ 585 if (cip->ci_state == IBMF_CI_STATE_PRESENT && (cip-> 586 ci_state_flags & (IBMF_CI_STATE_INVALIDATING | 587 IBMF_CI_STATE_INITING)) == 0) { 588 589 /* mark state as initing and init the ci */ 590 cip->ci_state_flags |= IBMF_CI_STATE_INITING; 591 mutex_exit(&cip->ci_mutex); 592 593 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cip)) 594 595 if (ibmf_i_init_ci(client_infop, cip) != IBMF_SUCCESS) { 596 invalid = B_TRUE; 597 break; 598 } 599 600 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cip)) 601 602 continue; 603 } 604 605 /* 606 * If CI is GONE and no validation is in progress, we should 607 * return failure. Also, if CI is INITED but in the process of 608 * being made GONE (ie., a hot remove in progress), return 609 * failure. 610 */ 611 if ((cip->ci_state == IBMF_CI_STATE_GONE && (cip-> 612 ci_state_flags & IBMF_CI_STATE_VALIDATING) == 0) || 613 (cip->ci_state == IBMF_CI_STATE_INITED && (cip-> 614 ci_state_flags & IBMF_CI_STATE_INVALIDATING) != 0)) { 615 616 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 617 ibmf_i_get_ci_err, IBMF_TNF_ERROR, "", 618 "ci_state = %x, ci_state_flags = %x\n", 619 tnf_opaque, cip->ci_state, cip->ci_state, 620 tnf_opaque, cip->ci_state_flags, 621 cip->ci_state_flags); 622 623 invalid = B_TRUE; 624 mutex_exit(&cip->ci_mutex); 625 626 break; 627 } 628 629 /* a state change in progress; block waiting for state change */ 630 if (cip->ci_state_flags & IBMF_CI_STATE_VALIDATING) 631 cip->ci_state_flags |= IBMF_CI_STATE_VALIDATE_WAIT; 632 else if (cip->ci_state_flags & IBMF_CI_STATE_INITING) 633 cip->ci_state_flags |= IBMF_CI_STATE_INIT_WAIT; 634 else if (cip->ci_state_flags & IBMF_CI_STATE_UNINITING) 635 cip->ci_state_flags |= IBMF_CI_STATE_UNINIT_WAIT; 636 637 cv_wait(&cip->ci_state_cv, &cip->ci_mutex); 638 639 mutex_exit(&cip->ci_mutex); 640 } 641 642 if (invalid == B_TRUE) { 643 IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L2, ibmf_i_get_ci_err, 644 IBMF_TNF_ERROR, "", "ibmf_i_get_ci() error\n"); 645 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end, 646 IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n"); 647 return (IBMF_FAILURE); 648 } 649 650 if (cip != NULL) { 651 *cipp = cip; 652 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end, 653 IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n"); 654 return (IBMF_SUCCESS); 655 } else { 656 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_ci_end, 657 IBMF_TNF_TRACE, "", "ibmf_i_get_ci() exit\n"); 658 return (IBMF_FAILURE); 659 } 660 } 661 662 /* 663 * ibmf_i_release_ci(): 664 * Drop the reference count for the CI. 665 */ 666 void 667 ibmf_i_release_ci(ibmf_ci_t *cip) 668 { 669 uint_t ref; 670 671 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_ci_start, 672 IBMF_TNF_TRACE, "", "ibmf_i_release_ci() enter, cip = %p\n", 673 tnf_opaque, cip, cip); 674 675 ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex)); 676 677 mutex_enter(&cip->ci_mutex); 678 ref = cip->ci_ref--; 679 if (ref == 1) { 680 ASSERT(cip->ci_state == IBMF_CI_STATE_INITED); 681 cip->ci_state_flags |= IBMF_CI_STATE_UNINITING; 682 } 683 mutex_exit(&cip->ci_mutex); 684 685 if (ref == 1) { 686 ibmf_i_uninit_ci(cip); 687 } 688 689 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_ci_end, 690 IBMF_TNF_TRACE, "", "ibmf_i_release_ci() exit\n"); 691 } 692 693 /* 694 * ibmf_i_init_ci(): 695 * Initialize the CI structure by setting up the HCA, allocating 696 * protection domains, completion queues, a pool of WQEs. 697 */ 698 /* ARGSUSED */ 699 static int 700 ibmf_i_init_ci(ibmf_register_info_t *client_infop, ibmf_ci_t *cip) 701 { 702 ibt_pd_hdl_t pd; 703 ibt_status_t status; 704 ib_guid_t ci_guid; 705 ibt_hca_attr_t hca_attrs; 706 ibt_hca_hdl_t hca_handle; 707 ibt_pd_flags_t pd_flags = IBT_PD_NO_FLAGS; 708 boolean_t error = B_FALSE; 709 int ibmfstatus = IBMF_SUCCESS; 710 char errmsg[128]; 711 712 _NOTE(ASSUMING_PROTECTED(*cip)) 713 714 ASSERT(MUTEX_NOT_HELD(&ibmf_statep->ibmf_mutex)); 715 ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex)); 716 717 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_start, 718 IBMF_TNF_TRACE, "", "ibmf_i_init_ci() enter, cip = %p\n", 719 tnf_opaque, ibmf_ci, cip); 720 721 mutex_enter(&cip->ci_mutex); 722 ci_guid = cip->ci_node_guid; 723 ASSERT(cip->ci_state == IBMF_CI_STATE_PRESENT); 724 ASSERT((cip->ci_state_flags & IBMF_CI_STATE_INITING) != 0); 725 mutex_exit(&cip->ci_mutex); 726 727 /* set up a connection to the HCA specified by the GUID */ 728 status = ibt_open_hca(ibmf_statep->ibmf_ibt_handle, ci_guid, 729 &hca_handle); 730 ASSERT(status != IBT_HCA_IN_USE); 731 if (status != IBT_SUCCESS) { 732 ibmf_i_init_ci_done(cip); 733 (void) sprintf(errmsg, "ibt open hca failed, status = 0x%x", 734 status); 735 error = B_TRUE; 736 ibmfstatus = IBMF_TRANSPORT_FAILURE; 737 goto bail; 738 } 739 740 /* get the HCA attributes */ 741 status = ibt_query_hca(hca_handle, &hca_attrs); 742 if (status != IBT_SUCCESS) { 743 (void) ibt_close_hca(hca_handle); 744 ibmf_i_init_ci_done(cip); 745 (void) sprintf(errmsg, "ibt query hca failed, status = 0x%x", 746 status); 747 error = B_TRUE; 748 ibmfstatus = IBMF_TRANSPORT_FAILURE; 749 goto bail; 750 } 751 752 /* allocate a Protection Domain */ 753 status = ibt_alloc_pd(hca_handle, pd_flags, &pd); 754 if (status != IBT_SUCCESS) { 755 (void) ibt_close_hca(hca_handle); 756 ibmf_i_init_ci_done(cip); 757 (void) sprintf(errmsg, "alloc PD failed, status = 0x%x", 758 status); 759 error = B_TRUE; 760 ibmfstatus = IBMF_TRANSPORT_FAILURE; 761 goto bail; 762 } 763 764 /* init the ci */ 765 mutex_enter(&cip->ci_mutex); 766 cip->ci_nports = hca_attrs.hca_nports; 767 cip->ci_vendor_id = hca_attrs.hca_vendor_id; 768 cip->ci_device_id = hca_attrs.hca_device_id; 769 cip->ci_ci_handle = hca_handle; 770 cip->ci_pd = pd; 771 cip->ci_init_state |= IBMF_CI_INIT_HCA_INITED; 772 mutex_exit(&cip->ci_mutex); 773 774 /* initialize cqs */ 775 if (ibmf_i_init_cqs(cip) != IBMF_SUCCESS) { 776 (void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd); 777 mutex_enter(&cip->ci_mutex); 778 cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED; 779 mutex_exit(&cip->ci_mutex); 780 (void) ibt_close_hca(cip->ci_ci_handle); 781 ibmf_i_init_ci_done(cip); 782 (void) sprintf(errmsg, "init CQs failed"); 783 error = B_TRUE; 784 ibmfstatus = IBMF_FAILURE; 785 goto bail; 786 } 787 788 /* initialize wqes */ 789 if (ibmf_i_init_wqes(cip) != IBMF_SUCCESS) { 790 ibmf_i_fini_cqs(cip); 791 (void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd); 792 mutex_enter(&cip->ci_mutex); 793 cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED; 794 mutex_exit(&cip->ci_mutex); 795 (void) ibt_close_hca(cip->ci_ci_handle); 796 ibmf_i_init_ci_done(cip); 797 (void) sprintf(errmsg, "init WQEs failed"); 798 error = B_TRUE; 799 ibmfstatus = IBMF_FAILURE; 800 goto bail; 801 } 802 803 /* initialize the UD destination structure pool */ 804 ibmf_i_init_ud_dest(cip); 805 806 /* initialize the QP list */ 807 ibmf_i_init_qplist(cip); 808 809 /* initialize condition variable, state, and enable CQ notification */ 810 cip->ci_init_state |= IBMF_CI_INIT_MUTEX_CV_INITED; 811 (void) ibt_enable_cq_notify(cip->ci_cq_handle, IBT_NEXT_COMPLETION); 812 (void) ibt_enable_cq_notify(cip->ci_alt_cq_handle, IBT_NEXT_COMPLETION); 813 814 /* set state to INITED */ 815 mutex_enter(&cip->ci_mutex); 816 cip->ci_state = IBMF_CI_STATE_INITED; 817 mutex_exit(&cip->ci_mutex); 818 819 /* wake up waiters blocked on an initialization done event */ 820 ibmf_i_init_ci_done(cip); 821 822 bail: 823 if (error) { 824 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_ci_err, 825 IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg, 826 errmsg, tnf_uint, ibmfstatus, ibmfstatus); 827 } 828 829 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_end, 830 IBMF_TNF_TRACE, "", "ibmf_i_init_ci() exit, cip = %p\n", 831 tnf_opaque, ibmf_ci, cip); 832 833 return (ibmfstatus); 834 } 835 836 /* 837 * ibmf_i_uninit_ci(): 838 * Free up the resources allocated when initalizing the CI structure. 839 */ 840 static void 841 ibmf_i_uninit_ci(ibmf_ci_t *cip) 842 { 843 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_start, 844 IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci() enter, cip = %p\n", 845 tnf_opaque, cip, cip); 846 847 ASSERT(MUTEX_HELD(&cip->ci_mutex) == 0); 848 849 /* clean up the QP list */ 850 ibmf_i_fini_qplist(cip); 851 852 /* empty completions directly */ 853 ibmf_i_mad_completions(cip->ci_cq_handle, (void*)cip); 854 ibmf_i_mad_completions(cip->ci_alt_cq_handle, (void*)cip); 855 856 mutex_enter(&cip->ci_mutex); 857 if (cip->ci_init_state & IBMF_CI_INIT_MUTEX_CV_INITED) { 858 cip->ci_init_state &= ~IBMF_CI_INIT_MUTEX_CV_INITED; 859 } 860 mutex_exit(&cip->ci_mutex); 861 862 /* clean up the UD destination structure pool */ 863 ibmf_i_fini_ud_dest(cip); 864 865 /* clean up any WQE caches */ 866 ibmf_i_fini_wqes(cip); 867 868 /* free up the completion queues */ 869 ibmf_i_fini_cqs(cip); 870 871 /* free up the protection domain */ 872 (void) ibt_free_pd(cip->ci_ci_handle, cip->ci_pd); 873 874 /* close the HCA connection */ 875 (void) ibt_close_hca(cip->ci_ci_handle); 876 877 /* set state down to PRESENT */ 878 mutex_enter(&cip->ci_mutex); 879 cip->ci_init_state &= ~IBMF_CI_INIT_HCA_INITED; 880 cip->ci_state = IBMF_CI_STATE_PRESENT; 881 mutex_exit(&cip->ci_mutex); 882 883 /* wake up waiters blocked on an un-initialization done event */ 884 ibmf_i_uninit_ci_done(cip); 885 886 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_end, 887 IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci() exit\n"); 888 } 889 890 /* 891 * ibmf_i_init_ci_done(): 892 * Mark CI initialization as "done", and wake up any waiters. 893 */ 894 static void 895 ibmf_i_init_ci_done(ibmf_ci_t *cip) 896 { 897 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_done_start, 898 IBMF_TNF_TRACE, "", "ibmf_i_init_ci_done() enter, cip = %p\n", 899 tnf_opaque, cip, cip); 900 901 mutex_enter(&cip->ci_mutex); 902 cip->ci_state_flags &= ~IBMF_CI_STATE_INITING; 903 if (cip->ci_state_flags & IBMF_CI_STATE_INIT_WAIT) { 904 cip->ci_state_flags &= ~IBMF_CI_STATE_INIT_WAIT; 905 cv_broadcast(&cip->ci_state_cv); 906 } 907 mutex_exit(&cip->ci_mutex); 908 909 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_ci_done_end, 910 IBMF_TNF_TRACE, "", "ibmf_i_init_ci_done() exit\n"); 911 } 912 913 /* 914 * ibmf_i_uninit_ci_done(): 915 * Mark CI uninitialization as "done", and wake up any waiters. 916 */ 917 static void 918 ibmf_i_uninit_ci_done(ibmf_ci_t *cip) 919 { 920 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_done_start, 921 IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci_done() enter, cip = %p\n", 922 tnf_opaque, cip, cip); 923 924 mutex_enter(&cip->ci_mutex); 925 cip->ci_state_flags &= ~IBMF_CI_STATE_UNINITING; 926 if (cip->ci_state_flags & IBMF_CI_STATE_UNINIT_WAIT) { 927 cip->ci_state_flags &= ~IBMF_CI_STATE_UNINIT_WAIT; 928 cv_broadcast(&cip->ci_state_cv); 929 } 930 mutex_exit(&cip->ci_mutex); 931 932 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_ci_done_end, 933 IBMF_TNF_TRACE, "", "ibmf_i_uninit_ci_done() exit\n"); 934 } 935 936 /* 937 * ibmf_i_init_cqs(): 938 * Allocate a completion queue and set the CQ handler. 939 */ 940 static int 941 ibmf_i_init_cqs(ibmf_ci_t *cip) 942 { 943 ibt_status_t status; 944 ibt_cq_attr_t cq_attrs; 945 ibt_cq_hdl_t cq_handle; 946 uint32_t num_entries; 947 948 ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex)); 949 950 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_start, 951 IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() enter, cip = %p\n", 952 tnf_opaque, cip, cip); 953 954 /* 955 * Allocate completion queue handle. 956 * The CQ size should be a 2^n - 1 value to avoid excess CQ allocation 957 * as done by some HCAs when the CQ size is specified as a 2^n 958 * quantity. 959 */ 960 cq_attrs.cq_size = (cip->ci_nports * (ibmf_send_wqes_posted_per_qp + 961 ibmf_recv_wqes_posted_per_qp)) - 1; 962 963 cq_attrs.cq_sched = NULL; 964 cq_attrs.cq_flags = 0; 965 966 /* Get the CQ handle for the special QPs */ 967 status = ibt_alloc_cq(cip->ci_ci_handle, &cq_attrs, 968 &cq_handle, &num_entries); 969 if (status != IBT_SUCCESS) { 970 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_cqs_err, 971 IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg, 972 "ibt_alloc_cq failed", tnf_uint, ibt_status, status); 973 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end, 974 IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n"); 975 return (IBMF_TRANSPORT_FAILURE); 976 } 977 ibt_set_cq_handler(cq_handle, ibmf_statep->ibmf_cq_handler, cip); 978 cip->ci_cq_handle = cq_handle; 979 980 /* Get the CQ handle for the alternate QPs */ 981 status = ibt_alloc_cq(cip->ci_ci_handle, &cq_attrs, 982 &cq_handle, &num_entries); 983 if (status != IBT_SUCCESS) { 984 (void) ibt_free_cq(cip->ci_cq_handle); 985 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_cqs_err, 986 IBMF_TNF_ERROR, "", "%s, status = %d\n", tnf_string, msg, 987 "ibt_alloc_cq failed", tnf_uint, ibt_status, status); 988 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end, 989 IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n"); 990 return (IBMF_TRANSPORT_FAILURE); 991 } 992 ibt_set_cq_handler(cq_handle, ibmf_statep->ibmf_cq_handler, cip); 993 cip->ci_alt_cq_handle = cq_handle; 994 995 /* set state to CQ INITED */ 996 mutex_enter(&cip->ci_mutex); 997 cip->ci_init_state |= IBMF_CI_INIT_CQ_INITED; 998 mutex_exit(&cip->ci_mutex); 999 1000 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_cqs_end, 1001 IBMF_TNF_TRACE, "", "ibmf_i_init_cqs() exit\n"); 1002 1003 return (IBMF_SUCCESS); 1004 } 1005 1006 /* 1007 * ibmf_i_fini_cqs(): 1008 * Free up the completion queue 1009 */ 1010 static void 1011 ibmf_i_fini_cqs(ibmf_ci_t *cip) 1012 { 1013 ibt_status_t status; 1014 uint_t ci_init_state; 1015 1016 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_cqs_start, 1017 IBMF_TNF_TRACE, "", "ibmf_i_fini_cqs() enter, cip = %p\n", 1018 tnf_opaque, cip, cip); 1019 1020 mutex_enter(&cip->ci_mutex); 1021 ci_init_state = cip->ci_init_state; 1022 cip->ci_init_state &= ~IBMF_CI_INIT_CQ_INITED; 1023 mutex_exit(&cip->ci_mutex); 1024 1025 if (ci_init_state & IBMF_CI_INIT_CQ_INITED) { 1026 status = ibt_free_cq(cip->ci_alt_cq_handle); 1027 if (status != IBT_SUCCESS) { 1028 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3, 1029 ibmf_i_fini_cqs_err, IBMF_TNF_ERROR, "", 1030 "%s, status = %d\n", tnf_string, msg, 1031 "ibt free cqs failed", tnf_uint, status, status); 1032 } 1033 1034 status = ibt_free_cq(cip->ci_cq_handle); 1035 if (status != IBT_SUCCESS) { 1036 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L3, 1037 ibmf_i_fini_cqs_err, IBMF_TNF_ERROR, "", 1038 "%s, status = %d\n", tnf_string, msg, 1039 "ibt free cqs failed", tnf_uint, status, status); 1040 } 1041 } 1042 1043 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_cqs_end, 1044 IBMF_TNF_TRACE, "", "ibmf_i_fini_cqs() exit"); 1045 } 1046 1047 /* 1048 * ibmf_i_init_qplist(): 1049 * Set the QP list inited state flag 1050 */ 1051 static void 1052 ibmf_i_init_qplist(ibmf_ci_t *ibmf_cip) 1053 { 1054 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qplist_start, 1055 IBMF_TNF_TRACE, "", "ibmf_i_init_qplist() enter, cip = %p\n", 1056 tnf_opaque, cip, ibmf_cip); 1057 1058 mutex_enter(&ibmf_cip->ci_mutex); 1059 ASSERT((ibmf_cip->ci_init_state & IBMF_CI_INIT_QP_LIST_INITED) == 0); 1060 ASSERT(ibmf_cip->ci_qp_list == NULL && ibmf_cip->ci_qp_list_tail == 1061 NULL); 1062 cv_init(&ibmf_cip->ci_qp_cv, NULL, CV_DRIVER, NULL); 1063 ibmf_cip->ci_init_state |= IBMF_CI_INIT_QP_LIST_INITED; 1064 mutex_exit(&ibmf_cip->ci_mutex); 1065 1066 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qplist_end, 1067 IBMF_TNF_TRACE, "", "ibmf_i_init_qplist() exit\n"); 1068 } 1069 1070 /* 1071 * ibmf_i_fini_qplist(): 1072 * Clean up the QP list 1073 */ 1074 static void 1075 ibmf_i_fini_qplist(ibmf_ci_t *ibmf_cip) 1076 { 1077 ibmf_qp_t *qpp; 1078 ibmf_alt_qp_t *altqpp; 1079 ibt_status_t status; 1080 1081 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_qplist_start, 1082 IBMF_TNF_TRACE, "", "ibmf_i_fini_qplist() enter, cip = %p\n", 1083 tnf_opaque, cip, ibmf_cip); 1084 1085 mutex_enter(&ibmf_cip->ci_mutex); 1086 1087 if ((ibmf_cip->ci_init_state & IBMF_CI_INIT_QP_LIST_INITED) != 0) { 1088 1089 /* walk through the qp list and free the memory */ 1090 qpp = ibmf_cip->ci_qp_list; 1091 while (qpp != NULL) { 1092 /* Remove qpp from the list */ 1093 ibmf_cip->ci_qp_list = qpp->iq_next; 1094 1095 ASSERT(qpp->iq_qp_ref == 0); 1096 ASSERT(qpp->iq_flags == IBMF_QP_FLAGS_INVALID); 1097 mutex_exit(&ibmf_cip->ci_mutex); 1098 if (qpp->iq_qp_handle != NULL) { 1099 /* Flush the special QP */ 1100 status = ibt_flush_qp(qpp->iq_qp_handle); 1101 if (status != IBT_SUCCESS) { 1102 IBMF_TRACE_2(IBMF_TNF_NODEBUG, 1103 DPRINT_L1, ibmf_i_fini_qplist_err, 1104 IBMF_TNF_ERROR, "", 1105 "%s, status = %d\n", tnf_string, 1106 msg, "ibt_flush_qp returned error", 1107 tnf_int, status, status); 1108 } 1109 1110 /* Grab the ci_mutex mutex before waiting */ 1111 mutex_enter(&ibmf_cip->ci_mutex); 1112 1113 /* Wait if WQEs for special QPs are alloced */ 1114 while (ibmf_cip->ci_wqes_alloced != 0) { 1115 cv_wait(&ibmf_cip->ci_wqes_cv, 1116 &ibmf_cip->ci_mutex); 1117 } 1118 1119 mutex_exit(&ibmf_cip->ci_mutex); 1120 1121 /* Free the special QP */ 1122 status = ibt_free_qp(qpp->iq_qp_handle); 1123 if (status != IBT_SUCCESS) { 1124 IBMF_TRACE_2(IBMF_TNF_NODEBUG, 1125 DPRINT_L1, ibmf_i_fini_qplist_err, 1126 IBMF_TNF_ERROR, "", 1127 "%s, status = %d\n", tnf_string, 1128 msg, "ibt_free_qp returned error", 1129 tnf_int, status, status); 1130 } 1131 } 1132 mutex_destroy(&qpp->iq_mutex); 1133 kmem_free((void *)qpp, sizeof (ibmf_qp_t)); 1134 1135 /* Grab the mutex again before accessing the QP list */ 1136 mutex_enter(&ibmf_cip->ci_mutex); 1137 qpp = ibmf_cip->ci_qp_list; 1138 } 1139 1140 cv_destroy(&ibmf_cip->ci_qp_cv); 1141 1142 ibmf_cip->ci_qp_list = ibmf_cip->ci_qp_list_tail = NULL; 1143 ibmf_cip->ci_init_state &= ~IBMF_CI_INIT_QP_LIST_INITED; 1144 1145 altqpp = ibmf_cip->ci_alt_qp_list; 1146 while (altqpp != NULL) { 1147 /* Remove altqpp from the list */ 1148 ibmf_cip->ci_alt_qp_list = altqpp->isq_next; 1149 mutex_exit(&ibmf_cip->ci_mutex); 1150 1151 if (altqpp->isq_qp_handle != NULL) { 1152 /* Flush the special QP */ 1153 status = ibt_flush_qp(altqpp->isq_qp_handle); 1154 if (status != IBT_SUCCESS) { 1155 IBMF_TRACE_2(IBMF_TNF_NODEBUG, 1156 DPRINT_L1, ibmf_i_fini_qplist_err, 1157 IBMF_TNF_ERROR, "", 1158 "%s, status = %d\n", tnf_string, 1159 msg, "ibt_flush_qp returned error", 1160 tnf_int, status, status); 1161 } 1162 1163 /* Free the special QP */ 1164 status = ibt_free_qp(altqpp->isq_qp_handle); 1165 if (status != IBT_SUCCESS) { 1166 IBMF_TRACE_2(IBMF_TNF_NODEBUG, 1167 DPRINT_L1, ibmf_i_fini_qplist_err, 1168 IBMF_TNF_ERROR, "", 1169 "%s, status = %d\n", tnf_string, 1170 msg, "ibt_free_qp returned error", 1171 tnf_int, status, status); 1172 } 1173 } 1174 mutex_destroy(&altqpp->isq_mutex); 1175 kmem_free((void *)altqpp, sizeof (ibmf_alt_qp_t)); 1176 1177 /* Grab the mutex again before accessing the QP list */ 1178 mutex_enter(&ibmf_cip->ci_mutex); 1179 altqpp = ibmf_cip->ci_alt_qp_list; 1180 } 1181 } 1182 1183 mutex_exit(&ibmf_cip->ci_mutex); 1184 1185 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_fini_qplist_end, 1186 IBMF_TNF_TRACE, "", "ibmf_i_fini_qplist() exit\n"); 1187 } 1188 1189 /* 1190 * ibmf_i_alloc_client(): 1191 * Allocate and initialize the client structure. 1192 */ 1193 int 1194 ibmf_i_alloc_client(ibmf_register_info_t *client_infop, uint_t flags, 1195 ibmf_client_t **clientpp) 1196 { 1197 ibmf_client_t *ibmf_clientp; 1198 char buf[128]; 1199 ibmf_kstat_t *ksp; 1200 1201 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_client_start, 1202 IBMF_TNF_TRACE, "", "ibmf_i_alloc_client() enter, " 1203 "client_infop = %p\n", tnf_opaque, client_infop, client_infop); 1204 1205 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ibmf_clientp)) 1206 1207 /* allocate memory for ibmf_client and initialize it */ 1208 ibmf_clientp = kmem_zalloc(sizeof (ibmf_client_t), KM_SLEEP); 1209 mutex_init(&ibmf_clientp->ic_mutex, NULL, MUTEX_DRIVER, NULL); 1210 mutex_init(&ibmf_clientp->ic_msg_mutex, NULL, MUTEX_DRIVER, NULL); 1211 mutex_init(&ibmf_clientp->ic_kstat_mutex, NULL, MUTEX_DRIVER, NULL); 1212 cv_init(&ibmf_clientp->ic_recv_cb_teardown_cv, NULL, CV_DRIVER, NULL); 1213 1214 (void) sprintf(buf, "s%08X_0x%08X", 1215 (uint32_t)client_infop->ir_ci_guid, client_infop->ir_client_class); 1216 1217 /* create a taskq to handle send completions based on reg flags */ 1218 if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) { 1219 if (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD) 1220 ibmf_clientp->ic_send_taskq = taskq_create(buf, 1221 IBMF_TASKQ_1THREAD, MINCLSYSPRI, 1, 1222 ibmf_taskq_max_tasks, TASKQ_PREPOPULATE); 1223 else 1224 ibmf_clientp->ic_send_taskq = taskq_create(buf, 1225 IBMF_TASKQ_NTHREADS, MINCLSYSPRI, 1, 1226 ibmf_taskq_max_tasks, 1227 TASKQ_DYNAMIC | TASKQ_PREPOPULATE); 1228 if (ibmf_clientp->ic_send_taskq == NULL) { 1229 cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv); 1230 mutex_destroy(&ibmf_clientp->ic_mutex); 1231 mutex_destroy(&ibmf_clientp->ic_msg_mutex); 1232 mutex_destroy(&ibmf_clientp->ic_kstat_mutex); 1233 kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t)); 1234 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1235 ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n", 1236 tnf_string, msg, buf); 1237 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1238 ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "", 1239 "ibmf_i_alloc_client() exit\n"); 1240 return (IBMF_NO_RESOURCES); 1241 } 1242 } 1243 ibmf_clientp->ic_init_state_class |= IBMF_CI_INIT_SEND_TASKQ_DONE; 1244 1245 (void) sprintf(buf, "r%08X_0x%08X", 1246 (uint32_t)client_infop->ir_ci_guid, client_infop->ir_client_class); 1247 1248 /* create a taskq to handle receive completions on reg flags */ 1249 if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) { 1250 if (flags & IBMF_REG_FLAG_SINGLE_OFFLOAD) 1251 ibmf_clientp->ic_recv_taskq = taskq_create(buf, 1252 IBMF_TASKQ_1THREAD, MINCLSYSPRI, 1, 1253 ibmf_taskq_max_tasks, TASKQ_PREPOPULATE); 1254 else 1255 ibmf_clientp->ic_recv_taskq = taskq_create(buf, 1256 IBMF_TASKQ_NTHREADS, MINCLSYSPRI, 1, 1257 ibmf_taskq_max_tasks, 1258 TASKQ_DYNAMIC | TASKQ_PREPOPULATE); 1259 if (ibmf_clientp->ic_recv_taskq == NULL) { 1260 cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv); 1261 mutex_destroy(&ibmf_clientp->ic_mutex); 1262 mutex_destroy(&ibmf_clientp->ic_msg_mutex); 1263 mutex_destroy(&ibmf_clientp->ic_kstat_mutex); 1264 taskq_destroy(ibmf_clientp->ic_send_taskq); 1265 kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t)); 1266 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1267 ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n", 1268 tnf_string, msg, buf); 1269 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1270 ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "", 1271 "ibmf_i_alloc_client() exit\n"); 1272 return (IBMF_NO_RESOURCES); 1273 } 1274 } 1275 ibmf_clientp->ic_init_state_class |= IBMF_CI_INIT_RECV_TASKQ_DONE; 1276 ibmf_clientp->ic_client_info.ci_guid = client_infop->ir_ci_guid; 1277 ibmf_clientp->ic_client_info.port_num = client_infop->ir_port_num; 1278 1279 /* Get the base LID */ 1280 (void) ibt_get_port_state_byguid(ibmf_clientp->ic_client_info.ci_guid, 1281 ibmf_clientp->ic_client_info.port_num, NULL, 1282 &ibmf_clientp->ic_base_lid); 1283 1284 ibmf_clientp->ic_client_info.client_class = 1285 client_infop->ir_client_class; 1286 1287 /* set up the per client ibmf kstats */ 1288 (void) sprintf(buf, "ibmf_%016" PRIx64 "_%d_%X_stat", 1289 client_infop->ir_ci_guid, client_infop->ir_port_num, 1290 client_infop->ir_client_class); 1291 if ((ibmf_clientp->ic_kstatp = kstat_create("ibmf", 0, buf, "misc", 1292 KSTAT_TYPE_NAMED, sizeof (ibmf_kstat_t) / sizeof (kstat_named_t), 1293 KSTAT_FLAG_WRITABLE)) == NULL) { 1294 cv_destroy(&ibmf_clientp->ic_recv_cb_teardown_cv); 1295 mutex_destroy(&ibmf_clientp->ic_mutex); 1296 mutex_destroy(&ibmf_clientp->ic_msg_mutex); 1297 mutex_destroy(&ibmf_clientp->ic_kstat_mutex); 1298 if ((flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) { 1299 taskq_destroy(ibmf_clientp->ic_send_taskq); 1300 taskq_destroy(ibmf_clientp->ic_recv_taskq); 1301 } 1302 kmem_free((void *)ibmf_clientp, sizeof (ibmf_client_t)); 1303 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1304 ibmf_i_alloc_client_err, IBMF_TNF_ERROR, "", "%s\n", 1305 tnf_string, msg, "kstat creation failed"); 1306 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1307 ibmf_i_alloc_client_end, IBMF_TNF_TRACE, "", 1308 "ibmf_i_alloc_client() exit\n"); 1309 return (IBMF_NO_RESOURCES); 1310 } 1311 ksp = (ibmf_kstat_t *)ibmf_clientp->ic_kstatp->ks_data; 1312 kstat_named_init(&ksp->msgs_alloced, "messages_allocated", 1313 KSTAT_DATA_UINT32); 1314 kstat_named_init(&ksp->msgs_active, "messages_active", 1315 KSTAT_DATA_UINT32); 1316 kstat_named_init(&ksp->msgs_sent, "messages_sent", KSTAT_DATA_UINT32); 1317 kstat_named_init(&ksp->msgs_received, "messages_received", 1318 KSTAT_DATA_UINT32); 1319 kstat_named_init(&ksp->sends_active, "sends_active", KSTAT_DATA_UINT32); 1320 kstat_named_init(&ksp->recvs_active, "receives_active", 1321 KSTAT_DATA_UINT32); 1322 kstat_named_init(&ksp->ud_dests_alloced, "ud_dests_allocated", 1323 KSTAT_DATA_UINT32); 1324 kstat_named_init(&ksp->alt_qps_alloced, "alt_qps_allocated", 1325 KSTAT_DATA_UINT32); 1326 kstat_named_init(&ksp->send_cb_active, "send_callbacks_active", 1327 KSTAT_DATA_UINT32); 1328 kstat_named_init(&ksp->recv_cb_active, "receive_callbacks_active", 1329 KSTAT_DATA_UINT32); 1330 kstat_named_init(&ksp->recv_bufs_alloced, "receive_bufs_allocated", 1331 KSTAT_DATA_UINT32); 1332 kstat_named_init(&ksp->msg_allocs_failed, "msg_allocs_failed", 1333 KSTAT_DATA_UINT32); 1334 kstat_named_init(&ksp->uddest_allocs_failed, "uddest_allocs_failed", 1335 KSTAT_DATA_UINT32); 1336 kstat_named_init(&ksp->alt_qp_allocs_failed, "alt_qp_allocs_failed", 1337 KSTAT_DATA_UINT32); 1338 kstat_named_init(&ksp->send_pkt_failed, "send_pkt_failed", 1339 KSTAT_DATA_UINT32); 1340 kstat_named_init(&ksp->rmpp_errors, "rmpp_errors", 1341 KSTAT_DATA_UINT32); 1342 1343 kstat_install(ibmf_clientp->ic_kstatp); 1344 1345 *clientpp = ibmf_clientp; 1346 1347 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ibmf_clientp)) 1348 1349 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_client_end, 1350 IBMF_TNF_TRACE, "", "ibmf_i_alloc_client() exit\n"); 1351 1352 return (IBMF_SUCCESS); 1353 } 1354 1355 /* 1356 * ibmf_i_free_client(): 1357 * Free up the client structure and release resources 1358 */ 1359 void 1360 ibmf_i_free_client(ibmf_client_t *clientp) 1361 { 1362 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_client_start, 1363 IBMF_TNF_TRACE, "", "ibmf_i_free_client() enter, clientp = %p\n", 1364 tnf_opaque, clientp, clientp); 1365 1366 /* delete the general ibmf kstats */ 1367 if (clientp->ic_kstatp != NULL) { 1368 kstat_delete(clientp->ic_kstatp); 1369 clientp->ic_kstatp = NULL; 1370 } 1371 1372 /* release references and destroy the resources */ 1373 if (clientp->ic_init_state_class & IBMF_CI_INIT_SEND_TASKQ_DONE) { 1374 if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) { 1375 taskq_destroy(clientp->ic_send_taskq); 1376 } 1377 clientp->ic_init_state_class &= ~IBMF_CI_INIT_SEND_TASKQ_DONE; 1378 } 1379 1380 if (clientp->ic_init_state_class & IBMF_CI_INIT_RECV_TASKQ_DONE) { 1381 if ((clientp->ic_reg_flags & IBMF_REG_FLAG_NO_OFFLOAD) == 0) { 1382 taskq_destroy(clientp->ic_recv_taskq); 1383 } 1384 clientp->ic_init_state_class &= ~IBMF_CI_INIT_RECV_TASKQ_DONE; 1385 } 1386 1387 mutex_destroy(&clientp->ic_mutex); 1388 mutex_destroy(&clientp->ic_msg_mutex); 1389 mutex_destroy(&clientp->ic_kstat_mutex); 1390 cv_destroy(&clientp->ic_recv_cb_teardown_cv); 1391 kmem_free((void *)clientp, sizeof (ibmf_client_t)); 1392 1393 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_client_end, 1394 IBMF_TNF_TRACE, "", "ibmf_i_free_client() exit\n"); 1395 } 1396 1397 /* 1398 * ibmf_i_validate_classes_and_port(): 1399 * Validate the class type and get the client structure 1400 */ 1401 int 1402 ibmf_i_validate_classes_and_port(ibmf_ci_t *ibmf_cip, 1403 ibmf_register_info_t *client_infop) 1404 { 1405 ibmf_client_t *ibmf_clientp; 1406 int status; 1407 1408 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 1409 ibmf_i_validate_classes_and_port_start, IBMF_TNF_TRACE, "", 1410 "ibmf_i_validate_classes_and_port() enter, cip = %p, " 1411 "clientp = %p\n", tnf_opaque, cip, ibmf_cip, 1412 tnf_opaque, client_infop, client_infop); 1413 1414 /* 1415 * the Solaris implementation of IBMF does not support 1416 * the UNIVERSAL_CLASS 1417 */ 1418 if (client_infop->ir_client_class == UNIVERSAL_CLASS) { 1419 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1420 ibmf_i_validate_classes_and_port_err, IBMF_TNF_ERROR, "", 1421 "%s\n", tnf_string, msg, 1422 "UNIVERSAL class is not supported"); 1423 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1424 ibmf_i_validate_classes_and_port_end, IBMF_TNF_TRACE, "", 1425 "ibmf_i_validate_classes_and_port() exit\n"); 1426 return (IBMF_NOT_SUPPORTED); 1427 } 1428 1429 /* 1430 * Check if the client context already exists on the list 1431 * maintained in the CI context. If it is, then the client class 1432 * has already been registered for. 1433 */ 1434 status = ibmf_i_lookup_client_by_info(ibmf_cip, client_infop, 1435 &ibmf_clientp); 1436 if (status != IBMF_SUCCESS) { 1437 /* client class has not been previously registered for */ 1438 status = IBMF_SUCCESS; 1439 } else { 1440 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1441 ibmf_i_validate_classes_and_port_err, IBMF_TNF_ERROR, "", 1442 "client already registered, class = 0x%X\n", 1443 tnf_uint, class, client_infop->ir_client_class); 1444 status = IBMF_PORT_IN_USE; 1445 } 1446 1447 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1448 ibmf_i_validate_classes_and_port_end, IBMF_TNF_TRACE, "", 1449 "ibmf_i_validate_classes_and_port() exit\n"); 1450 return (status); 1451 } 1452 1453 /* 1454 * ibmf_i_lookup_client_by_info(): 1455 * Get the client structure from the list 1456 */ 1457 static int 1458 ibmf_i_lookup_client_by_info(ibmf_ci_t *ibmf_cip, 1459 ibmf_register_info_t *ir_client, ibmf_client_t **clientpp) 1460 { 1461 ibmf_client_t *clientp; 1462 1463 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 1464 ibmf_i_lookup_client_by_info_start, IBMF_TNF_TRACE, "", 1465 "ibmf_i_lookup_client_by_info() enter, cip = %p, clientinfo = %p\n", 1466 tnf_opaque, cip, ibmf_cip, tnf_opaque, clientinfo, ir_client); 1467 1468 ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex)); 1469 1470 /* 1471 * walk the CI's client list searching for one with the specified class 1472 */ 1473 mutex_enter(&ibmf_cip->ci_clients_mutex); 1474 clientp = ibmf_cip->ci_clients; 1475 while (clientp != NULL) { 1476 ibmf_client_info_t *tmp = &clientp->ic_client_info; 1477 if (tmp->client_class == ir_client->ir_client_class && 1478 ir_client->ir_client_class != UNIVERSAL_CLASS && 1479 tmp->ci_guid == ir_client->ir_ci_guid && 1480 tmp->port_num == ir_client->ir_port_num) { 1481 /* found our match */ 1482 break; 1483 } 1484 clientp = clientp->ic_next; 1485 } 1486 mutex_exit(&ibmf_cip->ci_clients_mutex); 1487 1488 if (clientp != NULL) { 1489 *clientpp = clientp; 1490 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 1491 ibmf_i_lookup_client_by_info_end, IBMF_TNF_TRACE, "", 1492 "ibmf_i_lookup_client_by_info(): clientp = %p\n", 1493 tnf_opaque, clientp, clientp); 1494 return (IBMF_SUCCESS); 1495 } else { 1496 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1497 ibmf_i_lookup_client_by_info_end, IBMF_TNF_TRACE, "", 1498 "ibmf_i_lookup_client_by_info() exit\n"); 1499 return (IBMF_FAILURE); 1500 } 1501 } 1502 1503 /* 1504 * ibmf_i_add_client(): 1505 * Add a new client to the client list 1506 */ 1507 void 1508 ibmf_i_add_client(ibmf_ci_t *ibmf_cip, ibmf_client_t *ibmf_clientp) 1509 { 1510 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_add_start, 1511 IBMF_TNF_TRACE, "", 1512 "ibmf_i_add_client() enter, cip = %p, clientp = %p\n", 1513 tnf_opaque, ibmf_ci, ibmf_cip, tnf_opaque, client, ibmf_clientp); 1514 1515 ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex)); 1516 1517 mutex_enter(&ibmf_cip->ci_clients_mutex); 1518 ibmf_clientp->ic_next = NULL; 1519 ibmf_clientp->ic_prev = ibmf_cip->ci_clients_last; 1520 if (ibmf_cip->ci_clients == NULL) { 1521 ibmf_cip->ci_clients = ibmf_clientp; 1522 } 1523 if (ibmf_cip->ci_clients_last) { 1524 ibmf_cip->ci_clients_last->ic_next = ibmf_clientp; 1525 } 1526 ibmf_cip->ci_clients_last = ibmf_clientp; 1527 mutex_exit(&ibmf_cip->ci_clients_mutex); 1528 1529 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_add_end, 1530 IBMF_TNF_TRACE, "", "ibmf_i_add_client() exit\n"); 1531 } 1532 1533 /* 1534 * ibmf_i_delete_client(): 1535 * Delete a client from the client list 1536 */ 1537 void 1538 ibmf_i_delete_client(ibmf_ci_t *ibmf_cip, ibmf_client_t *ibmf_clientp) 1539 { 1540 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_delete_client_start, 1541 IBMF_TNF_TRACE, "", "ibmf_i_delete_client() enter, " 1542 "ibmf_i_delete_client() enter, cip = %p, clientp = %p\n", 1543 tnf_opaque, ibmf_ci, ibmf_cip, tnf_opaque, client, ibmf_clientp); 1544 1545 ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex)); 1546 1547 mutex_enter(&ibmf_cip->ci_clients_mutex); 1548 if (ibmf_clientp->ic_next) 1549 ibmf_clientp->ic_next->ic_prev = ibmf_clientp->ic_prev; 1550 1551 if (ibmf_clientp->ic_prev) 1552 ibmf_clientp->ic_prev->ic_next = ibmf_clientp->ic_next; 1553 1554 if (ibmf_cip->ci_clients == ibmf_clientp) { 1555 ibmf_cip->ci_clients = ibmf_clientp->ic_next; 1556 } 1557 if (ibmf_cip->ci_clients_last == ibmf_clientp) { 1558 ibmf_cip->ci_clients_last = ibmf_clientp->ic_prev; 1559 } 1560 mutex_exit(&ibmf_cip->ci_clients_mutex); 1561 1562 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_delete_client_end, 1563 IBMF_TNF_TRACE, "", "ibmf_i_delete_client() exit\n"); 1564 } 1565 1566 /* 1567 * ibmf_i_get_qp(): 1568 * Get the QP structure based on the client class 1569 */ 1570 int 1571 ibmf_i_get_qp(ibmf_ci_t *ibmf_cip, uint_t port_num, ibmf_client_type_t class, 1572 ibmf_qp_t **qppp) 1573 { 1574 ibmf_qp_t *qpp; 1575 int qp_num, status = IBMF_SUCCESS; 1576 1577 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_start, 1578 IBMF_TNF_TRACE, "", "ibmf_i_get_qp() enter, cip = %p, " 1579 "port = %d, class = %x\n", tnf_opaque, ibmf_ci, ibmf_cip, 1580 tnf_int, port, port_num, tnf_opaque, class, class); 1581 1582 ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_mutex)); 1583 1584 mutex_enter(&ibmf_cip->ci_mutex); 1585 1586 /* 1587 * walk through the list of qps on this ci, looking for one that 1588 * corresponds to the type and class the caller is interested in. 1589 * If it is not there, we need allocate it from the transport. Since 1590 * qp0 & qp1 can only be allocated once, we maintain a reference count 1591 * and call the transport for allocation iff the ref count is 0. 1592 */ 1593 qp_num = (class == SUBN_AGENT || class == SUBN_MANAGER) ? 0 : 1; 1594 1595 qpp = ibmf_cip->ci_qp_list; 1596 while (qpp != NULL) { 1597 if (port_num == qpp->iq_port_num && qp_num == qpp->iq_qp_num) 1598 break; 1599 qpp = qpp->iq_next; 1600 } 1601 1602 if (qpp == NULL) { 1603 /* 1604 * allocate qp and add it the qp list; recheck to 1605 * catch races 1606 */ 1607 ibmf_qp_t *tqpp; 1608 1609 mutex_exit(&ibmf_cip->ci_mutex); 1610 1611 tqpp = (ibmf_qp_t *)kmem_zalloc(sizeof (ibmf_qp_t), KM_SLEEP); 1612 1613 /* check the list under lock */ 1614 mutex_enter(&ibmf_cip->ci_mutex); 1615 1616 qpp = ibmf_cip->ci_qp_list; 1617 while (qpp != NULL) { 1618 if (port_num == qpp->iq_port_num && qp_num == 1619 qpp->iq_qp_num) 1620 break; 1621 qpp = qpp->iq_next; 1622 } 1623 1624 if (qpp != NULL) { 1625 /* some one raced past us and added to the list */ 1626 kmem_free((void *)tqpp, sizeof (ibmf_qp_t)); 1627 } else { 1628 /* add this to the qp list */ 1629 qpp = tqpp; 1630 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qpp)) 1631 qpp->iq_next = NULL; 1632 if (ibmf_cip->ci_qp_list == NULL) 1633 ibmf_cip->ci_qp_list = qpp; 1634 if (ibmf_cip->ci_qp_list_tail != NULL) 1635 ibmf_cip->ci_qp_list_tail->iq_next = qpp; 1636 ibmf_cip->ci_qp_list_tail = qpp; 1637 qpp->iq_port_num = port_num; 1638 qpp->iq_qp_num = qp_num; 1639 qpp->iq_flags = IBMF_QP_FLAGS_INVALID; 1640 mutex_init(&qpp->iq_mutex, NULL, MUTEX_DRIVER, NULL); 1641 } 1642 } 1643 1644 /* we now have a QP context */ 1645 for (;;) { 1646 if (qpp->iq_flags == IBMF_QP_FLAGS_INITING) { 1647 1648 /* block till qp is in VALID state */ 1649 cv_wait(&ibmf_cip->ci_qp_cv, &ibmf_cip->ci_mutex); 1650 continue; 1651 1652 } 1653 1654 if (qpp->iq_flags == IBMF_QP_FLAGS_UNINITING) { 1655 1656 /* block till qp is in INVALID state */ 1657 cv_wait(&ibmf_cip->ci_qp_cv, &ibmf_cip->ci_mutex); 1658 continue; 1659 } 1660 1661 if (qpp->iq_flags == IBMF_QP_FLAGS_INVALID) { 1662 if ((status = ibmf_i_init_qp(ibmf_cip, qpp)) != 1663 IBMF_SUCCESS) { 1664 ibmf_qp_t *tqpp; 1665 1666 /* 1667 * Remove the QP context from the CI's list. 1668 * Only initialized QPs should be on the list. 1669 * We know that this QP is on the list, so 1670 * the list is not empty. 1671 */ 1672 tqpp = ibmf_cip->ci_qp_list; 1673 if (tqpp == qpp) { 1674 /* Only QP context on the list */ 1675 ibmf_cip->ci_qp_list = NULL; 1676 ibmf_cip->ci_qp_list_tail = NULL; 1677 } 1678 1679 /* Find the QP context before the last one */ 1680 if (tqpp != qpp) { 1681 while (tqpp->iq_next != qpp) { 1682 tqpp = tqpp->iq_next; 1683 } 1684 1685 /* 1686 * We are at the second last element of 1687 * the list. Readjust the tail pointer. 1688 * Remove the last element from the 1689 * list. 1690 */ 1691 tqpp->iq_next = NULL; 1692 ibmf_cip->ci_qp_list_tail = tqpp; 1693 } 1694 1695 /* Free up the QP context */ 1696 kmem_free((void *)qpp, sizeof (ibmf_qp_t)); 1697 1698 break; 1699 } 1700 continue; 1701 } 1702 1703 if (qpp->iq_flags == IBMF_QP_FLAGS_INITED) { 1704 qpp->iq_qp_ref++; 1705 break; 1706 } 1707 } 1708 1709 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qpp)) 1710 1711 mutex_exit(&ibmf_cip->ci_mutex); 1712 1713 if (status == IBMF_SUCCESS) { 1714 *qppp = qpp; 1715 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_end, 1716 IBMF_TNF_TRACE, "", "ibmf_i_get_qp() exit " 1717 "qp_handle = %p\n", tnf_opaque, qp_handle, qpp); 1718 return (IBMF_SUCCESS); 1719 } else { 1720 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_get_qp_err, 1721 IBMF_TNF_ERROR, "", "%s\n", tnf_string, msg, 1722 "ibmf_i_get_qp(): qp_not found"); 1723 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_qp_end, 1724 IBMF_TNF_TRACE, "", "ibmf_i_get_qp() exit\n"); 1725 return (status); 1726 } 1727 } 1728 1729 /* 1730 * ibmf_i_release_qp(): 1731 * Drop the reference count on the QP structure 1732 */ 1733 void 1734 ibmf_i_release_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t **qppp) 1735 { 1736 ibmf_qp_t *qpp; 1737 1738 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_qp_start, 1739 IBMF_TNF_TRACE, "", "ibmf_i_release_qp() enter, cip = %p, " 1740 "qpp = %p\n", tnf_opaque, cip, ibmf_cip, tnf_opaque, qpp, *qppp); 1741 1742 ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_mutex)); 1743 1744 mutex_enter(&ibmf_cip->ci_mutex); 1745 qpp = *qppp; 1746 qpp->iq_qp_ref--; 1747 if (qpp->iq_qp_ref == 0) 1748 ibmf_i_uninit_qp(ibmf_cip, qpp); 1749 mutex_exit(&ibmf_cip->ci_mutex); 1750 1751 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_release_qp_end, 1752 IBMF_TNF_TRACE, "", "ibmf_i_release_qp() exit\n"); 1753 } 1754 1755 /* 1756 * ibmf_i_init_qp(): 1757 * Set up the QP context, request a QP from the IBT framework 1758 * and initialize it 1759 */ 1760 static int 1761 ibmf_i_init_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp) 1762 { 1763 ibt_sqp_type_t qp_type; 1764 ibt_qp_alloc_attr_t qp_attrs; 1765 ibt_qp_hdl_t qp_handle; 1766 ibt_qp_info_t qp_modify_attr; 1767 ibt_status_t ibt_status; 1768 int i, status; 1769 1770 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_start, 1771 IBMF_TNF_TRACE, "", "ibmf_i_init_qp() enter, cip = %p, " 1772 "port = %d, qp = %d\n", tnf_opaque, ibmf_ci, ibmf_cip, tnf_int, 1773 port, qpp->iq_port_num, tnf_int, num, qpp->iq_qp_num); 1774 1775 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(qpp->iq_qp_handle)) 1776 1777 ASSERT(MUTEX_HELD(&ibmf_cip->ci_mutex)); 1778 1779 qpp->iq_flags = IBMF_QP_FLAGS_INITING; 1780 mutex_exit(&ibmf_cip->ci_mutex); 1781 if (qpp->iq_qp_handle) { /* closed but not yet freed */ 1782 ibt_status = ibt_free_qp(qpp->iq_qp_handle); 1783 if (ibt_status != IBT_SUCCESS) { 1784 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 1785 ibmf_i_init_qp_err, IBMF_TNF_ERROR, "", 1786 "%s, status = %d\n", tnf_string, msg, 1787 "ibt_free_qp returned error", 1788 tnf_uint, ibt_status, ibt_status); 1789 } 1790 qpp->iq_qp_handle = NULL; 1791 } 1792 ASSERT(qpp->iq_qp_num == 0 || qpp->iq_qp_num == 1); 1793 if (qpp->iq_qp_num == 0) 1794 qp_type = IBT_SMI_SQP; 1795 else 1796 qp_type = IBT_GSI_SQP; 1797 qp_attrs.qp_scq_hdl = ibmf_cip->ci_cq_handle; 1798 qp_attrs.qp_rcq_hdl = ibmf_cip->ci_cq_handle; 1799 qp_attrs.qp_pd_hdl = ibmf_cip->ci_pd; 1800 qp_attrs.qp_sizes.cs_sq_sgl = 1; 1801 qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS; 1802 qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp; 1803 qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp; 1804 qp_attrs.qp_flags = IBT_ALL_SIGNALED; 1805 qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS; 1806 1807 /* call the IB transport to allocate a special QP */ 1808 ibt_status = ibt_alloc_special_qp(ibmf_cip->ci_ci_handle, 1809 qpp->iq_port_num, qp_type, &qp_attrs, NULL, &qp_handle); 1810 if (ibt_status != IBT_SUCCESS) { 1811 mutex_enter(&ibmf_cip->ci_mutex); 1812 qpp->iq_flags = IBMF_QP_FLAGS_INVALID; 1813 cv_broadcast(&ibmf_cip->ci_qp_cv); 1814 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err, 1815 IBMF_TNF_ERROR, "", "ibmf_i_init_qp() error status = %d\n", 1816 tnf_uint, ibt_status, ibt_status); 1817 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end, 1818 IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n"); 1819 return (IBMF_TRANSPORT_FAILURE); 1820 } 1821 1822 /* initialize qpp */ 1823 qpp->iq_qp_handle = qp_handle; 1824 qp_modify_attr.qp_trans = IBT_UD_SRV; 1825 qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS; 1826 1827 /* get the pkey index for the specified pkey */ 1828 if (ibmf_i_get_pkeyix(ibmf_cip->ci_ci_handle, IBMF_P_KEY_DEF_LIMITED, 1829 qpp->iq_port_num, &qp_modify_attr.qp_transport.ud.ud_pkey_ix) != 1830 IBMF_SUCCESS) { 1831 ibt_status = ibt_free_qp(qpp->iq_qp_handle); 1832 if (ibt_status != IBT_SUCCESS) { 1833 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 1834 ibmf_i_init_qp_err, IBMF_TNF_ERROR, "", 1835 "%s, status = %d\n", tnf_string, msg, 1836 "ibt_free_qp returned error", 1837 tnf_uint, ibt_status, ibt_status); 1838 } 1839 mutex_enter(&ibmf_cip->ci_mutex); 1840 qpp->iq_flags = IBMF_QP_FLAGS_INVALID; 1841 cv_broadcast(&ibmf_cip->ci_qp_cv); 1842 IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err, 1843 IBMF_TNF_ERROR, "", "ibmf_init_qp(): failed to get " 1844 "pkey index\n"); 1845 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end, 1846 IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n"); 1847 return (IBMF_FAILURE); 1848 } 1849 qp_modify_attr.qp_transport.ud.ud_sq_psn = 0; 1850 qp_modify_attr.qp_transport.ud.ud_port = qpp->iq_port_num; 1851 qp_modify_attr.qp_transport.ud.ud_qkey = IBMF_MGMT_Q_KEY; 1852 1853 /* call the IB transport to initialize the QP */ 1854 ibt_status = ibt_initialize_qp(qp_handle, &qp_modify_attr); 1855 if (ibt_status != IBT_SUCCESS) { 1856 ibt_status = ibt_free_qp(qpp->iq_qp_handle); 1857 if (ibt_status != IBT_SUCCESS) { 1858 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 1859 ibmf_i_init_qp_err, IBMF_TNF_ERROR, "", 1860 "%s, status = %d\n", tnf_string, msg, 1861 "ibt_free_qp returned error", 1862 tnf_uint, ibt_status, ibt_status); 1863 } 1864 mutex_enter(&ibmf_cip->ci_mutex); 1865 qpp->iq_flags = IBMF_QP_FLAGS_INVALID; 1866 cv_broadcast(&ibmf_cip->ci_qp_cv); 1867 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, ibmf_i_init_qp_err, 1868 IBMF_TNF_ERROR, "", "ibmf_init_qp(): error status = %d\n", 1869 tnf_uint, ibt_status, ibt_status); 1870 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end, 1871 IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n"); 1872 return (IBMF_TRANSPORT_FAILURE); 1873 } 1874 1875 /* post receive wqes to the RQ to handle unsolicited inbound packets */ 1876 for (i = 0; i < ibmf_recv_wqes_per_port; i++) { 1877 status = ibmf_i_post_recv_buffer(ibmf_cip, qpp, 1878 B_TRUE, IBMF_QP_HANDLE_DEFAULT); 1879 if (status != IBMF_SUCCESS) { 1880 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1, 1881 ibmf_i_init_qp, IBMF_TNF_TRACE, "", 1882 "%s\n", tnf_string, msg, "ibmf_i_init_qp(): " 1883 "ibmf_i_post_recv_buffer() failed"); 1884 } 1885 } 1886 mutex_enter(&ibmf_cip->ci_mutex); 1887 1888 /* set the state and signal blockers */ 1889 qpp->iq_flags = IBMF_QP_FLAGS_INITED; 1890 cv_broadcast(&ibmf_cip->ci_qp_cv); 1891 1892 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_qp_end, 1893 IBMF_TNF_TRACE, "", "ibmf_i_init_qp() exit\n"); 1894 return (IBMF_SUCCESS); 1895 } 1896 1897 /* 1898 * ibmf_i_uninit_qp(): 1899 * Invalidate the QP context 1900 */ 1901 static void 1902 ibmf_i_uninit_qp(ibmf_ci_t *ibmf_cip, ibmf_qp_t *qpp) 1903 { 1904 ibt_status_t status; 1905 1906 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_qp_start, 1907 IBMF_TNF_TRACE, "", "ibmf_i_uninit_qp() enter, cip = %p " 1908 "qpp = %p\n", tnf_opaque, cip, ibmf_cip, tnf_opaque, qpp, qpp); 1909 1910 ASSERT(MUTEX_HELD(&ibmf_cip->ci_mutex)); 1911 1912 /* mark the state as uniniting */ 1913 ASSERT(qpp->iq_qp_ref == 0); 1914 qpp->iq_flags = IBMF_QP_FLAGS_UNINITING; 1915 mutex_exit(&ibmf_cip->ci_mutex); 1916 1917 /* note: we ignore error values from ibt_flush_qp */ 1918 status = ibt_flush_qp(qpp->iq_qp_handle); 1919 if (status != IBT_SUCCESS) { 1920 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L2, 1921 ibmf_i_uninit_qp_err, IBMF_TNF_ERROR, "", 1922 "ibmf_i_uninit_qp(): %s, status = %d\n", tnf_string, msg, 1923 "ibt_flush_qp returned error", tnf_int, status, status); 1924 } 1925 1926 /* mark state as INVALID and signal any blockers */ 1927 mutex_enter(&ibmf_cip->ci_mutex); 1928 qpp->iq_flags = IBMF_QP_FLAGS_INVALID; 1929 cv_broadcast(&ibmf_cip->ci_qp_cv); 1930 1931 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_uninit_qp_end, 1932 IBMF_TNF_TRACE, "", "ibmf_i_uninit_qp() exit\n"); 1933 } 1934 1935 /* 1936 * ibmf_i_alloc_msg(): 1937 * Allocate and set up a message context 1938 */ 1939 int 1940 ibmf_i_alloc_msg(ibmf_client_t *clientp, ibmf_msg_impl_t **msgp, int km_flags) 1941 { 1942 ibmf_msg_impl_t *msgimplp; 1943 1944 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, 1945 ibmf_i_alloc_msg_start, IBMF_TNF_TRACE, "", 1946 "ibmf_i_alloc_msg() enter, clientp = %p, msg = %p, " 1947 " kmflags = %d\n", tnf_opaque, clientp, clientp, tnf_opaque, msg, 1948 *msgp, tnf_int, km_flags, km_flags); 1949 1950 /* allocate the message context */ 1951 msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t), 1952 km_flags); 1953 if (msgimplp != NULL) { 1954 1955 ibmf_ud_dest_t *ibmf_ud_dest; 1956 1957 if (km_flags == KM_SLEEP) { 1958 ibmf_i_pop_ud_dest_thread(clientp->ic_myci); 1959 } 1960 1961 /* get a UD dest structure from the pool */ 1962 ibmf_ud_dest = ibmf_i_get_ud_dest(clientp->ic_myci); 1963 if (ibmf_ud_dest == NULL) { 1964 kmem_free(msgimplp, sizeof (ibmf_msg_impl_t)); 1965 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1966 ibmf_i_alloc_msg_err, IBMF_TNF_ERROR, "", 1967 "ibmf_i_alloc_msg(): %s\n", 1968 tnf_string, msg, "No ud_dest available"); 1969 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 1970 ibmf_i_alloc_msg_end, IBMF_TNF_TRACE, "", 1971 "ibmf_i_alloc_msg() exit\n"); 1972 return (IBMF_NO_RESOURCES); 1973 } 1974 msgimplp->im_ibmf_ud_dest = ibmf_ud_dest; 1975 msgimplp->im_ud_dest = &ibmf_ud_dest->ud_dest; 1976 1977 } else { 1978 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 1979 ibmf_i_alloc_msg_err, IBMF_TNF_ERROR, "", 1980 "ibmf_i_alloc_msg(): %s\n", 1981 tnf_string, msg, "kmem_xalloc failed"); 1982 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_msg_end, 1983 IBMF_TNF_TRACE, "", "ibmf_i_alloc_msg() exit\n"); 1984 return (IBMF_NO_RESOURCES); 1985 } 1986 1987 *msgp = msgimplp; 1988 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_msg_end, 1989 IBMF_TNF_TRACE, "", "ibmf_i_alloc_msg() exit\n"); 1990 return (IBMF_SUCCESS); 1991 } 1992 1993 /* 1994 * ibmf_i_free_msg(): 1995 * frees up all buffers allocated by IBMF for 1996 * this message context, and then frees up the context 1997 */ 1998 void 1999 ibmf_i_free_msg(ibmf_msg_impl_t *msgimplp) 2000 { 2001 ibmf_msg_bufs_t *msgbufp = &msgimplp->im_msgbufs_recv; 2002 ibmf_client_t *clientp = (ibmf_client_t *)msgimplp->im_client; 2003 uint32_t cl_hdr_sz, cl_hdr_off; 2004 2005 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 2006 ibmf_i_free_msg_start, IBMF_TNF_TRACE, "", 2007 "ibmf_i_free_msg() enter, msg = %p\n", tnf_opaque, msg, msgimplp); 2008 2009 /* free up the UD destination resource */ 2010 if (msgimplp->im_ibmf_ud_dest != NULL) { 2011 ibmf_i_free_ud_dest(clientp, msgimplp); 2012 ibmf_i_clean_ud_dest_list(clientp->ic_myci, B_FALSE); 2013 } 2014 2015 /* free up the receive buffer if allocated previously */ 2016 if (msgbufp->im_bufs_mad_hdr != NULL) { 2017 ibmf_i_mgt_class_to_hdr_sz_off( 2018 msgbufp->im_bufs_mad_hdr->MgmtClass, 2019 &cl_hdr_sz, &cl_hdr_off); 2020 kmem_free(msgbufp->im_bufs_mad_hdr, sizeof (ib_mad_hdr_t) + 2021 cl_hdr_off + msgbufp->im_bufs_cl_hdr_len + 2022 msgbufp->im_bufs_cl_data_len); 2023 mutex_enter(&clientp->ic_kstat_mutex); 2024 IBMF_SUB32_KSTATS(clientp, recv_bufs_alloced, 1); 2025 mutex_exit(&clientp->ic_kstat_mutex); 2026 } 2027 2028 /* destroy the message mutex */ 2029 mutex_destroy(&msgimplp->im_mutex); 2030 2031 /* free the message context */ 2032 kmem_free(msgimplp, sizeof (ibmf_msg_impl_t)); 2033 2034 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_msg_end, 2035 IBMF_TNF_TRACE, "", "ibmf_i_free_msg() exit\n"); 2036 } 2037 2038 /* 2039 * ibmf_i_msg_transport(): 2040 * Send a message posted by the IBMF client using the RMPP protocol 2041 * if specified 2042 */ 2043 int 2044 ibmf_i_msg_transport(ibmf_client_t *clientp, ibmf_qp_handle_t ibmf_qp_handle, 2045 ibmf_msg_impl_t *msgimplp, int blocking) 2046 { 2047 ib_mad_hdr_t *madhdrp; 2048 ibmf_msg_bufs_t *msgbufp, *smsgbufp; 2049 uint32_t cl_hdr_sz, cl_hdr_off; 2050 boolean_t isDS = 0; /* double sided (sequenced) transaction */ 2051 boolean_t error = B_FALSE; 2052 int status = IBMF_SUCCESS; 2053 uint_t refcnt; 2054 char errmsg[128]; 2055 timeout_id_t msg_rp_unset_id, msg_tr_unset_id; 2056 2057 IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_msg_transport_start, 2058 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): clientp = 0x%p, " 2059 "qphdl = 0x%p, msgp = 0x%p, block = %d\n", 2060 tnf_opaque, clientp, clientp, tnf_opaque, qphdl, ibmf_qp_handle, 2061 tnf_opaque, msg, msgimplp, tnf_uint, block, blocking); 2062 2063 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp, *msgbufp)) 2064 2065 mutex_enter(&msgimplp->im_mutex); 2066 2067 madhdrp = msgimplp->im_msgbufs_send.im_bufs_mad_hdr; 2068 msgbufp = &msgimplp->im_msgbufs_recv; 2069 smsgbufp = &msgimplp->im_msgbufs_send; 2070 2071 /* 2072 * check if transp_op_flags specify that the transaction is 2073 * a single packet, then the size of the message header + data 2074 * does not exceed 256 bytes 2075 */ 2076 if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) == 0) { 2077 ibmf_i_mgt_class_to_hdr_sz_off( 2078 smsgbufp->im_bufs_mad_hdr->MgmtClass, 2079 &cl_hdr_sz, &cl_hdr_off); 2080 2081 if ((sizeof (ib_mad_hdr_t) + cl_hdr_off + 2082 smsgbufp->im_bufs_cl_hdr_len + 2083 smsgbufp->im_bufs_cl_data_len) > IBMF_MAD_SIZE) { 2084 mutex_exit(&msgimplp->im_mutex); 2085 (void) sprintf(errmsg, 2086 "Non-RMPP message size is too large"); 2087 error = B_TRUE; 2088 status = IBMF_BAD_SIZE; 2089 goto bail; 2090 } 2091 } 2092 2093 /* more message context initialization */ 2094 msgimplp->im_qp_hdl = ibmf_qp_handle; 2095 msgimplp->im_tid = b2h64(madhdrp->TransactionID); 2096 msgimplp->im_mgt_class = madhdrp->MgmtClass; 2097 msgimplp->im_unsolicited = B_FALSE; 2098 msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_UNINIT; 2099 msgimplp->im_rmpp_ctx.rmpp_state = IBMF_RMPP_STATE_UNDEFINED; 2100 msgimplp->im_rmpp_ctx.rmpp_respt = IBMF_RMPP_DEFAULT_RRESPT; 2101 msgimplp->im_rmpp_ctx.rmpp_retry_cnt = 0; 2102 IBMF_MSG_INCR_REFCNT(msgimplp); 2103 if (msgimplp->im_retrans.retrans_retries == 0) 2104 msgimplp->im_retrans.retrans_retries = IBMF_RETRANS_DEF_RETRIES; 2105 if (msgimplp->im_retrans.retrans_rtv == 0) 2106 msgimplp->im_retrans.retrans_rtv = IBMF_RETRANS_DEF_RTV; 2107 if (msgimplp->im_retrans.retrans_rttv == 0) 2108 msgimplp->im_retrans.retrans_rttv = IBMF_RETRANS_DEF_RTTV; 2109 2110 IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2111 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): %s, msgp = 0x%p, " 2112 "class = 0x%x, method = 0x%x, attributeID = 0x%x\n", 2113 tnf_string, msg, "Added message", tnf_opaque, msgimplp, 2114 msgimplp, tnf_opaque, class, msgimplp->im_mgt_class, tnf_opaque, 2115 method, madhdrp->R_Method, tnf_opaque, attrib_id, 2116 b2h16(madhdrp->AttributeID)); 2117 2118 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2119 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): msgp = 0x%p, " 2120 "TID = 0x%p, transp_op_flags = 0x%x\n", 2121 tnf_opaque, msgimplp, msgimplp, tnf_opaque, tid, msgimplp->im_tid, 2122 tnf_uint, transp_op_flags, msgimplp->im_transp_op_flags); 2123 2124 /* 2125 * Do not allow reuse of a message where the receive buffers are 2126 * being used as send buffers if this is a sequenced transaction 2127 */ 2128 if ((madhdrp == msgbufp->im_bufs_mad_hdr) && 2129 (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)) { 2130 IBMF_MSG_DECR_REFCNT(msgimplp); 2131 mutex_exit(&msgimplp->im_mutex); 2132 (void) sprintf(errmsg, 2133 "Send and Recv buffers are the same for sequenced" 2134 " transaction"); 2135 error = B_TRUE; 2136 status = IBMF_REQ_INVALID; 2137 goto bail; 2138 } 2139 2140 /* set transaction flags */ 2141 if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ) 2142 msgimplp->im_flags |= IBMF_MSG_FLAGS_SEQUENCED; 2143 2144 if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) 2145 msgimplp->im_flags |= IBMF_MSG_FLAGS_SEND_RMPP; 2146 else 2147 msgimplp->im_flags |= IBMF_MSG_FLAGS_NOT_RMPP; 2148 2149 /* free recv buffers if this is a reused message */ 2150 if ((msgbufp->im_bufs_mad_hdr != NULL) && 2151 (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ)) { 2152 2153 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2154 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): %s, " 2155 "msgp = 0x%p, mad_hdrp = 0x%p\n", tnf_string, msg, 2156 "Freeing recv buffer for reused message", 2157 tnf_opaque, msgimplp, msgimplp, 2158 tnf_opaque, mad_hdr, msgbufp->im_bufs_mad_hdr); 2159 2160 ibmf_i_mgt_class_to_hdr_sz_off( 2161 msgbufp->im_bufs_mad_hdr->MgmtClass, 2162 &cl_hdr_sz, &cl_hdr_off); 2163 2164 kmem_free(msgbufp->im_bufs_mad_hdr, sizeof (ib_mad_hdr_t) + 2165 cl_hdr_off + msgbufp->im_bufs_cl_hdr_len + 2166 msgbufp->im_bufs_cl_data_len); 2167 2168 msgbufp->im_bufs_mad_hdr = NULL; 2169 msgbufp->im_bufs_cl_hdr = NULL; 2170 msgbufp->im_bufs_cl_hdr_len = 0; 2171 msgbufp->im_bufs_cl_data = NULL; 2172 msgbufp->im_bufs_cl_data_len = 0; 2173 } 2174 2175 mutex_exit(&msgimplp->im_mutex); 2176 2177 /* initialize (and possibly allocate) the address handle */ 2178 status = ibmf_i_alloc_ud_dest(clientp, msgimplp, 2179 &msgimplp->im_ud_dest, blocking); 2180 if (status != IBMF_SUCCESS) { 2181 (void) sprintf(errmsg, "ibmf_i_alloc_ud_dest() failed"); 2182 error = B_TRUE; 2183 goto bail; 2184 } 2185 2186 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*msgimplp, *msgbufp)) 2187 2188 /* add the message to the client context's message list */ 2189 ibmf_i_client_add_msg(clientp, msgimplp); 2190 2191 mutex_enter(&msgimplp->im_mutex); 2192 2193 /* no one should have touched our state */ 2194 ASSERT(msgimplp->im_trans_state_flags == IBMF_TRANS_STATE_FLAG_UNINIT); 2195 2196 /* transition out of uninit state */ 2197 msgimplp->im_trans_state_flags = IBMF_TRANS_STATE_FLAG_INIT; 2198 2199 IBMF_TRACE_5(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2200 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): msgp = 0x%p, " 2201 "local_lid = 0x%x, remote_lid = 0x%x, remote_qpn = 0x%x, " 2202 "block = %d\n", tnf_opaque, msgp, msgimplp, 2203 tnf_uint, local_lid, msgimplp->im_local_addr.ia_local_lid, 2204 tnf_uint, remote_lid, msgimplp->im_local_addr.ia_remote_lid, 2205 tnf_uint, remote_qpn, msgimplp->im_local_addr.ia_remote_qno, 2206 tnf_uint, blocking, blocking); 2207 2208 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2209 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport(): " 2210 "unsetting timer %p %d\n", tnf_opaque, msgimplp, msgimplp, 2211 tnf_opaque, timeout_id, msgimplp->im_rp_timeout_id); 2212 2213 ASSERT(msgimplp->im_rp_timeout_id == 0); 2214 ASSERT(msgimplp->im_tr_timeout_id == 0); 2215 2216 if ((msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) == 0) { 2217 2218 /* Non-RMPP transaction */ 2219 2220 status = ibmf_i_send_single_pkt(clientp, ibmf_qp_handle, 2221 msgimplp, blocking); 2222 if (status != IBMF_SUCCESS) { 2223 IBMF_MSG_DECR_REFCNT(msgimplp); 2224 mutex_exit(&msgimplp->im_mutex); 2225 ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt); 2226 (void) sprintf(errmsg, "Single packet send failed"); 2227 error = B_TRUE; 2228 goto bail; 2229 } 2230 2231 } else if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_RMPP) { 2232 2233 /* RMPP transaction */ 2234 2235 /* check if client supports RMPP traffic */ 2236 if ((clientp->ic_reg_flags & IBMF_REG_FLAG_RMPP) == 0) { 2237 IBMF_MSG_DECR_REFCNT(msgimplp); 2238 mutex_exit(&msgimplp->im_mutex); 2239 ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt); 2240 (void) sprintf(errmsg, "Class does not support RMPP"); 2241 error = B_TRUE; 2242 status = IBMF_BAD_RMPP_OPT; 2243 goto bail; 2244 } 2245 2246 /* for non-special QPs, check if QP supports RMPP traffic */ 2247 if (ibmf_qp_handle != IBMF_QP_HANDLE_DEFAULT && 2248 (((ibmf_alt_qp_t *)ibmf_qp_handle)->isq_supports_rmpp == 2249 B_FALSE)) { 2250 IBMF_MSG_DECR_REFCNT(msgimplp); 2251 mutex_exit(&msgimplp->im_mutex); 2252 ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt); 2253 (void) sprintf(errmsg, "QP does not support RMPP"); 2254 error = B_TRUE; 2255 status = IBMF_BAD_RMPP_OPT; 2256 goto bail; 2257 } 2258 2259 /* check if transaction is "double sided" (send and receive) */ 2260 if (msgimplp->im_transp_op_flags & IBMF_MSG_TRANS_FLAG_SEQ) 2261 isDS = 1; 2262 2263 status = ibmf_i_send_rmpp_pkts(clientp, ibmf_qp_handle, 2264 msgimplp, isDS, blocking); 2265 if (status != IBMF_SUCCESS) { 2266 IBMF_MSG_DECR_REFCNT(msgimplp); 2267 mutex_exit(&msgimplp->im_mutex); 2268 ibmf_i_client_rem_msg(clientp, msgimplp, &refcnt); 2269 (void) sprintf(errmsg, "RMPP packets send failed"); 2270 error = B_TRUE; 2271 goto bail; 2272 } 2273 } 2274 2275 /* 2276 * decrement the reference count so notify_client() can remove the 2277 * message when it's ready 2278 */ 2279 IBMF_MSG_DECR_REFCNT(msgimplp); 2280 2281 /* check if the transaction is a blocking transaction */ 2282 if (blocking && ((msgimplp->im_trans_state_flags & 2283 IBMF_TRANS_STATE_FLAG_SIGNALED) == 0)) { 2284 2285 /* indicate that the tranaction is waiting */ 2286 msgimplp->im_trans_state_flags |= IBMF_TRANS_STATE_FLAG_WAIT; 2287 2288 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2289 IBMF_TNF_TRACE, "", 2290 "ibmf_i_msg_transport(): %s, msgp = 0x%p\n", 2291 tnf_string, msg, "blocking for completion", 2292 tnf_opaque, msgimplp, msgimplp); 2293 2294 /* wait for transaction completion */ 2295 cv_wait(&msgimplp->im_trans_cv, &msgimplp->im_mutex); 2296 2297 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_i_msg_transport, 2298 IBMF_TNF_TRACE, "", 2299 "ibmf_i_msg_transport(): %s, msgp = 0x%p\n", 2300 tnf_string, msg, "unblocking for completion", 2301 tnf_opaque, msgimplp, msgimplp); 2302 2303 /* clean up flags */ 2304 msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_WAIT; 2305 msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY; 2306 2307 if (msgimplp->im_msg_status != IBMF_SUCCESS) { 2308 2309 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 2310 ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "", 2311 "ibmf_i_msg_transport(): msg_status = %d\n", 2312 tnf_uint, msgstatus, msgimplp->im_msg_status); 2313 2314 status = msgimplp->im_msg_status; 2315 } 2316 } else if (blocking && (msgimplp->im_trans_state_flags & 2317 IBMF_TRANS_STATE_FLAG_SIGNALED)) { 2318 msgimplp->im_flags &= ~IBMF_MSG_FLAGS_BUSY; 2319 2320 if (msgimplp->im_msg_status != IBMF_SUCCESS) { 2321 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 2322 ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "", 2323 "ibmf_i_msg_transport(): msg_status = %d\n", 2324 tnf_uint, msgstatus, msgimplp->im_msg_status); 2325 status = msgimplp->im_msg_status; 2326 } 2327 } 2328 2329 msg_rp_unset_id = msg_tr_unset_id = 0; 2330 msg_rp_unset_id = msgimplp->im_rp_unset_timeout_id; 2331 msg_tr_unset_id = msgimplp->im_tr_unset_timeout_id; 2332 msgimplp->im_rp_unset_timeout_id = 0; 2333 msgimplp->im_tr_unset_timeout_id = 0; 2334 2335 mutex_exit(&msgimplp->im_mutex); 2336 2337 /* Unset the timers */ 2338 if (msg_rp_unset_id != 0) { 2339 (void) untimeout(msg_rp_unset_id); 2340 } 2341 2342 if (msg_tr_unset_id != 0) { 2343 (void) untimeout(msg_tr_unset_id); 2344 } 2345 2346 /* increment kstats of the number of sent messages */ 2347 mutex_enter(&clientp->ic_kstat_mutex); 2348 IBMF_ADD32_KSTATS(clientp, msgs_sent, 1); 2349 mutex_exit(&clientp->ic_kstat_mutex); 2350 2351 bail: 2352 if (error) { 2353 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2354 ibmf_i_msg_transport_err, IBMF_TNF_ERROR, "", 2355 "ibmf_i_msg_transport(): %s, msgp = 0x%p\n", 2356 tnf_string, msg, errmsg, tnf_opaque, msgimplp, msgimplp); 2357 } 2358 2359 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_msg_transport_end, 2360 IBMF_TNF_TRACE, "", "ibmf_i_msg_transport() exit, status = %d\n", 2361 tnf_uint, status, status); 2362 2363 return (status); 2364 } 2365 2366 /* 2367 * ibmf_i_init_msg(): 2368 * Initialize the message fields 2369 */ 2370 void 2371 ibmf_i_init_msg(ibmf_msg_impl_t *msgimplp, ibmf_msg_cb_t trans_cb, 2372 void *trans_cb_arg, ibmf_retrans_t *retrans, boolean_t block) 2373 { 2374 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_msg_start, 2375 IBMF_TNF_TRACE, "", "ibmf_i_init_msg() enter\n"); 2376 2377 _NOTE(ASSUMING_PROTECTED(msgimplp->im_trans_cb, 2378 msgimplp->im_trans_cb_arg)) 2379 2380 if (block == B_TRUE) 2381 msgimplp->im_msg_flags |= IBMF_MSG_FLAGS_BLOCKING; 2382 msgimplp->im_trans_cb = trans_cb; 2383 msgimplp->im_trans_cb_arg = trans_cb_arg; 2384 2385 if (retrans != NULL) { 2386 bcopy((void *)retrans, (void *)&msgimplp->im_retrans, 2387 sizeof (ibmf_retrans_t)); 2388 } 2389 2390 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_init_msg_end, 2391 IBMF_TNF_TRACE, "", "ibmf_i_init_msg() exit\n"); 2392 } 2393 2394 /* 2395 * ibmf_i_alloc_qp(): 2396 * Allocate a QP context for the alternate QPs 2397 */ 2398 int 2399 ibmf_i_alloc_qp(ibmf_client_t *clientp, ib_pkey_t p_key, ib_qkey_t q_key, 2400 uint_t flags, ibmf_qp_handle_t *ibmf_qp_handlep) 2401 { 2402 ibmf_ci_t *ibmf_cip = clientp->ic_myci; 2403 ibt_qp_alloc_attr_t qp_attrs; 2404 ibt_qp_info_t qp_modify_attr; 2405 ibmf_alt_qp_t *qp_ctx; 2406 uint16_t pkey_ix; 2407 ibt_status_t ibt_status; 2408 int i, blocking; 2409 boolean_t error = B_FALSE; 2410 int status = IBMF_SUCCESS; 2411 char errmsg[128]; 2412 2413 2414 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, 2415 ibmf_i_alloc_qp_start, IBMF_TNF_TRACE, "", 2416 "ibmf_i_alloc_qp() enter, clientp = %p, pkey = %x, qkey = %x \n", 2417 tnf_opaque, clientp, clientp, tnf_uint, p_key, p_key, 2418 tnf_uint, q_key, q_key); 2419 2420 /* 2421 * get the pkey index associated with this pkey if present in table 2422 */ 2423 if (ibmf_i_get_pkeyix(clientp->ic_ci_handle, p_key, 2424 clientp->ic_client_info.port_num, &pkey_ix) != IBMF_SUCCESS) { 2425 (void) sprintf(errmsg, "pkey not in table, pkey = %x", p_key); 2426 error = B_TRUE; 2427 status = IBMF_FAILURE; 2428 goto bail; 2429 } 2430 2431 /* allocate QP context memory */ 2432 qp_ctx = (ibmf_alt_qp_t *)kmem_zalloc(sizeof (ibmf_alt_qp_t), 2433 (flags & IBMF_ALLOC_SLEEP) ? KM_SLEEP : KM_NOSLEEP); 2434 if (qp_ctx == NULL) { 2435 (void) sprintf(errmsg, "failed to kmem_zalloc qp ctx"); 2436 error = B_TRUE; 2437 status = IBMF_NO_RESOURCES; 2438 goto bail; 2439 } 2440 2441 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qp_ctx)); 2442 2443 /* setup the qp attrs for the alloc call */ 2444 qp_attrs.qp_scq_hdl = ibmf_cip->ci_alt_cq_handle; 2445 qp_attrs.qp_rcq_hdl = ibmf_cip->ci_alt_cq_handle; 2446 qp_attrs.qp_pd_hdl = ibmf_cip->ci_pd; 2447 qp_attrs.qp_sizes.cs_sq_sgl = IBMF_MAX_SQ_WR_SGL_ELEMENTS; 2448 qp_attrs.qp_sizes.cs_rq_sgl = IBMF_MAX_RQ_WR_SGL_ELEMENTS; 2449 qp_attrs.qp_sizes.cs_sq = ibmf_send_wqes_posted_per_qp; 2450 qp_attrs.qp_sizes.cs_rq = ibmf_recv_wqes_posted_per_qp; 2451 qp_attrs.qp_flags = IBT_ALL_SIGNALED; 2452 qp_attrs.qp_alloc_flags = IBT_QP_NO_FLAGS; 2453 2454 /* request IBT for a qp with the desired attributes */ 2455 ibt_status = ibt_alloc_qp(clientp->ic_ci_handle, IBT_UD_RQP, 2456 &qp_attrs, &qp_ctx->isq_qp_sizes, &qp_ctx->isq_qpn, 2457 &qp_ctx->isq_qp_handle); 2458 if (ibt_status != IBT_SUCCESS) { 2459 kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t)); 2460 (void) sprintf(errmsg, "failed to alloc qp, status = %d", 2461 ibt_status); 2462 error = B_TRUE; 2463 status = IBMF_NO_RESOURCES; 2464 goto bail; 2465 } 2466 2467 qp_modify_attr.qp_trans = IBT_UD_SRV; 2468 qp_modify_attr.qp_flags = IBT_CEP_NO_FLAGS; 2469 qp_modify_attr.qp_transport.ud.ud_qkey = q_key; 2470 qp_modify_attr.qp_transport.ud.ud_sq_psn = 0; 2471 qp_modify_attr.qp_transport.ud.ud_pkey_ix = pkey_ix; 2472 qp_modify_attr.qp_transport.ud.ud_port = 2473 clientp->ic_client_info.port_num; 2474 2475 /* Set up the client handle in the QP context */ 2476 qp_ctx->isq_client_hdl = clientp; 2477 2478 /* call the IB transport to initialize the QP */ 2479 ibt_status = ibt_initialize_qp(qp_ctx->isq_qp_handle, &qp_modify_attr); 2480 if (ibt_status != IBT_SUCCESS) { 2481 (void) ibt_free_qp(qp_ctx->isq_qp_handle); 2482 kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t)); 2483 (void) sprintf(errmsg, "failed to initialize qp, status = %d", 2484 ibt_status); 2485 error = B_TRUE; 2486 status = IBMF_NO_RESOURCES; 2487 goto bail; 2488 } 2489 2490 /* Set up the WQE caches */ 2491 status = ibmf_i_init_altqp_wqes(qp_ctx); 2492 if (status != IBMF_SUCCESS) { 2493 (void) ibt_free_qp(qp_ctx->isq_qp_handle); 2494 kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t)); 2495 (void) sprintf(errmsg, "failed to init wqe caches, status = %d", 2496 status); 2497 error = B_TRUE; 2498 goto bail; 2499 } 2500 2501 qp_ctx->isq_next = NULL; 2502 qp_ctx->isq_pkey = p_key; 2503 qp_ctx->isq_qkey = q_key; 2504 qp_ctx->isq_port_num = clientp->ic_client_info.port_num; 2505 mutex_init(&qp_ctx->isq_mutex, NULL, MUTEX_DRIVER, NULL); 2506 mutex_init(&qp_ctx->isq_wqe_mutex, NULL, MUTEX_DRIVER, NULL); 2507 cv_init(&qp_ctx->isq_recv_cb_teardown_cv, NULL, CV_DRIVER, NULL); 2508 cv_init(&qp_ctx->isq_sqd_cv, NULL, CV_DRIVER, NULL); 2509 cv_init(&qp_ctx->isq_wqes_cv, NULL, CV_DRIVER, NULL); 2510 2511 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*qp_ctx)); 2512 2513 /* add alt qp to the list in CI context */ 2514 mutex_enter(&ibmf_cip->ci_mutex); 2515 if (ibmf_cip->ci_alt_qp_list == NULL) { 2516 ibmf_cip->ci_alt_qp_list = qp_ctx; 2517 } else { 2518 ibmf_alt_qp_t *qpp; 2519 2520 qpp = ibmf_cip->ci_alt_qp_list; 2521 while (qpp->isq_next != NULL) { 2522 qpp = qpp->isq_next; 2523 } 2524 qpp->isq_next = qp_ctx; 2525 } 2526 mutex_exit(&ibmf_cip->ci_mutex); 2527 2528 *ibmf_qp_handlep = (ibmf_qp_handle_t)qp_ctx; 2529 2530 if (flags & IBMF_ALLOC_SLEEP) 2531 blocking = 1; 2532 else 2533 blocking = 0; 2534 2535 /* post the max number of buffers to RQ */ 2536 for (i = 0; i < ibmf_recv_wqes_per_port; i++) { 2537 status = ibmf_i_post_recv_buffer(ibmf_cip, clientp->ic_qp, 2538 blocking, *ibmf_qp_handlep); 2539 if (status != IBMF_SUCCESS) { 2540 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3, 2541 ibmf_i_alloc_qp, IBMF_TNF_TRACE, "", 2542 "ibmf_i_alloc_qp(): %s, status = %d\n", 2543 tnf_string, msg, "ibmf_i_post_recv_buffer() failed", 2544 tnf_int, status, status); 2545 } 2546 } 2547 2548 mutex_enter(&clientp->ic_kstat_mutex); 2549 IBMF_ADD32_KSTATS(clientp, alt_qps_alloced, 1); 2550 mutex_exit(&clientp->ic_kstat_mutex); 2551 2552 bail: 2553 if (error) { 2554 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 2555 ibmf_i_alloc_qp_err, IBMF_TNF_TRACE, "", 2556 "ibmf_i_alloc_qp(): %s\n", tnf_string, msg, errmsg); 2557 } 2558 2559 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_alloc_qp_end, 2560 IBMF_TNF_TRACE, "", "ibmf_i_alloc_qp() exit, qp = %p\n", 2561 tnf_opaque, qp_handlep, *ibmf_qp_handlep); 2562 return (status); 2563 } 2564 2565 /* 2566 * ibmf_i_free_qp(): 2567 * Free an alternate QP context 2568 */ 2569 /* ARGSUSED */ 2570 int 2571 ibmf_i_free_qp(ibmf_qp_handle_t ibmf_qp_handle, uint_t flags) 2572 { 2573 ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle; 2574 ibmf_client_t *clientp = qp_ctx->isq_client_hdl; 2575 ibmf_ci_t *ibmf_cip = qp_ctx->isq_client_hdl->ic_myci; 2576 ibmf_alt_qp_t *qpp, *pqpp; 2577 ibt_status_t ibt_status; 2578 2579 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 2580 ibmf_i_free_qp_start, IBMF_TNF_TRACE, "", 2581 "ibmf_i_free_qp() enter, qp_hdl = %p, flags = %x\n", 2582 tnf_opaque, qp_hdl, ibmf_qp_handle, tnf_uint, flags, flags); 2583 2584 /* remove qp from the list in CI context */ 2585 2586 mutex_enter(&ibmf_cip->ci_mutex); 2587 qpp = ibmf_cip->ci_alt_qp_list; 2588 ASSERT(qpp != NULL); 2589 if (qpp == qp_ctx) { 2590 ibmf_cip->ci_alt_qp_list = qpp->isq_next; 2591 } else { 2592 while (qpp != NULL) { 2593 if (qpp == qp_ctx) 2594 break; 2595 pqpp = qpp; 2596 qpp = qpp->isq_next; 2597 } 2598 ASSERT(qpp != NULL); 2599 pqpp->isq_next = qpp->isq_next; 2600 } 2601 2602 mutex_exit(&ibmf_cip->ci_mutex); 2603 2604 /* flush the WQEs in the QP queues */ 2605 ibt_status = ibt_flush_qp(qp_ctx->isq_qp_handle); 2606 if (ibt_status != IBT_SUCCESS) { 2607 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2608 ibmf_i_free_qp_err, IBMF_TNF_TRACE, "", 2609 "ibmf_i_free_qp(): %s, status = %d\n", 2610 tnf_string, msg, "failed to close qp", 2611 tnf_uint, ibt_status, ibt_status); 2612 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end, 2613 IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n"); 2614 return (IBMF_TRANSPORT_FAILURE); 2615 } 2616 2617 /* Call the MAD completion handler */ 2618 ibmf_i_mad_completions(ibmf_cip->ci_alt_cq_handle, (void*)ibmf_cip); 2619 2620 /* Wait here for all WQE owned by this QP to get freed */ 2621 mutex_enter(&qpp->isq_mutex); 2622 while (qpp->isq_wqes_alloced != 0) { 2623 cv_wait(&qpp->isq_wqes_cv, &qpp->isq_mutex); 2624 } 2625 mutex_exit(&qpp->isq_mutex); 2626 2627 cv_destroy(&qp_ctx->isq_recv_cb_teardown_cv); 2628 cv_destroy(&qp_ctx->isq_sqd_cv); 2629 cv_destroy(&qp_ctx->isq_wqes_cv); 2630 2631 /* call the IB transport to free the QP */ 2632 ibt_status = ibt_free_qp(qp_ctx->isq_qp_handle); 2633 if (ibt_status != IBT_SUCCESS) { 2634 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2635 ibmf_i_free_qp_err, IBMF_TNF_TRACE, "", 2636 "ibmf_i_free_qp(): %s, status = %d\n", 2637 tnf_string, msg, "failed to free qp", 2638 tnf_uint, ibt_status, ibt_status); 2639 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end, 2640 IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n"); 2641 return (IBMF_TRANSPORT_FAILURE); 2642 } 2643 2644 /* Clean up the WQE caches */ 2645 ibmf_i_fini_altqp_wqes(qp_ctx); 2646 mutex_destroy(&qp_ctx->isq_wqe_mutex); 2647 mutex_destroy(&qp_ctx->isq_mutex); 2648 2649 mutex_enter(&clientp->ic_kstat_mutex); 2650 IBMF_SUB32_KSTATS(clientp, alt_qps_alloced, 1); 2651 mutex_exit(&clientp->ic_kstat_mutex); 2652 2653 kmem_free(qp_ctx, sizeof (ibmf_alt_qp_t)); 2654 2655 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_free_qp_end, 2656 IBMF_TNF_TRACE, "", "ibmf_i_free_qp() exit\n"); 2657 2658 return (IBMF_SUCCESS); 2659 } 2660 2661 /* 2662 * ibmf_i_query_qp(): 2663 * Query an alternate QP context 2664 */ 2665 /* ARGSUSED */ 2666 int 2667 ibmf_i_query_qp(ibmf_qp_handle_t ibmf_qp_handle, uint_t flags, 2668 uint_t *qp_nump, ib_pkey_t *p_keyp, ib_qkey_t *q_keyp, uint8_t *portnump) 2669 { 2670 ibt_qp_query_attr_t qp_query; 2671 ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle; 2672 uint16_t pkey_ix; 2673 ibt_status_t ibt_status; 2674 2675 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 2676 ibmf_i_free_qp_start, IBMF_TNF_TRACE, "", 2677 "ibmf_i_free_qp() enter, qp_hdl = %p, flags = %x\n", 2678 tnf_opaque, qp_hdl, ibmf_qp_handle, tnf_uint, flags, flags); 2679 2680 ibt_status = ibt_query_qp(qp_ctx->isq_qp_handle, &qp_query); 2681 if (ibt_status != IBT_SUCCESS) { 2682 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2683 ibmf_i_query_qp_err, IBMF_TNF_TRACE, "", 2684 "ibmf_i_query_qp(): %s, status = %d\n", 2685 tnf_string, msg, "failed to query qp", 2686 tnf_uint, ibt_status, ibt_status); 2687 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end, 2688 IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit\n"); 2689 return (IBMF_TRANSPORT_FAILURE); 2690 } 2691 2692 /* move the desired attributes into the locations provided */ 2693 *qp_nump = qp_query.qp_qpn; 2694 *q_keyp = qp_query.qp_info.qp_transport.ud.ud_qkey; 2695 *portnump = qp_query.qp_info.qp_transport.ud.ud_port; 2696 2697 pkey_ix = qp_query.qp_info.qp_transport.ud.ud_pkey_ix; 2698 2699 /* get the pkey based on the pkey_ix */ 2700 ibt_status = ibt_index2pkey(qp_ctx->isq_client_hdl->ic_ci_handle, 2701 *portnump, pkey_ix, p_keyp); 2702 if (ibt_status != IBT_SUCCESS) { 2703 IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1, 2704 ibmf_i_query_qp_err, IBMF_TNF_TRACE, "", 2705 "ibmf_i_query_qp(): %s, pkey_ix = %d, status = %d\n", 2706 tnf_string, msg, "failed to get pkey from index", 2707 tnf_uint, pkey_ix, pkey_ix, 2708 tnf_uint, ibt_status, ibt_status); 2709 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end, 2710 IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit\n"); 2711 return (IBMF_TRANSPORT_FAILURE); 2712 } 2713 2714 IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_query_qp_end, 2715 IBMF_TNF_TRACE, "", "ibmf_i_query_qp() exit, qp_num = 0x%x, " 2716 "pkey = 0x%x, qkey = 0x%x, portnum = %d\n", 2717 tnf_uint, qp_num, *qp_nump, tnf_uint, pkey, *p_keyp, 2718 tnf_uint, qkey, *q_keyp, tnf_uint, portnum, *portnump); 2719 2720 return (IBMF_SUCCESS); 2721 } 2722 2723 /* 2724 * ibmf_i_modify_qp(): 2725 * Modify an alternate QP context 2726 */ 2727 /* ARGSUSED */ 2728 int 2729 ibmf_i_modify_qp(ibmf_qp_handle_t ibmf_qp_handle, ib_pkey_t p_key, 2730 ib_qkey_t q_key, uint_t flags) 2731 { 2732 ibmf_alt_qp_t *qp_ctx = (ibmf_alt_qp_t *)ibmf_qp_handle; 2733 ibmf_client_t *clientp = qp_ctx->isq_client_hdl; 2734 ibmf_ci_t *ibmf_cip = clientp->ic_myci; 2735 ibmf_alt_qp_t *qpp; 2736 ibt_qp_info_t qp_mod; 2737 ibt_cep_modify_flags_t qp_mod_flags; 2738 ibt_queue_sizes_t actual_sz; 2739 uint16_t pkey_ix; 2740 ibt_status_t ibt_status; 2741 2742 IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, 2743 ibmf_i_modify_qp_start, IBMF_TNF_TRACE, "", 2744 "ibmf_i_modify_qp() enter, qp_hdl = %p, flags = %x, pkey = 0x%x, " 2745 "qkey = 0x%x\n", tnf_opaque, qp_hdl, ibmf_qp_handle, 2746 tnf_uint, flags, flags, tnf_uint, p_key, p_key, 2747 tnf_uint, q_key, q_key); 2748 2749 /* 2750 * get the pkey index associated with this pkey if present in table 2751 */ 2752 if (ibmf_i_get_pkeyix(clientp->ic_ci_handle, p_key, 2753 clientp->ic_client_info.port_num, &pkey_ix) != IBMF_SUCCESS) { 2754 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2755 ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "", 2756 "ibmf_i_modify_qp(): %s, pkey = %x\n", 2757 tnf_string, msg, "pkey not in table", 2758 tnf_uint, pkey, p_key); 2759 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end, 2760 IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n"); 2761 return (IBMF_FAILURE); 2762 } 2763 2764 /* Find the QP context in the CI QP context list */ 2765 mutex_enter(&ibmf_cip->ci_mutex); 2766 qpp = ibmf_cip->ci_alt_qp_list; 2767 while (qpp != NULL) { 2768 if (qpp == qp_ctx) { 2769 break; 2770 } 2771 qpp = qpp->isq_next; 2772 } 2773 2774 if (qpp == NULL) { 2775 mutex_exit(&ibmf_cip->ci_mutex); 2776 2777 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 2778 ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "", 2779 "ibmf_i_modify_qp(): %s\n", 2780 tnf_string, msg, "QP not in altqp list"); 2781 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end, 2782 IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n"); 2783 return (IBMF_BAD_QP_HANDLE); 2784 2785 } else { 2786 2787 mutex_enter(&qp_ctx->isq_mutex); 2788 } 2789 2790 mutex_exit(&ibmf_cip->ci_mutex); 2791 2792 /* 2793 * Transition the QP to SQD state 2794 */ 2795 bzero(&qp_mod, sizeof (ibt_qp_info_t)); 2796 qp_mod.qp_trans = IBT_UD_SRV; 2797 qp_mod.qp_state = IBT_STATE_SQD; 2798 qp_mod_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_SQD_EVENT; 2799 ibt_status = ibt_modify_qp(qp_ctx->isq_qp_handle, qp_mod_flags, 2800 &qp_mod, &actual_sz); 2801 if (ibt_status != IBT_SUCCESS) { 2802 mutex_exit(&qp_ctx->isq_mutex); 2803 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2804 ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "", 2805 "ibmf_i_modify_qp(): %s, qp_hdl = %p\n", 2806 tnf_string, msg, "QP transition RTS to SQD failed", 2807 tnf_opaque, qp_handle, qp_ctx->isq_qp_handle); 2808 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end, 2809 IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n"); 2810 return (IBMF_TRANSPORT_FAILURE); 2811 } 2812 2813 /* 2814 * Wait for an event indicating that the QP is in SQD state 2815 */ 2816 cv_wait(&qp_ctx->isq_sqd_cv, &qp_ctx->isq_mutex); 2817 2818 /* Setup QP modification information for transition to RTS state */ 2819 bzero(&qp_mod, sizeof (ibt_qp_info_t)); 2820 qp_mod.qp_trans = IBT_UD_SRV; 2821 qp_mod.qp_state = IBT_STATE_RTS; 2822 qp_mod.qp_current_state = IBT_STATE_SQD; 2823 qp_mod.qp_transport.ud.ud_pkey_ix = pkey_ix; 2824 qp_mod.qp_transport.ud.ud_qkey = q_key; 2825 qp_mod_flags = IBT_CEP_SET_STATE | IBT_CEP_SET_PKEY_IX | 2826 IBT_CEP_SET_QKEY; 2827 2828 /* 2829 * transition the QP back to RTS state to allow 2830 * modification of the pkey and qkey 2831 */ 2832 2833 ibt_status = ibt_modify_qp(qp_ctx->isq_qp_handle, qp_mod_flags, 2834 &qp_mod, &actual_sz); 2835 if (ibt_status != IBT_SUCCESS) { 2836 mutex_exit(&qp_ctx->isq_mutex); 2837 IBMF_TRACE_3(IBMF_TNF_NODEBUG, DPRINT_L1, 2838 ibmf_i_modify_qp_err, IBMF_TNF_TRACE, "", 2839 "ibmf_i_modify_qp(): %s, qp_hdl = %p, status = %d\n", 2840 tnf_string, msg, "QP transition SQD to RTS failed", 2841 tnf_opaque, qp_handle, qp_ctx->isq_qp_handle, 2842 tnf_uint, ibt_status, ibt_status); 2843 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end, 2844 IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n"); 2845 return (IBMF_TRANSPORT_FAILURE); 2846 } 2847 2848 qp_ctx->isq_pkey = p_key; 2849 qp_ctx->isq_qkey = q_key; 2850 mutex_exit(&qp_ctx->isq_mutex); 2851 2852 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_modify_qp_end, 2853 IBMF_TNF_TRACE, "", "ibmf_i_modify_qp() exit\n"); 2854 return (IBMF_SUCCESS); 2855 } 2856 2857 /* 2858 * ibmf_i_post_recv_buffer(): 2859 * Post a WQE to the RQ of the specified QP 2860 */ 2861 int 2862 ibmf_i_post_recv_buffer(ibmf_ci_t *cip, ibmf_qp_t *qpp, boolean_t block, 2863 ibmf_qp_handle_t ibmf_qp_handle) 2864 { 2865 int ret; 2866 ibt_wr_ds_t *sgl; 2867 ibt_status_t status; 2868 ibmf_recv_wqe_t *recv_wqep; 2869 ibt_qp_hdl_t ibt_qp_handle; 2870 struct kmem_cache *kmem_cachep; 2871 ibmf_alt_qp_t *altqp; 2872 2873 IBMF_TRACE_4(IBMF_TNF_DEBUG, DPRINT_L4, 2874 ibmf_i_post_recv_buffer_start, IBMF_TNF_TRACE, "", 2875 "ibmf_i_post_recv_buffer() enter, cip = %p, qpp = %p, " 2876 "qp_hdl = %p, block = %d\n", tnf_opaque, cip, cip, 2877 tnf_opaque, qpp, qpp, tnf_opaque, qp_hdl, ibmf_qp_handle, 2878 tnf_uint, block, block); 2879 2880 /* 2881 * if we haven't hit the max wqes per qp, attempt to allocate a recv 2882 * wqe and post it to the recv queue. 2883 * It is possible for more than one thread to get through this 2884 * check below and post wqes that could push us above the 2885 * ibmf_recv_wqes_posted_per_qp. We catch that case when the recv 2886 * completion is signaled. 2887 */ 2888 ASSERT(MUTEX_NOT_HELD(&cip->ci_mutex)); 2889 2890 /* Get the WQE kmem cache pointer based on the QP type */ 2891 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) 2892 kmem_cachep = cip->ci_recv_wqes_cache; 2893 else { 2894 altqp = (ibmf_alt_qp_t *)ibmf_qp_handle; 2895 kmem_cachep = altqp->isq_recv_wqes_cache; 2896 } 2897 2898 /* allocate a receive WQE from the receive WQE kmem cache */ 2899 recv_wqep = kmem_cache_alloc(kmem_cachep, 2900 (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP)); 2901 if (recv_wqep == NULL) { 2902 /* 2903 * Attempt to extend the cache and then retry the 2904 * kmem_cache_alloc() 2905 */ 2906 if (ibmf_i_extend_wqe_cache(cip, ibmf_qp_handle, block) == 2907 IBMF_NO_RESOURCES) { 2908 mutex_enter(&cip->ci_mutex); 2909 IBMF_ADD32_PORT_KSTATS(cip, rwqe_allocs_failed, 1); 2910 mutex_exit(&cip->ci_mutex); 2911 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2912 ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "", 2913 "ibmf_i_post_recv_buffer(): %s, status = %d\n", 2914 tnf_string, msg, "alloc recv_wqe failed", 2915 tnf_int, ibmf_status, IBMF_NO_RESOURCES); 2916 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 2917 ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "", 2918 "ibmf_i_post_recv_buffer() exit\n"); 2919 return (IBMF_NO_RESOURCES); 2920 } else { 2921 recv_wqep = kmem_cache_alloc(kmem_cachep, 2922 (block == B_TRUE ? KM_SLEEP : KM_NOSLEEP)); 2923 if (recv_wqep == NULL) { 2924 /* Allocation failed again. Give up here. */ 2925 mutex_enter(&cip->ci_mutex); 2926 IBMF_ADD32_PORT_KSTATS(cip, rwqe_allocs_failed, 2927 1); 2928 mutex_exit(&cip->ci_mutex); 2929 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2930 ibmf_i_post_recv_buffer_err, 2931 IBMF_TNF_ERROR, "", 2932 "ibmf_i_post_recv_buffer(): %s, " 2933 "status = %d\n", 2934 tnf_string, msg, "alloc recv_wqe failed", 2935 tnf_int, ibmf_status, IBMF_NO_RESOURCES); 2936 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 2937 ibmf_i_post_recv_buffer_end, 2938 IBMF_TNF_TRACE, "", 2939 "ibmf_i_post_recv_buffer() exit\n"); 2940 return (IBMF_NO_RESOURCES); 2941 } 2942 } 2943 } 2944 2945 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*recv_wqep)) 2946 2947 /* 2948 * if the qp handle provided in ibmf_send_pkt() or 2949 * ibmf_setup_recv_cb() is not the default qp handle 2950 * for this client, then the wqe must be queued on this qp, 2951 * else use the default qp handle set up during ibmf_register() 2952 */ 2953 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) { 2954 ibt_qp_handle = qpp->iq_qp_handle; 2955 } else { 2956 ibt_qp_handle = 2957 ((ibmf_alt_qp_t *)ibmf_qp_handle)->isq_qp_handle; 2958 } 2959 2960 /* allocate memory for the scatter-gather list */ 2961 sgl = kmem_zalloc(IBMF_MAX_RQ_WR_SGL_ELEMENTS * sizeof (ibt_wr_ds_t), 2962 (block == B_TRUE) ? KM_SLEEP : KM_NOSLEEP); 2963 if (sgl == NULL) { 2964 kmem_cache_free(kmem_cachep, recv_wqep); 2965 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 2966 ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "", 2967 "ibmf_i_post_recv_buffer(): %s\n", 2968 tnf_string, msg, "failed to kmem_zalloc qp ctx"); 2969 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 2970 ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "", 2971 "ibmf_i_post_recv_buffer() exit\n"); 2972 return (IBMF_NO_RESOURCES); 2973 } 2974 2975 /* initialize it */ 2976 ibmf_i_init_recv_wqe(qpp, sgl, recv_wqep, ibt_qp_handle, 2977 ibmf_qp_handle); 2978 2979 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*recv_wqep)) 2980 2981 /* and post it */ 2982 status = ibt_post_recv(recv_wqep->recv_qp_handle, &recv_wqep->recv_wr, 2983 1, NULL); 2984 2985 ret = ibmf_i_ibt_to_ibmf_status(status); 2986 if (ret != IBMF_SUCCESS) { 2987 kmem_free(sgl, IBMF_MAX_RQ_WR_SGL_ELEMENTS * 2988 sizeof (ibt_wr_ds_t)); 2989 kmem_cache_free(kmem_cachep, recv_wqep); 2990 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 2991 ibmf_i_post_recv_buffer_err, IBMF_TNF_ERROR, "", 2992 "ibmf_i_post_recv_buffer(): %s, status = %d\n", 2993 tnf_string, msg, "ibt_post_recv failed", 2994 tnf_uint, ibt_status, status); 2995 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 2996 ibmf_i_post_recv_buffer_end, IBMF_TNF_TRACE, "", 2997 "ibmf_i_post_recv_buffer() exit\n"); 2998 return (ret); 2999 } 3000 3001 mutex_enter(&cip->ci_mutex); 3002 IBMF_ADD32_PORT_KSTATS(cip, recv_wqes_alloced, 1); 3003 mutex_exit(&cip->ci_mutex); 3004 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) { 3005 mutex_enter(&qpp->iq_mutex); 3006 qpp->iq_rwqes_posted++; 3007 mutex_exit(&qpp->iq_mutex); 3008 mutex_enter(&cip->ci_mutex); 3009 cip->ci_wqes_alloced++; 3010 mutex_exit(&cip->ci_mutex); 3011 } else { 3012 mutex_enter(&altqp->isq_mutex); 3013 altqp->isq_wqes_alloced++; 3014 altqp->isq_rwqes_posted++; 3015 mutex_exit(&altqp->isq_mutex); 3016 } 3017 3018 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_post_recv_buffer_end, 3019 IBMF_TNF_TRACE, "", "ibmf_i_post_recv_buffer() exit\n"); 3020 3021 return (ret); 3022 } 3023 3024 /* 3025 * ibmf_i_mgt_class_to_hdr_sz_off(): 3026 * Determine class header offser and size for management classes 3027 */ 3028 void 3029 ibmf_i_mgt_class_to_hdr_sz_off(uint32_t mgt_class, uint32_t *szp, 3030 uint32_t *offp) 3031 { 3032 uint32_t hdr_sz = 0, hdr_off = 0; 3033 3034 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 3035 ibmf_i_mgt_class_to_hdr_sz_off_start, IBMF_TNF_TRACE, "", 3036 "ibmf_i_mgt_class_to_hdr_sz_off(): mgt_class = 0x%x\n", 3037 tnf_uint, mgt_class, mgt_class); 3038 3039 switch (mgt_class) { 3040 case MAD_MGMT_CLASS_SUBN_LID_ROUTED : 3041 case MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE : 3042 case MAD_MGMT_CLASS_PERF : 3043 case MAD_MGMT_CLASS_BM : 3044 case MAD_MGMT_CLASS_DEV_MGT : 3045 case MAD_MGMT_CLASS_SNMP : 3046 hdr_sz = IBMF_MAD_CL_HDR_SZ_1; 3047 hdr_off = IBMF_MAD_CL_HDR_OFF_1; 3048 break; 3049 case MAD_MGMT_CLASS_SUBN_ADM : 3050 hdr_sz = IBMF_MAD_CL_HDR_SZ_2; 3051 hdr_off = IBMF_MAD_CL_HDR_OFF_2; 3052 break; 3053 } 3054 3055 if (((mgt_class >= MAD_MGMT_CLASS_VENDOR_START) && 3056 (mgt_class <= MAD_MGMT_CLASS_VENDOR_END)) || 3057 ((mgt_class >= MAD_MGMT_CLASS_APPLICATION_START) && 3058 (mgt_class <= MAD_MGMT_CLASS_APPLICATION_END))) { 3059 hdr_sz = IBMF_MAD_CL_HDR_SZ_3; 3060 hdr_off = IBMF_MAD_CL_HDR_OFF_1; 3061 } 3062 3063 if ((mgt_class >= MAD_MGMT_CLASS_VENDOR2_START) && 3064 (mgt_class <= MAD_MGMT_CLASS_VENDOR2_END)) { 3065 hdr_sz = IBMF_MAD_CL_HDR_SZ_4; 3066 hdr_off = IBMF_MAD_CL_HDR_OFF_2; 3067 } 3068 3069 *szp = hdr_sz; 3070 *offp = hdr_off; 3071 3072 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 3073 ibmf_i_mgt_class_to_hdr_sz_off_end, IBMF_TNF_TRACE, "", 3074 "ibmf_i_mgt_class_to_hdr_sz_off() exit,hdr_sz = %d, hdr_off = %d\n", 3075 tnf_uint, hdr_sz, hdr_sz, tnf_uint, hdr_off, hdr_off); 3076 } 3077 3078 /* 3079 * ibmf_i_lookup_client_by_mgmt_class(): 3080 * Lookup the client context based on the management class of 3081 * the incoming packet 3082 */ 3083 int 3084 ibmf_i_lookup_client_by_mgmt_class(ibmf_ci_t *ibmf_cip, int port_num, 3085 ibmf_client_type_t class, ibmf_client_t **clientpp) 3086 { 3087 ibmf_client_t *clientp; 3088 ibmf_client_info_t *client_infop; 3089 3090 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, 3091 ibmf_i_lookup_client_by_mgmt_class_start, IBMF_TNF_TRACE, "", 3092 "ibmf_i_lookup_client_by_mgmt_class() enter, cip = %p, " 3093 "port_num = %d, class = 0x%x\n", tnf_opaque, cip, ibmf_cip, 3094 tnf_int, port, port_num, tnf_opaque, class, class); 3095 3096 ASSERT(MUTEX_NOT_HELD(&ibmf_cip->ci_clients_mutex)); 3097 3098 mutex_enter(&ibmf_cip->ci_clients_mutex); 3099 3100 clientp = ibmf_cip->ci_clients; 3101 3102 /* walk client context list looking for class/portnum match */ 3103 while (clientp != NULL) { 3104 client_infop = &clientp->ic_client_info; 3105 if (class == client_infop->client_class && 3106 port_num == client_infop->port_num) { 3107 /* found our match */ 3108 break; 3109 } 3110 clientp = clientp->ic_next; 3111 } 3112 3113 mutex_exit(&ibmf_cip->ci_clients_mutex); 3114 3115 if (clientp != NULL) { 3116 *clientpp = clientp; 3117 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 3118 ibmf_i_lookup_client_by_mgmt_class_end, IBMF_TNF_TRACE, "", 3119 "ibmf_i_lookup_client_by_mgmt_class() exit, clp = %p\n", 3120 tnf_opaque, clientp, clientp); 3121 return (IBMF_SUCCESS); 3122 } else { 3123 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3124 ibmf_i_lookup_client_by_mgmt_class_end, IBMF_TNF_TRACE, "", 3125 "ibmf_i_lookup_client_by_mgmt_class() failure exit\n"); 3126 return (IBMF_FAILURE); 3127 } 3128 } 3129 3130 /* 3131 * ibmf_i_get_pkeyix(): 3132 * Get the pkey index of the pkey in the pkey table of the specified 3133 * port. Take into account the partition membership. 3134 */ 3135 int 3136 ibmf_i_get_pkeyix(ibt_hca_hdl_t hca_handle, ib_pkey_t pkey, uint8_t port, 3137 ib_pkey_t *pkeyixp) 3138 { 3139 ib_pkey_t tpkey; 3140 ibt_status_t ibt_status; 3141 3142 IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_start, 3143 IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix() enter, hcahdl = %p, " 3144 "pkey = 0x%x, port = %d\n", tnf_opaque, hcahdl, hca_handle, 3145 tnf_int, pkey, pkey, tnf_int, port, port); 3146 3147 /* 3148 * If the client specifies the FULL membership pkey and the 3149 * pkey is not in the table, this function should fail. 3150 */ 3151 if (pkey & IBMF_PKEY_MEMBERSHIP_MASK) { 3152 ibt_status = ibt_pkey2index(hca_handle, port, 3153 pkey, pkeyixp); 3154 if (ibt_status != IBT_SUCCESS) { 3155 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 3156 ibmf_i_get_pkeyix_err, IBMF_TNF_ERROR, "", 3157 "ibmf_i_get_pkeyix() error status = %d\n", 3158 tnf_uint, ibt_status, ibt_status); 3159 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3160 ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "", 3161 "ibmf_i_get_pkeyix() exit\n"); 3162 return (IBMF_TRANSPORT_FAILURE); 3163 } 3164 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_end, 3165 IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix() exit\n"); 3166 return (IBMF_SUCCESS); 3167 } 3168 3169 /* 3170 * Limited member pkey processing 3171 * Check if this limited member pkey is in the pkey table 3172 */ 3173 ibt_status = ibt_pkey2index(hca_handle, port, pkey, pkeyixp); 3174 if (ibt_status == IBT_SUCCESS) { 3175 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3176 ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "", 3177 "ibmf_i_get_pkeyix() exit\n"); 3178 return (IBMF_SUCCESS); 3179 } 3180 3181 /* 3182 * Could not find the limited member version of the pkey. 3183 * Now check if the full member version of the pkey is in the 3184 * pkey table. If not, fail the call. 3185 */ 3186 tpkey = pkey | IBMF_PKEY_MEMBERSHIP_MASK; 3187 ibt_status = ibt_pkey2index(hca_handle, port, tpkey, pkeyixp); 3188 if (ibt_status != IBT_SUCCESS) { 3189 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 3190 ibmf_i_get_pkeyix_err, IBMF_TNF_ERROR, "", 3191 "ibmf_i_get_pkeyix() error status = %d\n", 3192 tnf_uint, ibt_status, ibt_status); 3193 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3194 ibmf_i_get_pkeyix_end, IBMF_TNF_TRACE, "", 3195 "ibmf_i_get_pkeyix() exit\n"); 3196 return (IBMF_TRANSPORT_FAILURE); 3197 } 3198 3199 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_get_pkeyix_end, 3200 IBMF_TNF_TRACE, "", "ibmf_i_get_pkeyix(): pkey_ix = %d\n", 3201 tnf_int, pkeyix, *pkeyixp); 3202 return (IBMF_SUCCESS); 3203 } 3204 3205 /* 3206 * ibmf_i_pkey_ix_to_key(): 3207 * Figure out pkey from pkey index 3208 */ 3209 int 3210 ibmf_i_pkey_ix_to_key(ibmf_ci_t *cip, uint_t port_num, uint_t pkey_ix, 3211 ib_pkey_t *pkeyp) 3212 { 3213 ibt_status_t ibt_status; 3214 3215 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_pkey_ix_to_key_start, 3216 IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() enter\n"); 3217 3218 ibt_status = ibt_index2pkey(cip->ci_ci_handle, port_num, pkey_ix, 3219 pkeyp); 3220 if (ibt_status != IBT_SUCCESS) { 3221 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 3222 ibmf_i_pkey_ix_to_key, IBMF_TNF_TRACE, "", 3223 "ibmf_i_pkey_ix_to_key(): ibt_index2pkey failed for " 3224 " pkey index %d \n", tnf_uint, pkey_ix, pkey_ix); 3225 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3226 ibmf_i_pkey_ix_to_key_end, 3227 IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() exit\n"); 3228 return (IBMF_TRANSPORT_FAILURE); 3229 } 3230 3231 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_pkey_ix_to_key_end, 3232 IBMF_TNF_TRACE, "", "ibmf_i_pkey_ix_to_key() exit\n"); 3233 3234 return (IBMF_SUCCESS); 3235 } 3236 3237 /* 3238 * ibmf_i_ibt_to_ibmf_status(): 3239 * Map IBT return code to IBMF return code 3240 */ 3241 int 3242 ibmf_i_ibt_to_ibmf_status(ibt_status_t ibt_status) 3243 { 3244 int ibmf_status; 3245 3246 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_ibt_to_ibmf_status_start, 3247 IBMF_TNF_TRACE, "", "ibmf_i_ibt_to_ibmf_status() enter, " 3248 "status = %d\n", tnf_uint, ibt_status, ibt_status); 3249 3250 switch (ibt_status) { 3251 3252 case IBT_SUCCESS: 3253 ibmf_status = IBMF_SUCCESS; 3254 break; 3255 3256 case IBT_INSUFF_KERNEL_RESOURCE: 3257 case IBT_INSUFF_RESOURCE: 3258 case IBT_QP_FULL: 3259 ibmf_status = IBMF_NO_RESOURCES; 3260 break; 3261 3262 case IBT_HCA_IN_USE: 3263 case IBT_QP_IN_USE: 3264 case IBT_CQ_BUSY: 3265 case IBT_PD_IN_USE: 3266 case IBT_MR_IN_USE: 3267 ibmf_status = IBMF_BUSY; 3268 break; 3269 3270 default: 3271 ibmf_status = IBMF_FAILURE; 3272 break; 3273 } 3274 3275 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_i_ibt_to_ibmf_status_end, 3276 IBMF_TNF_TRACE, "", "ibmf_i_ibt_to_ibmf_status() exit, " 3277 "ibt_status = %d, ibmf_status = %d\n", tnf_uint, ibt_status, 3278 ibt_status, tnf_int, ibmf_status, ibmf_status); 3279 3280 return (ibmf_status); 3281 } 3282 3283 /* 3284 * ibmf_i_ibt_wc_to_ibmf_status(): 3285 * Map work completion code to IBMF return code 3286 */ 3287 int 3288 ibmf_i_ibt_wc_to_ibmf_status(ibt_wc_status_t ibt_wc_status) 3289 { 3290 int ibmf_status; 3291 3292 IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L4, 3293 ibmf_i_ibt_wc_to_ibmf_status_start, IBMF_TNF_TRACE, "", 3294 "ibmf_i_ibt_to_ibmf_status() enter, status = %d\n", 3295 tnf_uint, ibt_wc_status, ibt_wc_status); 3296 3297 switch (ibt_wc_status) { 3298 3299 case IBT_WC_SUCCESS: 3300 ibmf_status = IBMF_SUCCESS; 3301 break; 3302 3303 default: 3304 ibmf_status = IBMF_FAILURE; 3305 break; 3306 } 3307 3308 IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L4, 3309 ibmf_i_ibt_wc_to_ibmf_status_end, IBMF_TNF_TRACE, "", 3310 "ibmf_i_ibt_to_ibmf_status() exit, wc_status = %d, " 3311 "ibmf_status = %d\n", tnf_uint, ibt_wc_status, 3312 ibt_wc_status, tnf_int, ibmf_status, ibmf_status); 3313 3314 return (ibmf_status); 3315 } 3316 3317 /* 3318 * ibmf_i_is_ibmf_handle_valid(): 3319 * Validate the ibmf handle 3320 */ 3321 int 3322 ibmf_i_is_ibmf_handle_valid(ibmf_handle_t ibmf_handle) 3323 { 3324 ibmf_ci_t *cip; 3325 ibmf_client_t *clp, *clientp = (ibmf_client_t *)ibmf_handle; 3326 3327 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3328 ibmf_i_is_ibmf_handle_valid_start, IBMF_TNF_TRACE, "", 3329 "ibmf_i_is_ibmf_handle_valid() enter\n"); 3330 3331 mutex_enter(&ibmf_statep->ibmf_mutex); 3332 3333 cip = ibmf_statep->ibmf_ci_list; 3334 3335 /* iterate through all the channel interace contexts */ 3336 while (cip != NULL) { 3337 3338 mutex_enter(&cip->ci_clients_mutex); 3339 3340 clp = cip->ci_clients; 3341 3342 /* search all registration contexts for this ci */ 3343 while (clp != NULL) { 3344 if (clp == clientp) 3345 break; 3346 clp = clp->ic_next; 3347 } 3348 3349 mutex_exit(&cip->ci_clients_mutex); 3350 3351 if (clp == clientp) { 3352 /* ci found */ 3353 break; 3354 } else { 3355 /* ci not found, move onto next ci */ 3356 cip = cip->ci_next; 3357 } 3358 } 3359 3360 mutex_exit(&ibmf_statep->ibmf_mutex); 3361 3362 if (cip != NULL) { 3363 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3364 ibmf_i_is_ibmf_handle_valid_end, IBMF_TNF_TRACE, "", 3365 "ibmf_i_is_ibmf_handle_valid() exit\n"); 3366 return (IBMF_SUCCESS); 3367 } else { 3368 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3369 ibmf_i_is_ibmf_handle_valid_end, IBMF_TNF_TRACE, "", 3370 "ibmf_i_is_ibmf_handle_valid() failure exit\n"); 3371 return (IBMF_FAILURE); 3372 } 3373 } 3374 3375 /* 3376 * ibmf_i_is_qp_handle_valid(): 3377 * Validate the QP handle 3378 */ 3379 int 3380 ibmf_i_is_qp_handle_valid(ibmf_handle_t ibmf_handle, 3381 ibmf_qp_handle_t ibmf_qp_handle) 3382 { 3383 ibmf_client_t *clientp = (ibmf_client_t *)ibmf_handle; 3384 ibmf_alt_qp_t *alt_qp, *qpp = (ibmf_alt_qp_t *)ibmf_qp_handle; 3385 ibmf_ci_t *cip = clientp->ic_myci; 3386 3387 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3388 ibmf_i_is_qp_handle_valid_start, IBMF_TNF_TRACE, "", 3389 "ibmf_i_is_qp_handle_valid() enter\n"); 3390 3391 /* the default qp handle is always valid */ 3392 if (ibmf_qp_handle == IBMF_QP_HANDLE_DEFAULT) 3393 return (IBMF_SUCCESS); 3394 3395 mutex_enter(&cip->ci_mutex); 3396 3397 alt_qp = cip->ci_alt_qp_list; 3398 3399 while (alt_qp != NULL) { 3400 if (alt_qp == qpp) { 3401 /* qp handle found */ 3402 break; 3403 } else { 3404 /* qp handle not found, get next qp on list */ 3405 alt_qp = alt_qp->isq_next; 3406 } 3407 } 3408 3409 mutex_exit(&cip->ci_mutex); 3410 3411 if (alt_qp != NULL) { 3412 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3413 ibmf_i_is_qp_handle_valid_end, IBMF_TNF_TRACE, "", 3414 "ibmf_i_is_qp_handle_valid() exit\n"); 3415 return (IBMF_SUCCESS); 3416 } else { 3417 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3418 ibmf_i_is_qp_handle_valid_end, IBMF_TNF_TRACE, "", 3419 "ibmf_i_is_qp_handle_valid() failure exit\n"); 3420 return (IBMF_FAILURE); 3421 } 3422 } 3423 3424 void 3425 ibmf_dprintf(int l, const char *fmt, ...) 3426 { 3427 va_list ap; 3428 3429 if ((l) > ibmf_trace_level) { 3430 3431 return; 3432 } 3433 3434 va_start(ap, fmt); 3435 (void) vprintf(fmt, ap); 3436 va_end(ap); 3437 } 3438 3439 /* 3440 * ibmf_setup_term_ctx(): 3441 * Sets up a message context that is the duplicate of the one 3442 * passed in the regmsgimplp argument. The duplicate message context 3443 * is not visible to the client. It is managed internally by ibmf 3444 * to process the RMPP receiver termination flow logic for the 3445 * transaction while the client is notified of the completion of the 3446 * same transaction (i.e. all the solicited data has been received). 3447 */ 3448 int 3449 ibmf_setup_term_ctx(ibmf_client_t *clientp, ibmf_msg_impl_t *regmsgimplp) 3450 { 3451 ibmf_msg_impl_t *msgimplp; 3452 size_t offset; 3453 uint32_t cl_hdr_sz, cl_hdr_off; 3454 int status; 3455 3456 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3457 ibmf_setup_term_ctx_start, IBMF_TNF_TRACE, "", 3458 "ibmf_setup_term_ctx() enter\n"); 3459 3460 /* 3461 * Allocate the termination message context 3462 */ 3463 msgimplp = (ibmf_msg_impl_t *)kmem_zalloc(sizeof (ibmf_msg_impl_t), 3464 KM_NOSLEEP); 3465 if (msgimplp == NULL) { 3466 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 3467 ibmf_setup_term_ctx_error, IBMF_TNF_ERROR, "", 3468 "ibmf_setup_term_ctx(): %s\n", tnf_string, msg, 3469 "message mem allocation failure"); 3470 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3471 ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "", 3472 "ibmf_setup_term_ctx() exit\n"); 3473 return (IBMF_NO_RESOURCES); 3474 } 3475 3476 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*msgimplp)) 3477 3478 /* Copy the message context to the termination message structure */ 3479 *msgimplp = *regmsgimplp; 3480 3481 /* Initialize the message mutex */ 3482 mutex_init(&msgimplp->im_mutex, NULL, MUTEX_DRIVER, NULL); 3483 3484 /* 3485 * Allocate enough memory for the MAD header only. 3486 */ 3487 msgimplp->im_msgbufs_recv.im_bufs_mad_hdr = 3488 (ib_mad_hdr_t *)kmem_zalloc(IBMF_MAD_SIZE, KM_NOSLEEP); 3489 if (msgimplp->im_msgbufs_recv.im_bufs_mad_hdr == NULL) { 3490 kmem_free(msgimplp, sizeof (ibmf_msg_impl_t)); 3491 IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1, 3492 ibmf_setup_term_ctx_error, IBMF_TNF_ERROR, "", 3493 "ibmf_setup_term_ctx(): %s\n", tnf_string, msg, 3494 "recv buf mem allocation failure"); 3495 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3496 ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "", 3497 "ibmf_setup_term_ctx() exit\n"); 3498 return (IBMF_NO_RESOURCES); 3499 } 3500 3501 /* Copy over just the MAD header contents */ 3502 bcopy((const void *)regmsgimplp->im_msgbufs_recv.im_bufs_mad_hdr, 3503 (void *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr, 3504 sizeof (ib_mad_hdr_t)); 3505 3506 offset = sizeof (ib_mad_hdr_t); 3507 ibmf_i_mgt_class_to_hdr_sz_off( 3508 regmsgimplp->im_msgbufs_recv.im_bufs_mad_hdr->MgmtClass, 3509 &cl_hdr_sz, &cl_hdr_off); 3510 offset += cl_hdr_off; 3511 3512 /* 3513 * Copy the management class header 3514 */ 3515 msgimplp->im_msgbufs_recv.im_bufs_cl_hdr = 3516 (uchar_t *)msgimplp->im_msgbufs_recv.im_bufs_mad_hdr + offset; 3517 msgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len = 3518 regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len; 3519 bcopy((void *)regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr, 3520 (void *)msgimplp->im_msgbufs_recv.im_bufs_cl_hdr, 3521 regmsgimplp->im_msgbufs_recv.im_bufs_cl_hdr_len); 3522 3523 /* 3524 * Clear the termination message timers copied from the regular message 3525 * since ibmf_i_set_timer() expects them to be cleared. 3526 */ 3527 msgimplp->im_rp_timeout_id = 0; 3528 msgimplp->im_tr_timeout_id = 0; 3529 3530 /* Mark this message as being in a receiver RMPP mode */ 3531 msgimplp->im_flags |= IBMF_MSG_FLAGS_RECV_RMPP; 3532 3533 /* Mark this message as being a "termination flow" message */ 3534 msgimplp->im_flags |= IBMF_MSG_FLAGS_TERMINATION; 3535 3536 /* 3537 * Clear the IBMF_MSG_FLAGS_SET_TERMINATION copied over from the regular 3538 * message. 3539 */ 3540 msgimplp->im_flags &= ~IBMF_MSG_FLAGS_SET_TERMINATION; 3541 3542 /* 3543 * Clear the trans_state RECV_DONE and DONE flags so that the 3544 * protocol continues with the termination message context. 3545 */ 3546 msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_RECV_DONE; 3547 msgimplp->im_trans_state_flags &= ~IBMF_TRANS_STATE_FLAG_DONE; 3548 3549 /* Clear out references to the old UD dest handles */ 3550 msgimplp->im_ibmf_ud_dest = NULL; 3551 msgimplp->im_ud_dest = NULL; 3552 3553 /* 3554 * Request new UD dest resources for the termination phase. 3555 * The old UD dest resources are freed when the IBMF client 3556 * calls ibmf_free_msg(), so they cannot be relied on to exist 3557 * when the RMPP termination loop completes. 3558 */ 3559 status = ibmf_i_alloc_ud_dest(clientp, msgimplp, &msgimplp->im_ud_dest, 3560 B_FALSE); 3561 if (status != IBMF_SUCCESS) { 3562 kmem_free(msgimplp, sizeof (ibmf_msg_impl_t)); 3563 IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1, 3564 ibmf_setup_term_ctx_err, IBMF_TNF_ERROR, "", 3565 "ibmf_setup_term_ctx(): %s, status = %d\n", 3566 tnf_string, msg, "UD destination resource allocation" 3567 " failed", tnf_int, ibmf_status, status); 3568 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, 3569 ibmf_setup_term_ctx_end, IBMF_TNF_TRACE, "", 3570 "ibmf_setup_term_ctx() exit\n"); 3571 return (status); 3572 } 3573 3574 /* 3575 * Add the message to the termination client list by virtue of 3576 * having the IBMF_MSG_FLAGS_TERMINATION "im_flags" flag set. 3577 */ 3578 ibmf_i_client_add_msg(clientp, msgimplp); 3579 3580 /* 3581 * Increase the "allocted messages" count so that the client 3582 * does not unregister before this message has been freed. 3583 * This is necessary because we want the client context to 3584 * be around when the receive timeout expires for this termination 3585 * loop, otherwise the code will access freed memory and crash. 3586 */ 3587 mutex_enter(&clientp->ic_mutex); 3588 clientp->ic_msgs_alloced++; 3589 mutex_exit(&clientp->ic_mutex); 3590 3591 mutex_enter(&msgimplp->im_mutex); 3592 /* Set the response timer for the termination message. */ 3593 ibmf_i_set_timer(ibmf_i_recv_timeout, msgimplp, IBMF_RESP_TIMER); 3594 mutex_exit(&msgimplp->im_mutex); 3595 3596 IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_setup_term_ctx_end, 3597 IBMF_TNF_TRACE, "", "ibmf_setup_term_ctx() exit\n"); 3598 3599 return (IBMF_SUCCESS); 3600 } 3601