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 * Copyright (c) 2008 Xsigo Systems Inc. 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_sm_t. 40 * This object represents the SM Receiver object. 41 * This object is part of the opensm family of objects. 42 */ 43 44#if HAVE_CONFIG_H 45# include <config.h> 46#endif /* HAVE_CONFIG_H */ 47 48#include <stdlib.h> 49#include <string.h> 50#include <iba/ib_types.h> 51#include <complib/cl_qmap.h> 52#include <complib/cl_passivelock.h> 53#include <complib/cl_debug.h> 54#include <complib/cl_thread.h> 55#include <opensm/osm_sm.h> 56#include <opensm/osm_madw.h> 57#include <opensm/osm_log.h> 58#include <opensm/osm_node.h> 59#include <opensm/osm_msgdef.h> 60#include <opensm/osm_mcm_info.h> 61#include <opensm/osm_perfmgr.h> 62#include <opensm/osm_opensm.h> 63 64#define OSM_SM_INITIAL_TID_VALUE 0x1233 65 66extern void osm_lft_rcv_process(IN void *context, IN void *data); 67extern void osm_mft_rcv_process(IN void *context, IN void *data); 68extern void osm_nd_rcv_process(IN void *context, IN void *data); 69extern void osm_ni_rcv_process(IN void *context, IN void *data); 70extern void osm_pkey_rcv_process(IN void *context, IN void *data); 71extern void osm_pi_rcv_process(IN void *context, IN void *data); 72extern void osm_slvl_rcv_process(IN void *context, IN void *p_data); 73extern void osm_sminfo_rcv_process(IN void *context, IN void *data); 74extern void osm_si_rcv_process(IN void *context, IN void *data); 75extern void osm_trap_rcv_process(IN void *context, IN void *data); 76extern void osm_vla_rcv_process(IN void *context, IN void *data); 77 78extern void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal); 79extern void osm_sm_state_mgr_polling_callback(IN void *context); 80 81/********************************************************************** 82 **********************************************************************/ 83static void osm_sm_process(osm_sm_t * sm, osm_signal_t signal) 84{ 85#ifdef ENABLE_OSM_PERF_MGR 86 if (signal == OSM_SIGNAL_PERFMGR_SWEEP) 87 osm_perfmgr_process(&sm->p_subn->p_osm->perfmgr); 88 else 89#endif 90 osm_state_mgr_process(sm, signal); 91} 92 93static void __osm_sm_sweeper(IN void *p_ptr) 94{ 95 ib_api_status_t status; 96 osm_sm_t *const p_sm = (osm_sm_t *) p_ptr; 97 unsigned signals, i; 98 99 OSM_LOG_ENTER(p_sm->p_log); 100 101 while (p_sm->thread_state == OSM_THREAD_STATE_RUN) { 102 /* 103 * Wait on the event with a timeout. 104 * Sweeps may be initiated "off schedule" by simply 105 * signaling the event. 106 */ 107 status = cl_event_wait_on(&p_sm->signal_event, 108 EVENT_NO_TIMEOUT, TRUE); 109 110 if (status == CL_SUCCESS) 111 OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG, 112 "Off schedule sweep signalled\n"); 113 else if (status != CL_TIMEOUT) { 114 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E01: " 115 "Event wait failed (%s)\n", 116 CL_STATUS_MSG(status)); 117 continue; 118 } 119 120 if (osm_exit_flag) 121 break; 122 123 cl_spinlock_acquire(&p_sm->signal_lock); 124 signals = p_sm->signal_mask; 125 p_sm->signal_mask = 0; 126 cl_spinlock_release(&p_sm->signal_lock); 127 128 for (i = 0; signals; signals >>= 1, i++) 129 if (signals & 1) 130 osm_sm_process(p_sm, i); 131 } 132 133 OSM_LOG_EXIT(p_sm->p_log); 134} 135 136static void sm_sweep(void *arg) 137{ 138 osm_sm_t *sm = arg; 139 140 /* do the sweep only if we are in MASTER state */ 141 if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER || 142 sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING) 143 osm_sm_signal(sm, OSM_SIGNAL_SWEEP); 144 cl_timer_start(&sm->sweep_timer, sm->p_subn->opt.sweep_interval * 1000); 145} 146 147static void sweep_fail_process(IN void *context, IN void *p_data) 148{ 149 osm_sm_t *sm = context; 150 151 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "light sweep failed\n"); 152 sm->p_subn->force_heavy_sweep = TRUE; 153} 154 155/********************************************************************** 156 **********************************************************************/ 157void osm_sm_construct(IN osm_sm_t * const p_sm) 158{ 159 memset(p_sm, 0, sizeof(*p_sm)); 160 p_sm->thread_state = OSM_THREAD_STATE_NONE; 161 p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE; 162 cl_spinlock_construct(&p_sm->signal_lock); 163 cl_spinlock_construct(&p_sm->state_lock); 164 cl_timer_construct(&p_sm->polling_timer); 165 cl_event_construct(&p_sm->signal_event); 166 cl_event_construct(&p_sm->subnet_up_event); 167 cl_event_wheel_construct(&p_sm->trap_aging_tracker); 168 cl_thread_construct(&p_sm->sweeper); 169 cl_spinlock_construct(&p_sm->mgrp_lock); 170 osm_sm_mad_ctrl_construct(&p_sm->mad_ctrl); 171 osm_lid_mgr_construct(&p_sm->lid_mgr); 172 osm_ucast_mgr_construct(&p_sm->ucast_mgr); 173} 174 175/********************************************************************** 176 **********************************************************************/ 177void osm_sm_shutdown(IN osm_sm_t * const p_sm) 178{ 179 boolean_t signal_event = FALSE; 180 181 OSM_LOG_ENTER(p_sm->p_log); 182 183 /* 184 * Signal our threads that we're leaving. 185 */ 186 if (p_sm->thread_state != OSM_THREAD_STATE_NONE) 187 signal_event = TRUE; 188 189 p_sm->thread_state = OSM_THREAD_STATE_EXIT; 190 191 /* 192 * Don't trigger unless event has been initialized. 193 * Destroy the thread before we tear down the other objects. 194 */ 195 if (signal_event) 196 cl_event_signal(&p_sm->signal_event); 197 198 cl_timer_stop(&p_sm->polling_timer); 199 cl_timer_stop(&p_sm->sweep_timer); 200 cl_thread_destroy(&p_sm->sweeper); 201 202 /* 203 * Always destroy controllers before the corresponding 204 * receiver to guarantee that all callbacks from the 205 * dispatcher are complete. 206 */ 207 osm_sm_mad_ctrl_destroy(&p_sm->mad_ctrl); 208 cl_disp_unregister(p_sm->ni_disp_h); 209 cl_disp_unregister(p_sm->pi_disp_h); 210 cl_disp_unregister(p_sm->si_disp_h); 211 cl_disp_unregister(p_sm->nd_disp_h); 212 cl_disp_unregister(p_sm->lft_disp_h); 213 cl_disp_unregister(p_sm->mft_disp_h); 214 cl_disp_unregister(p_sm->sm_info_disp_h); 215 cl_disp_unregister(p_sm->trap_disp_h); 216 cl_disp_unregister(p_sm->slvl_disp_h); 217 cl_disp_unregister(p_sm->vla_disp_h); 218 cl_disp_unregister(p_sm->pkey_disp_h); 219 cl_disp_unregister(p_sm->sweep_fail_disp_h); 220 221 OSM_LOG_EXIT(p_sm->p_log); 222} 223 224/********************************************************************** 225 **********************************************************************/ 226void osm_sm_destroy(IN osm_sm_t * const p_sm) 227{ 228 OSM_LOG_ENTER(p_sm->p_log); 229 osm_lid_mgr_destroy(&p_sm->lid_mgr); 230 osm_ucast_mgr_destroy(&p_sm->ucast_mgr); 231 cl_event_wheel_destroy(&p_sm->trap_aging_tracker); 232 cl_timer_destroy(&p_sm->sweep_timer); 233 cl_timer_destroy(&p_sm->polling_timer); 234 cl_event_destroy(&p_sm->signal_event); 235 cl_event_destroy(&p_sm->subnet_up_event); 236 cl_spinlock_destroy(&p_sm->signal_lock); 237 cl_spinlock_destroy(&p_sm->mgrp_lock); 238 cl_spinlock_destroy(&p_sm->state_lock); 239 240 osm_log(p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n"); /* Format Waived */ 241 OSM_LOG_EXIT(p_sm->p_log); 242} 243 244/********************************************************************** 245 **********************************************************************/ 246ib_api_status_t 247osm_sm_init(IN osm_sm_t * const p_sm, 248 IN osm_subn_t * const p_subn, 249 IN osm_db_t * const p_db, 250 IN osm_vendor_t * const p_vendor, 251 IN osm_mad_pool_t * const p_mad_pool, 252 IN osm_vl15_t * const p_vl15, 253 IN osm_log_t * const p_log, 254 IN osm_stats_t * const p_stats, 255 IN cl_dispatcher_t * const p_disp, IN cl_plock_t * const p_lock) 256{ 257 ib_api_status_t status = IB_SUCCESS; 258 259 OSM_LOG_ENTER(p_log); 260 261 p_sm->p_subn = p_subn; 262 p_sm->p_db = p_db; 263 p_sm->p_vendor = p_vendor; 264 p_sm->p_mad_pool = p_mad_pool; 265 p_sm->p_vl15 = p_vl15; 266 p_sm->p_log = p_log; 267 p_sm->p_disp = p_disp; 268 p_sm->p_lock = p_lock; 269 270 status = cl_spinlock_init(&p_sm->signal_lock); 271 if (status != CL_SUCCESS) 272 goto Exit; 273 274 status = cl_spinlock_init(&p_sm->state_lock); 275 if (status != CL_SUCCESS) 276 goto Exit; 277 278 status = cl_event_init(&p_sm->signal_event, FALSE); 279 if (status != CL_SUCCESS) 280 goto Exit; 281 282 status = cl_event_init(&p_sm->subnet_up_event, FALSE); 283 if (status != CL_SUCCESS) 284 goto Exit; 285 286 status = cl_timer_init(&p_sm->sweep_timer, sm_sweep, p_sm); 287 if (status != CL_SUCCESS) 288 goto Exit; 289 290 status = cl_timer_init(&p_sm->polling_timer, 291 osm_sm_state_mgr_polling_callback, p_sm); 292 if (status != CL_SUCCESS) 293 goto Exit; 294 295 cl_qlist_init(&p_sm->mgrp_list); 296 297 status = cl_spinlock_init(&p_sm->mgrp_lock); 298 if (status != CL_SUCCESS) 299 goto Exit; 300 301 status = osm_sm_mad_ctrl_init(&p_sm->mad_ctrl, 302 p_sm->p_subn, 303 p_sm->p_mad_pool, 304 p_sm->p_vl15, 305 p_sm->p_vendor, 306 p_log, p_stats, p_lock, p_disp); 307 if (status != IB_SUCCESS) 308 goto Exit; 309 310 status = cl_event_wheel_init(&p_sm->trap_aging_tracker); 311 if (status != IB_SUCCESS) 312 goto Exit; 313 314 status = osm_lid_mgr_init(&p_sm->lid_mgr, p_sm); 315 if (status != IB_SUCCESS) 316 goto Exit; 317 318 status = osm_ucast_mgr_init(&p_sm->ucast_mgr, p_sm); 319 if (status != IB_SUCCESS) 320 goto Exit; 321 322 p_sm->sweep_fail_disp_h = cl_disp_register(p_disp, 323 OSM_MSG_LIGHT_SWEEP_FAIL, 324 sweep_fail_process, p_sm); 325 if (p_sm->sweep_fail_disp_h == CL_DISP_INVALID_HANDLE) 326 goto Exit; 327 328 p_sm->ni_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_INFO, 329 osm_ni_rcv_process, p_sm); 330 if (p_sm->ni_disp_h == CL_DISP_INVALID_HANDLE) 331 goto Exit; 332 333 p_sm->pi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORT_INFO, 334 osm_pi_rcv_process, p_sm); 335 if (p_sm->pi_disp_h == CL_DISP_INVALID_HANDLE) 336 goto Exit; 337 338 p_sm->si_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO, 339 osm_si_rcv_process, p_sm); 340 if (p_sm->si_disp_h == CL_DISP_INVALID_HANDLE) 341 goto Exit; 342 343 p_sm->nd_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_DESC, 344 osm_nd_rcv_process, p_sm); 345 if (p_sm->nd_disp_h == CL_DISP_INVALID_HANDLE) 346 goto Exit; 347 348 p_sm->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT, 349 osm_lft_rcv_process, p_sm); 350 if (p_sm->lft_disp_h == CL_DISP_INVALID_HANDLE) 351 goto Exit; 352 353 p_sm->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT, 354 osm_mft_rcv_process, p_sm); 355 if (p_sm->mft_disp_h == CL_DISP_INVALID_HANDLE) 356 goto Exit; 357 358 p_sm->sm_info_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SM_INFO, 359 osm_sminfo_rcv_process, p_sm); 360 if (p_sm->sm_info_disp_h == CL_DISP_INVALID_HANDLE) 361 goto Exit; 362 363 p_sm->trap_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NOTICE, 364 osm_trap_rcv_process, p_sm); 365 if (p_sm->trap_disp_h == CL_DISP_INVALID_HANDLE) 366 goto Exit; 367 368 p_sm->slvl_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SLVL, 369 osm_slvl_rcv_process, p_sm); 370 if (p_sm->slvl_disp_h == CL_DISP_INVALID_HANDLE) 371 goto Exit; 372 373 p_sm->vla_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB, 374 osm_vla_rcv_process, p_sm); 375 if (p_sm->vla_disp_h == CL_DISP_INVALID_HANDLE) 376 goto Exit; 377 378 p_sm->pkey_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PKEY, 379 osm_pkey_rcv_process, p_sm); 380 if (p_sm->pkey_disp_h == CL_DISP_INVALID_HANDLE) 381 goto Exit; 382 383 p_subn->sm_state = p_subn->opt.sm_inactive ? 384 IB_SMINFO_STATE_NOTACTIVE : IB_SMINFO_STATE_DISCOVERING; 385 osm_report_sm_state(p_sm); 386 387 /* 388 * Now that the component objects are initialized, start 389 * the sweeper thread if the user wants sweeping. 390 */ 391 p_sm->thread_state = OSM_THREAD_STATE_RUN; 392 status = cl_thread_init(&p_sm->sweeper, __osm_sm_sweeper, p_sm, 393 "opensm sweeper"); 394 if (status != IB_SUCCESS) 395 goto Exit; 396 397 if (p_sm->p_subn->opt.sweep_interval) 398 cl_timer_start(&p_sm->sweep_timer, 399 p_sm->p_subn->opt.sweep_interval * 1000); 400 401Exit: 402 OSM_LOG_EXIT(p_log); 403 return (status); 404} 405 406/********************************************************************** 407 **********************************************************************/ 408void osm_sm_signal(osm_sm_t * p_sm, osm_signal_t signal) 409{ 410 cl_spinlock_acquire(&p_sm->signal_lock); 411 p_sm->signal_mask |= 1 << signal; 412 cl_event_signal(&p_sm->signal_event); 413 cl_spinlock_release(&p_sm->signal_lock); 414} 415 416/********************************************************************** 417 **********************************************************************/ 418void osm_sm_sweep(IN osm_sm_t * const p_sm) 419{ 420 OSM_LOG_ENTER(p_sm->p_log); 421 osm_sm_signal(p_sm, OSM_SIGNAL_SWEEP); 422 OSM_LOG_EXIT(p_sm->p_log); 423} 424 425/********************************************************************** 426 **********************************************************************/ 427ib_api_status_t 428osm_sm_bind(IN osm_sm_t * const p_sm, IN const ib_net64_t port_guid) 429{ 430 ib_api_status_t status; 431 432 OSM_LOG_ENTER(p_sm->p_log); 433 434 status = osm_sm_mad_ctrl_bind(&p_sm->mad_ctrl, port_guid); 435 436 if (status != IB_SUCCESS) { 437 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E10: " 438 "SM MAD Controller bind failed (%s)\n", 439 ib_get_err_str(status)); 440 goto Exit; 441 } 442 443Exit: 444 OSM_LOG_EXIT(p_sm->p_log); 445 return (status); 446} 447 448/********************************************************************** 449 **********************************************************************/ 450static ib_api_status_t 451__osm_sm_mgrp_process(IN osm_sm_t * const p_sm, 452 IN osm_mgrp_t * const p_mgrp, 453 IN const ib_net64_t port_guid, 454 IN osm_mcast_req_type_t req_type) 455{ 456 osm_mcast_mgr_ctxt_t *ctx; 457 458 /* 459 * 'Schedule' all the QP0 traffic for when the state manager 460 * isn't busy trying to do something else. 461 */ 462 ctx = malloc(sizeof(*ctx)); 463 if (!ctx) 464 return IB_ERROR; 465 memset(ctx, 0, sizeof(*ctx)); 466 ctx->mlid = p_mgrp->mlid; 467 ctx->req_type = req_type; 468 ctx->port_guid = port_guid; 469 470 cl_spinlock_acquire(&p_sm->mgrp_lock); 471 cl_qlist_insert_tail(&p_sm->mgrp_list, &ctx->list_item); 472 cl_spinlock_release(&p_sm->mgrp_lock); 473 474 osm_sm_signal(p_sm, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST); 475 476 return IB_SUCCESS; 477} 478 479/********************************************************************** 480 **********************************************************************/ 481static ib_api_status_t 482__osm_sm_mgrp_connect(IN osm_sm_t * const p_sm, 483 IN osm_mgrp_t * const p_mgrp, 484 IN const ib_net64_t port_guid, 485 IN osm_mcast_req_type_t req_type) 486{ 487 return __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, req_type); 488} 489 490/********************************************************************** 491 **********************************************************************/ 492static void 493__osm_sm_mgrp_disconnect(IN osm_sm_t * const p_sm, 494 IN osm_mgrp_t * const p_mgrp, 495 IN const ib_net64_t port_guid) 496{ 497 __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, 498 OSM_MCAST_REQ_TYPE_LEAVE); 499} 500 501/********************************************************************** 502 **********************************************************************/ 503ib_api_status_t 504osm_sm_mcgrp_join(IN osm_sm_t * const p_sm, 505 IN const ib_net16_t mlid, 506 IN const ib_net64_t port_guid, 507 IN osm_mcast_req_type_t req_type) 508{ 509 osm_mgrp_t *p_mgrp; 510 osm_port_t *p_port; 511 ib_api_status_t status = IB_SUCCESS; 512 osm_mcm_info_t *p_mcm; 513 514 OSM_LOG_ENTER(p_sm->p_log); 515 516 OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE, 517 "Port 0x%016" PRIx64 " joining MLID 0x%X\n", 518 cl_ntoh64(port_guid), cl_ntoh16(mlid)); 519 520 /* 521 * Acquire the port object for the port joining this group. 522 */ 523 CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock); 524 p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid); 525 if (!p_port) { 526 CL_PLOCK_RELEASE(p_sm->p_lock); 527 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E05: " 528 "No port object for port 0x%016" PRIx64 "\n", 529 cl_ntoh64(port_guid)); 530 status = IB_INVALID_PARAMETER; 531 goto Exit; 532 } 533 534 /* 535 * If this multicast group does not already exist, create it. 536 */ 537 p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid); 538 if (!p_mgrp || !osm_mgrp_is_guid(p_mgrp, port_guid)) { 539 /* 540 * The group removed or the port is not a 541 * member of the group, then fail immediately. 542 * This can happen since the spinlock is released briefly 543 * before the SA calls this function. 544 */ 545 CL_PLOCK_RELEASE(p_sm->p_lock); 546 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E12: " 547 "MC group with mlid 0x%x doesn't exist or " 548 "port 0x%016" PRIx64 " is not in the group.\n", 549 cl_ntoh16(mlid), cl_ntoh64(port_guid)); 550 status = IB_NOT_FOUND; 551 goto Exit; 552 } 553 554 /* 555 * Check if the object (according to mlid) already exists on this port. 556 * If it does - then no need to update it again, and no need to 557 * create the mc tree again. Just goto Exit. 558 */ 559 p_mcm = (osm_mcm_info_t *) cl_qlist_head(&p_port->mcm_list); 560 while (p_mcm != (osm_mcm_info_t *) cl_qlist_end(&p_port->mcm_list)) { 561 if (p_mcm->mlid == mlid) { 562 CL_PLOCK_RELEASE(p_sm->p_lock); 563 OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG, 564 "Found mlid object for Port:" 565 "0x%016" PRIx64 " lid:0x%X\n", 566 cl_ntoh64(port_guid), cl_ntoh16(mlid)); 567 goto Exit; 568 } 569 p_mcm = (osm_mcm_info_t *) cl_qlist_next(&p_mcm->list_item); 570 } 571 572 status = osm_port_add_mgrp(p_port, mlid); 573 if (status != IB_SUCCESS) { 574 CL_PLOCK_RELEASE(p_sm->p_lock); 575 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E03: " 576 "Unable to associate port 0x%" PRIx64 " to mlid 0x%X\n", 577 cl_ntoh64(osm_port_get_guid(p_port)), 578 cl_ntoh16(osm_mgrp_get_mlid(p_mgrp))); 579 goto Exit; 580 } 581 582 status = __osm_sm_mgrp_connect(p_sm, p_mgrp, port_guid, req_type); 583 CL_PLOCK_RELEASE(p_sm->p_lock); 584 585Exit: 586 OSM_LOG_EXIT(p_sm->p_log); 587 return (status); 588} 589 590/********************************************************************** 591 **********************************************************************/ 592ib_api_status_t 593osm_sm_mcgrp_leave(IN osm_sm_t * const p_sm, 594 IN const ib_net16_t mlid, IN const ib_net64_t port_guid) 595{ 596 osm_mgrp_t *p_mgrp; 597 osm_port_t *p_port; 598 ib_api_status_t status = IB_SUCCESS; 599 600 OSM_LOG_ENTER(p_sm->p_log); 601 602 OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE, 603 "Port 0x%" PRIx64 " leaving MLID 0x%X\n", 604 cl_ntoh64(port_guid), cl_ntoh16(mlid)); 605 606 /* 607 * Acquire the port object for the port leaving this group. 608 */ 609 CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock); 610 611 p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid); 612 if (!p_port) { 613 CL_PLOCK_RELEASE(p_sm->p_lock); 614 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E04: " 615 "No port object for port 0x%" PRIx64 "\n", 616 cl_ntoh64(port_guid)); 617 status = IB_INVALID_PARAMETER; 618 goto Exit; 619 } 620 621 /* 622 * Get the multicast group object for this group. 623 */ 624 p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid); 625 if (!p_mgrp) { 626 CL_PLOCK_RELEASE(p_sm->p_lock); 627 OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E08: " 628 "No multicast group for MLID 0x%X\n", cl_ntoh16(mlid)); 629 status = IB_INVALID_PARAMETER; 630 goto Exit; 631 } 632 633 /* 634 * Walk the list of ports in the group, and remove the appropriate one. 635 */ 636 osm_port_remove_mgrp(p_port, mlid); 637 638 __osm_sm_mgrp_disconnect(p_sm, p_mgrp, port_guid); 639 CL_PLOCK_RELEASE(p_sm->p_lock); 640 641Exit: 642 OSM_LOG_EXIT(p_sm->p_log); 643 return (status); 644} 645 646void osm_set_sm_priority(osm_sm_t *sm, uint8_t priority) 647{ 648 uint8_t old_pri = sm->p_subn->opt.sm_priority; 649 650 sm->p_subn->opt.sm_priority = priority; 651 652 if (old_pri < priority && 653 sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY) 654 osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE); 655} 656