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/* 37 * Abstract: 38 * Implementation of osm_sm_mad_ctrl_t. 39 * This object represents the SM MAD request controller object. 40 * This object is part of the opensm family of objects. 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_sm_mad_ctrl.h> 51#include <vendor/osm_vendor_api.h> 52#include <opensm/osm_madw.h> 53#include <opensm/osm_msgdef.h> 54#include <opensm/osm_helper.h> 55#include <opensm/osm_opensm.h> 56 57/****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad 58 * NAME 59 * __osm_sm_mad_ctrl_retire_trans_mad 60 * 61 * DESCRIPTION 62 * This function handles clean-up of MADs associated with the SM's 63 * outstanding transactions on the wire. 64 * 65 * SYNOPSIS 66 */ 67 68static void 69__osm_sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * const p_ctrl, 70 IN osm_madw_t * const p_madw) 71{ 72 uint32_t outstanding; 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_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 81 "Retiring MAD with TID 0x%" PRIx64 "\n", 82 cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id)); 83 84 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 85 86 outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats); 87 88 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n", 89 p_ctrl->p_stats->qp0_mads_outstanding, 90 outstanding ? "" : ": wire is clean."); 91 92 OSM_LOG_EXIT(p_ctrl->p_log); 93} 94 95/************/ 96 97/****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback 98 * NAME 99 * __osm_sm_mad_ctrl_disp_done_callback 100 * 101 * DESCRIPTION 102 * This function is the Dispatcher callback that indicates 103 * a received MAD has been processed by the recipient. 104 * 105 * SYNOPSIS 106 */ 107static void 108__osm_sm_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data) 109{ 110 osm_sm_mad_ctrl_t *const p_ctrl = (osm_sm_mad_ctrl_t *) context; 111 osm_madw_t *const p_madw = (osm_madw_t *) p_data; 112 ib_smp_t *p_smp; 113 114 OSM_LOG_ENTER(p_ctrl->p_log); 115 116 /* 117 If the MAD that just finished processing was a response, 118 then retire the transaction, since we must have generated 119 the request. 120 121 Otherwise, retire the transaction if a response was expected, 122 as in the case of a send failure. If a response was not expected, 123 just put the MAD back in the pool, because the MAD was a query 124 from some outside agent, e.g. Get(SMInfo) from another SM. 125 */ 126 p_smp = osm_madw_get_smp_ptr(p_madw); 127 if (ib_smp_is_response(p_smp)) { 128 CL_ASSERT(p_madw->resp_expected == FALSE); 129 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 130 } else if (p_madw->resp_expected == TRUE) 131 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 132 else 133 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 134 135 OSM_LOG_EXIT(p_ctrl->p_log); 136} 137 138/************/ 139 140/****f* opensm: SM/__osm_sm_mad_ctrl_update_wire_stats 141 * NAME 142 * __osm_sm_mad_ctrl_update_wire_stats 143 * 144 * DESCRIPTION 145 * Updates wire stats for outstanding MADs and calls the VL15 poller. 146 * 147 * SYNOPSIS 148 */ 149static void 150__osm_sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * const p_ctrl) 151{ 152 uint32_t mads_on_wire; 153 154 OSM_LOG_ENTER(p_ctrl->p_log); 155 156 mads_on_wire = 157 cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire); 158 159 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 160 "%u SMPs on the wire, %u outstanding\n", mads_on_wire, 161 p_ctrl->p_stats->qp0_mads_outstanding); 162 163 /* 164 We can signal the VL15 controller to send another MAD 165 if any are waiting for transmission. 166 */ 167 osm_vl15_poll(p_ctrl->p_vl15); 168 OSM_LOG_EXIT(p_ctrl->p_log); 169} 170 171/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp 172 * NAME 173 * __osm_sm_mad_ctrl_process_get_resp 174 * 175 * DESCRIPTION 176 * This function handles method GetResp() for received MADs. 177 * This is the most common path for QP0 MADs. 178 * 179 * SYNOPSIS 180 */ 181static void 182__osm_sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * const p_ctrl, 183 IN osm_madw_t * p_madw, 184 IN void *transaction_context) 185{ 186 ib_smp_t *p_smp; 187 cl_status_t status; 188 osm_madw_t *p_old_madw; 189 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 190 191 OSM_LOG_ENTER(p_ctrl->p_log); 192 193 CL_ASSERT(p_madw); 194 CL_ASSERT(transaction_context); 195 196 p_smp = osm_madw_get_smp_ptr(p_madw); 197 198 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) { 199 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: " 200 "'D' bit not set in returned SMP\n"); 201 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 202 } 203 204 p_old_madw = (osm_madw_t *) transaction_context; 205 206 __osm_sm_mad_ctrl_update_wire_stats(p_ctrl); 207 208 /* 209 Copy the MAD Wrapper context from the requesting MAD 210 to the new MAD. This mechanism allows the recipient 211 controller to recover its own context regarding this 212 MAD transaction. Once we've copied the context, we 213 can return the original MAD to the pool. 214 */ 215 osm_madw_copy_context(p_madw, p_old_madw); 216 osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw); 217 218 /* 219 Note that attr_id (like the rest of the MAD) is in 220 network byte order. 221 */ 222 switch (p_smp->attr_id) { 223 case IB_MAD_ATTR_NODE_DESC: 224 msg_id = OSM_MSG_MAD_NODE_DESC; 225 break; 226 case IB_MAD_ATTR_NODE_INFO: 227 msg_id = OSM_MSG_MAD_NODE_INFO; 228 break; 229 case IB_MAD_ATTR_SWITCH_INFO: 230 msg_id = OSM_MSG_MAD_SWITCH_INFO; 231 break; 232 case IB_MAD_ATTR_PORT_INFO: 233 msg_id = OSM_MSG_MAD_PORT_INFO; 234 break; 235 case IB_MAD_ATTR_LIN_FWD_TBL: 236 msg_id = OSM_MSG_MAD_LFT; 237 break; 238 case IB_MAD_ATTR_MCAST_FWD_TBL: 239 msg_id = OSM_MSG_MAD_MFT; 240 break; 241 case IB_MAD_ATTR_SM_INFO: 242 msg_id = OSM_MSG_MAD_SM_INFO; 243 break; 244 case IB_MAD_ATTR_SLVL_TABLE: 245 msg_id = OSM_MSG_MAD_SLVL; 246 break; 247 case IB_MAD_ATTR_VL_ARBITRATION: 248 msg_id = OSM_MSG_MAD_VL_ARB; 249 break; 250 case IB_MAD_ATTR_P_KEY_TABLE: 251 msg_id = OSM_MSG_MAD_PKEY; 252 break; 253 254 case IB_MAD_ATTR_GUID_INFO: 255 case IB_MAD_ATTR_CLASS_PORT_INFO: 256 case IB_MAD_ATTR_NOTICE: 257 case IB_MAD_ATTR_INFORM_INFO: 258 default: 259 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 260 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: " 261 "Unsupported attribute = 0x%X\n", 262 cl_ntoh16(p_smp->attr_id)); 263 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 264 goto Exit; 265 } 266 267 if (msg_id == CL_DISP_MSGID_NONE) 268 goto Exit; 269 270 /* 271 Post this MAD to the dispatcher for asynchronous 272 processing by the appropriate controller. 273 */ 274 275 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 276 osm_get_disp_msg_str(msg_id)); 277 278 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 279 __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 280 281 if (status != CL_SUCCESS) { 282 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: " 283 "Dispatcher post message failed (%s) for attribute = 0x%X\n", 284 CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id)); 285 goto Exit; 286 } 287 288Exit: 289 OSM_LOG_EXIT(p_ctrl->p_log); 290} 291 292/****f* opensm: SM/__osm_sm_mad_ctrl_process_get 293 * NAME 294 * __osm_sm_mad_ctrl_process_get 295 * 296 * DESCRIPTION 297 * This function handles method Get() for received MADs. 298 * 299 * SYNOPSIS 300 */ 301static void 302__osm_sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * const p_ctrl, 303 IN osm_madw_t * p_madw) 304{ 305 ib_smp_t *p_smp; 306 cl_status_t status; 307 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 308 309 OSM_LOG_ENTER(p_ctrl->p_log); 310 311 p_smp = osm_madw_get_smp_ptr(p_madw); 312 313 /* 314 Note that attr_id (like the rest of the MAD) is in 315 network byte order. 316 */ 317 switch (p_smp->attr_id) { 318 case IB_MAD_ATTR_SM_INFO: 319 msg_id = OSM_MSG_MAD_SM_INFO; 320 break; 321 322 default: 323 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 324 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 325 "Ignoring SubnGet MAD - unsupported attribute = 0x%X\n", 326 cl_ntoh16(p_smp->attr_id)); 327 break; 328 } 329 330 if (msg_id == CL_DISP_MSGID_NONE) { 331 /* 332 There is an unknown MAD attribute type for which there is 333 no recipient. Simply retire the MAD here. 334 */ 335 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 336 goto Exit; 337 } 338 339 /* 340 Post this MAD to the dispatcher for asynchronous 341 processing by the appropriate controller. 342 */ 343 344 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 345 osm_get_disp_msg_str(msg_id)); 346 347 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 348 __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 349 350 if (status != CL_SUCCESS) { 351 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: " 352 "Dispatcher post message failed (%s)\n", 353 CL_STATUS_MSG(status)); 354 goto Exit; 355 } 356 357Exit: 358 OSM_LOG_EXIT(p_ctrl->p_log); 359} 360 361/* 362 * PARAMETERS 363 * 364 * RETURN VALUES 365 * 366 * NOTES 367 * 368 * SEE ALSO 369 *********/ 370 371/****f* opensm: SM/__osm_sm_mad_ctrl_process_set 372 * NAME 373 * __osm_sm_mad_ctrl_process_set 374 * 375 * DESCRIPTION 376 * This function handles method Set() for received MADs. 377 * 378 * SYNOPSIS 379 */ 380static void 381__osm_sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * const p_ctrl, 382 IN osm_madw_t * p_madw) 383{ 384 ib_smp_t *p_smp; 385 cl_status_t status; 386 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 387 388 OSM_LOG_ENTER(p_ctrl->p_log); 389 390 p_smp = osm_madw_get_smp_ptr(p_madw); 391 392 /* 393 Note that attr_id (like the rest of the MAD) is in 394 network byte order. 395 */ 396 switch (p_smp->attr_id) { 397 case IB_MAD_ATTR_SM_INFO: 398 msg_id = OSM_MSG_MAD_SM_INFO; 399 break; 400 401 default: 402 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 403 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: " 404 "Unsupported attribute = 0x%X\n", 405 cl_ntoh16(p_smp->attr_id)); 406 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 407 break; 408 } 409 410 if (msg_id == CL_DISP_MSGID_NONE) { 411 /* 412 There is an unknown MAD attribute type for which there is 413 no recipient. Simply retire the MAD here. 414 */ 415 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 416 goto Exit; 417 } 418 419 /* 420 Post this MAD to the dispatcher for asynchronous 421 processing by the appropriate controller. 422 */ 423 424 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 425 osm_get_disp_msg_str(msg_id)); 426 427 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 428 __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 429 430 if (status != CL_SUCCESS) { 431 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: " 432 "Dispatcher post message failed (%s)\n", 433 CL_STATUS_MSG(status)); 434 goto Exit; 435 } 436 437Exit: 438 OSM_LOG_EXIT(p_ctrl->p_log); 439} 440 441/* 442 * PARAMETERS 443 * 444 * RETURN VALUES 445 * 446 * NOTES 447 * 448 * SEE ALSO 449 *********/ 450 451/****f* opensm: SM/__osm_sm_mad_ctrl_process_trap 452 * NAME 453 * __osm_sm_mad_ctrl_process_trap 454 * 455 * DESCRIPTION 456 * This function handles method Trap() for received MADs. 457 * 458 * SYNOPSIS 459 */ 460static void 461__osm_sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * const p_ctrl, 462 IN osm_madw_t * p_madw) 463{ 464 ib_smp_t *p_smp; 465 cl_status_t status; 466 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 467 468 OSM_LOG_ENTER(p_ctrl->p_log); 469 470 p_smp = osm_madw_get_smp_ptr(p_madw); 471 472 /* Make sure OpenSM is master. If not - then we should not process the trap */ 473 if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) { 474 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 475 "Received trap but OpenSM is not in MASTER state. " 476 "Dropping mad\n"); 477 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 478 goto Exit; 479 } 480 481 /* 482 Note that attr_id (like the rest of the MAD) is in 483 network byte order. 484 */ 485 switch (p_smp->attr_id) { 486 case IB_MAD_ATTR_NOTICE: 487 msg_id = OSM_MSG_MAD_NOTICE; 488 break; 489 490 default: 491 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 492 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: " 493 "Unsupported attribute = 0x%X\n", 494 cl_ntoh16(p_smp->attr_id)); 495 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 496 break; 497 } 498 499 if (msg_id == CL_DISP_MSGID_NONE) { 500 /* 501 There is an unknown MAD attribute type for which there is 502 no recipient. Simply retire the MAD here. 503 */ 504 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 505 goto Exit; 506 } 507 508 /* 509 Post this MAD to the dispatcher for asynchronous 510 processing by the appropriate controller. 511 */ 512 513 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 514 osm_get_disp_msg_str(msg_id)); 515 516 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 517 __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 518 519 if (status != CL_SUCCESS) { 520 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: " 521 "Dispatcher post message failed (%s)\n", 522 CL_STATUS_MSG(status)); 523 goto Exit; 524 } 525 526Exit: 527 OSM_LOG_EXIT(p_ctrl->p_log); 528} 529 530/* 531 * PARAMETERS 532 * 533 * RETURN VALUES 534 * 535 * NOTES 536 * 537 * SEE ALSO 538 *********/ 539 540/****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback 541 * NAME 542 * __osm_sm_mad_ctrl_rcv_callback 543 * 544 * DESCRIPTION 545 * This is the callback from the transport layer for received MADs. 546 * 547 * SYNOPSIS 548 */ 549static void 550__osm_sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, 551 IN void *bind_context, 552 IN osm_madw_t * p_req_madw) 553{ 554 osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context; 555 ib_smp_t *p_smp; 556 ib_net16_t status; 557 558 OSM_LOG_ENTER(p_ctrl->p_log); 559 560 CL_ASSERT(p_madw); 561 562 /* 563 A MAD was received from the wire, possibly in response to a request. 564 */ 565 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd); 566 567 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n", 568 p_ctrl->p_stats->qp0_mads_rcvd); 569 570 p_smp = osm_madw_get_smp_ptr(p_madw); 571 572 /* if we are closing down simply do nothing */ 573 if (osm_exit_flag) { 574 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, 575 "Ignoring received mad - since we are exiting\n"); 576 577 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_DEBUG); 578 579 /* retire the mad or put it back */ 580 if (ib_smp_is_response(p_smp) || 581 (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS)) { 582 CL_ASSERT(p_madw->resp_expected == FALSE); 583 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 584 } else if (p_madw->resp_expected == TRUE) 585 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 586 else 587 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 588 589 goto Exit; 590 } 591 592 if (osm_log_is_active(p_ctrl->p_log, OSM_LOG_FRAMES)) 593 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_FRAMES); 594 595 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) 596 status = ib_smp_get_status(p_smp); 597 else 598 status = p_smp->status; 599 600 if (status != 0) { 601 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3111: " 602 "Error status = 0x%X\n", status); 603 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 604 } 605 606 switch (p_smp->method) { 607 case IB_MAD_METHOD_GET_RESP: 608 CL_ASSERT(p_req_madw != NULL); 609 __osm_sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw); 610 break; 611 612 case IB_MAD_METHOD_GET: 613 CL_ASSERT(p_req_madw == NULL); 614 __osm_sm_mad_ctrl_process_get(p_ctrl, p_madw); 615 break; 616 617 case IB_MAD_METHOD_TRAP: 618 CL_ASSERT(p_req_madw == NULL); 619 __osm_sm_mad_ctrl_process_trap(p_ctrl, p_madw); 620 break; 621 622 case IB_MAD_METHOD_SET: 623 CL_ASSERT(p_req_madw == NULL); 624 __osm_sm_mad_ctrl_process_set(p_ctrl, p_madw); 625 break; 626 627 case IB_MAD_METHOD_SEND: 628 case IB_MAD_METHOD_REPORT: 629 case IB_MAD_METHOD_REPORT_RESP: 630 case IB_MAD_METHOD_TRAP_REPRESS: 631 default: 632 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 633 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: " 634 "Unsupported method = 0x%X\n", p_smp->method); 635 osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 636 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 637 goto Exit; 638 } 639 640Exit: 641 OSM_LOG_EXIT(p_ctrl->p_log); 642} 643 644/* 645 * PARAMETERS 646 * 647 * RETURN VALUES 648 * 649 * NOTES 650 * 651 * SEE ALSO 652 *********/ 653 654/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb 655 * NAME 656 * __osm_sm_mad_ctrl_send_err_cb 657 * 658 * DESCRIPTION 659 * This is the callback from the transport layer for send errors 660 * on MADs that were expecting a response. 661 * 662 * SYNOPSIS 663 */ 664static void 665__osm_sm_mad_ctrl_send_err_cb(IN void *bind_context, IN osm_madw_t * p_madw) 666{ 667 osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context; 668 ib_api_status_t status; 669 ib_smp_t *p_smp; 670 671 OSM_LOG_ENTER(p_ctrl->p_log); 672 673 CL_ASSERT(p_madw); 674 675 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: " 676 "MAD completed in error (%s)\n", 677 ib_get_err_str(p_madw->status)); 678 679 /* 680 If this was a SubnSet MAD, then this error might indicate a problem 681 in configuring the subnet. In this case - need to mark that there was 682 such a problem. The subnet will not be up, and the next sweep should 683 be a heavy sweep as well. 684 */ 685 p_smp = osm_madw_get_smp_ptr(p_madw); 686 if (p_smp->method == IB_MAD_METHOD_SET && 687 (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO || 688 p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL || 689 p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO || 690 p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL)) { 691 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: " 692 "Set method failed\n"); 693 p_ctrl->p_subn->subnet_initialization_error = TRUE; 694 } 695 696 /* 697 Since we did not get any response we suspect the DR path 698 used for the target port. 699 Find it and replace it with an alternate path. 700 This is true only if the destination lid is not 0xFFFF, since 701 then we are aiming for a specific path and not specific destination 702 lid. 703 */ 704 /* For now - do not add the alternate dr path to the release */ 705#if 0 706 if (p_madw->mad_addr.dest_lid != 0xFFFF) { 707 osm_physp_t *p_physp = 708 osm_get_physp_by_mad_addr(p_ctrl->p_log, 709 p_ctrl->p_subn, 710 &(p_madw->mad_addr)); 711 if (!p_physp) { 712 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: " 713 "Failed to find the corresponding phys port\n"); 714 } else { 715 osm_physp_replace_dr_path_with_alternate_dr_path 716 (p_ctrl->p_log, p_ctrl->p_subn, p_physp, 717 p_madw->h_bind); 718 } 719 } 720#endif 721 722 /* 723 An error occurred. No response was received to a request MAD. 724 Retire the original request MAD. 725 */ 726 727 osm_dump_dr_smp(p_ctrl->p_log, osm_madw_get_smp_ptr(p_madw), 728 OSM_LOG_ERROR); 729 730 __osm_sm_mad_ctrl_update_wire_stats(p_ctrl); 731 732 if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) { 733 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 734 "Posting Dispatcher message %s\n", 735 osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw))); 736 737 status = cl_disp_post(p_ctrl->h_disp, 738 osm_madw_get_err_msg(p_madw), 739 p_madw, 740 __osm_sm_mad_ctrl_disp_done_callback, 741 p_ctrl); 742 if (status != CL_SUCCESS) 743 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: " 744 "Dispatcher post message failed (%s)\n", 745 CL_STATUS_MSG(status)); 746 } else 747 /* 748 No error message was provided, just retire the MAD. 749 */ 750 __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 751 752 OSM_LOG_EXIT(p_ctrl->p_log); 753} 754 755/* 756 * PARAMETERS 757 * 758 * RETURN VALUES 759 * 760 * NOTES 761 * 762 * SEE ALSO 763 *********/ 764 765/********************************************************************** 766 **********************************************************************/ 767void osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * const p_ctrl) 768{ 769 CL_ASSERT(p_ctrl); 770 memset(p_ctrl, 0, sizeof(*p_ctrl)); 771 p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; 772} 773 774/********************************************************************** 775 **********************************************************************/ 776void osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * const p_ctrl) 777{ 778 CL_ASSERT(p_ctrl); 779 780 if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE) 781 osm_vendor_unbind(p_ctrl->h_bind); 782 cl_disp_unregister(p_ctrl->h_disp); 783} 784 785/********************************************************************** 786 **********************************************************************/ 787ib_api_status_t 788osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * const p_ctrl, 789 IN osm_subn_t * const p_subn, 790 IN osm_mad_pool_t * const p_mad_pool, 791 IN osm_vl15_t * const p_vl15, 792 IN osm_vendor_t * const p_vendor, 793 IN osm_log_t * const p_log, 794 IN osm_stats_t * const p_stats, 795 IN cl_plock_t * const p_lock, 796 IN cl_dispatcher_t * const p_disp) 797{ 798 ib_api_status_t status = IB_SUCCESS; 799 800 OSM_LOG_ENTER(p_log); 801 802 osm_sm_mad_ctrl_construct(p_ctrl); 803 804 p_ctrl->p_subn = p_subn; 805 p_ctrl->p_log = p_log; 806 p_ctrl->p_disp = p_disp; 807 p_ctrl->p_mad_pool = p_mad_pool; 808 p_ctrl->p_vendor = p_vendor; 809 p_ctrl->p_stats = p_stats; 810 p_ctrl->p_lock = p_lock; 811 p_ctrl->p_vl15 = p_vl15; 812 813 p_ctrl->h_disp = cl_disp_register(p_disp, 814 CL_DISP_MSGID_NONE, NULL, NULL); 815 816 if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) { 817 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: " 818 "Dispatcher registration failed\n"); 819 status = IB_INSUFFICIENT_RESOURCES; 820 goto Exit; 821 } 822 823Exit: 824 OSM_LOG_EXIT(p_log); 825 return (status); 826} 827 828/********************************************************************** 829 **********************************************************************/ 830ib_api_status_t 831osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * const p_ctrl, 832 IN const ib_net64_t port_guid) 833{ 834 osm_bind_info_t bind_info; 835 ib_api_status_t status = IB_SUCCESS; 836 837 OSM_LOG_ENTER(p_ctrl->p_log); 838 839 if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) { 840 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: " 841 "Multiple binds not allowed\n"); 842 status = IB_ERROR; 843 goto Exit; 844 } 845 846 bind_info.class_version = 1; 847 bind_info.is_report_processor = FALSE; 848 bind_info.is_responder = TRUE; 849 bind_info.is_trap_processor = TRUE; 850 bind_info.mad_class = IB_MCLASS_SUBN_DIR; 851 bind_info.port_guid = port_guid; 852 bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE; 853 bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE; 854 855 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 856 "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); 857 858 p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, 859 &bind_info, 860 p_ctrl->p_mad_pool, 861 __osm_sm_mad_ctrl_rcv_callback, 862 __osm_sm_mad_ctrl_send_err_cb, p_ctrl); 863 864 if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { 865 status = IB_ERROR; 866 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3118: " 867 "Vendor specific bind failed\n"); 868 goto Exit; 869 } 870 871Exit: 872 OSM_LOG_EXIT(p_ctrl->p_log); 873 return (status); 874} 875