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 **********************************************************************/
osm_sm_process(osm_sm_t * sm,osm_signal_t signal)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
__osm_sm_sweeper(IN void * p_ptr)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
sm_sweep(void * arg)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
sweep_fail_process(IN void * context,IN void * p_data)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 **********************************************************************/
osm_sm_construct(IN osm_sm_t * const p_sm)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 **********************************************************************/
osm_sm_shutdown(IN osm_sm_t * const p_sm)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 **********************************************************************/
osm_sm_destroy(IN osm_sm_t * const p_sm)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
osm_sm_init(IN osm_sm_t * const p_sm,IN osm_subn_t * const p_subn,IN osm_db_t * const p_db,IN osm_vendor_t * const p_vendor,IN osm_mad_pool_t * const p_mad_pool,IN osm_vl15_t * const p_vl15,IN osm_log_t * const p_log,IN osm_stats_t * const p_stats,IN cl_dispatcher_t * const p_disp,IN cl_plock_t * const p_lock)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 **********************************************************************/
osm_sm_signal(osm_sm_t * p_sm,osm_signal_t signal)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 **********************************************************************/
osm_sm_sweep(IN osm_sm_t * const p_sm)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
osm_sm_bind(IN osm_sm_t * const p_sm,IN const ib_net64_t port_guid)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
__osm_sm_mgrp_process(IN osm_sm_t * const p_sm,IN osm_mgrp_t * const p_mgrp,IN const ib_net64_t port_guid,IN osm_mcast_req_type_t req_type)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
__osm_sm_mgrp_connect(IN osm_sm_t * const p_sm,IN osm_mgrp_t * const p_mgrp,IN const ib_net64_t port_guid,IN osm_mcast_req_type_t req_type)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
__osm_sm_mgrp_disconnect(IN osm_sm_t * const p_sm,IN osm_mgrp_t * const p_mgrp,IN const ib_net64_t port_guid)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
osm_sm_mcgrp_join(IN osm_sm_t * const p_sm,IN const ib_net16_t mlid,IN const ib_net64_t port_guid,IN osm_mcast_req_type_t req_type)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
osm_sm_mcgrp_leave(IN osm_sm_t * const p_sm,IN const ib_net16_t mlid,IN const ib_net64_t port_guid)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
osm_set_sm_priority(osm_sm_t * sm,uint8_t priority)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 }
656