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.
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:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
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.
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
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.
46 #endif /* HAVE_CONFIG_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>
64 #define OSM_SM_INITIAL_TID_VALUE 0x1233
66 extern void osm_lft_rcv_process(IN void *context, IN void *data);
67 extern void osm_mft_rcv_process(IN void *context, IN void *data);
68 extern void osm_nd_rcv_process(IN void *context, IN void *data);
69 extern void osm_ni_rcv_process(IN void *context, IN void *data);
70 extern void osm_pkey_rcv_process(IN void *context, IN void *data);
71 extern void osm_pi_rcv_process(IN void *context, IN void *data);
72 extern void osm_slvl_rcv_process(IN void *context, IN void *p_data);
73 extern void osm_sminfo_rcv_process(IN void *context, IN void *data);
74 extern void osm_si_rcv_process(IN void *context, IN void *data);
75 extern void osm_trap_rcv_process(IN void *context, IN void *data);
76 extern void osm_vla_rcv_process(IN void *context, IN void *data);
78 extern void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal);
79 extern void osm_sm_state_mgr_polling_callback(IN void *context);
81 /**********************************************************************
82 **********************************************************************/
83 static void osm_sm_process(osm_sm_t * sm, osm_signal_t signal)
85 #ifdef ENABLE_OSM_PERF_MGR
86 if (signal == OSM_SIGNAL_PERFMGR_SWEEP)
87 osm_perfmgr_process(&sm->p_subn->p_osm->perfmgr);
90 osm_state_mgr_process(sm, signal);
93 static void __osm_sm_sweeper(IN void *p_ptr)
95 ib_api_status_t status;
96 osm_sm_t *const p_sm = (osm_sm_t *) p_ptr;
99 OSM_LOG_ENTER(p_sm->p_log);
101 while (p_sm->thread_state == OSM_THREAD_STATE_RUN) {
103 * Wait on the event with a timeout.
104 * Sweeps may be initiated "off schedule" by simply
105 * signaling the event.
107 status = cl_event_wait_on(&p_sm->signal_event,
108 EVENT_NO_TIMEOUT, TRUE);
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));
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);
128 for (i = 0; signals; signals >>= 1, i++)
130 osm_sm_process(p_sm, i);
133 OSM_LOG_EXIT(p_sm->p_log);
136 static void sm_sweep(void *arg)
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);
147 static void sweep_fail_process(IN void *context, IN void *p_data)
149 osm_sm_t *sm = context;
151 OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "light sweep failed\n");
152 sm->p_subn->force_heavy_sweep = TRUE;
155 /**********************************************************************
156 **********************************************************************/
157 void osm_sm_construct(IN osm_sm_t * const p_sm)
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);
175 /**********************************************************************
176 **********************************************************************/
177 void osm_sm_shutdown(IN osm_sm_t * const p_sm)
179 boolean_t signal_event = FALSE;
181 OSM_LOG_ENTER(p_sm->p_log);
184 * Signal our threads that we're leaving.
186 if (p_sm->thread_state != OSM_THREAD_STATE_NONE)
189 p_sm->thread_state = OSM_THREAD_STATE_EXIT;
192 * Don't trigger unless event has been initialized.
193 * Destroy the thread before we tear down the other objects.
196 cl_event_signal(&p_sm->signal_event);
198 cl_timer_stop(&p_sm->polling_timer);
199 cl_timer_stop(&p_sm->sweep_timer);
200 cl_thread_destroy(&p_sm->sweeper);
203 * Always destroy controllers before the corresponding
204 * receiver to guarantee that all callbacks from the
205 * dispatcher are complete.
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);
221 OSM_LOG_EXIT(p_sm->p_log);
224 /**********************************************************************
225 **********************************************************************/
226 void osm_sm_destroy(IN osm_sm_t * const p_sm)
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);
240 osm_log(p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n"); /* Format Waived */
241 OSM_LOG_EXIT(p_sm->p_log);
244 /**********************************************************************
245 **********************************************************************/
247 osm_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)
257 ib_api_status_t status = IB_SUCCESS;
259 OSM_LOG_ENTER(p_log);
261 p_sm->p_subn = p_subn;
263 p_sm->p_vendor = p_vendor;
264 p_sm->p_mad_pool = p_mad_pool;
265 p_sm->p_vl15 = p_vl15;
267 p_sm->p_disp = p_disp;
268 p_sm->p_lock = p_lock;
270 status = cl_spinlock_init(&p_sm->signal_lock);
271 if (status != CL_SUCCESS)
274 status = cl_spinlock_init(&p_sm->state_lock);
275 if (status != CL_SUCCESS)
278 status = cl_event_init(&p_sm->signal_event, FALSE);
279 if (status != CL_SUCCESS)
282 status = cl_event_init(&p_sm->subnet_up_event, FALSE);
283 if (status != CL_SUCCESS)
286 status = cl_timer_init(&p_sm->sweep_timer, sm_sweep, p_sm);
287 if (status != CL_SUCCESS)
290 status = cl_timer_init(&p_sm->polling_timer,
291 osm_sm_state_mgr_polling_callback, p_sm);
292 if (status != CL_SUCCESS)
295 cl_qlist_init(&p_sm->mgrp_list);
297 status = cl_spinlock_init(&p_sm->mgrp_lock);
298 if (status != CL_SUCCESS)
301 status = osm_sm_mad_ctrl_init(&p_sm->mad_ctrl,
306 p_log, p_stats, p_lock, p_disp);
307 if (status != IB_SUCCESS)
310 status = cl_event_wheel_init(&p_sm->trap_aging_tracker);
311 if (status != IB_SUCCESS)
314 status = osm_lid_mgr_init(&p_sm->lid_mgr, p_sm);
315 if (status != IB_SUCCESS)
318 status = osm_ucast_mgr_init(&p_sm->ucast_mgr, p_sm);
319 if (status != IB_SUCCESS)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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);
388 * Now that the component objects are initialized, start
389 * the sweeper thread if the user wants sweeping.
391 p_sm->thread_state = OSM_THREAD_STATE_RUN;
392 status = cl_thread_init(&p_sm->sweeper, __osm_sm_sweeper, p_sm,
394 if (status != IB_SUCCESS)
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);
406 /**********************************************************************
407 **********************************************************************/
408 void osm_sm_signal(osm_sm_t * p_sm, osm_signal_t signal)
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);
416 /**********************************************************************
417 **********************************************************************/
418 void osm_sm_sweep(IN osm_sm_t * const p_sm)
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);
425 /**********************************************************************
426 **********************************************************************/
428 osm_sm_bind(IN osm_sm_t * const p_sm, IN const ib_net64_t port_guid)
430 ib_api_status_t status;
432 OSM_LOG_ENTER(p_sm->p_log);
434 status = osm_sm_mad_ctrl_bind(&p_sm->mad_ctrl, port_guid);
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));
444 OSM_LOG_EXIT(p_sm->p_log);
448 /**********************************************************************
449 **********************************************************************/
450 static 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)
456 osm_mcast_mgr_ctxt_t *ctx;
459 * 'Schedule' all the QP0 traffic for when the state manager
460 * isn't busy trying to do something else.
462 ctx = malloc(sizeof(*ctx));
465 memset(ctx, 0, sizeof(*ctx));
466 ctx->mlid = p_mgrp->mlid;
467 ctx->req_type = req_type;
468 ctx->port_guid = port_guid;
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);
474 osm_sm_signal(p_sm, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST);
479 /**********************************************************************
480 **********************************************************************/
481 static 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)
487 return __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, req_type);
490 /**********************************************************************
491 **********************************************************************/
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)
497 __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid,
498 OSM_MCAST_REQ_TYPE_LEAVE);
501 /**********************************************************************
502 **********************************************************************/
504 osm_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)
511 ib_api_status_t status = IB_SUCCESS;
512 osm_mcm_info_t *p_mcm;
514 OSM_LOG_ENTER(p_sm->p_log);
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));
521 * Acquire the port object for the port joining this group.
523 CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock);
524 p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid);
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;
535 * If this multicast group does not already exist, create it.
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)) {
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.
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;
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.
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));
569 p_mcm = (osm_mcm_info_t *) cl_qlist_next(&p_mcm->list_item);
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)));
582 status = __osm_sm_mgrp_connect(p_sm, p_mgrp, port_guid, req_type);
583 CL_PLOCK_RELEASE(p_sm->p_lock);
586 OSM_LOG_EXIT(p_sm->p_log);
590 /**********************************************************************
591 **********************************************************************/
593 osm_sm_mcgrp_leave(IN osm_sm_t * const p_sm,
594 IN const ib_net16_t mlid, IN const ib_net64_t port_guid)
598 ib_api_status_t status = IB_SUCCESS;
600 OSM_LOG_ENTER(p_sm->p_log);
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));
607 * Acquire the port object for the port leaving this group.
609 CL_PLOCK_EXCL_ACQUIRE(p_sm->p_lock);
611 p_port = osm_get_port_by_guid(p_sm->p_subn, port_guid);
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;
622 * Get the multicast group object for this group.
624 p_mgrp = osm_get_mgrp_by_mlid(p_sm->p_subn, mlid);
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;
634 * Walk the list of ports in the group, and remove the appropriate one.
636 osm_port_remove_mgrp(p_port, mlid);
638 __osm_sm_mgrp_disconnect(p_sm, p_mgrp, port_guid);
639 CL_PLOCK_RELEASE(p_sm->p_lock);
642 OSM_LOG_EXIT(p_sm->p_log);
646 void osm_set_sm_priority(osm_sm_t *sm, uint8_t priority)
648 uint8_t old_pri = sm->p_subn->opt.sm_priority;
650 sm->p_subn->opt.sm_priority = priority;
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);