1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. 6219820Sjeff * 7219820Sjeff * This software is available to you under a choice of one of two 8219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 9219820Sjeff * General Public License (GPL) Version 2, available from the file 10219820Sjeff * COPYING in the main directory of this source tree, or the 11219820Sjeff * OpenIB.org BSD license below: 12219820Sjeff * 13219820Sjeff * Redistribution and use in source and binary forms, with or 14219820Sjeff * without modification, are permitted provided that the following 15219820Sjeff * conditions are met: 16219820Sjeff * 17219820Sjeff * - Redistributions of source code must retain the above 18219820Sjeff * copyright notice, this list of conditions and the following 19219820Sjeff * disclaimer. 20219820Sjeff * 21219820Sjeff * - Redistributions in binary form must reproduce the above 22219820Sjeff * copyright notice, this list of conditions and the following 23219820Sjeff * disclaimer in the documentation and/or other materials 24219820Sjeff * provided with the distribution. 25219820Sjeff * 26219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33219820Sjeff * SOFTWARE. 34219820Sjeff * 35219820Sjeff */ 36219820Sjeff 37219820Sjeff/* 38219820Sjeff * Abstract: 39219820Sjeff * Implementation of osm_sm_t. 40219820Sjeff * This object represents the SM Receiver object. 41219820Sjeff * This object is part of the opensm family of objects. 42219820Sjeff */ 43219820Sjeff 44219820Sjeff#if HAVE_CONFIG_H 45219820Sjeff# include <config.h> 46219820Sjeff#endif /* HAVE_CONFIG_H */ 47219820Sjeff 48219820Sjeff#include <stdlib.h> 49219820Sjeff#include <string.h> 50219820Sjeff#include <iba/ib_types.h> 51219820Sjeff#include <complib/cl_qmap.h> 52219820Sjeff#include <complib/cl_passivelock.h> 53219820Sjeff#include <complib/cl_debug.h> 54219820Sjeff#include <complib/cl_thread.h> 55219820Sjeff#include <opensm/osm_sm.h> 56219820Sjeff#include <opensm/osm_madw.h> 57219820Sjeff#include <opensm/osm_log.h> 58219820Sjeff#include <opensm/osm_node.h> 59219820Sjeff#include <opensm/osm_msgdef.h> 60219820Sjeff#include <opensm/osm_mcm_info.h> 61219820Sjeff#include <opensm/osm_perfmgr.h> 62219820Sjeff#include <opensm/osm_opensm.h> 63219820Sjeff 64219820Sjeff#define OSM_SM_INITIAL_TID_VALUE 0x1233 65219820Sjeff 66219820Sjeffextern void osm_lft_rcv_process(IN void *context, IN void *data); 67219820Sjeffextern void osm_mft_rcv_process(IN void *context, IN void *data); 68219820Sjeffextern void osm_nd_rcv_process(IN void *context, IN void *data); 69219820Sjeffextern void osm_ni_rcv_process(IN void *context, IN void *data); 70219820Sjeffextern void osm_pkey_rcv_process(IN void *context, IN void *data); 71219820Sjeffextern void osm_pi_rcv_process(IN void *context, IN void *data); 72219820Sjeffextern void osm_slvl_rcv_process(IN void *context, IN void *p_data); 73219820Sjeffextern void osm_sminfo_rcv_process(IN void *context, IN void *data); 74219820Sjeffextern void osm_si_rcv_process(IN void *context, IN void *data); 75219820Sjeffextern void osm_trap_rcv_process(IN void *context, IN void *data); 76219820Sjeffextern void osm_vla_rcv_process(IN void *context, IN void *data); 77219820Sjeff 78219820Sjeffextern void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal); 79219820Sjeffextern void osm_sm_state_mgr_polling_callback(IN void *context); 80219820Sjeff 81219820Sjeff/********************************************************************** 82219820Sjeff **********************************************************************/ 83219820Sjeffstatic void osm_sm_process(osm_sm_t * sm, osm_signal_t signal) 84219820Sjeff{ 85219820Sjeff#ifdef ENABLE_OSM_PERF_MGR 86219820Sjeff if (signal == OSM_SIGNAL_PERFMGR_SWEEP) 87219820Sjeff osm_perfmgr_process(&sm->p_subn->p_osm->perfmgr); 88219820Sjeff else 89219820Sjeff#endif 90219820Sjeff osm_state_mgr_process(sm, signal); 91219820Sjeff} 92219820Sjeff 93219820Sjeffstatic void __osm_sm_sweeper(IN void *p_ptr) 94219820Sjeff{ 95219820Sjeff ib_api_status_t status; 96219820Sjeff osm_sm_t *const p_sm = (osm_sm_t *) p_ptr; 97219820Sjeff unsigned signals, i; 98219820Sjeff 99219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 100219820Sjeff 101219820Sjeff while (p_sm->thread_state == OSM_THREAD_STATE_RUN) { 102219820Sjeff /* 103219820Sjeff * Wait on the event with a timeout. 104219820Sjeff * Sweeps may be initiated "off schedule" by simply 105219820Sjeff * signaling the event. 106219820Sjeff */ 107219820Sjeff status = cl_event_wait_on(&p_sm->signal_event, 108219820Sjeff EVENT_NO_TIMEOUT, TRUE); 109219820Sjeff 110219820Sjeff if (status == CL_SUCCESS) 111219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG, 112219820Sjeff "Off schedule sweep signalled\n"); 113219820Sjeff else if (status != CL_TIMEOUT) { 114219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E01: " 115219820Sjeff "Event wait failed (%s)\n", 116219820Sjeff CL_STATUS_MSG(status)); 117219820Sjeff continue; 118219820Sjeff } 119219820Sjeff 120219820Sjeff if (osm_exit_flag) 121219820Sjeff break; 122219820Sjeff 123219820Sjeff cl_spinlock_acquire(&p_sm->signal_lock); 124219820Sjeff signals = p_sm->signal_mask; 125219820Sjeff p_sm->signal_mask = 0; 126219820Sjeff cl_spinlock_release(&p_sm->signal_lock); 127219820Sjeff 128219820Sjeff for (i = 0; signals; signals >>= 1, i++) 129219820Sjeff if (signals & 1) 130219820Sjeff osm_sm_process(p_sm, i); 131219820Sjeff } 132219820Sjeff 133219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 134219820Sjeff} 135219820Sjeff 136219820Sjeffstatic void sm_sweep(void *arg) 137219820Sjeff{ 138219820Sjeff osm_sm_t *sm = arg; 139219820Sjeff 140219820Sjeff /* do the sweep only if we are in MASTER state */ 141219820Sjeff if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER || 142219820Sjeff sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING) 143219820Sjeff osm_sm_signal(sm, OSM_SIGNAL_SWEEP); 144219820Sjeff cl_timer_start(&sm->sweep_timer, sm->p_subn->opt.sweep_interval * 1000); 145219820Sjeff} 146219820Sjeff 147219820Sjeffstatic void sweep_fail_process(IN void *context, IN void *p_data) 148219820Sjeff{ 149219820Sjeff osm_sm_t *sm = context; 150219820Sjeff 151219820Sjeff OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "light sweep failed\n"); 152219820Sjeff sm->p_subn->force_heavy_sweep = TRUE; 153219820Sjeff} 154219820Sjeff 155219820Sjeff/********************************************************************** 156219820Sjeff **********************************************************************/ 157219820Sjeffvoid osm_sm_construct(IN osm_sm_t * const p_sm) 158219820Sjeff{ 159219820Sjeff memset(p_sm, 0, sizeof(*p_sm)); 160219820Sjeff p_sm->thread_state = OSM_THREAD_STATE_NONE; 161219820Sjeff p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE; 162219820Sjeff cl_spinlock_construct(&p_sm->signal_lock); 163219820Sjeff cl_spinlock_construct(&p_sm->state_lock); 164219820Sjeff cl_timer_construct(&p_sm->polling_timer); 165219820Sjeff cl_event_construct(&p_sm->signal_event); 166219820Sjeff cl_event_construct(&p_sm->subnet_up_event); 167219820Sjeff cl_event_wheel_construct(&p_sm->trap_aging_tracker); 168219820Sjeff cl_thread_construct(&p_sm->sweeper); 169219820Sjeff cl_spinlock_construct(&p_sm->mgrp_lock); 170219820Sjeff osm_sm_mad_ctrl_construct(&p_sm->mad_ctrl); 171219820Sjeff osm_lid_mgr_construct(&p_sm->lid_mgr); 172219820Sjeff osm_ucast_mgr_construct(&p_sm->ucast_mgr); 173219820Sjeff} 174219820Sjeff 175219820Sjeff/********************************************************************** 176219820Sjeff **********************************************************************/ 177219820Sjeffvoid osm_sm_shutdown(IN osm_sm_t * const p_sm) 178219820Sjeff{ 179219820Sjeff boolean_t signal_event = FALSE; 180219820Sjeff 181219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 182219820Sjeff 183219820Sjeff /* 184219820Sjeff * Signal our threads that we're leaving. 185219820Sjeff */ 186219820Sjeff if (p_sm->thread_state != OSM_THREAD_STATE_NONE) 187219820Sjeff signal_event = TRUE; 188219820Sjeff 189219820Sjeff p_sm->thread_state = OSM_THREAD_STATE_EXIT; 190219820Sjeff 191219820Sjeff /* 192219820Sjeff * Don't trigger unless event has been initialized. 193219820Sjeff * Destroy the thread before we tear down the other objects. 194219820Sjeff */ 195219820Sjeff if (signal_event) 196219820Sjeff cl_event_signal(&p_sm->signal_event); 197219820Sjeff 198219820Sjeff cl_timer_stop(&p_sm->polling_timer); 199219820Sjeff cl_timer_stop(&p_sm->sweep_timer); 200219820Sjeff cl_thread_destroy(&p_sm->sweeper); 201219820Sjeff 202219820Sjeff /* 203219820Sjeff * Always destroy controllers before the corresponding 204219820Sjeff * receiver to guarantee that all callbacks from the 205219820Sjeff * dispatcher are complete. 206219820Sjeff */ 207219820Sjeff osm_sm_mad_ctrl_destroy(&p_sm->mad_ctrl); 208219820Sjeff cl_disp_unregister(p_sm->ni_disp_h); 209219820Sjeff cl_disp_unregister(p_sm->pi_disp_h); 210219820Sjeff cl_disp_unregister(p_sm->si_disp_h); 211219820Sjeff cl_disp_unregister(p_sm->nd_disp_h); 212219820Sjeff cl_disp_unregister(p_sm->lft_disp_h); 213219820Sjeff cl_disp_unregister(p_sm->mft_disp_h); 214219820Sjeff cl_disp_unregister(p_sm->sm_info_disp_h); 215219820Sjeff cl_disp_unregister(p_sm->trap_disp_h); 216219820Sjeff cl_disp_unregister(p_sm->slvl_disp_h); 217219820Sjeff cl_disp_unregister(p_sm->vla_disp_h); 218219820Sjeff cl_disp_unregister(p_sm->pkey_disp_h); 219219820Sjeff cl_disp_unregister(p_sm->sweep_fail_disp_h); 220219820Sjeff 221219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 222219820Sjeff} 223219820Sjeff 224219820Sjeff/********************************************************************** 225219820Sjeff **********************************************************************/ 226219820Sjeffvoid osm_sm_destroy(IN osm_sm_t * const p_sm) 227219820Sjeff{ 228219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 229219820Sjeff osm_lid_mgr_destroy(&p_sm->lid_mgr); 230219820Sjeff osm_ucast_mgr_destroy(&p_sm->ucast_mgr); 231219820Sjeff cl_event_wheel_destroy(&p_sm->trap_aging_tracker); 232219820Sjeff cl_timer_destroy(&p_sm->sweep_timer); 233219820Sjeff cl_timer_destroy(&p_sm->polling_timer); 234219820Sjeff cl_event_destroy(&p_sm->signal_event); 235219820Sjeff cl_event_destroy(&p_sm->subnet_up_event); 236219820Sjeff cl_spinlock_destroy(&p_sm->signal_lock); 237219820Sjeff cl_spinlock_destroy(&p_sm->mgrp_lock); 238219820Sjeff cl_spinlock_destroy(&p_sm->state_lock); 239219820Sjeff 240219820Sjeff osm_log(p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n"); /* Format Waived */ 241219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 242219820Sjeff} 243219820Sjeff 244219820Sjeff/********************************************************************** 245219820Sjeff **********************************************************************/ 246219820Sjeffib_api_status_t 247219820Sjeffosm_sm_init(IN osm_sm_t * const p_sm, 248219820Sjeff IN osm_subn_t * const p_subn, 249219820Sjeff IN osm_db_t * const p_db, 250219820Sjeff IN osm_vendor_t * const p_vendor, 251219820Sjeff IN osm_mad_pool_t * const p_mad_pool, 252219820Sjeff IN osm_vl15_t * const p_vl15, 253219820Sjeff IN osm_log_t * const p_log, 254219820Sjeff IN osm_stats_t * const p_stats, 255219820Sjeff IN cl_dispatcher_t * const p_disp, IN cl_plock_t * const p_lock) 256219820Sjeff{ 257219820Sjeff ib_api_status_t status = IB_SUCCESS; 258219820Sjeff 259219820Sjeff OSM_LOG_ENTER(p_log); 260219820Sjeff 261219820Sjeff p_sm->p_subn = p_subn; 262219820Sjeff p_sm->p_db = p_db; 263219820Sjeff p_sm->p_vendor = p_vendor; 264219820Sjeff p_sm->p_mad_pool = p_mad_pool; 265219820Sjeff p_sm->p_vl15 = p_vl15; 266219820Sjeff p_sm->p_log = p_log; 267219820Sjeff p_sm->p_disp = p_disp; 268219820Sjeff p_sm->p_lock = p_lock; 269219820Sjeff 270219820Sjeff status = cl_spinlock_init(&p_sm->signal_lock); 271219820Sjeff if (status != CL_SUCCESS) 272219820Sjeff goto Exit; 273219820Sjeff 274219820Sjeff status = cl_spinlock_init(&p_sm->state_lock); 275219820Sjeff if (status != CL_SUCCESS) 276219820Sjeff goto Exit; 277219820Sjeff 278219820Sjeff status = cl_event_init(&p_sm->signal_event, FALSE); 279219820Sjeff if (status != CL_SUCCESS) 280219820Sjeff goto Exit; 281219820Sjeff 282219820Sjeff status = cl_event_init(&p_sm->subnet_up_event, FALSE); 283219820Sjeff if (status != CL_SUCCESS) 284219820Sjeff goto Exit; 285219820Sjeff 286219820Sjeff status = cl_timer_init(&p_sm->sweep_timer, sm_sweep, p_sm); 287219820Sjeff if (status != CL_SUCCESS) 288219820Sjeff goto Exit; 289219820Sjeff 290219820Sjeff status = cl_timer_init(&p_sm->polling_timer, 291219820Sjeff osm_sm_state_mgr_polling_callback, p_sm); 292219820Sjeff if (status != CL_SUCCESS) 293219820Sjeff goto Exit; 294219820Sjeff 295219820Sjeff cl_qlist_init(&p_sm->mgrp_list); 296219820Sjeff 297219820Sjeff status = cl_spinlock_init(&p_sm->mgrp_lock); 298219820Sjeff if (status != CL_SUCCESS) 299219820Sjeff goto Exit; 300219820Sjeff 301219820Sjeff status = osm_sm_mad_ctrl_init(&p_sm->mad_ctrl, 302219820Sjeff p_sm->p_subn, 303219820Sjeff p_sm->p_mad_pool, 304219820Sjeff p_sm->p_vl15, 305219820Sjeff p_sm->p_vendor, 306219820Sjeff p_log, p_stats, p_lock, p_disp); 307219820Sjeff if (status != IB_SUCCESS) 308219820Sjeff goto Exit; 309219820Sjeff 310219820Sjeff status = cl_event_wheel_init(&p_sm->trap_aging_tracker); 311219820Sjeff if (status != IB_SUCCESS) 312219820Sjeff goto Exit; 313219820Sjeff 314219820Sjeff status = osm_lid_mgr_init(&p_sm->lid_mgr, p_sm); 315219820Sjeff if (status != IB_SUCCESS) 316219820Sjeff goto Exit; 317219820Sjeff 318219820Sjeff status = osm_ucast_mgr_init(&p_sm->ucast_mgr, p_sm); 319219820Sjeff if (status != IB_SUCCESS) 320219820Sjeff goto Exit; 321219820Sjeff 322219820Sjeff p_sm->sweep_fail_disp_h = cl_disp_register(p_disp, 323219820Sjeff OSM_MSG_LIGHT_SWEEP_FAIL, 324219820Sjeff sweep_fail_process, p_sm); 325219820Sjeff if (p_sm->sweep_fail_disp_h == CL_DISP_INVALID_HANDLE) 326219820Sjeff goto Exit; 327219820Sjeff 328219820Sjeff p_sm->ni_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_INFO, 329219820Sjeff osm_ni_rcv_process, p_sm); 330219820Sjeff if (p_sm->ni_disp_h == CL_DISP_INVALID_HANDLE) 331219820Sjeff goto Exit; 332219820Sjeff 333219820Sjeff p_sm->pi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORT_INFO, 334219820Sjeff osm_pi_rcv_process, p_sm); 335219820Sjeff if (p_sm->pi_disp_h == CL_DISP_INVALID_HANDLE) 336219820Sjeff goto Exit; 337219820Sjeff 338219820Sjeff p_sm->si_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO, 339219820Sjeff osm_si_rcv_process, p_sm); 340219820Sjeff if (p_sm->si_disp_h == CL_DISP_INVALID_HANDLE) 341219820Sjeff goto Exit; 342219820Sjeff 343219820Sjeff p_sm->nd_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_DESC, 344219820Sjeff osm_nd_rcv_process, p_sm); 345219820Sjeff if (p_sm->nd_disp_h == CL_DISP_INVALID_HANDLE) 346219820Sjeff goto Exit; 347219820Sjeff 348219820Sjeff p_sm->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT, 349219820Sjeff osm_lft_rcv_process, p_sm); 350219820Sjeff if (p_sm->lft_disp_h == CL_DISP_INVALID_HANDLE) 351219820Sjeff goto Exit; 352219820Sjeff 353219820Sjeff p_sm->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT, 354219820Sjeff osm_mft_rcv_process, p_sm); 355219820Sjeff if (p_sm->mft_disp_h == CL_DISP_INVALID_HANDLE) 356219820Sjeff goto Exit; 357219820Sjeff 358219820Sjeff p_sm->sm_info_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SM_INFO, 359219820Sjeff osm_sminfo_rcv_process, p_sm); 360219820Sjeff if (p_sm->sm_info_disp_h == CL_DISP_INVALID_HANDLE) 361219820Sjeff goto Exit; 362219820Sjeff 363219820Sjeff p_sm->trap_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NOTICE, 364219820Sjeff osm_trap_rcv_process, p_sm); 365219820Sjeff if (p_sm->trap_disp_h == CL_DISP_INVALID_HANDLE) 366219820Sjeff goto Exit; 367219820Sjeff 368219820Sjeff p_sm->slvl_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SLVL, 369219820Sjeff osm_slvl_rcv_process, p_sm); 370219820Sjeff if (p_sm->slvl_disp_h == CL_DISP_INVALID_HANDLE) 371219820Sjeff goto Exit; 372219820Sjeff 373219820Sjeff p_sm->vla_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB, 374219820Sjeff osm_vla_rcv_process, p_sm); 375219820Sjeff if (p_sm->vla_disp_h == CL_DISP_INVALID_HANDLE) 376219820Sjeff goto Exit; 377219820Sjeff 378219820Sjeff p_sm->pkey_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PKEY, 379219820Sjeff osm_pkey_rcv_process, p_sm); 380219820Sjeff if (p_sm->pkey_disp_h == CL_DISP_INVALID_HANDLE) 381219820Sjeff goto Exit; 382219820Sjeff 383219820Sjeff p_subn->sm_state = p_subn->opt.sm_inactive ? 384219820Sjeff IB_SMINFO_STATE_NOTACTIVE : IB_SMINFO_STATE_DISCOVERING; 385219820Sjeff osm_report_sm_state(p_sm); 386219820Sjeff 387219820Sjeff /* 388219820Sjeff * Now that the component objects are initialized, start 389219820Sjeff * the sweeper thread if the user wants sweeping. 390219820Sjeff */ 391219820Sjeff p_sm->thread_state = OSM_THREAD_STATE_RUN; 392219820Sjeff status = cl_thread_init(&p_sm->sweeper, __osm_sm_sweeper, p_sm, 393219820Sjeff "opensm sweeper"); 394219820Sjeff if (status != IB_SUCCESS) 395219820Sjeff goto Exit; 396219820Sjeff 397219820Sjeff if (p_sm->p_subn->opt.sweep_interval) 398219820Sjeff cl_timer_start(&p_sm->sweep_timer, 399219820Sjeff p_sm->p_subn->opt.sweep_interval * 1000); 400219820Sjeff 401219820SjeffExit: 402219820Sjeff OSM_LOG_EXIT(p_log); 403219820Sjeff return (status); 404219820Sjeff} 405219820Sjeff 406219820Sjeff/********************************************************************** 407219820Sjeff **********************************************************************/ 408219820Sjeffvoid osm_sm_signal(osm_sm_t * p_sm, osm_signal_t signal) 409219820Sjeff{ 410219820Sjeff cl_spinlock_acquire(&p_sm->signal_lock); 411219820Sjeff p_sm->signal_mask |= 1 << signal; 412219820Sjeff cl_event_signal(&p_sm->signal_event); 413219820Sjeff cl_spinlock_release(&p_sm->signal_lock); 414219820Sjeff} 415219820Sjeff 416219820Sjeff/********************************************************************** 417219820Sjeff **********************************************************************/ 418219820Sjeffvoid osm_sm_sweep(IN osm_sm_t * const p_sm) 419219820Sjeff{ 420219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 421219820Sjeff osm_sm_signal(p_sm, OSM_SIGNAL_SWEEP); 422219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 423219820Sjeff} 424219820Sjeff 425219820Sjeff/********************************************************************** 426219820Sjeff **********************************************************************/ 427219820Sjeffib_api_status_t 428219820Sjeffosm_sm_bind(IN osm_sm_t * const p_sm, IN const ib_net64_t port_guid) 429219820Sjeff{ 430219820Sjeff ib_api_status_t status; 431219820Sjeff 432219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 433219820Sjeff 434219820Sjeff status = osm_sm_mad_ctrl_bind(&p_sm->mad_ctrl, port_guid); 435219820Sjeff 436219820Sjeff if (status != IB_SUCCESS) { 437219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E10: " 438219820Sjeff "SM MAD Controller bind failed (%s)\n", 439219820Sjeff ib_get_err_str(status)); 440219820Sjeff goto Exit; 441219820Sjeff } 442219820Sjeff 443219820SjeffExit: 444219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 445219820Sjeff return (status); 446219820Sjeff} 447219820Sjeff 448219820Sjeff/********************************************************************** 449219820Sjeff **********************************************************************/ 450219820Sjeffstatic ib_api_status_t 451219820Sjeff__osm_sm_mgrp_process(IN osm_sm_t * const p_sm, 452219820Sjeff IN osm_mgrp_t * const p_mgrp, 453219820Sjeff IN const ib_net64_t port_guid, 454219820Sjeff IN osm_mcast_req_type_t req_type) 455219820Sjeff{ 456219820Sjeff osm_mcast_mgr_ctxt_t *ctx; 457219820Sjeff 458219820Sjeff /* 459219820Sjeff * 'Schedule' all the QP0 traffic for when the state manager 460219820Sjeff * isn't busy trying to do something else. 461219820Sjeff */ 462219820Sjeff ctx = malloc(sizeof(*ctx)); 463219820Sjeff if (!ctx) 464219820Sjeff return IB_ERROR; 465219820Sjeff memset(ctx, 0, sizeof(*ctx)); 466219820Sjeff ctx->mlid = p_mgrp->mlid; 467219820Sjeff ctx->req_type = req_type; 468219820Sjeff ctx->port_guid = port_guid; 469219820Sjeff 470219820Sjeff cl_spinlock_acquire(&p_sm->mgrp_lock); 471219820Sjeff cl_qlist_insert_tail(&p_sm->mgrp_list, &ctx->list_item); 472219820Sjeff cl_spinlock_release(&p_sm->mgrp_lock); 473219820Sjeff 474219820Sjeff osm_sm_signal(p_sm, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST); 475219820Sjeff 476219820Sjeff return IB_SUCCESS; 477219820Sjeff} 478219820Sjeff 479219820Sjeff/********************************************************************** 480219820Sjeff **********************************************************************/ 481219820Sjeffstatic ib_api_status_t 482219820Sjeff__osm_sm_mgrp_connect(IN osm_sm_t * const p_sm, 483219820Sjeff IN osm_mgrp_t * const p_mgrp, 484219820Sjeff IN const ib_net64_t port_guid, 485219820Sjeff IN osm_mcast_req_type_t req_type) 486219820Sjeff{ 487219820Sjeff return __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, req_type); 488219820Sjeff} 489219820Sjeff 490219820Sjeff/********************************************************************** 491219820Sjeff **********************************************************************/ 492219820Sjeffstatic void 493219820Sjeff__osm_sm_mgrp_disconnect(IN osm_sm_t * const p_sm, 494219820Sjeff IN osm_mgrp_t * const p_mgrp, 495219820Sjeff IN const ib_net64_t port_guid) 496219820Sjeff{ 497219820Sjeff __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, 498219820Sjeff OSM_MCAST_REQ_TYPE_LEAVE); 499219820Sjeff} 500219820Sjeff 501219820Sjeff/********************************************************************** 502219820Sjeff **********************************************************************/ 503219820Sjeffib_api_status_t 504219820Sjeffosm_sm_mcgrp_join(IN osm_sm_t * const p_sm, 505219820Sjeff IN const ib_net16_t mlid, 506219820Sjeff IN const ib_net64_t port_guid, 507219820Sjeff IN osm_mcast_req_type_t req_type) 508219820Sjeff{ 509219820Sjeff osm_mgrp_t *p_mgrp; 510219820Sjeff osm_port_t *p_port; 511219820Sjeff ib_api_status_t status = IB_SUCCESS; 512219820Sjeff osm_mcm_info_t *p_mcm; 513219820Sjeff 514219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 515219820Sjeff 516219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE, 517219820Sjeff "Port 0x%016" PRIx64 " joining MLID 0x%X\n", 518219820Sjeff cl_ntoh64(port_guid), cl_ntoh16(mlid)); 519219820Sjeff 520219820Sjeff /* 521219820Sjeff * Acquire the port object for the port joining this group. 522219820Sjeff */ 523219820Sjeff CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock); 524219820Sjeff p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid); 525219820Sjeff if (!p_port) { 526219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 527219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E05: " 528219820Sjeff "No port object for port 0x%016" PRIx64 "\n", 529219820Sjeff cl_ntoh64(port_guid)); 530219820Sjeff status = IB_INVALID_PARAMETER; 531219820Sjeff goto Exit; 532219820Sjeff } 533219820Sjeff 534219820Sjeff /* 535219820Sjeff * If this multicast group does not already exist, create it. 536219820Sjeff */ 537219820Sjeff p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid); 538219820Sjeff if (!p_mgrp || !osm_mgrp_is_guid(p_mgrp, port_guid)) { 539219820Sjeff /* 540219820Sjeff * The group removed or the port is not a 541219820Sjeff * member of the group, then fail immediately. 542219820Sjeff * This can happen since the spinlock is released briefly 543219820Sjeff * before the SA calls this function. 544219820Sjeff */ 545219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 546219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E12: " 547219820Sjeff "MC group with mlid 0x%x doesn't exist or " 548219820Sjeff "port 0x%016" PRIx64 " is not in the group.\n", 549219820Sjeff cl_ntoh16(mlid), cl_ntoh64(port_guid)); 550219820Sjeff status = IB_NOT_FOUND; 551219820Sjeff goto Exit; 552219820Sjeff } 553219820Sjeff 554219820Sjeff /* 555219820Sjeff * Check if the object (according to mlid) already exists on this port. 556219820Sjeff * If it does - then no need to update it again, and no need to 557219820Sjeff * create the mc tree again. Just goto Exit. 558219820Sjeff */ 559219820Sjeff p_mcm = (osm_mcm_info_t *) cl_qlist_head(&p_port->mcm_list); 560219820Sjeff while (p_mcm != (osm_mcm_info_t *) cl_qlist_end(&p_port->mcm_list)) { 561219820Sjeff if (p_mcm->mlid == mlid) { 562219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 563219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG, 564219820Sjeff "Found mlid object for Port:" 565219820Sjeff "0x%016" PRIx64 " lid:0x%X\n", 566219820Sjeff cl_ntoh64(port_guid), cl_ntoh16(mlid)); 567219820Sjeff goto Exit; 568219820Sjeff } 569219820Sjeff p_mcm = (osm_mcm_info_t *) cl_qlist_next(&p_mcm->list_item); 570219820Sjeff } 571219820Sjeff 572219820Sjeff status = osm_port_add_mgrp(p_port, mlid); 573219820Sjeff if (status != IB_SUCCESS) { 574219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 575219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E03: " 576219820Sjeff "Unable to associate port 0x%" PRIx64 " to mlid 0x%X\n", 577219820Sjeff cl_ntoh64(osm_port_get_guid(p_port)), 578219820Sjeff cl_ntoh16(osm_mgrp_get_mlid(p_mgrp))); 579219820Sjeff goto Exit; 580219820Sjeff } 581219820Sjeff 582219820Sjeff status = __osm_sm_mgrp_connect(p_sm, p_mgrp, port_guid, req_type); 583219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 584219820Sjeff 585219820SjeffExit: 586219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 587219820Sjeff return (status); 588219820Sjeff} 589219820Sjeff 590219820Sjeff/********************************************************************** 591219820Sjeff **********************************************************************/ 592219820Sjeffib_api_status_t 593219820Sjeffosm_sm_mcgrp_leave(IN osm_sm_t * const p_sm, 594219820Sjeff IN const ib_net16_t mlid, IN const ib_net64_t port_guid) 595219820Sjeff{ 596219820Sjeff osm_mgrp_t *p_mgrp; 597219820Sjeff osm_port_t *p_port; 598219820Sjeff ib_api_status_t status = IB_SUCCESS; 599219820Sjeff 600219820Sjeff OSM_LOG_ENTER(p_sm->p_log); 601219820Sjeff 602219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE, 603219820Sjeff "Port 0x%" PRIx64 " leaving MLID 0x%X\n", 604219820Sjeff cl_ntoh64(port_guid), cl_ntoh16(mlid)); 605219820Sjeff 606219820Sjeff /* 607219820Sjeff * Acquire the port object for the port leaving this group. 608219820Sjeff */ 609219820Sjeff CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock); 610219820Sjeff 611219820Sjeff p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid); 612219820Sjeff if (!p_port) { 613219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 614219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E04: " 615219820Sjeff "No port object for port 0x%" PRIx64 "\n", 616219820Sjeff cl_ntoh64(port_guid)); 617219820Sjeff status = IB_INVALID_PARAMETER; 618219820Sjeff goto Exit; 619219820Sjeff } 620219820Sjeff 621219820Sjeff /* 622219820Sjeff * Get the multicast group object for this group. 623219820Sjeff */ 624219820Sjeff p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid); 625219820Sjeff if (!p_mgrp) { 626219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 627219820Sjeff OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E08: " 628219820Sjeff "No multicast group for MLID 0x%X\n", cl_ntoh16(mlid)); 629219820Sjeff status = IB_INVALID_PARAMETER; 630219820Sjeff goto Exit; 631219820Sjeff } 632219820Sjeff 633219820Sjeff /* 634219820Sjeff * Walk the list of ports in the group, and remove the appropriate one. 635219820Sjeff */ 636219820Sjeff osm_port_remove_mgrp(p_port, mlid); 637219820Sjeff 638219820Sjeff __osm_sm_mgrp_disconnect(p_sm, p_mgrp, port_guid); 639219820Sjeff CL_PLOCK_RELEASE(p_sm->p_lock); 640219820Sjeff 641219820SjeffExit: 642219820Sjeff OSM_LOG_EXIT(p_sm->p_log); 643219820Sjeff return (status); 644219820Sjeff} 645219820Sjeff 646219820Sjeffvoid osm_set_sm_priority(osm_sm_t *sm, uint8_t priority) 647219820Sjeff{ 648219820Sjeff uint8_t old_pri = sm->p_subn->opt.sm_priority; 649219820Sjeff 650219820Sjeff sm->p_subn->opt.sm_priority = priority; 651219820Sjeff 652219820Sjeff if (old_pri < priority && 653219820Sjeff sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY) 654219820Sjeff osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE); 655219820Sjeff} 656