1321936Shselasky/*
2321936Shselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3321936Shselasky * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5321936Shselasky * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
6321936Shselasky *
7321936Shselasky * This software is available to you under a choice of one of two
8321936Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
9321936Shselasky * General Public License (GPL) Version 2, available from the file
10321936Shselasky * COPYING in the main directory of this source tree, or the
11321936Shselasky * OpenIB.org BSD license below:
12321936Shselasky *
13321936Shselasky *     Redistribution and use in source and binary forms, with or
14321936Shselasky *     without modification, are permitted provided that the following
15321936Shselasky *     conditions are met:
16321936Shselasky *
17321936Shselasky *      - Redistributions of source code must retain the above
18321936Shselasky *        copyright notice, this list of conditions and the following
19321936Shselasky *        disclaimer.
20321936Shselasky *
21321936Shselasky *      - Redistributions in binary form must reproduce the above
22321936Shselasky *        copyright notice, this list of conditions and the following
23321936Shselasky *        disclaimer in the documentation and/or other materials
24321936Shselasky *        provided with the distribution.
25321936Shselasky *
26321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33321936Shselasky * SOFTWARE.
34321936Shselasky *
35321936Shselasky */
36321936Shselasky
37321936Shselasky/*
38321936Shselasky * Abstract:
39321936Shselasky *    Implementation of osm_sm_t.
40321936Shselasky * This object represents the SM Receiver object.
41321936Shselasky * This object is part of the opensm family of objects.
42321936Shselasky */
43321936Shselasky
44321936Shselasky#if HAVE_CONFIG_H
45321936Shselasky#  include <config.h>
46321936Shselasky#endif				/* HAVE_CONFIG_H */
47321936Shselasky
48321936Shselasky#include <stdlib.h>
49321936Shselasky#include <string.h>
50321936Shselasky#include <iba/ib_types.h>
51321936Shselasky#include <complib/cl_qmap.h>
52321936Shselasky#include <complib/cl_passivelock.h>
53321936Shselasky#include <complib/cl_debug.h>
54321936Shselasky#include <complib/cl_thread.h>
55321936Shselasky#include <opensm/osm_file_ids.h>
56321936Shselasky#define FILE_ID OSM_FILE_SM_C
57321936Shselasky#include <opensm/osm_sm.h>
58321936Shselasky#include <opensm/osm_madw.h>
59321936Shselasky#include <opensm/osm_log.h>
60321936Shselasky#include <opensm/osm_node.h>
61321936Shselasky#include <opensm/osm_msgdef.h>
62321936Shselasky#include <opensm/osm_perfmgr.h>
63321936Shselasky#include <opensm/osm_opensm.h>
64321936Shselasky
65321936Shselasky#define  OSM_SM_INITIAL_TID_VALUE 0x1233
66321936Shselasky
67321936Shselaskyextern void osm_lft_rcv_process(IN void *context, IN void *data);
68321936Shselaskyextern void osm_mft_rcv_process(IN void *context, IN void *data);
69321936Shselaskyextern void osm_nd_rcv_process(IN void *context, IN void *data);
70321936Shselaskyextern void osm_ni_rcv_process(IN void *context, IN void *data);
71321936Shselaskyextern void osm_pkey_rcv_process(IN void *context, IN void *data);
72321936Shselaskyextern void osm_pi_rcv_process(IN void *context, IN void *data);
73321936Shselaskyextern void osm_gi_rcv_process(IN void *context, IN void *data);
74321936Shselaskyextern void osm_slvl_rcv_process(IN void *context, IN void *p_data);
75321936Shselaskyextern void osm_sminfo_rcv_process(IN void *context, IN void *data);
76321936Shselaskyextern void osm_si_rcv_process(IN void *context, IN void *data);
77321936Shselaskyextern void osm_trap_rcv_process(IN void *context, IN void *data);
78321936Shselaskyextern void osm_vla_rcv_process(IN void *context, IN void *data);
79321936Shselaskyextern void osm_mlnx_epi_rcv_process(IN void *context, IN void *data);
80321936Shselasky
81321936Shselaskyextern void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal);
82321936Shselaskyextern void osm_sm_state_mgr_polling_callback(IN void *context);
83321936Shselasky
84321936Shselaskystatic void sm_process(osm_sm_t * sm, osm_signal_t signal)
85321936Shselasky{
86321936Shselasky#ifdef ENABLE_OSM_PERF_MGR
87321936Shselasky	if (signal == OSM_SIGNAL_PERFMGR_SWEEP)
88321936Shselasky		osm_perfmgr_process(&sm->p_subn->p_osm->perfmgr);
89321936Shselasky	else
90321936Shselasky#endif
91321936Shselasky		osm_state_mgr_process(sm, signal);
92321936Shselasky}
93321936Shselasky
94321936Shselaskystatic void sm_sweeper(IN void *p_ptr)
95321936Shselasky{
96321936Shselasky	ib_api_status_t status;
97321936Shselasky	osm_sm_t * p_sm = p_ptr;
98321936Shselasky	unsigned signals, i;
99321936Shselasky
100321936Shselasky	OSM_LOG_ENTER(p_sm->p_log);
101321936Shselasky
102321936Shselasky	while (p_sm->thread_state == OSM_THREAD_STATE_RUN) {
103321936Shselasky		/*
104321936Shselasky		 * Wait on the event with a timeout.
105321936Shselasky		 * Sweeps may be initiated "off schedule" by simply
106321936Shselasky		 * signaling the event.
107321936Shselasky		 */
108321936Shselasky		status = cl_event_wait_on(&p_sm->signal_event,
109321936Shselasky					  EVENT_NO_TIMEOUT, TRUE);
110321936Shselasky
111321936Shselasky		if (status == CL_SUCCESS)
112321936Shselasky			OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG,
113321936Shselasky				"Off schedule sweep signalled\n");
114321936Shselasky		else {
115321936Shselasky			OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E01: "
116321936Shselasky				"Event wait failed (%s)\n",
117321936Shselasky				CL_STATUS_MSG(status));
118321936Shselasky			continue;
119321936Shselasky		}
120321936Shselasky
121321936Shselasky		if (osm_exit_flag)
122321936Shselasky			break;
123321936Shselasky
124321936Shselasky		cl_spinlock_acquire(&p_sm->signal_lock);
125321936Shselasky		signals = p_sm->signal_mask;
126321936Shselasky		p_sm->signal_mask = 0;
127321936Shselasky		cl_spinlock_release(&p_sm->signal_lock);
128321936Shselasky
129321936Shselasky		for (i = 0; signals; signals >>= 1, i++)
130321936Shselasky			if (signals & 1)
131321936Shselasky				sm_process(p_sm, i);
132321936Shselasky	}
133321936Shselasky
134321936Shselasky	OSM_LOG_EXIT(p_sm->p_log);
135321936Shselasky}
136321936Shselasky
137321936Shselaskystatic void sm_sweep(void *arg)
138321936Shselasky{
139321936Shselasky	osm_sm_t *sm = arg;
140321936Shselasky
141321936Shselasky	/*  do the sweep only if we are in MASTER state */
142321936Shselasky	if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER ||
143321936Shselasky	    sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING)
144321936Shselasky		osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
145321936Shselasky	cl_timer_start(&sm->sweep_timer, sm->p_subn->opt.sweep_interval * 1000);
146321936Shselasky}
147321936Shselasky
148321936Shselaskystatic void sweep_fail_process(IN void *context, IN void *p_data)
149321936Shselasky{
150321936Shselasky	osm_sm_t *sm = context;
151321936Shselasky
152321936Shselasky	OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "light sweep failed\n");
153321936Shselasky	sm->p_subn->force_heavy_sweep = TRUE;
154321936Shselasky}
155321936Shselasky
156321936Shselaskyvoid osm_sm_construct(IN osm_sm_t * p_sm)
157321936Shselasky{
158321936Shselasky	memset(p_sm, 0, sizeof(*p_sm));
159321936Shselasky	p_sm->thread_state = OSM_THREAD_STATE_NONE;
160321936Shselasky	p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE;
161321936Shselasky	cl_spinlock_construct(&p_sm->signal_lock);
162321936Shselasky	cl_spinlock_construct(&p_sm->state_lock);
163321936Shselasky	cl_timer_construct(&p_sm->polling_timer);
164321936Shselasky	cl_event_construct(&p_sm->signal_event);
165321936Shselasky	cl_event_construct(&p_sm->subnet_up_event);
166321936Shselasky	cl_event_wheel_construct(&p_sm->trap_aging_tracker);
167321936Shselasky	cl_thread_construct(&p_sm->sweeper);
168321936Shselasky	osm_sm_mad_ctrl_construct(&p_sm->mad_ctrl);
169321936Shselasky	osm_lid_mgr_construct(&p_sm->lid_mgr);
170321936Shselasky	osm_ucast_mgr_construct(&p_sm->ucast_mgr);
171321936Shselasky}
172321936Shselasky
173321936Shselaskyvoid osm_sm_shutdown(IN osm_sm_t * p_sm)
174321936Shselasky{
175321936Shselasky	boolean_t signal_event = FALSE;
176321936Shselasky
177321936Shselasky	OSM_LOG_ENTER(p_sm->p_log);
178321936Shselasky
179321936Shselasky	/*
180321936Shselasky	 * Signal our threads that we're leaving.
181321936Shselasky	 */
182321936Shselasky	if (p_sm->thread_state != OSM_THREAD_STATE_NONE)
183321936Shselasky		signal_event = TRUE;
184321936Shselasky
185321936Shselasky	p_sm->thread_state = OSM_THREAD_STATE_EXIT;
186321936Shselasky
187321936Shselasky	/*
188321936Shselasky	 * Don't trigger unless event has been initialized.
189321936Shselasky	 * Destroy the thread before we tear down the other objects.
190321936Shselasky	 */
191321936Shselasky	if (signal_event)
192321936Shselasky		cl_event_signal(&p_sm->signal_event);
193321936Shselasky
194321936Shselasky	cl_timer_stop(&p_sm->polling_timer);
195321936Shselasky	cl_timer_stop(&p_sm->sweep_timer);
196321936Shselasky	cl_thread_destroy(&p_sm->sweeper);
197321936Shselasky
198321936Shselasky	/*
199321936Shselasky	 * Always destroy controllers before the corresponding
200321936Shselasky	 * receiver to guarantee that all callbacks from the
201321936Shselasky	 * dispatcher are complete.
202321936Shselasky	 */
203321936Shselasky	osm_sm_mad_ctrl_destroy(&p_sm->mad_ctrl);
204321936Shselasky	cl_disp_unregister(p_sm->ni_disp_h);
205321936Shselasky	cl_disp_unregister(p_sm->pi_disp_h);
206321936Shselasky	cl_disp_unregister(p_sm->gi_disp_h);
207321936Shselasky	cl_disp_unregister(p_sm->si_disp_h);
208321936Shselasky	cl_disp_unregister(p_sm->nd_disp_h);
209321936Shselasky	cl_disp_unregister(p_sm->lft_disp_h);
210321936Shselasky	cl_disp_unregister(p_sm->mft_disp_h);
211321936Shselasky	cl_disp_unregister(p_sm->sm_info_disp_h);
212321936Shselasky	cl_disp_unregister(p_sm->trap_disp_h);
213321936Shselasky	cl_disp_unregister(p_sm->slvl_disp_h);
214321936Shselasky	cl_disp_unregister(p_sm->vla_disp_h);
215321936Shselasky	cl_disp_unregister(p_sm->pkey_disp_h);
216321936Shselasky	cl_disp_unregister(p_sm->mlnx_epi_disp_h);
217321936Shselasky	cl_disp_unregister(p_sm->sweep_fail_disp_h);
218321936Shselasky
219321936Shselasky	OSM_LOG_EXIT(p_sm->p_log);
220321936Shselasky}
221321936Shselasky
222321936Shselaskyvoid osm_sm_destroy(IN osm_sm_t * p_sm)
223321936Shselasky{
224321936Shselasky	OSM_LOG_ENTER(p_sm->p_log);
225321936Shselasky	osm_lid_mgr_destroy(&p_sm->lid_mgr);
226321936Shselasky	osm_ucast_mgr_destroy(&p_sm->ucast_mgr);
227321936Shselasky	cl_event_wheel_destroy(&p_sm->trap_aging_tracker);
228321936Shselasky	cl_timer_destroy(&p_sm->sweep_timer);
229321936Shselasky	cl_timer_destroy(&p_sm->polling_timer);
230321936Shselasky	cl_event_destroy(&p_sm->signal_event);
231321936Shselasky	cl_event_destroy(&p_sm->subnet_up_event);
232321936Shselasky	cl_spinlock_destroy(&p_sm->signal_lock);
233321936Shselasky	cl_spinlock_destroy(&p_sm->state_lock);
234321936Shselasky	free(p_sm->mlids_req);
235321936Shselasky
236321936Shselasky	osm_log_v2(p_sm->p_log, OSM_LOG_SYS, FILE_ID, "Exiting SM\n");	/* Format Waived */
237321936Shselasky	OSM_LOG_EXIT(p_sm->p_log);
238321936Shselasky}
239321936Shselasky
240321936Shselaskyib_api_status_t osm_sm_init(IN osm_sm_t * p_sm, IN osm_subn_t * p_subn,
241321936Shselasky			    IN osm_db_t * p_db, IN osm_vendor_t * p_vendor,
242321936Shselasky			    IN osm_mad_pool_t * p_mad_pool,
243321936Shselasky			    IN osm_vl15_t * p_vl15, IN osm_log_t * p_log,
244321936Shselasky			    IN osm_stats_t * p_stats,
245321936Shselasky			    IN cl_dispatcher_t * p_disp, IN cl_plock_t * p_lock)
246321936Shselasky{
247321936Shselasky	ib_api_status_t status;
248321936Shselasky
249321936Shselasky	OSM_LOG_ENTER(p_log);
250321936Shselasky
251321936Shselasky	p_sm->p_subn = p_subn;
252321936Shselasky	p_sm->p_db = p_db;
253321936Shselasky	p_sm->p_vendor = p_vendor;
254321936Shselasky	p_sm->p_mad_pool = p_mad_pool;
255321936Shselasky	p_sm->p_vl15 = p_vl15;
256321936Shselasky	p_sm->p_log = p_log;
257321936Shselasky	p_sm->p_disp = p_disp;
258321936Shselasky	p_sm->p_lock = p_lock;
259321936Shselasky
260321936Shselasky	status = cl_spinlock_init(&p_sm->signal_lock);
261321936Shselasky	if (status != CL_SUCCESS)
262321936Shselasky		goto Exit;
263321936Shselasky
264321936Shselasky	status = cl_spinlock_init(&p_sm->state_lock);
265321936Shselasky	if (status != CL_SUCCESS)
266321936Shselasky		goto Exit;
267321936Shselasky
268321936Shselasky	status = cl_event_init(&p_sm->signal_event, FALSE);
269321936Shselasky	if (status != CL_SUCCESS)
270321936Shselasky		goto Exit;
271321936Shselasky
272321936Shselasky	status = cl_event_init(&p_sm->subnet_up_event, FALSE);
273321936Shselasky	if (status != CL_SUCCESS)
274321936Shselasky		goto Exit;
275321936Shselasky
276321936Shselasky	status = cl_timer_init(&p_sm->sweep_timer, sm_sweep, p_sm);
277321936Shselasky	if (status != CL_SUCCESS)
278321936Shselasky		goto Exit;
279321936Shselasky
280321936Shselasky	status = cl_timer_init(&p_sm->polling_timer,
281321936Shselasky			       osm_sm_state_mgr_polling_callback, p_sm);
282321936Shselasky	if (status != CL_SUCCESS)
283321936Shselasky		goto Exit;
284321936Shselasky
285321936Shselasky	p_sm->mlids_req_max = 0;
286321936Shselasky	p_sm->mlids_req = malloc((IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO +
287321936Shselasky				  1) * sizeof(p_sm->mlids_req[0]));
288321936Shselasky	if (!p_sm->mlids_req)
289321936Shselasky		goto Exit;
290321936Shselasky	memset(p_sm->mlids_req, 0,
291321936Shselasky	       (IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO +
292321936Shselasky		1) * sizeof(p_sm->mlids_req[0]));
293321936Shselasky
294321936Shselasky	status = osm_sm_mad_ctrl_init(&p_sm->mad_ctrl, p_sm->p_subn,
295321936Shselasky				      p_sm->p_mad_pool, p_sm->p_vl15,
296321936Shselasky				      p_sm->p_vendor,
297321936Shselasky				      p_log, p_stats, p_lock, p_disp);
298321936Shselasky	if (status != IB_SUCCESS)
299321936Shselasky		goto Exit;
300321936Shselasky
301321936Shselasky	status = cl_event_wheel_init(&p_sm->trap_aging_tracker);
302321936Shselasky	if (status != IB_SUCCESS)
303321936Shselasky		goto Exit;
304321936Shselasky
305321936Shselasky	status = osm_lid_mgr_init(&p_sm->lid_mgr, p_sm);
306321936Shselasky	if (status != IB_SUCCESS)
307321936Shselasky		goto Exit;
308321936Shselasky
309321936Shselasky	status = osm_ucast_mgr_init(&p_sm->ucast_mgr, p_sm);
310321936Shselasky	if (status != IB_SUCCESS)
311321936Shselasky		goto Exit;
312321936Shselasky
313321936Shselasky	status = IB_INSUFFICIENT_RESOURCES;
314321936Shselasky	p_sm->sweep_fail_disp_h = cl_disp_register(p_disp,
315321936Shselasky						   OSM_MSG_LIGHT_SWEEP_FAIL,
316321936Shselasky						   sweep_fail_process, p_sm);
317321936Shselasky	if (p_sm->sweep_fail_disp_h == CL_DISP_INVALID_HANDLE)
318321936Shselasky		goto Exit;
319321936Shselasky
320321936Shselasky	p_sm->ni_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_INFO,
321321936Shselasky					   osm_ni_rcv_process, p_sm);
322321936Shselasky	if (p_sm->ni_disp_h == CL_DISP_INVALID_HANDLE)
323321936Shselasky		goto Exit;
324321936Shselasky
325321936Shselasky	p_sm->pi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORT_INFO,
326321936Shselasky					   osm_pi_rcv_process, p_sm);
327321936Shselasky	if (p_sm->pi_disp_h == CL_DISP_INVALID_HANDLE)
328321936Shselasky		goto Exit;
329321936Shselasky
330321936Shselasky	p_sm->gi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUID_INFO,
331321936Shselasky					   osm_gi_rcv_process, p_sm);
332321936Shselasky	if (p_sm->gi_disp_h == CL_DISP_INVALID_HANDLE)
333321936Shselasky		goto Exit;
334321936Shselasky
335321936Shselasky	p_sm->si_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO,
336321936Shselasky					   osm_si_rcv_process, p_sm);
337321936Shselasky	if (p_sm->si_disp_h == CL_DISP_INVALID_HANDLE)
338321936Shselasky		goto Exit;
339321936Shselasky
340321936Shselasky	p_sm->nd_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_DESC,
341321936Shselasky					   osm_nd_rcv_process, p_sm);
342321936Shselasky	if (p_sm->nd_disp_h == CL_DISP_INVALID_HANDLE)
343321936Shselasky		goto Exit;
344321936Shselasky
345321936Shselasky	p_sm->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT,
346321936Shselasky					    osm_lft_rcv_process, p_sm);
347321936Shselasky	if (p_sm->lft_disp_h == CL_DISP_INVALID_HANDLE)
348321936Shselasky		goto Exit;
349321936Shselasky
350321936Shselasky	p_sm->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT,
351321936Shselasky					    osm_mft_rcv_process, p_sm);
352321936Shselasky	if (p_sm->mft_disp_h == CL_DISP_INVALID_HANDLE)
353321936Shselasky		goto Exit;
354321936Shselasky
355321936Shselasky	p_sm->sm_info_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SM_INFO,
356321936Shselasky						osm_sminfo_rcv_process, p_sm);
357321936Shselasky	if (p_sm->sm_info_disp_h == CL_DISP_INVALID_HANDLE)
358321936Shselasky		goto Exit;
359321936Shselasky
360321936Shselasky	p_sm->trap_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NOTICE,
361321936Shselasky					     osm_trap_rcv_process, p_sm);
362321936Shselasky	if (p_sm->trap_disp_h == CL_DISP_INVALID_HANDLE)
363321936Shselasky		goto Exit;
364321936Shselasky
365321936Shselasky	p_sm->slvl_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SLVL,
366321936Shselasky					     osm_slvl_rcv_process, p_sm);
367321936Shselasky	if (p_sm->slvl_disp_h == CL_DISP_INVALID_HANDLE)
368321936Shselasky		goto Exit;
369321936Shselasky
370321936Shselasky	p_sm->vla_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB,
371321936Shselasky					    osm_vla_rcv_process, p_sm);
372321936Shselasky	if (p_sm->vla_disp_h == CL_DISP_INVALID_HANDLE)
373321936Shselasky		goto Exit;
374321936Shselasky
375321936Shselasky	p_sm->pkey_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PKEY,
376321936Shselasky					     osm_pkey_rcv_process, p_sm);
377321936Shselasky	if (p_sm->pkey_disp_h == CL_DISP_INVALID_HANDLE)
378321936Shselasky		goto Exit;
379321936Shselasky
380321936Shselasky	p_sm->mlnx_epi_disp_h = cl_disp_register(p_disp,
381321936Shselasky						 OSM_MSG_MAD_MLNX_EXT_PORT_INFO,
382321936Shselasky						 osm_mlnx_epi_rcv_process, p_sm);
383321936Shselasky	if (p_sm->mlnx_epi_disp_h == CL_DISP_INVALID_HANDLE)
384321936Shselasky		goto Exit;
385321936Shselasky
386321936Shselasky	p_subn->sm_state = p_subn->opt.sm_inactive ?
387321936Shselasky	    IB_SMINFO_STATE_NOTACTIVE : IB_SMINFO_STATE_DISCOVERING;
388321936Shselasky	osm_report_sm_state(p_sm);
389321936Shselasky
390321936Shselasky	/*
391321936Shselasky	 * Now that the component objects are initialized, start
392321936Shselasky	 * the sweeper thread if the user wants sweeping.
393321936Shselasky	 */
394321936Shselasky	p_sm->thread_state = OSM_THREAD_STATE_RUN;
395321936Shselasky	status = cl_thread_init(&p_sm->sweeper, sm_sweeper, p_sm,
396321936Shselasky				"opensm sweeper");
397321936Shselasky	if (status != IB_SUCCESS)
398321936Shselasky		goto Exit;
399321936Shselasky
400321936Shselasky	if (p_sm->p_subn->opt.sweep_interval)
401321936Shselasky		cl_timer_start(&p_sm->sweep_timer,
402321936Shselasky			       p_sm->p_subn->opt.sweep_interval * 1000);
403321936Shselasky
404321936ShselaskyExit:
405321936Shselasky	OSM_LOG_EXIT(p_log);
406321936Shselasky	return status;
407321936Shselasky}
408321936Shselasky
409321936Shselaskyvoid osm_sm_signal(osm_sm_t * p_sm, osm_signal_t signal)
410321936Shselasky{
411321936Shselasky	cl_spinlock_acquire(&p_sm->signal_lock);
412321936Shselasky	p_sm->signal_mask |= 1 << signal;
413321936Shselasky	cl_event_signal(&p_sm->signal_event);
414321936Shselasky	cl_spinlock_release(&p_sm->signal_lock);
415321936Shselasky}
416321936Shselasky
417321936Shselaskyvoid osm_sm_sweep(IN osm_sm_t * p_sm)
418321936Shselasky{
419321936Shselasky	OSM_LOG_ENTER(p_sm->p_log);
420321936Shselasky	osm_sm_signal(p_sm, OSM_SIGNAL_SWEEP);
421321936Shselasky	OSM_LOG_EXIT(p_sm->p_log);
422321936Shselasky}
423321936Shselasky
424321936Shselaskyib_api_status_t osm_sm_bind(IN osm_sm_t * p_sm, IN ib_net64_t port_guid)
425321936Shselasky{
426321936Shselasky	ib_api_status_t status;
427321936Shselasky
428321936Shselasky	OSM_LOG_ENTER(p_sm->p_log);
429321936Shselasky
430321936Shselasky	status = osm_sm_mad_ctrl_bind(&p_sm->mad_ctrl, port_guid);
431321936Shselasky
432321936Shselasky	if (status != IB_SUCCESS) {
433321936Shselasky		OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E10: "
434321936Shselasky			"SM MAD Controller bind failed (%s)\n",
435321936Shselasky			ib_get_err_str(status));
436321936Shselasky		goto Exit;
437321936Shselasky	}
438321936Shselasky
439321936ShselaskyExit:
440321936Shselasky	OSM_LOG_EXIT(p_sm->p_log);
441321936Shselasky	return status;
442321936Shselasky}
443321936Shselasky
444321936Shselaskyvoid osm_sm_reroute_mlid(osm_sm_t * sm, ib_net16_t mlid)
445321936Shselasky{
446321936Shselasky	mlid = cl_ntoh16(mlid) - IB_LID_MCAST_START_HO;
447321936Shselasky	sm->mlids_req[mlid] = 1;
448321936Shselasky	if (sm->mlids_req_max < mlid)
449321936Shselasky		sm->mlids_req_max = mlid;
450321936Shselasky	osm_sm_signal(sm, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST);
451321936Shselasky	OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "rerouting requested for MLID 0x%x\n",
452321936Shselasky		mlid + IB_LID_MCAST_START_HO);
453321936Shselasky}
454321936Shselasky
455321936Shselaskyvoid osm_set_sm_priority(osm_sm_t * sm, uint8_t priority)
456321936Shselasky{
457321936Shselasky	uint8_t old_pri = sm->p_subn->opt.sm_priority;
458321936Shselasky
459321936Shselasky	sm->p_subn->opt.sm_priority = priority;
460321936Shselasky
461321936Shselasky	if (old_pri < priority &&
462321936Shselasky	    sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY)
463321936Shselasky		osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE);
464321936Shselasky}
465