1/*
2 * Copyright (c) 2004-2009 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) 2009 HNR Consulting. 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_sa_mad_ctrl_t.
40 * This object is part of the SA object.
41 */
42
43#if HAVE_CONFIG_H
44#  include <config.h>
45#endif				/* HAVE_CONFIG_H */
46
47#include <string.h>
48#include <complib/cl_debug.h>
49#include <iba/ib_types.h>
50#include <opensm/osm_file_ids.h>
51#define FILE_ID OSM_FILE_SA_MAD_CTRL_C
52#include <vendor/osm_vendor_api.h>
53#include <opensm/osm_sa_mad_ctrl.h>
54#include <opensm/osm_msgdef.h>
55#include <opensm/osm_helper.h>
56#include <opensm/osm_sa.h>
57#include <opensm/osm_opensm.h>
58
59/****f* opensm: SA/sa_mad_ctrl_disp_done_callback
60 * NAME
61 * sa_mad_ctrl_disp_done_callback
62 *
63 * DESCRIPTION
64 * This function is the Dispatcher callback that indicates
65 * a received MAD has been processed by the recipient.
66 *
67 * SYNOPSIS
68 */
69static void sa_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data)
70{
71	osm_sa_mad_ctrl_t *p_ctrl = context;
72	osm_madw_t *p_madw = p_data;
73
74	OSM_LOG_ENTER(p_ctrl->p_log);
75
76	CL_ASSERT(p_madw);
77	/*
78	   Return the MAD & wrapper to the pool.
79	 */
80	osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
81	OSM_LOG_EXIT(p_ctrl->p_log);
82}
83
84/************/
85
86/****f* opensm: SA/sa_mad_ctrl_process
87 * NAME
88 * sa_mad_ctrl_process
89 *
90 * DESCRIPTION
91 * This function handles known methods for received MADs.
92 *
93 * SYNOPSIS
94 */
95static void sa_mad_ctrl_process(IN osm_sa_mad_ctrl_t * p_ctrl,
96				IN osm_madw_t * p_madw,
97				IN boolean_t is_get_request)
98{
99	ib_sa_mad_t *p_sa_mad;
100	cl_disp_reg_handle_t h_disp;
101	cl_status_t status;
102	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
103	uint64_t last_dispatched_msg_queue_time_msec;
104	uint32_t num_messages;
105
106	OSM_LOG_ENTER(p_ctrl->p_log);
107
108	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
109
110	/*
111	   If the dispatcher is showing us that it is overloaded
112	   there is no point in placing the request in. We should instead
113	   provide immediate response - IB_RESOURCE_BUSY
114	   But how do we know?
115	   The dispatcher reports back the number of outstanding messages and
116	   the time the last message stayed in the queue.
117	   HACK: Actually, we cannot send a mad from within the receive callback;
118	   thus - we will just drop it.
119	 */
120
121	if (!is_get_request && p_ctrl->p_set_disp) {
122		h_disp = p_ctrl->h_set_disp;
123		goto SKIP_QUEUE_CHECK;
124	}
125
126	h_disp = p_ctrl->h_disp;
127	cl_disp_get_queue_status(h_disp, &num_messages,
128				 &last_dispatched_msg_queue_time_msec);
129
130	if (num_messages > 1 && p_ctrl->p_subn->opt.max_msg_fifo_timeout &&
131	    last_dispatched_msg_queue_time_msec >
132	    p_ctrl->p_subn->opt.max_msg_fifo_timeout) {
133		OSM_LOG(p_ctrl->p_log, OSM_LOG_INFO,
134			/*             "Responding BUSY status since the dispatcher is already" */
135			"Dropping MAD since the dispatcher is already"
136			" overloaded with %u messages and queue time of:"
137			"%" PRIu64 "[msec]\n",
138			num_messages, last_dispatched_msg_queue_time_msec);
139
140		/* send a busy response */
141		/* osm_sa_send_error(p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY); */
142
143		/* return the request to the pool */
144		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
145
146		goto Exit;
147	}
148
149SKIP_QUEUE_CHECK:
150	/*
151	   Note that attr_id (like the rest of the MAD) is in
152	   network byte order.
153	 */
154	switch (p_sa_mad->attr_id) {
155	case IB_MAD_ATTR_CLASS_PORT_INFO:
156		msg_id = OSM_MSG_MAD_CLASS_PORT_INFO;
157		break;
158
159	case IB_MAD_ATTR_NODE_RECORD:
160		msg_id = OSM_MSG_MAD_NODE_RECORD;
161		break;
162
163	case IB_MAD_ATTR_PORTINFO_RECORD:
164		msg_id = OSM_MSG_MAD_PORTINFO_RECORD;
165		break;
166
167	case IB_MAD_ATTR_LINK_RECORD:
168		msg_id = OSM_MSG_MAD_LINK_RECORD;
169		break;
170
171	case IB_MAD_ATTR_SMINFO_RECORD:
172		msg_id = OSM_MSG_MAD_SMINFO_RECORD;
173		break;
174
175	case IB_MAD_ATTR_SERVICE_RECORD:
176		msg_id = OSM_MSG_MAD_SERVICE_RECORD;
177		break;
178
179	case IB_MAD_ATTR_PATH_RECORD:
180		msg_id = OSM_MSG_MAD_PATH_RECORD;
181		break;
182
183	case IB_MAD_ATTR_MCMEMBER_RECORD:
184		msg_id = OSM_MSG_MAD_MCMEMBER_RECORD;
185		break;
186
187	case IB_MAD_ATTR_INFORM_INFO:
188		msg_id = OSM_MSG_MAD_INFORM_INFO;
189		break;
190
191	case IB_MAD_ATTR_VLARB_RECORD:
192		msg_id = OSM_MSG_MAD_VL_ARB_RECORD;
193		break;
194
195	case IB_MAD_ATTR_SLVL_RECORD:
196		msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD;
197		break;
198
199	case IB_MAD_ATTR_PKEY_TBL_RECORD:
200		msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD;
201		break;
202
203	case IB_MAD_ATTR_LFT_RECORD:
204		msg_id = OSM_MSG_MAD_LFT_RECORD;
205		break;
206
207	case IB_MAD_ATTR_GUIDINFO_RECORD:
208		msg_id = OSM_MSG_MAD_GUIDINFO_RECORD;
209		break;
210
211	case IB_MAD_ATTR_INFORM_INFO_RECORD:
212		msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD;
213		break;
214
215	case IB_MAD_ATTR_SWITCH_INFO_RECORD:
216		msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD;
217		break;
218
219	case IB_MAD_ATTR_MFT_RECORD:
220		msg_id = OSM_MSG_MAD_MFT_RECORD;
221		break;
222
223#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
224	case IB_MAD_ATTR_MULTIPATH_RECORD:
225		msg_id = OSM_MSG_MAD_MULTIPATH_RECORD;
226		break;
227#endif
228
229	default:
230		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A01: "
231			"Unsupported attribute 0x%X (%s)\n",
232			cl_ntoh16(p_sa_mad->attr_id),
233			ib_get_sa_attr_str(p_sa_mad->attr_id));
234		osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_ERROR);
235	}
236
237	if (msg_id != CL_DISP_MSGID_NONE) {
238		/*
239		   Post this MAD to the dispatcher for asynchronous
240		   processing by the appropriate controller.
241		 */
242
243		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
244			"Posting Dispatcher message %s\n",
245			osm_get_disp_msg_str(msg_id));
246
247		status = cl_disp_post(h_disp, msg_id, p_madw,
248				      sa_mad_ctrl_disp_done_callback, p_ctrl);
249
250		if (status != CL_SUCCESS) {
251			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A02: "
252				"Dispatcher post message failed (%s) for attribute 0x%X (%s)\n",
253				CL_STATUS_MSG(status),
254				cl_ntoh16(p_sa_mad->attr_id),
255				ib_get_sa_attr_str(p_sa_mad->attr_id));
256
257			osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
258			goto Exit;
259		}
260	} else {
261		/*
262		   There is an unknown MAD attribute type for which there is
263		   no recipient.  Simply retire the MAD here.
264		 */
265		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
266		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
267	}
268
269Exit:
270	OSM_LOG_EXIT(p_ctrl->p_log);
271}
272
273/*
274 * PARAMETERS
275 *
276 * RETURN VALUES
277 *
278 * NOTES
279 *
280 * SEE ALSO
281 *********/
282
283/****f* opensm: SA/sa_mad_ctrl_rcv_callback
284 * NAME
285 * sa_mad_ctrl_rcv_callback
286 *
287 * DESCRIPTION
288 * This is the callback from the transport layer for received MADs.
289 *
290 * SYNOPSIS
291 */
292static void sa_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, IN void *context,
293				     IN osm_madw_t * p_req_madw)
294{
295	osm_sa_mad_ctrl_t *p_ctrl = context;
296	ib_sa_mad_t *p_sa_mad;
297	boolean_t is_get_request = FALSE;
298
299	OSM_LOG_ENTER(p_ctrl->p_log);
300
301	CL_ASSERT(p_madw);
302
303	/*
304	   A MAD was received from the wire, possibly in response to a request.
305	 */
306	cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd);
307
308	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
309		"%u SA MADs received\n", p_ctrl->p_stats->sa_mads_rcvd);
310
311	/*
312	 * C15-0.1.3 requires not responding to any MAD if the SM is
313	 * not in active state!
314	 * We will not respond if the sm_state is not MASTER, or if the
315	 * first_time_master_sweep flag (of the subnet) is TRUE - this
316	 * flag indicates that the master still didn't finish its first
317	 * sweep, so the subnet is not up and stable yet.
318	 */
319	if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
320		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
321		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
322			"Received SA MAD while SM not MASTER. MAD ignored\n");
323		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
324		goto Exit;
325	}
326	if (p_ctrl->p_subn->first_time_master_sweep == TRUE) {
327		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
328		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
329			"Received SA MAD while SM in first sweep. MAD ignored\n");
330		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
331		goto Exit;
332	}
333
334	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
335
336	if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES))
337		osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_FRAMES);
338
339	/*
340	 * C15-0.1.5 - Table 185: SA Header - p884
341	 * SM_key should be either 0 or match the current SM_Key
342	 * otherwise discard the MAD.
343	 */
344	if (p_sa_mad->sm_key != 0 &&
345	    p_sa_mad->sm_key != p_ctrl->p_subn->opt.sa_key) {
346		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A04: "
347			"Non-Zero MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%"
348			PRIx64 "; SA MAD ignored for method 0x%X attribute 0x%X (%s)\n",
349			cl_ntoh64(p_sa_mad->sm_key),
350			cl_ntoh64(p_ctrl->p_subn->opt.sa_key),
351			p_sa_mad->method, cl_ntoh16(p_sa_mad->attr_id),
352			ib_get_sa_attr_str(p_sa_mad->attr_id));
353		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
354		goto Exit;
355	}
356
357	switch (p_sa_mad->method) {
358	case IB_MAD_METHOD_REPORT_RESP:
359		/* we do not really do anything with report responses -
360		   just retire the transaction */
361		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
362			"Received Report Response. Retiring the transaction\n");
363
364		if (p_req_madw)
365			osm_mad_pool_put(p_ctrl->p_mad_pool, p_req_madw);
366		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
367
368		break;
369
370	case IB_MAD_METHOD_GET:
371	case IB_MAD_METHOD_GETTABLE:
372#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
373	case IB_MAD_METHOD_GETMULTI:
374#endif
375		is_get_request = TRUE;
376	case IB_MAD_METHOD_SET:
377	case IB_MAD_METHOD_DELETE:
378		/* if we are closing down simply do nothing */
379		if (osm_exit_flag)
380			osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
381		else
382			sa_mad_ctrl_process(p_ctrl, p_madw, is_get_request);
383		break;
384
385	default:
386		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
387		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A05: "
388			"Unsupported method = 0x%X\n", p_sa_mad->method);
389		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
390		goto Exit;
391	}
392
393Exit:
394	OSM_LOG_EXIT(p_ctrl->p_log);
395}
396
397/*
398 * PARAMETERS
399 *
400 * RETURN VALUES
401 *
402 * NOTES
403 *
404 * SEE ALSO
405 *********/
406
407/****f* opensm: SA/sa_mad_ctrl_send_err_callback
408 * NAME
409 * sa_mad_ctrl_send_err_callback
410 *
411 * DESCRIPTION
412 * This is the callback from the transport layer for send errors
413 * on MADs that were expecting a response.
414 *
415 * SYNOPSIS
416 */
417static void sa_mad_ctrl_send_err_callback(IN void *context,
418					  IN osm_madw_t * p_madw)
419{
420	osm_sa_mad_ctrl_t *p_ctrl = context;
421	cl_status_t status;
422
423	OSM_LOG_ENTER(p_ctrl->p_log);
424
425	/*
426	   We should never be here since the SA never originates a request.
427	   Unless we generated a Report(Notice)
428	 */
429
430	CL_ASSERT(p_madw);
431
432	OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A06: "
433		"MAD completed in error (%s): "
434		"%s(%s), attr_mod 0x%x, LID %u, TID 0x%" PRIx64 "\n",
435		ib_get_err_str(p_madw->status),
436		ib_get_sa_method_str(p_madw->p_mad->method),
437		ib_get_sa_attr_str(p_madw->p_mad->attr_id),
438		cl_ntoh32(p_madw->p_mad->attr_mod),
439		cl_ntoh16(p_madw->mad_addr.dest_lid),
440		cl_ntoh64(p_madw->p_mad->trans_id));
441
442	osm_dump_sa_mad_v2(p_ctrl->p_log, osm_madw_get_sa_mad_ptr(p_madw),
443			   FILE_ID, OSM_LOG_ERROR);
444
445	/*
446	   An error occurred.  No response was received to a request MAD.
447	   Retire the original request MAD.
448	 */
449
450	if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
451		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
452			"Posting Dispatcher message %s\n",
453			osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
454
455		if (p_ctrl->p_set_disp &&
456		    (p_madw->p_mad->method == IB_MAD_METHOD_SET ||
457		     p_madw->p_mad->method == IB_MAD_METHOD_DELETE))
458			status = cl_disp_post(p_ctrl->h_set_disp,
459					      osm_madw_get_err_msg(p_madw),
460					      p_madw,
461					      sa_mad_ctrl_disp_done_callback,
462					      p_ctrl);
463		else
464			status = cl_disp_post(p_ctrl->h_disp,
465					      osm_madw_get_err_msg(p_madw),
466					      p_madw,
467					      sa_mad_ctrl_disp_done_callback,
468					      p_ctrl);
469		if (status != CL_SUCCESS) {
470			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A07: "
471				"Dispatcher post message failed (%s)\n",
472				CL_STATUS_MSG(status));
473		}
474	} else			/* No error message was provided, just retire the MAD. */
475		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
476
477	OSM_LOG_EXIT(p_ctrl->p_log);
478}
479
480/*
481 * PARAMETERS
482 *
483 * RETURN VALUES
484 *
485 * NOTES
486 *
487 * SEE ALSO
488 *********/
489
490void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * p_ctrl)
491{
492	CL_ASSERT(p_ctrl);
493	memset(p_ctrl, 0, sizeof(*p_ctrl));
494	p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
495	p_ctrl->h_set_disp = CL_DISP_INVALID_HANDLE;
496}
497
498void osm_sa_mad_ctrl_destroy(IN osm_sa_mad_ctrl_t * p_ctrl)
499{
500	CL_ASSERT(p_ctrl);
501	cl_disp_unregister(p_ctrl->h_disp);
502	cl_disp_unregister(p_ctrl->h_set_disp);
503}
504
505ib_api_status_t osm_sa_mad_ctrl_init(IN osm_sa_mad_ctrl_t * p_ctrl,
506				     IN osm_sa_t * sa,
507				     IN osm_mad_pool_t * p_mad_pool,
508				     IN osm_vendor_t * p_vendor,
509				     IN osm_subn_t * p_subn,
510				     IN osm_log_t * p_log,
511				     IN osm_stats_t * p_stats,
512				     IN cl_dispatcher_t * p_disp,
513				     IN cl_dispatcher_t * p_set_disp)
514{
515	ib_api_status_t status = IB_SUCCESS;
516
517	OSM_LOG_ENTER(p_log);
518
519	osm_sa_mad_ctrl_construct(p_ctrl);
520
521	p_ctrl->sa = sa;
522	p_ctrl->p_log = p_log;
523	p_ctrl->p_disp = p_disp;
524	p_ctrl->p_set_disp = p_set_disp;
525	p_ctrl->p_mad_pool = p_mad_pool;
526	p_ctrl->p_vendor = p_vendor;
527	p_ctrl->p_stats = p_stats;
528	p_ctrl->p_subn = p_subn;
529
530	p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL,
531					  p_ctrl);
532
533	if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
534		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A08: "
535			"Dispatcher registration failed\n");
536		status = IB_INSUFFICIENT_RESOURCES;
537		goto Exit;
538	}
539
540	if (p_set_disp) {
541		p_ctrl->h_set_disp =
542		    cl_disp_register(p_set_disp, CL_DISP_MSGID_NONE, NULL,
543				     p_ctrl);
544
545		if (p_ctrl->h_set_disp == CL_DISP_INVALID_HANDLE) {
546			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A0A: "
547				"SA set dispatcher registration failed\n");
548			status = IB_INSUFFICIENT_RESOURCES;
549			goto Exit;
550		}
551	}
552
553Exit:
554	OSM_LOG_EXIT(p_log);
555	return status;
556}
557
558ib_api_status_t osm_sa_mad_ctrl_bind(IN osm_sa_mad_ctrl_t * p_ctrl,
559				     IN ib_net64_t port_guid)
560{
561	osm_bind_info_t bind_info;
562	ib_api_status_t status = IB_SUCCESS;
563
564	OSM_LOG_ENTER(p_ctrl->p_log);
565
566	if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
567		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A09: "
568			"Multiple binds not allowed\n");
569		status = IB_ERROR;
570		goto Exit;
571	}
572
573	bind_info.class_version = 2;
574	bind_info.is_responder = TRUE;
575	bind_info.is_report_processor = FALSE;
576	bind_info.is_trap_processor = FALSE;
577	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
578	bind_info.port_guid = port_guid;
579	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
580	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
581	bind_info.timeout = p_ctrl->sa->p_subn->opt.transaction_timeout;
582	bind_info.retries = p_ctrl->sa->p_subn->opt.transaction_retries;
583
584	OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
585		"Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
586
587	p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, &bind_info,
588					 p_ctrl->p_mad_pool,
589					 sa_mad_ctrl_rcv_callback,
590					 sa_mad_ctrl_send_err_callback, p_ctrl);
591
592	if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
593		status = IB_ERROR;
594		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A10: "
595			"Vendor specific bind failed (%s)\n",
596			ib_get_err_str(status));
597		goto Exit;
598	}
599
600Exit:
601	OSM_LOG_EXIT(p_ctrl->p_log);
602	return status;
603}
604
605ib_api_status_t osm_sa_mad_ctrl_unbind(IN osm_sa_mad_ctrl_t * p_ctrl)
606{
607	ib_api_status_t status = IB_SUCCESS;
608
609	OSM_LOG_ENTER(p_ctrl->p_log);
610
611	if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
612		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A11: "
613			"No previous bind\n");
614		status = IB_ERROR;
615		goto Exit;
616	}
617
618	osm_vendor_unbind(p_ctrl->h_bind);
619Exit:
620	OSM_LOG_EXIT(p_ctrl->p_log);
621	return status;
622}
623