1/* 2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 */ 35 36#if HAVE_CONFIG_H 37# include <config.h> 38#endif /* HAVE_CONFIG_H */ 39 40#include <sys/ioctl.h> 41#include <stdlib.h> 42#include <stddef.h> 43#include <sys/types.h> 44#include <sys/stat.h> 45#include <fcntl.h> 46#include <errno.h> 47 48#include <vendor/osm_vendor_mlx.h> 49#include <vendor/osm_vendor_mlx_transport.h> 50#include <vendor/osm_vendor_mlx_transport_anafa.h> 51#include <vendor/osm_vendor_mlx_svc.h> 52#include <vendor/osm_vendor_mlx_sender.h> 53#include <vendor/osm_pkt_randomizer.h> 54#include <vendor/osm_ts_useraccess.h> 55 56/** 57 * FORWARD REFERENCES 58 */ 59static ib_api_status_t 60__osmv_get_send_txn(IN osm_bind_handle_t h_bind, 61 IN osm_madw_t * const p_madw, 62 IN boolean_t is_rmpp, 63 IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn); 64 65static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind); 66 67/* 68 * NAME osm_vendor_new 69 * 70 * DESCRIPTION Create and Initialize the osm_vendor_t Object 71 */ 72 73osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log, 74 IN const uint32_t timeout) 75{ 76 ib_api_status_t status; 77 osm_vendor_t *p_vend; 78 79 OSM_LOG_ENTER(p_log); 80 81 CL_ASSERT(p_log); 82 83 p_vend = malloc(sizeof(*p_vend)); 84 if (p_vend != NULL) { 85 memset(p_vend, 0, sizeof(*p_vend)); 86 status = osm_vendor_init(p_vend, p_log, timeout); 87 if (status != IB_SUCCESS) { 88 osm_vendor_delete(&p_vend); 89 } 90 } else { 91 osm_log(p_vend->p_log, OSM_LOG_ERROR, 92 "osm_vendor_new: ERR 7401: " 93 "Fail to allocate vendor object.\n"); 94 } 95 96 OSM_LOG_EXIT(p_log); 97 return (p_vend); 98} 99 100/* 101 * NAME osm_vendor_delete 102 * 103 * DESCRIPTION Delete all the binds behind the vendor + free the vendor object 104 */ 105 106void osm_vendor_delete(IN osm_vendor_t ** const pp_vend) 107{ 108 cl_list_item_t *p_item; 109 cl_list_obj_t *p_obj; 110 osm_bind_handle_t bind_h; 111 osm_log_t *p_log; 112 113 OSM_LOG_ENTER((*pp_vend)->p_log); 114 p_log = (*pp_vend)->p_log; 115 116 /* go over the bind handles , unbind them and remove from list */ 117 /* Note that if we reached here due to problem in the init, then 118 the bind_handles list is not initialized yet */ 119 if ((*pp_vend)->bind_handles.state == CL_INITIALIZED) { 120 p_item = cl_qlist_remove_head(&((*pp_vend)->bind_handles)); 121 while (p_item != cl_qlist_end(&((*pp_vend)->bind_handles))) { 122 123 p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); 124 bind_h = (osm_bind_handle_t *) cl_qlist_obj(p_obj); 125 osm_log(p_log, OSM_LOG_DEBUG, 126 "osm_vendor_delete: unbinding bind_h:%p \n", 127 bind_h); 128 129 __osm_vendor_internal_unbind(bind_h); 130 131 free(p_obj); 132 /* removing from list */ 133 p_item = 134 cl_qlist_remove_head(&((*pp_vend)->bind_handles)); 135 } 136 } 137 138 if (NULL != ((*pp_vend)->p_transport_info)) { 139 free((*pp_vend)->p_transport_info); 140 (*pp_vend)->p_transport_info = NULL; 141 } 142 143 /* remove the packet randomizer object */ 144 if ((*pp_vend)->run_randomizer == TRUE) 145 osm_pkt_randomizer_destroy(&((*pp_vend)->p_pkt_randomizer), 146 p_log); 147 148 free(*pp_vend); 149 *pp_vend = NULL; 150 151 OSM_LOG_EXIT(p_log); 152} 153 154/* 155 * NAME osm_vendor_init 156 * 157 * DESCRIPTION Initialize the vendor object 158 */ 159 160ib_api_status_t 161osm_vendor_init(IN osm_vendor_t * const p_vend, 162 IN osm_log_t * const p_log, IN const uint32_t timeout) 163{ 164 ib_api_status_t status = IB_SUCCESS; 165 char device_file[16]; 166 int device_fd; 167 168 OSM_LOG_ENTER(p_log); 169 170 p_vend->p_log = p_log; 171 p_vend->resp_timeout = timeout; 172 p_vend->ttime_timeout = timeout * OSMV_TXN_TIMEOUT_FACTOR; 173 174 p_vend->p_transport_info = (osmv_TOPSPIN_ANAFA_transport_info_t *) 175 malloc(sizeof(osmv_TOPSPIN_ANAFA_transport_info_t)); 176 if (!p_vend->p_transport_info) { 177 return IB_ERROR; 178 } 179 180 memset(p_vend->p_transport_info, 0, 181 sizeof(osmv_TOPSPIN_ANAFA_transport_info_t)); 182 183 /* update the run_randomizer flag */ 184 if (getenv("OSM_PKT_DROP_RATE") != NULL 185 && atol(getenv("OSM_PKT_DROP_RATE")) != 0) { 186 /* if the OSM_PKT_DROP_RATE global variable is defined 187 to a non-zero value - 188 then the randomizer should be called. 189 Need to create the packet randomizer object */ 190 p_vend->run_randomizer = TRUE; 191 status = 192 osm_pkt_randomizer_init(&(p_vend->p_pkt_randomizer), p_log); 193 if (status != IB_SUCCESS) 194 return status; 195 } else { 196 p_vend->run_randomizer = FALSE; 197 p_vend->p_pkt_randomizer = NULL; 198 } 199 200 /* open TopSpin file device */ 201 sprintf(device_file, "/dev/ts_ua0"); 202 device_fd = open("/dev/ts_ua0", O_RDWR); 203 if (device_fd < 0) { 204 fprintf(stderr, "Fatal: Fail to open the file:%s(%d)\n", 205 device_file, errno); 206 return IB_ERROR; 207 } 208 209 ((osmv_TOPSPIN_ANAFA_transport_info_t *) p_vend->p_transport_info)-> 210 device_fd = device_fd; 211 212 cl_qlist_init(&p_vend->bind_handles); 213 214 OSM_LOG_EXIT(p_log); 215 return (IB_SUCCESS); 216} 217 218/* 219 * NAME osm_vendor_bind 220 * 221 * DESCRIPTION Create a new bind object under the vendor object 222 */ 223 224osm_bind_handle_t 225osm_vendor_bind(IN osm_vendor_t * const p_vend, 226 IN osm_bind_info_t * const p_bind_info, 227 IN osm_mad_pool_t * const p_mad_pool, 228 IN osm_vend_mad_recv_callback_t mad_recv_callback, 229 IN osm_vend_mad_send_err_callback_t send_err_callback, 230 IN void *context) 231{ 232 osmv_bind_obj_t *p_bo; 233 cl_status_t cl_st; 234 cl_list_obj_t *p_obj; 235 uint8_t hca_idx = 0; 236 237 if (NULL == p_vend || NULL == p_bind_info || NULL == p_mad_pool 238 || NULL == mad_recv_callback || NULL == send_err_callback) { 239 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 240 "osm_vendor_bind: ERR 7402: " 241 "NULL parameter passed in: p_vend=%p p_bind_info=%p p_mad_pool=%p recv_cb=%p send_err_cb=%p\n", 242 p_vend, p_bind_info, p_mad_pool, mad_recv_callback, 243 send_err_callback); 244 245 return OSM_BIND_INVALID_HANDLE; 246 } 247 248 p_bo = malloc(sizeof(osmv_bind_obj_t)); 249 if (NULL == p_bo) { 250 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 251 "osm_vendor_bind: ERR 7403: " 252 "could not allocate the bind object\n"); 253 return OSM_BIND_INVALID_HANDLE; 254 } 255 256 memset(p_bo, 0, sizeof(osmv_bind_obj_t)); 257 p_bo->p_vendor = p_vend; 258 p_bo->recv_cb = mad_recv_callback; 259 p_bo->send_err_cb = send_err_callback; 260 p_bo->cb_context = context; 261 p_bo->p_osm_pool = p_mad_pool; 262 p_bo->port_num = 1; /* anafa2 has one port */ 263 p_bo->hca_hndl = 0; /* only one ca on anafa system */ 264 265 /* obtain the hca name and port num from the guid */ 266 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 267 "osm_vendor_bind: " 268 "Finding CA and Port that owns port guid 0x%" PRIx64 ".\n", 269 cl_ntoh64(p_bind_info->port_guid)); 270 271 p_bo->is_closing = FALSE; 272 cl_spinlock_construct(&(p_bo->lock)); 273 cl_st = cl_spinlock_init(&(p_bo->lock)); 274 if (cl_st != CL_SUCCESS) { 275 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 276 "osm_vendor_bind: ERR 7405: " 277 "could not initialize the spinlock ...\n"); 278 free(p_bo); 279 return OSM_BIND_INVALID_HANDLE; 280 } 281 282 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, 283 "osm_vendor_bind: osmv_txnmgr_init ... \n"); 284 if (osmv_txnmgr_init(&p_bo->txn_mgr, p_vend->p_log, &(p_bo->lock)) != 285 IB_SUCCESS) { 286 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 287 "osm_vendor_bind: ERR 7406: " 288 "osmv_txnmgr_init failed \n"); 289 cl_spinlock_destroy(&p_bo->lock); 290 free(p_bo); 291 return OSM_BIND_INVALID_HANDLE; 292 } 293 294 /* Do the real job! (Transport-dependent) */ 295 if (IB_SUCCESS != 296 osmv_transport_init(p_bind_info, OSMV_ANAFA_ID, hca_idx, p_bo)) { 297 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 298 "osm_vendor_bind: ERR 7407: " 299 "osmv_transport_init failed \n"); 300 osmv_txnmgr_done((osm_bind_handle_t) p_bo); 301 cl_spinlock_destroy(&p_bo->lock); 302 free(p_bo); 303 return OSM_BIND_INVALID_HANDLE; 304 } 305 306 /* insert bind handle into db */ 307 p_obj = malloc(sizeof(cl_list_obj_t)); 308 if (NULL == p_obj) { 309 310 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 311 "osm_vendor_bind: ERR 7408: " 312 "osm_vendor_bind: could not allocate the list object\n"); 313 314 osmv_transport_done(p_bo->p_transp_mgr); 315 osmv_txnmgr_done((osm_bind_handle_t) p_bo); 316 cl_spinlock_destroy(&p_bo->lock); 317 free(p_bo); 318 return OSM_BIND_INVALID_HANDLE; 319 } 320 if (p_obj) 321 memset(p_obj, 0, sizeof(cl_list_obj_t)); 322 cl_qlist_set_obj(p_obj, p_bo); 323 324 cl_qlist_insert_head(&p_vend->bind_handles, &p_obj->list_item); 325 326 return (osm_bind_handle_t) p_bo; 327} 328 329/* 330 * NAME osm_vendor_unbind 331 * 332 * DESCRIPTION Destroy the bind object and remove it from the vendor's list 333 */ 334 335void osm_vendor_unbind(IN osm_bind_handle_t h_bind) 336{ 337 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 338 osm_log_t *p_log = p_bo->p_vendor->p_log; 339 cl_list_obj_t *p_obj; 340 cl_list_item_t *p_item, *p_item_tmp; 341 cl_qlist_t *const p_bh_list = 342 (cl_qlist_t * const)&p_bo->p_vendor->bind_handles; 343 344 OSM_LOG_ENTER(p_log); 345 346 /* go over all the items in the list and remove the specific item */ 347 p_item = cl_qlist_head(&p_bo->p_vendor->bind_handles); 348 while (p_item != cl_qlist_end(&p_bo->p_vendor->bind_handles)) { 349 p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); 350 if (cl_qlist_obj(p_obj) == h_bind) { 351 break; 352 } 353 p_item_tmp = cl_qlist_next(p_item); 354 p_item = p_item_tmp; 355 } 356 357 CL_ASSERT(p_item != cl_qlist_end(p_bh_list)); 358 359 cl_qlist_remove_item(p_bh_list, p_item); 360 free(p_obj); 361 362 __osm_vendor_internal_unbind(h_bind); 363 364 OSM_LOG_EXIT(p_bo->p_vendor->p_log); 365} 366 367/* 368 * NAME osm_vendor_get 369 * 370 * DESCRIPTION Allocate the space for a new MAD 371 */ 372 373ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind, 374 IN const uint32_t mad_size, 375 IN osm_vend_wrap_t * const p_vw) 376{ 377 ib_mad_t *p_mad; 378 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 379 osm_vendor_t const *p_vend = p_bo->p_vendor; 380 uint32_t act_mad_size; 381 382 OSM_LOG_ENTER(p_vend->p_log); 383 384 CL_ASSERT(p_vw); 385 386 if (mad_size < MAD_BLOCK_SIZE) { 387 /* Stupid, but the applications want that! */ 388 act_mad_size = MAD_BLOCK_SIZE; 389 } else { 390 act_mad_size = mad_size; 391 } 392 393 /* allocate it */ 394 p_mad = (ib_mad_t *) malloc(act_mad_size); 395 if (p_mad == NULL) { 396 osm_log(p_vend->p_log, OSM_LOG_ERROR, 397 "osm_vendor_get: ERR 7409: " 398 "Error Obtaining MAD buffer.\n"); 399 goto Exit; 400 } 401 402 memset(p_mad, 0, act_mad_size); 403 404 if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) { 405 osm_log(p_vend->p_log, OSM_LOG_DEBUG, 406 "osm_vendor_get: " 407 "Allocated MAD %p, size = %u.\n", p_mad, act_mad_size); 408 } 409 p_vw->p_mad = p_mad; 410 411Exit: 412 OSM_LOG_EXIT(p_vend->p_log); 413 return (p_mad); 414} 415 416/* 417 * NAME osm_vendor_send 418 * 419 * DESCRIPTION Send a MAD buffer (RMPP or simple send). 420 * 421 * Semantics: 422 * (1) The RMPP send completes when every segment 423 * is acknowledged (synchronous) 424 * (2) The simple send completes when the send completion 425 * is received (asynchronous) 426 */ 427 428ib_api_status_t 429osm_vendor_send(IN osm_bind_handle_t h_bind, 430 IN osm_madw_t * const p_madw, IN boolean_t const resp_expected) 431{ 432 ib_api_status_t ret = IB_SUCCESS; 433 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 434 boolean_t is_rmpp = FALSE, is_rmpp_ds = FALSE; 435 osmv_txn_ctx_t *p_txn = NULL; 436 ib_mad_t *p_mad; 437 438 OSM_LOG_ENTER(p_bo->p_vendor->p_log); 439 440 if (NULL == h_bind || NULL == p_madw || 441 NULL == (p_mad = osm_madw_get_mad_ptr(p_madw)) || 442 NULL == osm_madw_get_mad_addr_ptr(p_madw)) { 443 444 return IB_INVALID_PARAMETER; 445 } 446 447 is_rmpp = (p_madw->mad_size > MAD_BLOCK_SIZE 448 || osmv_mad_is_rmpp(p_mad)); 449 is_rmpp_ds = (TRUE == is_rmpp && TRUE == resp_expected); 450 451 /* Make our operations with the send context atomic */ 452 osmv_txn_lock(p_bo); 453 454 if (TRUE == p_bo->is_closing) { 455 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 456 "osm_vendor_send: ERR 7410: " 457 "The handle %p is being unbound, cannot send.\n", 458 h_bind); 459 ret = IB_INTERRUPTED; 460 goto send_done; 461 } 462 463 if (TRUE == resp_expected || TRUE == is_rmpp) { 464 465 /* We must run under a transaction framework. 466 * Get the transaction object (old or new) */ 467 ret = __osmv_get_send_txn(h_bind, p_madw, is_rmpp, 468 resp_expected, &p_txn); 469 if (IB_SUCCESS != ret) { 470 goto send_done; 471 } 472 } 473 474 if (TRUE == is_rmpp) { 475 /* Do the job - RMPP! 476 * The call returns as all the packets are ACK'ed/upon error 477 * The txn lock will be released each time the function sleeps 478 * and re-acquired when it wakes up 479 */ 480 ret = osmv_rmpp_send_madw(h_bind, p_madw, p_txn, is_rmpp_ds); 481 } else { 482 483 /* Do the job - single MAD! 484 * The call returns as soon as the MAD is put on the wire 485 */ 486 ret = osmv_simple_send_madw(h_bind, p_madw, p_txn, FALSE); /* anafa2 */ 487 } 488 489 if (IB_SUCCESS == ret) { 490 491 if ((TRUE == is_rmpp) && (FALSE == is_rmpp_ds)) { 492 /* For double-sided sends, the txn continues to live */ 493 osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), 494 FALSE /*not in callback */ ); 495 } 496 497 if (FALSE == resp_expected) { 498 osm_mad_pool_put(p_bo->p_osm_pool, p_madw); 499 } 500 } else { 501 if (NULL != p_txn) { 502 osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), 503 FALSE /*not in callback */ ); 504 } 505 506 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 507 "osm_vendor_send: ERR 7411: failed to send MADW %p\n", 508 p_madw); 509 510 if (TRUE == resp_expected) { 511 /* Change the status on the p_madw */ 512 p_madw->status = ret; 513 /* Only the requester expects the error callback */ 514 p_bo->send_err_cb(p_bo->cb_context, p_madw); 515 } else { 516 /* put back the mad - it is useless ... */ 517 osm_mad_pool_put(p_bo->p_osm_pool, p_madw); 518 } 519 } 520 521send_done: 522 523 osmv_txn_unlock(p_bo); 524 525 OSM_LOG_EXIT(p_bo->p_vendor->p_log); 526 return ret; 527} 528 529/* 530 * NAME osm_vendor_put 531 * 532 * DESCRIPTION Free the MAD's memory 533 */ 534 535void 536osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw) 537{ 538 539 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 540 osm_vendor_t const *p_vend = p_bo->p_vendor; 541 542 OSM_LOG_ENTER(p_vend->p_log); 543 544 CL_ASSERT(p_vw); 545 CL_ASSERT(p_vw->p_mad); 546 547 if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) { 548 osm_log(p_vend->p_log, OSM_LOG_DEBUG, 549 "osm_vendor_put: " "Retiring MAD %p.\n", p_vw->p_mad); 550 } 551 552 free(p_vw->p_mad); 553 p_vw->p_mad = NULL; 554 555 OSM_LOG_EXIT(p_vend->p_log); 556} 557 558/* 559 * NAME osm_vendor_local_lid_change 560 * 561 * DESCRIPTION Notifies the vendor transport layer that the local address 562 * has changed. This allows the vendor layer to perform 563 * housekeeping functions such as address vector updates. 564 */ 565 566ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind) 567{ 568 osm_vendor_t const *p_vend = ((osmv_bind_obj_t *) h_bind)->p_vendor; 569 OSM_LOG_ENTER(p_vend->p_log); 570 571 osm_log(p_vend->p_log, OSM_LOG_DEBUG, 572 "osm_vendor_local_lid_change: " "Change of LID.\n"); 573 574 OSM_LOG_EXIT(p_vend->p_log); 575 576 return (IB_SUCCESS); 577 578} 579 580/* 581 * NAME osm_vendor_set_sm 582 * 583 * DESCRIPTION Modifies the port info for the bound port to set the "IS_SM" bit. 584 */ 585 586void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val) 587{ 588 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 589 osm_vendor_t const *p_vend = p_bo->p_vendor; 590 osmv_TOPSPIN_ANAFA_transport_mgr_t *p_mgr; 591 int ioctl_ret; 592 osm_ts_set_port_info_ioctl port_info; 593 594 OSM_LOG_ENTER(p_vend->p_log); 595 596 port_info.port = 0; /* anafa has only 1 port */ 597 port_info.port_info.valid_fields = IB_PORT_IS_SM; 598 port_info.port_info.is_sm = is_sm_val; 599 600 p_mgr = (osmv_TOPSPIN_ANAFA_transport_mgr_t *) p_bo->p_transp_mgr; 601 ioctl_ret = ioctl(p_mgr->device_fd, TS_IB_IOCSPORTINFO, &port_info); 602 603 if (ioctl_ret < 0) { 604 osm_log(p_vend->p_log, OSM_LOG_ERROR, 605 "osm_vendor_set_sm: ERR 7412: " 606 "Unable set 'IS_SM' bit to:%u in port attributes (%d). errno=%d\n", 607 is_sm_val, ioctl_ret, errno); 608 } 609 610 OSM_LOG_EXIT(p_vend->p_log); 611} 612 613/* 614 * NAME __osm_vendor_internal_unbind 615 * 616 * DESCRIPTION Destroying a bind: 617 * (1) Wait for the completion of the sends in flight 618 * (2) Destroy the associated data structures 619 */ 620 621static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind) 622{ 623 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 624 osm_log_t *p_log = p_bo->p_vendor->p_log; 625 626 OSM_LOG_ENTER(p_log); 627 628 /* "notifying" all that from now on no new sends can be done */ 629 p_bo->txn_mgr.p_event_wheel->closing = TRUE; 630 631 osmv_txn_lock(p_bo); 632 p_bo->is_closing = TRUE; 633 634 /* notifying all sleeping rmpp sends to exit */ 635 osmv_txn_abort_rmpp_txns(h_bind); 636 637 /* frees all data in bind handle */ 638 osm_log(p_log, OSM_LOG_DEBUG, 639 "__osm_vendor_internal_unbind: destroying transport mgr.. \n"); 640 osmv_txn_unlock(p_bo); 641 642 osmv_transport_done(h_bind); 643 osm_log(p_log, OSM_LOG_DEBUG, 644 "__osm_vendor_internal_unbind: destroying txn mgr.. \n"); 645 osmv_txn_lock(p_bo); 646 osmv_txnmgr_done(h_bind); 647 osm_log(p_log, OSM_LOG_DEBUG, 648 "__osm_vendor_internal_unbind: destroying bind lock.. \n"); 649 650 osmv_txn_unlock(p_bo); 651 /* 652 we intentionally let the p_bo and its lock leak - 653 as we did not implement a way to track active bind handles provided to 654 the client - and the client might use them 655 656 cl_spinlock_destroy(&p_bo->lock); 657 free(p_bo); 658 */ 659 660 OSM_LOG_EXIT(p_log); 661} 662 663/* 664 * NAME __osmv_get_send_txn 665 * 666 * DESCRIPTION Return a transaction object that corresponds to this MAD. 667 * Optionally, create it, if the new request (query) is sent or received. 668 */ 669 670static ib_api_status_t 671__osmv_get_send_txn(IN osm_bind_handle_t h_bind, 672 IN osm_madw_t * const p_madw, 673 IN boolean_t is_rmpp, 674 IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn) 675{ 676 ib_api_status_t ret; 677 uint64_t tid, key; 678 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; 679 ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw); 680 681 OSM_LOG_ENTER(p_bo->p_vendor->p_log); 682 CL_ASSERT(NULL != pp_txn); 683 684 key = tid = cl_ntoh64(p_mad->trans_id); 685 if (TRUE == resp_expected) { 686 /* Create a unique identifier at the requester side */ 687 key = osmv_txn_uniq_key(tid); 688 } 689 690 /* We must run under a transaction framework */ 691 ret = osmv_txn_lookup(h_bind, key, pp_txn); 692 if (IB_NOT_FOUND == ret) { 693 /* Generally, we start a new transaction */ 694 ret = osmv_txn_init(h_bind, tid, key, pp_txn); 695 if (IB_SUCCESS != ret) { 696 goto get_send_txn_done; 697 } 698 } else { 699 CL_ASSERT(NULL != *pp_txn); 700 /* The transaction context exists. 701 * This is legal only if I am going to return an 702 * (RMPP?) reply to an RMPP request sent by the other part 703 * (double-sided RMPP transfer) 704 */ 705 if (FALSE == is_rmpp 706 || FALSE == osmv_txn_is_rmpp_init_by_peer(*pp_txn)) { 707 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 708 "__osmv_get_send_txn: ERR 7413: " 709 "The transaction id=0x%llX is not unique. Send failed.\n", 710 tid); 711 712 ret = IB_INVALID_SETTING; 713 goto get_send_txn_done; 714 } 715 716 if (TRUE == resp_expected) { 717 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, 718 "__osmv_get_send_txn: ERR 7414: " 719 "The transaction id=%llX can\'t expect a response. Send failed.\n", 720 tid); 721 722 ret = IB_INVALID_PARAMETER; 723 goto get_send_txn_done; 724 } 725 } 726 727 if (TRUE == is_rmpp) { 728 ret = osmv_txn_init_rmpp_sender(h_bind, *pp_txn, p_madw); 729 if (IB_SUCCESS != ret) { 730 osmv_txn_done(h_bind, tid, FALSE); 731 goto get_send_txn_done; 732 } 733 } 734 735 /* Save a reference to the MAD in the txn context 736 * We'll need to match it in two cases: 737 * (1) When the response is returned, if I am the requester 738 * (2) In RMPP retransmissions 739 */ 740 osmv_txn_set_madw(*pp_txn, p_madw); 741 742get_send_txn_done: 743 OSM_LOG_EXIT(p_bo->p_vendor->p_log); 744 745 return ret; 746} 747 748void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level) 749{ 750 751} 752