1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. 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_opensm_t.
40  * This object represents the opensm super 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 <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <complib/cl_dispatcher.h>
52 #include <complib/cl_passivelock.h>
53 #include <opensm/osm_file_ids.h>
54 #define FILE_ID OSM_FILE_OPENSM_C
55 #include <vendor/osm_vendor_api.h>
56 #include <opensm/osm_version.h>
57 #include <opensm/osm_base.h>
58 #include <opensm/osm_opensm.h>
59 #include <opensm/osm_log.h>
60 #include <opensm/osm_subnet.h>
61 #include <opensm/osm_sm.h>
62 #include <opensm/osm_vl15intf.h>
63 #include <opensm/osm_event_plugin.h>
64 #include <opensm/osm_congestion_control.h>
65 
66 struct routing_engine_module {
67 	const char *name;
68 	int (*setup) (struct osm_routing_engine *, osm_opensm_t *);
69 };
70 
71 extern int osm_ucast_minhop_setup(struct osm_routing_engine *, osm_opensm_t *);
72 extern int osm_ucast_updn_setup(struct osm_routing_engine *, osm_opensm_t *);
73 extern int osm_ucast_dnup_setup(struct osm_routing_engine *, osm_opensm_t *);
74 extern int osm_ucast_file_setup(struct osm_routing_engine *, osm_opensm_t *);
75 extern int osm_ucast_ftree_setup(struct osm_routing_engine *, osm_opensm_t *);
76 extern int osm_ucast_lash_setup(struct osm_routing_engine *, osm_opensm_t *);
77 extern int osm_ucast_dor_setup(struct osm_routing_engine *, osm_opensm_t *);
78 extern int osm_ucast_torus2QoS_setup(struct osm_routing_engine *, osm_opensm_t *);
79 extern int osm_ucast_sssp_setup(struct osm_routing_engine *, osm_opensm_t *);
80 extern int osm_ucast_dfsssp_setup(struct osm_routing_engine *, osm_opensm_t *);
81 
82 const static struct routing_engine_module routing_modules[] = {
83 	{"minhop", osm_ucast_minhop_setup},
84 	{"updn", osm_ucast_updn_setup},
85 	{"dnup", osm_ucast_dnup_setup},
86 	{"file", osm_ucast_file_setup},
87 	{"ftree", osm_ucast_ftree_setup},
88 	{"lash", osm_ucast_lash_setup},
89 	{"dor", osm_ucast_dor_setup},
90 	{"torus-2QoS", osm_ucast_torus2QoS_setup},
91 	{"dfsssp", osm_ucast_dfsssp_setup},
92 	{"sssp", osm_ucast_sssp_setup},
93 	{NULL, NULL}
94 };
95 
osm_routing_engine_type_str(IN osm_routing_engine_type_t type)96 const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type)
97 {
98 	switch (type) {
99 	case OSM_ROUTING_ENGINE_TYPE_NONE:
100 		return "none";
101 	case OSM_ROUTING_ENGINE_TYPE_MINHOP:
102 		return "minhop";
103 	case OSM_ROUTING_ENGINE_TYPE_UPDN:
104 		return "updn";
105 	case OSM_ROUTING_ENGINE_TYPE_DNUP:
106 		return "dnup";
107 	case OSM_ROUTING_ENGINE_TYPE_FILE:
108 		return "file";
109 	case OSM_ROUTING_ENGINE_TYPE_FTREE:
110 		return "ftree";
111 	case OSM_ROUTING_ENGINE_TYPE_LASH:
112 		return "lash";
113 	case OSM_ROUTING_ENGINE_TYPE_DOR:
114 		return "dor";
115 	case OSM_ROUTING_ENGINE_TYPE_TORUS_2QOS:
116 		return "torus-2QoS";
117 	case OSM_ROUTING_ENGINE_TYPE_DFSSSP:
118 		return "dfsssp";
119 	case OSM_ROUTING_ENGINE_TYPE_SSSP:
120 		return "sssp";
121 	default:
122 		break;
123 	}
124 	return "unknown";
125 }
126 
osm_routing_engine_type(IN const char * str)127 osm_routing_engine_type_t osm_routing_engine_type(IN const char *str)
128 {
129 	/* For legacy reasons, consider a NULL pointer and the string
130 	 * "null" as the minhop routing engine.
131 	 */
132 	if (!str || !strcasecmp(str, "null")
133 	    || !strcasecmp(str, "minhop"))
134 		return OSM_ROUTING_ENGINE_TYPE_MINHOP;
135 	else if (!strcasecmp(str, "none"))
136 		return OSM_ROUTING_ENGINE_TYPE_NONE;
137 	else if (!strcasecmp(str, "updn"))
138 		return OSM_ROUTING_ENGINE_TYPE_UPDN;
139 	else if (!strcasecmp(str, "dnup"))
140 		return OSM_ROUTING_ENGINE_TYPE_DNUP;
141 	else if (!strcasecmp(str, "file"))
142 		return OSM_ROUTING_ENGINE_TYPE_FILE;
143 	else if (!strcasecmp(str, "ftree"))
144 		return OSM_ROUTING_ENGINE_TYPE_FTREE;
145 	else if (!strcasecmp(str, "lash"))
146 		return OSM_ROUTING_ENGINE_TYPE_LASH;
147 	else if (!strcasecmp(str, "dor"))
148 		return OSM_ROUTING_ENGINE_TYPE_DOR;
149 	else if (!strcasecmp(str, "torus-2QoS"))
150 		return OSM_ROUTING_ENGINE_TYPE_TORUS_2QOS;
151 	else if (!strcasecmp(str, "sssp"))
152 		return OSM_ROUTING_ENGINE_TYPE_SSSP;
153 	else if (!strcasecmp(str, "dfsssp"))
154 		return OSM_ROUTING_ENGINE_TYPE_DFSSSP;
155 	else
156 		return OSM_ROUTING_ENGINE_TYPE_UNKNOWN;
157 }
158 
append_routing_engine(osm_opensm_t * osm,struct osm_routing_engine * routing_engine)159 static void append_routing_engine(osm_opensm_t *osm,
160 				  struct osm_routing_engine *routing_engine)
161 {
162 	struct osm_routing_engine *r;
163 
164 	routing_engine->next = NULL;
165 
166 	if (!osm->routing_engine_list) {
167 		osm->routing_engine_list = routing_engine;
168 		return;
169 	}
170 
171 	r = osm->routing_engine_list;
172 	while (r->next)
173 		r = r->next;
174 
175 	r->next = routing_engine;
176 }
177 
setup_routing_engine(osm_opensm_t * osm,const char * name)178 static struct osm_routing_engine *setup_routing_engine(osm_opensm_t *osm,
179 						       const char *name)
180 {
181 	struct osm_routing_engine *re;
182 	const struct routing_engine_module *m;
183 
184 	if (!strcmp(name, "no_fallback")) {
185 		osm->no_fallback_routing_engine = TRUE;
186 		return NULL;
187 	}
188 
189 	for (m = routing_modules; m->name && *m->name; m++) {
190 		if (!strcmp(m->name, name)) {
191 			re = malloc(sizeof(struct osm_routing_engine));
192 			if (!re) {
193 				OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
194 					"memory allocation failed\n");
195 				return NULL;
196 			}
197 			memset(re, 0, sizeof(struct osm_routing_engine));
198 
199 			re->name = m->name;
200 			re->type = osm_routing_engine_type(m->name);
201 			if (m->setup(re, osm)) {
202 				OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
203 					"setup of routing"
204 					" engine \'%s\' failed\n", name);
205 				free(re);
206 				return NULL;
207 			}
208 			OSM_LOG(&osm->log, OSM_LOG_DEBUG,
209 				"\'%s\' routing engine set up\n", re->name);
210 			if (re->type == OSM_ROUTING_ENGINE_TYPE_MINHOP)
211 				osm->default_routing_engine = re;
212 			return re;
213 		}
214 	}
215 
216 	OSM_LOG(&osm->log, OSM_LOG_ERROR,
217 		"cannot find or setup routing engine \'%s\'\n", name);
218 	return NULL;
219 }
220 
setup_routing_engines(osm_opensm_t * osm,const char * engine_names)221 static void setup_routing_engines(osm_opensm_t *osm, const char *engine_names)
222 {
223 	char *name, *str, *p;
224 	struct osm_routing_engine *re;
225 
226 	if (engine_names && *engine_names) {
227 		str = strdup(engine_names);
228 		name = strtok_r(str, ", \t\n", &p);
229 		while (name && *name) {
230 			re = setup_routing_engine(osm, name);
231 			if (re)
232 				append_routing_engine(osm, re);
233 			name = strtok_r(NULL, ", \t\n", &p);
234 		}
235 		free(str);
236 	}
237 	if (!osm->default_routing_engine)
238 		setup_routing_engine(osm, "minhop");
239 }
240 
osm_opensm_construct(IN osm_opensm_t * p_osm)241 void osm_opensm_construct(IN osm_opensm_t * p_osm)
242 {
243 	memset(p_osm, 0, sizeof(*p_osm));
244 	p_osm->osm_version = OSM_VERSION;
245 	osm_subn_construct(&p_osm->subn);
246 	osm_db_construct(&p_osm->db);
247 	osm_log_construct(&p_osm->log);
248 }
249 
osm_opensm_construct_finish(IN osm_opensm_t * p_osm)250 void osm_opensm_construct_finish(IN osm_opensm_t * p_osm)
251 {
252 	osm_sm_construct(&p_osm->sm);
253 	osm_sa_construct(&p_osm->sa);
254 	osm_mad_pool_construct(&p_osm->mad_pool);
255 	p_osm->mad_pool_constructed = TRUE;
256 	osm_vl15_construct(&p_osm->vl15);
257 	p_osm->vl15_constructed = TRUE;
258 }
259 
destroy_routing_engines(osm_opensm_t * osm)260 static void destroy_routing_engines(osm_opensm_t *osm)
261 {
262 	struct osm_routing_engine *r, *next;
263 
264 	next = osm->routing_engine_list;
265 	while (next) {
266 		r = next;
267 		next = r->next;
268 		if (r->destroy)
269 			r->destroy(r->context);
270 		free(r);
271 	}
272 }
273 
destroy_plugins(osm_opensm_t * osm)274 static void destroy_plugins(osm_opensm_t *osm)
275 {
276 	osm_epi_plugin_t *p;
277 	/* remove from the list, and destroy it */
278 	while (!cl_is_qlist_empty(&osm->plugin_list)){
279 		p = (osm_epi_plugin_t *)cl_qlist_remove_head(&osm->plugin_list);
280 		/* plugin is responsible for freeing its own resources */
281 		osm_epi_destroy(p);
282 	}
283 }
284 
osm_opensm_destroy(IN osm_opensm_t * p_osm)285 void osm_opensm_destroy(IN osm_opensm_t * p_osm)
286 {
287 	/* in case of shutdown through exit proc - no ^C */
288 	osm_exit_flag = TRUE;
289 
290 	/*
291 	 * First of all, clear the is_sm bit.
292 	 */
293 	if (p_osm->sm.mad_ctrl.h_bind)
294 		osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, FALSE);
295 
296 #ifdef ENABLE_OSM_PERF_MGR
297 	/* Shutdown the PerfMgr */
298 	osm_perfmgr_shutdown(&p_osm->perfmgr);
299 #endif				/* ENABLE_OSM_PERF_MGR */
300 
301 	osm_congestion_control_shutdown(&p_osm->cc);
302 
303 	/* shut down the SM
304 	 * - make sure the SM sweeper thread exited
305 	 * - unbind from QP0 messages
306 	 */
307 	osm_sm_shutdown(&p_osm->sm);
308 
309 	/* shut down the SA
310 	 * - unbind from QP1 messages
311 	 */
312 	osm_sa_shutdown(&p_osm->sa);
313 
314 	/* cleanup all messages on VL15 fifo that were not sent yet */
315 	osm_vl15_shutdown(&p_osm->vl15, &p_osm->mad_pool);
316 
317 	/* shut down the dispatcher - so no new messages cross */
318 	cl_disp_shutdown(&p_osm->disp);
319 	if (p_osm->sa_set_disp_initialized)
320 		cl_disp_shutdown(&p_osm->sa_set_disp);
321 
322 	/* dump SA DB */
323 	if ((p_osm->sm.p_subn->sm_state == IB_SMINFO_STATE_MASTER) &&
324 	     p_osm->subn.opt.sa_db_dump)
325 		osm_sa_db_file_dump(p_osm);
326 
327 	/* do the destruction in reverse order as init */
328 	destroy_plugins(p_osm);
329 	destroy_routing_engines(p_osm);
330 	osm_sa_destroy(&p_osm->sa);
331 	osm_sm_destroy(&p_osm->sm);
332 #ifdef ENABLE_OSM_PERF_MGR
333 	osm_perfmgr_destroy(&p_osm->perfmgr);
334 #endif				/* ENABLE_OSM_PERF_MGR */
335 	osm_congestion_control_destroy(&p_osm->cc);
336 }
337 
osm_opensm_destroy_finish(IN osm_opensm_t * p_osm)338 void osm_opensm_destroy_finish(IN osm_opensm_t * p_osm)
339 {
340 	osm_db_destroy(&p_osm->db);
341 	if (p_osm->vl15_constructed && p_osm->mad_pool_constructed)
342 		osm_vl15_destroy(&p_osm->vl15, &p_osm->mad_pool);
343 	if (p_osm->mad_pool_constructed)
344 		osm_mad_pool_destroy(&p_osm->mad_pool);
345 	p_osm->vl15_constructed = FALSE;
346 	p_osm->mad_pool_constructed = FALSE;
347 	osm_vendor_delete(&p_osm->p_vendor);
348 	osm_subn_destroy(&p_osm->subn);
349 	cl_disp_destroy(&p_osm->disp);
350 	if (p_osm->sa_set_disp_initialized)
351 		cl_disp_destroy(&p_osm->sa_set_disp);
352 #ifdef HAVE_LIBPTHREAD
353 	pthread_cond_destroy(&p_osm->stats.cond);
354 	pthread_mutex_destroy(&p_osm->stats.mutex);
355 #else
356 	cl_event_destroy(&p_osm->stats.event);
357 #endif
358 	if (p_osm->node_name_map)
359 		close_node_name_map(p_osm->node_name_map);
360 	cl_plock_destroy(&p_osm->lock);
361 
362 	osm_log_destroy(&p_osm->log);
363 }
364 
load_plugins(osm_opensm_t * osm,const char * plugin_names)365 static void load_plugins(osm_opensm_t *osm, const char *plugin_names)
366 {
367 	osm_epi_plugin_t *epi;
368 	char *p_names, *name, *p;
369 
370 	p_names = strdup(plugin_names);
371 	name = strtok_r(p_names, ", \t\n", &p);
372 	while (name && *name) {
373 		epi = osm_epi_construct(osm, name);
374 		if (!epi)
375 			osm_log_v2(&osm->log, OSM_LOG_ERROR, FILE_ID,
376 				   "ERR 1000: cannot load plugin \'%s\'\n",
377 				   name);
378 		else
379 			cl_qlist_insert_tail(&osm->plugin_list, &epi->list);
380 		name = strtok_r(NULL, " \t\n", &p);
381 	}
382 	free(p_names);
383 }
384 
osm_opensm_init(IN osm_opensm_t * p_osm,IN const osm_subn_opt_t * p_opt)385 ib_api_status_t osm_opensm_init(IN osm_opensm_t * p_osm,
386 				IN const osm_subn_opt_t * p_opt)
387 {
388 	ib_api_status_t status;
389 
390 	/* Can't use log macros here, since we're initializing the log */
391 	osm_opensm_construct(p_osm);
392 
393 	if (p_opt->daemon)
394 		p_osm->log.daemon = 1;
395 
396 	status = osm_log_init_v2(&p_osm->log, p_opt->force_log_flush,
397 				 p_opt->log_flags, p_opt->log_file,
398 				 p_opt->log_max_size, p_opt->accum_log_file);
399 	if (status != IB_SUCCESS)
400 		return status;
401 	p_osm->log.log_prefix = p_opt->log_prefix;
402 
403 	/* If there is a log level defined - add the OSM_VERSION to it */
404 	osm_log_v2(&p_osm->log,
405 		   osm_log_get_level(&p_osm->log) & (OSM_LOG_SYS ^ 0xFF),
406 		   FILE_ID, "%s\n", p_osm->osm_version);
407 	/* Write the OSM_VERSION to the SYS_LOG */
408 	osm_log_v2(&p_osm->log, OSM_LOG_SYS, FILE_ID, "%s\n", p_osm->osm_version);	/* Format Waived */
409 
410 	OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "[\n");	/* Format Waived */
411 
412 	status = cl_plock_init(&p_osm->lock);
413 	if (status != IB_SUCCESS)
414 		goto Exit;
415 
416 #ifdef HAVE_LIBPTHREAD
417 	pthread_mutex_init(&p_osm->stats.mutex, NULL);
418 	pthread_cond_init(&p_osm->stats.cond, NULL);
419 #else
420 	status = cl_event_init(&p_osm->stats.event, FALSE);
421 	if (status != IB_SUCCESS)
422 		goto Exit;
423 #endif
424 
425 	if (p_opt->single_thread) {
426 		OSM_LOG(&p_osm->log, OSM_LOG_INFO,
427 			"Forcing single threaded dispatcher\n");
428 		status = cl_disp_init(&p_osm->disp, 1, "opensm");
429 	} else {
430 		/*
431 		 * Normal behavior is to initialize the dispatcher with
432 		 * one thread per CPU, as specified by a thread count of '0'.
433 		 */
434 		status = cl_disp_init(&p_osm->disp, 0, "opensm");
435 	}
436 	if (status != IB_SUCCESS)
437 		goto Exit;
438 
439 	/* Unless OpenSM runs in single threaded mode, we create new single
440 	 * threaded dispatcher for SA Set and Delete requets.
441 	 */
442 	p_osm->sa_set_disp_initialized = FALSE;
443 	if (!p_opt->single_thread) {
444 		status = cl_disp_init(&p_osm->sa_set_disp, 1, "subnadmin_set");
445 		if (status != IB_SUCCESS)
446 			goto Exit;
447 		p_osm->sa_set_disp_initialized = TRUE;
448 	}
449 
450 	/* the DB is in use by subn so init before */
451 	status = osm_db_init(&p_osm->db, &p_osm->log);
452 	if (status != IB_SUCCESS)
453 		goto Exit;
454 
455 	status = osm_subn_init(&p_osm->subn, p_osm, p_opt);
456 	if (status != IB_SUCCESS)
457 		goto Exit;
458 
459 	p_osm->p_vendor =
460 	    osm_vendor_new(&p_osm->log, p_opt->transaction_timeout);
461 	if (p_osm->p_vendor == NULL)
462 		status = IB_INSUFFICIENT_RESOURCES;
463 
464 Exit:
465 	OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n");	/* Format Waived */
466 	return status;
467 }
468 
osm_opensm_init_finish(IN osm_opensm_t * p_osm,IN const osm_subn_opt_t * p_opt)469 ib_api_status_t osm_opensm_init_finish(IN osm_opensm_t * p_osm,
470 				       IN const osm_subn_opt_t * p_opt)
471 {
472 	ib_api_status_t status;
473 
474 	osm_opensm_construct_finish(p_osm);
475 
476 	p_osm->subn.sm_port_guid = p_opt->guid;
477 
478 	status = osm_mad_pool_init(&p_osm->mad_pool);
479 	if (status != IB_SUCCESS)
480 		goto Exit;
481 
482 	status = osm_vl15_init(&p_osm->vl15, p_osm->p_vendor,
483 			       &p_osm->log, &p_osm->stats, &p_osm->subn,
484 			       p_opt->max_wire_smps, p_opt->max_wire_smps2,
485 			       p_opt->max_smps_timeout);
486 	if (status != IB_SUCCESS)
487 		goto Exit;
488 
489 	status = osm_sm_init(&p_osm->sm, &p_osm->subn, &p_osm->db,
490 			     p_osm->p_vendor, &p_osm->mad_pool, &p_osm->vl15,
491 			     &p_osm->log, &p_osm->stats, &p_osm->disp,
492 			     &p_osm->lock);
493 	if (status != IB_SUCCESS)
494 		goto Exit;
495 
496 	status = osm_sa_init(&p_osm->sm, &p_osm->sa, &p_osm->subn,
497 			     p_osm->p_vendor, &p_osm->mad_pool, &p_osm->log,
498 			     &p_osm->stats, &p_osm->disp,
499 			     p_opt->single_thread ? NULL : &p_osm->sa_set_disp,
500 			     &p_osm->lock);
501 	if (status != IB_SUCCESS)
502 		goto Exit;
503 
504 	cl_qlist_init(&p_osm->plugin_list);
505 
506 	if (p_opt->event_plugin_name)
507 		load_plugins(p_osm, p_opt->event_plugin_name);
508 
509 #ifdef ENABLE_OSM_PERF_MGR
510 	status = osm_perfmgr_init(&p_osm->perfmgr, p_osm, p_opt);
511 	if (status != IB_SUCCESS)
512 		goto Exit;
513 #endif				/* ENABLE_OSM_PERF_MGR */
514 
515 	status = osm_congestion_control_init(&p_osm->cc,
516 					     p_osm, p_opt);
517 	if (status != IB_SUCCESS)
518 		goto Exit;
519 
520 	p_osm->no_fallback_routing_engine = FALSE;
521 
522 	setup_routing_engines(p_osm, p_opt->routing_engine_names);
523 
524 	p_osm->routing_engine_used = NULL /* OSM_ROUTING_ENGINE_TYPE_NONE */;
525 
526 	p_osm->node_name_map = open_node_name_map(p_opt->node_name_map_name);
527 
528 Exit:
529 	OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n");	/* Format Waived */
530 	return status;
531 }
532 
osm_opensm_bind(IN osm_opensm_t * p_osm,IN ib_net64_t guid)533 ib_api_status_t osm_opensm_bind(IN osm_opensm_t * p_osm, IN ib_net64_t guid)
534 {
535 	ib_api_status_t status;
536 
537 	OSM_LOG_ENTER(&p_osm->log);
538 
539 	status = osm_sm_bind(&p_osm->sm, guid);
540 	if (status != IB_SUCCESS)
541 		goto Exit;
542 
543 	status = osm_sa_bind(&p_osm->sa, guid);
544 	if (status != IB_SUCCESS)
545 		goto Exit;
546 
547 #ifdef ENABLE_OSM_PERF_MGR
548 	status = osm_perfmgr_bind(&p_osm->perfmgr, guid);
549 	if (status != IB_SUCCESS)
550 		goto Exit;
551 #endif				/* ENABLE_OSM_PERF_MGR */
552 
553 	status = osm_congestion_control_bind(&p_osm->cc, guid);
554 	if (status != IB_SUCCESS)
555 		goto Exit;
556 
557 	/* setting IS_SM in capability mask */
558 	OSM_LOG(&p_osm->log, OSM_LOG_INFO, "Setting IS_SM on port 0x%016" PRIx64 "\n",
559 			cl_ntoh64(guid));
560 	osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, TRUE);
561 
562 Exit:
563 	OSM_LOG_EXIT(&p_osm->log);
564 	return status;
565 }
566 
osm_opensm_report_event(osm_opensm_t * osm,osm_epi_event_id_t event_id,void * event_data)567 void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id,
568 			     void *event_data)
569 {
570 	cl_list_item_t *item;
571 
572 	for (item = cl_qlist_head(&osm->plugin_list);
573 	     !osm_exit_flag && item != cl_qlist_end(&osm->plugin_list);
574 	     item = cl_qlist_next(item)) {
575 		osm_epi_plugin_t *p = (osm_epi_plugin_t *)item;
576 		if (p->impl->report)
577 			p->impl->report(p->plugin_data, event_id, event_data);
578 	}
579 }
580