1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/kmem.h> 28 #include <sys/conf.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/ksynch.h> 32 33 #include <sys/ib/clients/eoib/enx_impl.h> 34 35 /* 36 * Acquire an SWQE 37 */ 38 39 /*ARGSUSED*/ 40 eibnx_wqe_t * 41 eibnx_acquire_swqe(eibnx_thr_info_t *info, int flag) 42 { 43 eibnx_wqe_t *wqe = NULL; 44 eibnx_tx_t *snd_p = &info->ti_snd; 45 int i; 46 47 for (i = 0; i < ENX_NUM_SWQE; i++) { 48 wqe = &(snd_p->tx_wqe[i]); 49 50 mutex_enter(&wqe->qe_lock); 51 if ((wqe->qe_flags & ENX_QEFL_INUSE) == 0) { 52 wqe->qe_flags |= ENX_QEFL_INUSE; 53 mutex_exit(&wqe->qe_lock); 54 break; 55 } 56 mutex_exit(&wqe->qe_lock); 57 } 58 59 /* 60 * We probably have enough swqe entries for doing our solicitations. 61 * If we find it not enough in practice, we need to implement some 62 * sort of dynamic allocation. 63 */ 64 if (i == ENX_NUM_SWQE) 65 wqe = NULL; 66 67 return (wqe); 68 } 69 70 /* 71 * Return a SWQE from completion. We may have to release 72 * it or keep it. 73 */ 74 void 75 eibnx_return_swqe(eibnx_wqe_t *wqe) 76 { 77 ASSERT(wqe->qe_type == ENX_QETYP_SWQE); 78 79 mutex_enter(&wqe->qe_lock); 80 81 /* 82 * This send wqe is from the completion queue. We need to 83 * clear the 'posted' flag first. 84 */ 85 ASSERT((wqe->qe_flags & ENX_QEFL_POSTED) == ENX_QEFL_POSTED); 86 wqe->qe_flags &= (~ENX_QEFL_POSTED); 87 88 /* 89 * See if we need to release this send wqe back to the pool 90 * on completion. We may not need to do so if, for example, 91 * this were a swqe acquired specifically for a particular gw. 92 */ 93 if (wqe->qe_flags & ENX_QEFL_RELONCOMP) { 94 wqe->qe_sgl.ds_len = wqe->qe_bufsz; 95 wqe->qe_flags &= (~ENX_QEFL_INUSE); 96 97 wqe->qe_flags &= (~ENX_QEFL_RELONCOMP); 98 } 99 100 mutex_exit(&wqe->qe_lock); 101 } 102 103 /* 104 * Return a RWQE from completion. We probably have to repost it. 105 */ 106 void 107 eibnx_return_rwqe(eibnx_thr_info_t *info, eibnx_wqe_t *wqe) 108 { 109 ibt_status_t ret; 110 111 ASSERT(wqe->qe_type == ENX_QETYP_RWQE); 112 113 mutex_enter(&wqe->qe_lock); 114 115 /* 116 * We should never need to free an rwqe on completion. 117 */ 118 ASSERT((wqe->qe_flags & ENX_QEFL_RELONCOMP) == 0); 119 120 /* 121 * An rwqe is always in-use and posted, so we only need to make 122 * sure the ds_len is adjusted back to the value it's supposed 123 * to have. 124 */ 125 wqe->qe_sgl.ds_len = wqe->qe_bufsz; 126 127 /* 128 * Repost the recv wqe 129 */ 130 ret = ibt_post_recv(info->ti_chan, &(wqe->qe_wr.recv), 1, NULL); 131 if (ret != IBT_SUCCESS) { 132 ENX_DPRINTF_WARN("ibt_post_recv(chan_hdl=0x%llx) failed, " 133 "ret=%d", info->ti_chan, ret); 134 } 135 136 mutex_exit(&wqe->qe_lock); 137 } 138 139 /* 140 * Release an SWQE that was acquired earlier. 141 */ 142 void 143 eibnx_release_swqe(eibnx_wqe_t *wqe) 144 { 145 ASSERT(wqe->qe_type == ENX_QETYP_SWQE); 146 147 mutex_enter(&wqe->qe_lock); 148 149 /* 150 * Make sure this swqe is in use. Since this routine may also be 151 * called when we're trying to cleanup the eoib nodes, we 152 * should clear all flag bits. 153 */ 154 ASSERT((wqe->qe_flags & ENX_QEFL_INUSE) == ENX_QEFL_INUSE); 155 wqe->qe_flags = 0; 156 157 mutex_exit(&wqe->qe_lock); 158 } 159 160 /* 161 * Insert the passed child to the head of the queue 162 */ 163 void 164 eibnx_enqueue_child(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi, 165 char *node_name, dev_info_t *dip) 166 { 167 eibnx_child_t *ch; 168 eibnx_child_t *new_ch; 169 170 new_ch = kmem_zalloc(sizeof (eibnx_child_t), KM_SLEEP); 171 new_ch->ch_dip = dip; 172 new_ch->ch_node_name = node_name; 173 new_ch->ch_gwi = gwi; 174 175 mutex_enter(&info->ti_child_lock); 176 177 /* 178 * Search existing children to see if we already have this 179 * child. If so, simply update its dip and node_name 180 */ 181 for (ch = info->ti_child; ch; ch = ch->ch_next) { 182 if (ch->ch_gwi->gw_portid == gwi->gw_portid) { 183 ch->ch_dip = dip; 184 if (ch->ch_node_name) { 185 kmem_free(ch->ch_node_name, MAXNAMELEN); 186 } 187 ch->ch_node_name = node_name; 188 kmem_free(new_ch, sizeof (eibnx_child_t)); 189 return; 190 } 191 } 192 193 /* 194 * If not, add the new child to the list of children 195 */ 196 new_ch->ch_next = info->ti_child; 197 info->ti_child = new_ch; 198 199 mutex_exit(&info->ti_child_lock); 200 } 201 202 int 203 eibnx_update_child(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi, 204 dev_info_t *dip) 205 { 206 eibnx_child_t *ch; 207 208 mutex_enter(&info->ti_child_lock); 209 for (ch = info->ti_child; ch; ch = ch->ch_next) { 210 if (ch->ch_gwi->gw_portid == gwi->gw_portid) { 211 if (ch->ch_dip != dip) { 212 ENX_DPRINTF_DEBUG("updating child dip for " 213 "gw portid 0x%x to 0x%llx", 214 gwi->gw_portid, dip); 215 ch->ch_dip = dip; 216 } 217 mutex_exit(&info->ti_child_lock); 218 219 return (ENX_E_SUCCESS); 220 } 221 } 222 mutex_exit(&info->ti_child_lock); 223 224 return (ENX_E_FAILURE); 225 } 226 227 dev_info_t * 228 eibnx_find_child_dip_by_inst(eibnx_thr_info_t *info, int inst) 229 { 230 eibnx_child_t *ch; 231 dev_info_t *dip = NULL; 232 233 mutex_enter(&info->ti_child_lock); 234 for (ch = info->ti_child; ch != NULL; ch = ch->ch_next) { 235 dip = ch->ch_dip; 236 if (ddi_get_instance(dip) == inst) 237 break; 238 } 239 mutex_exit(&info->ti_child_lock); 240 241 return (dip); 242 } 243 244 dev_info_t * 245 eibnx_find_child_dip_by_gw(eibnx_thr_info_t *info, uint16_t gw_portid) 246 { 247 eibnx_child_t *ch; 248 dev_info_t *dip = NULL; 249 250 mutex_enter(&info->ti_child_lock); 251 for (ch = info->ti_child; ch != NULL; ch = ch->ch_next) { 252 dip = ch->ch_dip; 253 if (ch->ch_gwi->gw_portid == gw_portid) 254 break; 255 } 256 mutex_exit(&info->ti_child_lock); 257 258 return (dip); 259 } 260 261 /* 262 * See if the passed gateway is already found in our list. Note 263 * that we assume that the gateway port id uniquely identifies each 264 * gateway. 265 */ 266 eibnx_gw_info_t * 267 eibnx_find_gw_in_gwlist(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi) 268 { 269 eibnx_gw_info_t *lgw = NULL; 270 271 mutex_enter(&info->ti_gw_lock); 272 for (lgw = info->ti_gw; lgw; lgw = lgw->gw_next) { 273 if (lgw->gw_portid == gwi->gw_portid) 274 break; 275 } 276 mutex_exit(&info->ti_gw_lock); 277 278 return (lgw); 279 } 280 281 /* 282 * Add a newly discovered gateway to the gateway list. Since we'll 283 * need to send unicast solicitations to this gateway soon, we'll 284 * also grab a swqe entry, and initialize basic gw adress parameters 285 * such as the gid, qpn, qkey and pkey of the GW. When we eventually 286 * get to sending the unicast to this gateway for the first time, 287 * we'll discover the path to this gateway using these parameters 288 * and modify the ud destination handle appropriately. 289 */ 290 eibnx_gw_info_t * 291 eibnx_add_gw_to_gwlist(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi, 292 ibt_wc_t *wc, uint8_t *recv_buf) 293 { 294 eibnx_gw_info_t *new_gwi; 295 eibnx_wqe_t *wqe; 296 ib_grh_t *grh; 297 ib_gid_t sgid; 298 clock_t timeout_usecs; 299 300 /* 301 * For now, we'll simply do KM_NOSLEEP allocation, since this code 302 * is called from within rx processing 303 */ 304 new_gwi = kmem_zalloc(sizeof (eibnx_gw_info_t), KM_NOSLEEP); 305 if (new_gwi == NULL) { 306 ENX_DPRINTF_WARN("no memory, gw port_id 0x%x " 307 "will be ignored by hca_guid=0x%llx, port=0x%x", 308 gwi->gw_portid, info->ti_hca_guid, 309 info->ti_pi->p_port_num); 310 return (NULL); 311 } 312 313 /* 314 * We also need to acquire a send wqe to do unicast solicitations 315 * to this gateway later on. We should've enough pre-allocated swqes 316 * to do this without sleeping. 317 */ 318 if ((wqe = eibnx_acquire_swqe(info, KM_NOSLEEP)) == NULL) { 319 ENX_DPRINTF_WARN("no swqe available, gw port_id 0x%x " 320 "will be ignored by hca_guid=0x%llx, port=0x%x", 321 gwi->gw_portid, info->ti_hca_guid, 322 info->ti_pi->p_port_num); 323 kmem_free(new_gwi, sizeof (eibnx_gw_info_t)); 324 return (NULL); 325 } 326 327 /* 328 * Initialize gw state and wqe information. 329 */ 330 new_gwi->gw_next = NULL; 331 new_gwi->gw_swqe = wqe; 332 new_gwi->gw_state = gwi->gw_state; 333 334 /* 335 * Set up gateway advertisement monitoring parameters. Since we 336 * always need to check against a timeout value of 2.5 * gw_adv_period, 337 * we'll keep this pre-calculated value as well. 338 */ 339 mutex_init(&new_gwi->gw_adv_lock, NULL, MUTEX_DRIVER, NULL); 340 new_gwi->gw_adv_flag = gwi->gw_adv_flag; 341 new_gwi->gw_adv_last_lbolt = ddi_get_lbolt64(); 342 timeout_usecs = gwi->gw_adv_period * 1000; 343 timeout_usecs = ((timeout_usecs << 2) + timeout_usecs) >> 1; 344 new_gwi->gw_adv_timeout_ticks = drv_usectohz(timeout_usecs); 345 346 /* 347 * Initialize gateway address information. Note that if the message has 348 * a GRH, we'll use the subnet prefix, otherwise we'll assume that the 349 * gateway is in the same subnet as ourselves. 350 */ 351 new_gwi->gw_addr.ga_vect = NULL; 352 if (wc->wc_flags & IBT_WC_GRH_PRESENT) { 353 grh = (ib_grh_t *)(uintptr_t)recv_buf; 354 new_gwi->gw_addr.ga_gid.gid_prefix = 355 ntohll(grh->SGID.gid_prefix); 356 } else { 357 sgid = info->ti_pi->p_sgid_tbl[0]; 358 new_gwi->gw_addr.ga_gid.gid_prefix = 359 sgid.gid_prefix; 360 } 361 new_gwi->gw_addr.ga_gid.gid_guid = gwi->gw_guid; 362 new_gwi->gw_addr.ga_qpn = gwi->gw_ctrl_qpn; 363 new_gwi->gw_addr.ga_qkey = EIB_FIP_QKEY; 364 new_gwi->gw_addr.ga_pkey = EIB_ADMIN_PKEY; 365 366 /* 367 * Initialize gateway parameters received via the advertisement 368 */ 369 new_gwi->gw_system_guid = gwi->gw_system_guid; 370 new_gwi->gw_guid = gwi->gw_guid; 371 new_gwi->gw_adv_period = gwi->gw_adv_period; 372 new_gwi->gw_ka_period = gwi->gw_ka_period; 373 new_gwi->gw_vnic_ka_period = gwi->gw_vnic_ka_period; 374 new_gwi->gw_ctrl_qpn = gwi->gw_ctrl_qpn; 375 new_gwi->gw_lid = gwi->gw_lid; 376 new_gwi->gw_portid = gwi->gw_portid; 377 new_gwi->gw_num_net_vnics = gwi->gw_num_net_vnics; 378 new_gwi->gw_is_host_adm_vnics = gwi->gw_is_host_adm_vnics; 379 new_gwi->gw_sl = gwi->gw_sl; 380 new_gwi->gw_n_rss_qpn = gwi->gw_n_rss_qpn; 381 new_gwi->gw_flag_ucast_advt = gwi->gw_flag_ucast_advt; 382 new_gwi->gw_flag_available = gwi->gw_flag_available; 383 bcopy(gwi->gw_system_name, new_gwi->gw_system_name, 384 sizeof (new_gwi->gw_system_name)); 385 bcopy(gwi->gw_port_name, new_gwi->gw_port_name, 386 sizeof (new_gwi->gw_port_name)); 387 bcopy(gwi->gw_vendor_id, new_gwi->gw_vendor_id, 388 sizeof (new_gwi->gw_vendor_id)); 389 390 /* 391 * Queue up the new gwi and return it 392 */ 393 mutex_enter(&info->ti_gw_lock); 394 new_gwi->gw_next = info->ti_gw; 395 info->ti_gw = new_gwi; 396 mutex_exit(&info->ti_gw_lock); 397 398 return (new_gwi); 399 } 400 401 /* 402 * Update old data for the gateway in our list with the new data. 403 */ 404 void 405 eibnx_replace_gw_in_gwlist(eibnx_thr_info_t *info, eibnx_gw_info_t *orig_gwi, 406 eibnx_gw_info_t *new_gwi, ibt_wc_t *wc, uint8_t *recv_buf, 407 boolean_t *gwi_changed) 408 { 409 ib_sn_prefix_t new_gw_sn_prefix; 410 ib_grh_t *grh; 411 ib_gid_t sgid; 412 boolean_t changed = B_FALSE; 413 boolean_t gw_addr_changed = B_TRUE; 414 415 /* 416 * We'll update all info received in the new advertisement in 417 * the original gwi and also move the gw_state to that of the state 418 * in the new gwi. 419 */ 420 mutex_enter(&info->ti_gw_lock); 421 422 orig_gwi->gw_state = new_gwi->gw_state; 423 424 /* 425 * The guids shouldn't really change for the "same" gateway 426 */ 427 if (new_gwi->gw_system_guid != orig_gwi->gw_system_guid) { 428 ENX_DPRINTF_WARN("gateway system guid changed for the " 429 "*same* gateway from 0x%llx to 0x%llx", 430 orig_gwi->gw_system_guid, new_gwi->gw_system_guid); 431 432 orig_gwi->gw_system_guid = new_gwi->gw_system_guid; 433 changed = B_TRUE; 434 } 435 if (new_gwi->gw_guid != orig_gwi->gw_guid) { 436 ENX_DPRINTF_WARN("gateway guid changed for the " 437 "*same* gateway from 0x%llx to 0x%llx", 438 orig_gwi->gw_guid, new_gwi->gw_guid); 439 440 orig_gwi->gw_guid = new_gwi->gw_guid; 441 changed = B_TRUE; 442 gw_addr_changed = B_TRUE; 443 } 444 445 if (new_gwi->gw_adv_period != orig_gwi->gw_adv_period) { 446 ENX_DPRINTF_DEBUG("gateway adv period changed " 447 "from 0x%lx to 0x%lx", orig_gwi->gw_adv_period, 448 new_gwi->gw_adv_period); 449 450 orig_gwi->gw_adv_period = new_gwi->gw_adv_period; 451 changed = B_TRUE; 452 } 453 if (new_gwi->gw_ka_period != orig_gwi->gw_ka_period) { 454 ENX_DPRINTF_DEBUG("gateway ka period changed " 455 "from 0x%lx to 0x%lx", orig_gwi->gw_ka_period, 456 new_gwi->gw_ka_period); 457 458 orig_gwi->gw_ka_period = new_gwi->gw_ka_period; 459 changed = B_TRUE; 460 } 461 if (new_gwi->gw_vnic_ka_period != orig_gwi->gw_vnic_ka_period) { 462 ENX_DPRINTF_DEBUG("vnic ka period changed " 463 "from 0x%lx to 0x%lx", orig_gwi->gw_vnic_ka_period, 464 new_gwi->gw_vnic_ka_period); 465 466 orig_gwi->gw_vnic_ka_period = new_gwi->gw_vnic_ka_period; 467 changed = B_TRUE; 468 } 469 if (new_gwi->gw_ctrl_qpn != orig_gwi->gw_ctrl_qpn) { 470 ENX_DPRINTF_DEBUG("gateway control qpn changed " 471 "from 0x%lx to 0x%lx", orig_gwi->gw_ctrl_qpn, 472 new_gwi->gw_ctrl_qpn); 473 474 orig_gwi->gw_ctrl_qpn = new_gwi->gw_ctrl_qpn; 475 changed = B_TRUE; 476 } 477 if (new_gwi->gw_lid != orig_gwi->gw_lid) { 478 ENX_DPRINTF_DEBUG("gateway lid changed from 0x%x to 0x%x", 479 orig_gwi->gw_lid, new_gwi->gw_lid); 480 481 orig_gwi->gw_lid = new_gwi->gw_lid; 482 changed = B_TRUE; 483 gw_addr_changed = B_TRUE; 484 } 485 486 /* 487 * The identity of the gateway is currently defined by its portid, 488 * so this cannot be different or eibnx_find_gw_in_gwlist() wouldn't 489 * have thought it's the same. For now though, we'll treat it 490 * like any other parameter, and flag it if we find this different. 491 */ 492 if (new_gwi->gw_portid != orig_gwi->gw_portid) { 493 ENX_DPRINTF_WARN("gateway portid changed for the *same* " 494 "gateway from 0x%x to 0x%x", orig_gwi->gw_portid, 495 new_gwi->gw_portid); 496 497 orig_gwi->gw_portid = new_gwi->gw_portid; 498 changed = B_TRUE; 499 } 500 501 if (new_gwi->gw_is_host_adm_vnics != orig_gwi->gw_is_host_adm_vnics) { 502 ENX_DPRINTF_DEBUG("host adm vnics changed from 0x%x to 0x%x", 503 orig_gwi->gw_is_host_adm_vnics, 504 new_gwi->gw_is_host_adm_vnics); 505 506 orig_gwi->gw_is_host_adm_vnics = new_gwi->gw_is_host_adm_vnics; 507 changed = B_TRUE; 508 } 509 if (new_gwi->gw_sl != orig_gwi->gw_sl) { 510 ENX_DPRINTF_DEBUG("gateway sl changed from 0x%x to 0x%x", 511 orig_gwi->gw_sl, new_gwi->gw_sl); 512 513 orig_gwi->gw_sl = new_gwi->gw_sl; 514 changed = B_TRUE; 515 } 516 if (new_gwi->gw_n_rss_qpn != orig_gwi->gw_n_rss_qpn) { 517 ENX_DPRINTF_DEBUG("gateway n_rss_qpn changed from 0x%x to 0x%x", 518 orig_gwi->gw_n_rss_qpn, new_gwi->gw_n_rss_qpn); 519 520 orig_gwi->gw_n_rss_qpn = new_gwi->gw_n_rss_qpn; 521 changed = B_TRUE; 522 } 523 524 /* 525 * The gw_flag_ucast_advt and gw_flag_available are expected to 526 * change over time (and even gw_num_net_vnics could change, but 527 * it's of no use to us presently), and we shouldn't trigger any 528 * flag for these 529 */ 530 orig_gwi->gw_flag_ucast_advt = new_gwi->gw_flag_ucast_advt; 531 orig_gwi->gw_flag_available = new_gwi->gw_flag_available; 532 orig_gwi->gw_num_net_vnics = new_gwi->gw_num_net_vnics; 533 534 if (strncmp((const char *)new_gwi->gw_system_name, 535 (const char *)orig_gwi->gw_system_name, EIB_GW_SYSNAME_LEN) != 0) { 536 ENX_DPRINTF_DEBUG("gateway system name changed from %s to %s", 537 orig_gwi->gw_system_name, new_gwi->gw_system_name); 538 539 bcopy(new_gwi->gw_system_name, orig_gwi->gw_system_name, 540 EIB_GW_SYSNAME_LEN); 541 changed = B_TRUE; 542 } 543 if (strncmp((const char *)new_gwi->gw_port_name, 544 (const char *)orig_gwi->gw_port_name, EIB_GW_PORTNAME_LEN) != 0) { 545 ENX_DPRINTF_DEBUG("gateway port name changed from %s to %s", 546 orig_gwi->gw_port_name, new_gwi->gw_port_name); 547 548 bcopy(new_gwi->gw_port_name, orig_gwi->gw_port_name, 549 EIB_GW_PORTNAME_LEN); 550 changed = B_TRUE; 551 } 552 if (strncmp((const char *)new_gwi->gw_vendor_id, 553 (const char *)orig_gwi->gw_vendor_id, EIB_GW_VENDOR_LEN) != 0) { 554 ENX_DPRINTF_DEBUG("vendor id changed from %s to %s", 555 orig_gwi->gw_vendor_id, new_gwi->gw_vendor_id); 556 557 bcopy(new_gwi->gw_vendor_id, orig_gwi->gw_vendor_id, 558 EIB_GW_VENDOR_LEN); 559 changed = B_TRUE; 560 } 561 562 /* 563 * See if the subnet prefix for the gateway has changed 564 */ 565 if (wc->wc_flags & IBT_WC_GRH_PRESENT) { 566 grh = (ib_grh_t *)(uintptr_t)recv_buf; 567 new_gw_sn_prefix = ntohll(grh->SGID.gid_prefix); 568 } else { 569 sgid = info->ti_pi->p_sgid_tbl[0]; 570 new_gw_sn_prefix = sgid.gid_prefix; 571 } 572 if (new_gw_sn_prefix != orig_gwi->gw_addr.ga_gid.gid_prefix) { 573 ENX_DPRINTF_WARN("subnet prefix changed from 0x%llx to 0x%llx", 574 orig_gwi->gw_addr.ga_gid.gid_prefix, new_gw_sn_prefix); 575 576 changed = B_TRUE; 577 gw_addr_changed = B_TRUE; 578 } 579 580 /* 581 * If the gateway address has changed in any way, clear the current 582 * address vector and update the gateway guid and gateway qpn. The 583 * address vector will be created the next time a unicast solicit 584 * is attempted for this gateway. 585 */ 586 if (gw_addr_changed) { 587 if (orig_gwi->gw_addr.ga_vect != NULL) { 588 kmem_free(orig_gwi->gw_addr.ga_vect, 589 sizeof (ibt_adds_vect_t)); 590 orig_gwi->gw_addr.ga_vect = NULL; 591 } 592 orig_gwi->gw_addr.ga_gid.gid_prefix = new_gw_sn_prefix; 593 orig_gwi->gw_addr.ga_gid.gid_guid = new_gwi->gw_guid; 594 orig_gwi->gw_addr.ga_qpn = new_gwi->gw_ctrl_qpn; 595 orig_gwi->gw_addr.ga_qkey = EIB_FIP_QKEY; 596 orig_gwi->gw_addr.ga_pkey = EIB_ADMIN_PKEY; 597 } 598 599 mutex_exit(&info->ti_gw_lock); 600 601 if (gwi_changed) { 602 *gwi_changed = changed; 603 } 604 } 605 606 /* 607 * Queue up a node for EoIB instantiation and wake up the thread 608 * that creates eoib nodes. 609 */ 610 void 611 eibnx_queue_for_creation(eibnx_thr_info_t *info, eibnx_gw_info_t *gwi) 612 { 613 eibnx_t *ss = enx_global_ss; 614 eibnx_nodeq_t *new_node; 615 616 /* 617 * For now, we'll simply do KM_NOSLEEP allocation, since this 618 * code is called from within rx processing 619 */ 620 new_node = kmem_zalloc(sizeof (eibnx_nodeq_t), KM_NOSLEEP); 621 if (new_node == NULL) { 622 ENX_DPRINTF_WARN("no memory, eoib node will not be " 623 "created for hca_guid=0x%llx, hca_port=0x%x, " 624 "gw_port_id=0x%x", info->ti_hca_guid, 625 info->ti_pi->p_port_num, gwi->gw_portid); 626 return; 627 } 628 new_node->nc_info = info; 629 new_node->nc_gwi = gwi; 630 631 /* 632 * If the eoib node creation thread is dying (or dead), don't 633 * queue up any more requests for creation 634 */ 635 mutex_enter(&ss->nx_nodeq_lock); 636 if (ss->nx_nodeq_thr_die) { 637 kmem_free(new_node, sizeof (eibnx_nodeq_t)); 638 } else { 639 new_node->nc_next = ss->nx_nodeq; 640 ss->nx_nodeq = new_node; 641 cv_signal(&ss->nx_nodeq_cv); 642 } 643 mutex_exit(&ss->nx_nodeq_lock); 644 } 645