1 /* 2 * Copyright (c) 2004-2009 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 * Copyright (c) 2009 HNR Consulting. All rights reserved. 6 * 7 * This software is available to you under a choice of one of two 8 * licenses. You may choose to be licensed under the terms of the GNU 9 * General Public License (GPL) Version 2, available from the file 10 * COPYING in the main directory of this source tree, or the 11 * OpenIB.org BSD license below: 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 * 35 */ 36 37 /* 38 * Abstract: 39 * Implementation of osm_sa_mad_ctrl_t. 40 * This object is part of the SA object. 41 */ 42 43 #if HAVE_CONFIG_H 44 # include <config.h> 45 #endif /* HAVE_CONFIG_H */ 46 47 #include <string.h> 48 #include <complib/cl_debug.h> 49 #include <iba/ib_types.h> 50 #include <opensm/osm_file_ids.h> 51 #define FILE_ID OSM_FILE_SA_MAD_CTRL_C 52 #include <vendor/osm_vendor_api.h> 53 #include <opensm/osm_sa_mad_ctrl.h> 54 #include <opensm/osm_msgdef.h> 55 #include <opensm/osm_helper.h> 56 #include <opensm/osm_sa.h> 57 #include <opensm/osm_opensm.h> 58 59 /****f* opensm: SA/sa_mad_ctrl_disp_done_callback 60 * NAME 61 * sa_mad_ctrl_disp_done_callback 62 * 63 * DESCRIPTION 64 * This function is the Dispatcher callback that indicates 65 * a received MAD has been processed by the recipient. 66 * 67 * SYNOPSIS 68 */ 69 static void sa_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data) 70 { 71 osm_sa_mad_ctrl_t *p_ctrl = context; 72 osm_madw_t *p_madw = p_data; 73 74 OSM_LOG_ENTER(p_ctrl->p_log); 75 76 CL_ASSERT(p_madw); 77 /* 78 Return the MAD & wrapper to the pool. 79 */ 80 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 81 OSM_LOG_EXIT(p_ctrl->p_log); 82 } 83 84 /************/ 85 86 /****f* opensm: SA/sa_mad_ctrl_process 87 * NAME 88 * sa_mad_ctrl_process 89 * 90 * DESCRIPTION 91 * This function handles known methods for received MADs. 92 * 93 * SYNOPSIS 94 */ 95 static void sa_mad_ctrl_process(IN osm_sa_mad_ctrl_t * p_ctrl, 96 IN osm_madw_t * p_madw, 97 IN boolean_t is_get_request) 98 { 99 ib_sa_mad_t *p_sa_mad; 100 cl_disp_reg_handle_t h_disp; 101 cl_status_t status; 102 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 103 uint64_t last_dispatched_msg_queue_time_msec; 104 uint32_t num_messages; 105 106 OSM_LOG_ENTER(p_ctrl->p_log); 107 108 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 109 110 /* 111 If the dispatcher is showing us that it is overloaded 112 there is no point in placing the request in. We should instead 113 provide immediate response - IB_RESOURCE_BUSY 114 But how do we know? 115 The dispatcher reports back the number of outstanding messages and 116 the time the last message stayed in the queue. 117 HACK: Actually, we cannot send a mad from within the receive callback; 118 thus - we will just drop it. 119 */ 120 121 if (!is_get_request && p_ctrl->p_set_disp) { 122 h_disp = p_ctrl->h_set_disp; 123 goto SKIP_QUEUE_CHECK; 124 } 125 126 h_disp = p_ctrl->h_disp; 127 cl_disp_get_queue_status(h_disp, &num_messages, 128 &last_dispatched_msg_queue_time_msec); 129 130 if (num_messages > 1 && p_ctrl->p_subn->opt.max_msg_fifo_timeout && 131 last_dispatched_msg_queue_time_msec > 132 p_ctrl->p_subn->opt.max_msg_fifo_timeout) { 133 OSM_LOG(p_ctrl->p_log, OSM_LOG_INFO, 134 /* "Responding BUSY status since the dispatcher is already" */ 135 "Dropping MAD since the dispatcher is already" 136 " overloaded with %u messages and queue time of:" 137 "%" PRIu64 "[msec]\n", 138 num_messages, last_dispatched_msg_queue_time_msec); 139 140 /* send a busy response */ 141 /* osm_sa_send_error(p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY); */ 142 143 /* return the request to the pool */ 144 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 145 146 goto Exit; 147 } 148 149 SKIP_QUEUE_CHECK: 150 /* 151 Note that attr_id (like the rest of the MAD) is in 152 network byte order. 153 */ 154 switch (p_sa_mad->attr_id) { 155 case IB_MAD_ATTR_CLASS_PORT_INFO: 156 msg_id = OSM_MSG_MAD_CLASS_PORT_INFO; 157 break; 158 159 case IB_MAD_ATTR_NODE_RECORD: 160 msg_id = OSM_MSG_MAD_NODE_RECORD; 161 break; 162 163 case IB_MAD_ATTR_PORTINFO_RECORD: 164 msg_id = OSM_MSG_MAD_PORTINFO_RECORD; 165 break; 166 167 case IB_MAD_ATTR_LINK_RECORD: 168 msg_id = OSM_MSG_MAD_LINK_RECORD; 169 break; 170 171 case IB_MAD_ATTR_SMINFO_RECORD: 172 msg_id = OSM_MSG_MAD_SMINFO_RECORD; 173 break; 174 175 case IB_MAD_ATTR_SERVICE_RECORD: 176 msg_id = OSM_MSG_MAD_SERVICE_RECORD; 177 break; 178 179 case IB_MAD_ATTR_PATH_RECORD: 180 msg_id = OSM_MSG_MAD_PATH_RECORD; 181 break; 182 183 case IB_MAD_ATTR_MCMEMBER_RECORD: 184 msg_id = OSM_MSG_MAD_MCMEMBER_RECORD; 185 break; 186 187 case IB_MAD_ATTR_INFORM_INFO: 188 msg_id = OSM_MSG_MAD_INFORM_INFO; 189 break; 190 191 case IB_MAD_ATTR_VLARB_RECORD: 192 msg_id = OSM_MSG_MAD_VL_ARB_RECORD; 193 break; 194 195 case IB_MAD_ATTR_SLVL_RECORD: 196 msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD; 197 break; 198 199 case IB_MAD_ATTR_PKEY_TBL_RECORD: 200 msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD; 201 break; 202 203 case IB_MAD_ATTR_LFT_RECORD: 204 msg_id = OSM_MSG_MAD_LFT_RECORD; 205 break; 206 207 case IB_MAD_ATTR_GUIDINFO_RECORD: 208 msg_id = OSM_MSG_MAD_GUIDINFO_RECORD; 209 break; 210 211 case IB_MAD_ATTR_INFORM_INFO_RECORD: 212 msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD; 213 break; 214 215 case IB_MAD_ATTR_SWITCH_INFO_RECORD: 216 msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD; 217 break; 218 219 case IB_MAD_ATTR_MFT_RECORD: 220 msg_id = OSM_MSG_MAD_MFT_RECORD; 221 break; 222 223 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) 224 case IB_MAD_ATTR_MULTIPATH_RECORD: 225 msg_id = OSM_MSG_MAD_MULTIPATH_RECORD; 226 break; 227 #endif 228 229 default: 230 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A01: " 231 "Unsupported attribute 0x%X (%s)\n", 232 cl_ntoh16(p_sa_mad->attr_id), 233 ib_get_sa_attr_str(p_sa_mad->attr_id)); 234 osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_ERROR); 235 } 236 237 if (msg_id != CL_DISP_MSGID_NONE) { 238 /* 239 Post this MAD to the dispatcher for asynchronous 240 processing by the appropriate controller. 241 */ 242 243 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 244 "Posting Dispatcher message %s\n", 245 osm_get_disp_msg_str(msg_id)); 246 247 status = cl_disp_post(h_disp, msg_id, p_madw, 248 sa_mad_ctrl_disp_done_callback, p_ctrl); 249 250 if (status != CL_SUCCESS) { 251 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A02: " 252 "Dispatcher post message failed (%s) for attribute 0x%X (%s)\n", 253 CL_STATUS_MSG(status), 254 cl_ntoh16(p_sa_mad->attr_id), 255 ib_get_sa_attr_str(p_sa_mad->attr_id)); 256 257 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 258 goto Exit; 259 } 260 } else { 261 /* 262 There is an unknown MAD attribute type for which there is 263 no recipient. Simply retire the MAD here. 264 */ 265 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown); 266 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 267 } 268 269 Exit: 270 OSM_LOG_EXIT(p_ctrl->p_log); 271 } 272 273 /* 274 * PARAMETERS 275 * 276 * RETURN VALUES 277 * 278 * NOTES 279 * 280 * SEE ALSO 281 *********/ 282 283 /****f* opensm: SA/sa_mad_ctrl_rcv_callback 284 * NAME 285 * sa_mad_ctrl_rcv_callback 286 * 287 * DESCRIPTION 288 * This is the callback from the transport layer for received MADs. 289 * 290 * SYNOPSIS 291 */ 292 static void sa_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, IN void *context, 293 IN osm_madw_t * p_req_madw) 294 { 295 osm_sa_mad_ctrl_t *p_ctrl = context; 296 ib_sa_mad_t *p_sa_mad; 297 boolean_t is_get_request = FALSE; 298 299 OSM_LOG_ENTER(p_ctrl->p_log); 300 301 CL_ASSERT(p_madw); 302 303 /* 304 A MAD was received from the wire, possibly in response to a request. 305 */ 306 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd); 307 308 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 309 "%u SA MADs received\n", p_ctrl->p_stats->sa_mads_rcvd); 310 311 /* 312 * C15-0.1.3 requires not responding to any MAD if the SM is 313 * not in active state! 314 * We will not respond if the sm_state is not MASTER, or if the 315 * first_time_master_sweep flag (of the subnet) is TRUE - this 316 * flag indicates that the master still didn't finish its first 317 * sweep, so the subnet is not up and stable yet. 318 */ 319 if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) { 320 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored); 321 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 322 "Received SA MAD while SM not MASTER. MAD ignored\n"); 323 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 324 goto Exit; 325 } 326 if (p_ctrl->p_subn->first_time_master_sweep == TRUE) { 327 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored); 328 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 329 "Received SA MAD while SM in first sweep. MAD ignored\n"); 330 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 331 goto Exit; 332 } 333 334 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 335 336 if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES)) 337 osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_FRAMES); 338 339 /* 340 * C15-0.1.5 - Table 185: SA Header - p884 341 * SM_key should be either 0 or match the current SM_Key 342 * otherwise discard the MAD. 343 */ 344 if (p_sa_mad->sm_key != 0 && 345 p_sa_mad->sm_key != p_ctrl->p_subn->opt.sa_key) { 346 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A04: " 347 "Non-Zero MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%" 348 PRIx64 "; SA MAD ignored for method 0x%X attribute 0x%X (%s)\n", 349 cl_ntoh64(p_sa_mad->sm_key), 350 cl_ntoh64(p_ctrl->p_subn->opt.sa_key), 351 p_sa_mad->method, cl_ntoh16(p_sa_mad->attr_id), 352 ib_get_sa_attr_str(p_sa_mad->attr_id)); 353 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 354 goto Exit; 355 } 356 357 switch (p_sa_mad->method) { 358 case IB_MAD_METHOD_REPORT_RESP: 359 /* we do not really do anything with report responses - 360 just retire the transaction */ 361 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 362 "Received Report Response. Retiring the transaction\n"); 363 364 if (p_req_madw) 365 osm_mad_pool_put(p_ctrl->p_mad_pool, p_req_madw); 366 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 367 368 break; 369 370 case IB_MAD_METHOD_GET: 371 case IB_MAD_METHOD_GETTABLE: 372 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) 373 case IB_MAD_METHOD_GETMULTI: 374 #endif 375 is_get_request = TRUE; 376 /* FALLTHROUGH */ 377 case IB_MAD_METHOD_SET: 378 case IB_MAD_METHOD_DELETE: 379 /* if we are closing down simply do nothing */ 380 if (osm_exit_flag) 381 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 382 else 383 sa_mad_ctrl_process(p_ctrl, p_madw, is_get_request); 384 break; 385 386 default: 387 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown); 388 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A05: " 389 "Unsupported method = 0x%X\n", p_sa_mad->method); 390 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 391 goto Exit; 392 } 393 394 Exit: 395 OSM_LOG_EXIT(p_ctrl->p_log); 396 } 397 398 /* 399 * PARAMETERS 400 * 401 * RETURN VALUES 402 * 403 * NOTES 404 * 405 * SEE ALSO 406 *********/ 407 408 /****f* opensm: SA/sa_mad_ctrl_send_err_callback 409 * NAME 410 * sa_mad_ctrl_send_err_callback 411 * 412 * DESCRIPTION 413 * This is the callback from the transport layer for send errors 414 * on MADs that were expecting a response. 415 * 416 * SYNOPSIS 417 */ 418 static void sa_mad_ctrl_send_err_callback(IN void *context, 419 IN osm_madw_t * p_madw) 420 { 421 osm_sa_mad_ctrl_t *p_ctrl = context; 422 cl_status_t status; 423 424 OSM_LOG_ENTER(p_ctrl->p_log); 425 426 /* 427 We should never be here since the SA never originates a request. 428 Unless we generated a Report(Notice) 429 */ 430 431 CL_ASSERT(p_madw); 432 433 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A06: " 434 "MAD completed in error (%s): " 435 "%s(%s), attr_mod 0x%x, LID %u, TID 0x%" PRIx64 "\n", 436 ib_get_err_str(p_madw->status), 437 ib_get_sa_method_str(p_madw->p_mad->method), 438 ib_get_sa_attr_str(p_madw->p_mad->attr_id), 439 cl_ntoh32(p_madw->p_mad->attr_mod), 440 cl_ntoh16(p_madw->mad_addr.dest_lid), 441 cl_ntoh64(p_madw->p_mad->trans_id)); 442 443 osm_dump_sa_mad_v2(p_ctrl->p_log, osm_madw_get_sa_mad_ptr(p_madw), 444 FILE_ID, OSM_LOG_ERROR); 445 446 /* 447 An error occurred. No response was received to a request MAD. 448 Retire the original request MAD. 449 */ 450 451 if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) { 452 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 453 "Posting Dispatcher message %s\n", 454 osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw))); 455 456 if (p_ctrl->p_set_disp && 457 (p_madw->p_mad->method == IB_MAD_METHOD_SET || 458 p_madw->p_mad->method == IB_MAD_METHOD_DELETE)) 459 status = cl_disp_post(p_ctrl->h_set_disp, 460 osm_madw_get_err_msg(p_madw), 461 p_madw, 462 sa_mad_ctrl_disp_done_callback, 463 p_ctrl); 464 else 465 status = cl_disp_post(p_ctrl->h_disp, 466 osm_madw_get_err_msg(p_madw), 467 p_madw, 468 sa_mad_ctrl_disp_done_callback, 469 p_ctrl); 470 if (status != CL_SUCCESS) { 471 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A07: " 472 "Dispatcher post message failed (%s)\n", 473 CL_STATUS_MSG(status)); 474 } 475 } else /* No error message was provided, just retire the MAD. */ 476 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 477 478 OSM_LOG_EXIT(p_ctrl->p_log); 479 } 480 481 /* 482 * PARAMETERS 483 * 484 * RETURN VALUES 485 * 486 * NOTES 487 * 488 * SEE ALSO 489 *********/ 490 491 void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * p_ctrl) 492 { 493 CL_ASSERT(p_ctrl); 494 memset(p_ctrl, 0, sizeof(*p_ctrl)); 495 p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; 496 p_ctrl->h_set_disp = CL_DISP_INVALID_HANDLE; 497 } 498 499 void osm_sa_mad_ctrl_destroy(IN osm_sa_mad_ctrl_t * p_ctrl) 500 { 501 CL_ASSERT(p_ctrl); 502 cl_disp_unregister(p_ctrl->h_disp); 503 cl_disp_unregister(p_ctrl->h_set_disp); 504 } 505 506 ib_api_status_t osm_sa_mad_ctrl_init(IN osm_sa_mad_ctrl_t * p_ctrl, 507 IN osm_sa_t * sa, 508 IN osm_mad_pool_t * p_mad_pool, 509 IN osm_vendor_t * p_vendor, 510 IN osm_subn_t * p_subn, 511 IN osm_log_t * p_log, 512 IN osm_stats_t * p_stats, 513 IN cl_dispatcher_t * p_disp, 514 IN cl_dispatcher_t * p_set_disp) 515 { 516 ib_api_status_t status = IB_SUCCESS; 517 518 OSM_LOG_ENTER(p_log); 519 520 osm_sa_mad_ctrl_construct(p_ctrl); 521 522 p_ctrl->sa = sa; 523 p_ctrl->p_log = p_log; 524 p_ctrl->p_disp = p_disp; 525 p_ctrl->p_set_disp = p_set_disp; 526 p_ctrl->p_mad_pool = p_mad_pool; 527 p_ctrl->p_vendor = p_vendor; 528 p_ctrl->p_stats = p_stats; 529 p_ctrl->p_subn = p_subn; 530 531 p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL, 532 p_ctrl); 533 534 if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) { 535 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A08: " 536 "Dispatcher registration failed\n"); 537 status = IB_INSUFFICIENT_RESOURCES; 538 goto Exit; 539 } 540 541 if (p_set_disp) { 542 p_ctrl->h_set_disp = 543 cl_disp_register(p_set_disp, CL_DISP_MSGID_NONE, NULL, 544 p_ctrl); 545 546 if (p_ctrl->h_set_disp == CL_DISP_INVALID_HANDLE) { 547 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A0A: " 548 "SA set dispatcher registration failed\n"); 549 status = IB_INSUFFICIENT_RESOURCES; 550 goto Exit; 551 } 552 } 553 554 Exit: 555 OSM_LOG_EXIT(p_log); 556 return status; 557 } 558 559 ib_api_status_t osm_sa_mad_ctrl_bind(IN osm_sa_mad_ctrl_t * p_ctrl, 560 IN ib_net64_t port_guid) 561 { 562 osm_bind_info_t bind_info; 563 ib_api_status_t status = IB_SUCCESS; 564 565 OSM_LOG_ENTER(p_ctrl->p_log); 566 567 if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) { 568 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A09: " 569 "Multiple binds not allowed\n"); 570 status = IB_ERROR; 571 goto Exit; 572 } 573 574 bind_info.class_version = 2; 575 bind_info.is_responder = TRUE; 576 bind_info.is_report_processor = FALSE; 577 bind_info.is_trap_processor = FALSE; 578 bind_info.mad_class = IB_MCLASS_SUBN_ADM; 579 bind_info.port_guid = port_guid; 580 bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE; 581 bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE; 582 bind_info.timeout = p_ctrl->sa->p_subn->opt.transaction_timeout; 583 bind_info.retries = p_ctrl->sa->p_subn->opt.transaction_retries; 584 585 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 586 "Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); 587 588 p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, &bind_info, 589 p_ctrl->p_mad_pool, 590 sa_mad_ctrl_rcv_callback, 591 sa_mad_ctrl_send_err_callback, p_ctrl); 592 593 if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { 594 status = IB_ERROR; 595 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A10: " 596 "Vendor specific bind failed (%s)\n", 597 ib_get_err_str(status)); 598 goto Exit; 599 } 600 601 Exit: 602 OSM_LOG_EXIT(p_ctrl->p_log); 603 return status; 604 } 605 606 ib_api_status_t osm_sa_mad_ctrl_unbind(IN osm_sa_mad_ctrl_t * p_ctrl) 607 { 608 ib_api_status_t status = IB_SUCCESS; 609 610 OSM_LOG_ENTER(p_ctrl->p_log); 611 612 if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { 613 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A11: " 614 "No previous bind\n"); 615 status = IB_ERROR; 616 goto Exit; 617 } 618 619 osm_vendor_unbind(p_ctrl->h_bind); 620 Exit: 621 OSM_LOG_EXIT(p_ctrl->p_log); 622 return status; 623 } 624