]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_sm.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / opensm / osm_sm.c
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
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);
77
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);
80
81 /**********************************************************************
82  **********************************************************************/
83 static 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
93 static 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
136 static 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
147 static 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  **********************************************************************/
157 void 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  **********************************************************************/
177 void 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  **********************************************************************/
226 void 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  **********************************************************************/
246 ib_api_status_t
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)
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
401 Exit:
402         OSM_LOG_EXIT(p_log);
403         return (status);
404 }
405
406 /**********************************************************************
407  **********************************************************************/
408 void 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  **********************************************************************/
418 void 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  **********************************************************************/
427 ib_api_status_t
428 osm_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
443 Exit:
444         OSM_LOG_EXIT(p_sm->p_log);
445         return (status);
446 }
447
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)
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  **********************************************************************/
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)
486 {
487         return __osm_sm_mgrp_process(p_sm, p_mgrp, port_guid, req_type);
488 }
489
490 /**********************************************************************
491  **********************************************************************/
492 static 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  **********************************************************************/
503 ib_api_status_t
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)
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
585 Exit:
586         OSM_LOG_EXIT(p_sm->p_log);
587         return (status);
588 }
589
590 /**********************************************************************
591  **********************************************************************/
592 ib_api_status_t
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)
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
641 Exit:
642         OSM_LOG_EXIT(p_sm->p_log);
643         return (status);
644 }
645
646 void 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 }