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 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36#if HAVE_CONFIG_H
37#  include <config.h>
38#endif				/* HAVE_CONFIG_H */
39
40#include <stdlib.h>
41#include <string.h>
42#include <sys/time.h>
43#include <vendor/osm_vendor_api.h>
44#include <vendor/osm_vendor_sa_api.h>
45#include <complib/cl_event.h>
46
47/*****************************************************************************
48 *****************************************************************************/
49
50/* this struct is the internal rep of the bind handle */
51typedef struct _osmv_sa_bind_info {
52	osm_bind_handle_t h_bind;
53	osm_log_t *p_log;
54	osm_vendor_t *p_vendor;
55	osm_mad_pool_t *p_mad_pool;
56	cl_event_t sync_event;
57	time_t last_lids_update_sec;
58} osmv_sa_bind_info_t;
59
60/*****************************************************************************
61 *****************************************************************************/
62
63/*
64  Call back on new mad received:
65
66  We basically only need to set the context of the query.
67  Or report an error.
68
69  A pointer to the actual context of the request (a copy of the oriignal
70  request structure) is attached as the p_madw->context.ni_context.node_guid
71*/
72static void
73__osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
74		     IN void *bind_context, IN osm_madw_t * p_req_madw)
75{
76	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
77	osmv_query_req_t *p_query_req_copy = NULL;
78	osmv_query_res_t query_res;
79	ib_sa_mad_t *p_sa_mad;
80	ib_net16_t mad_status;
81
82	OSM_LOG_ENTER(p_bind->p_log);
83
84	if (!p_req_madw) {
85		OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
86			"Ignoring a non-response mad\n");
87		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
88		goto Exit;
89	}
90
91	/* obtain the sent context since we store it during send in the ni_ctx */
92	p_query_req_copy =
93	    (osmv_query_req_t *) (long *)(long)(p_req_madw->context.ni_context.
94						node_guid);
95
96	/* provide the context of the original request in the result */
97	query_res.query_context = p_query_req_copy->query_context;
98
99	/* provide the resulting madw */
100	query_res.p_result_madw = p_madw;
101
102	/* update the req fields */
103	p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;
104
105	/* if we got a remote error track it in the status */
106	mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
107	if (mad_status != IB_SUCCESS) {
108		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5501: "
109			"Remote error:0x%04X\n", cl_ntoh16(mad_status));
110		query_res.status = IB_REMOTE_ERROR;
111	} else
112		query_res.status = IB_SUCCESS;
113
114	/* what if we have got back an empty mad ? */
115	if (!p_madw->mad_size) {
116		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5502: "
117			"Got an empty mad\n");
118		query_res.status = IB_ERROR;
119	}
120
121	if (IB_SUCCESS == mad_status) {
122
123		/* if we are in not in a method response of an rmpp nature we must get only 1 */
124		/* HACK: in the future we might need to be smarter for other methods... */
125		if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
126			query_res.result_cnt = 1;
127		} else {
128#ifndef VENDOR_RMPP_SUPPORT
129			if (mad_status != IB_SUCCESS)
130				query_res.result_cnt = 0;
131			else
132				query_res.result_cnt = 1;
133#else
134			if (ib_get_attr_size(p_sa_mad->attr_offset)) {
135				/* we used the offset value to calculate the
136				   number of records in here */
137				query_res.result_cnt = (uintn_t)
138				    ((p_madw->mad_size - IB_SA_MAD_HDR_SIZE) /
139				     ib_get_attr_size(p_sa_mad->attr_offset));
140				OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
141					"Count = %u = %zu / %u (%zu)\n",
142					query_res.result_cnt,
143					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
144					ib_get_attr_size(p_sa_mad->attr_offset),
145					(p_madw->mad_size -
146					 IB_SA_MAD_HDR_SIZE) %
147					ib_get_attr_size(p_sa_mad->attr_offset));
148			} else
149				query_res.result_cnt = 0;
150#endif
151		}
152	}
153
154	query_res.query_type = p_query_req_copy->query_type;
155
156	p_query_req_copy->pfn_query_cb(&query_res);
157
158	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
159		cl_event_signal(&p_bind->sync_event);
160
161Exit:
162
163	/* free the copied query request if found */
164	if (p_query_req_copy)
165		free(p_query_req_copy);
166
167	/* put back the request madw */
168	if (p_req_madw)
169		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
170
171	OSM_LOG_EXIT(p_bind->p_log);
172}
173
174/*****************************************************************************
175 ****************************************************************************/
176/*
177  Send Error Callback:
178
179  Only report the error and get rid of the mad wrapper
180*/
181static void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
182{
183	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
184	osmv_query_req_t *p_query_req_copy = NULL;
185	osmv_query_res_t query_res;
186
187	OSM_LOG_ENTER(p_bind->p_log);
188
189	/* Obtain the sent context etc */
190	p_query_req_copy =
191	    (osmv_query_req_t *) (long *)(long)(p_madw->context.ni_context.
192						node_guid);
193
194	/* provide the context of the original request in the result */
195	query_res.query_context = p_query_req_copy->query_context;
196
197	query_res.p_result_madw = p_madw;
198
199	query_res.status = IB_TIMEOUT;
200	query_res.result_cnt = 0;
201
202	query_res.query_type = p_query_req_copy->query_type;
203
204	p_query_req_copy->pfn_query_cb(&query_res);
205
206	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
207		cl_event_signal(&p_bind->sync_event);
208
209	if (p_query_req_copy)
210		free(p_query_req_copy);
211	OSM_LOG_EXIT(p_bind->p_log);
212}
213
214/*****************************************************************************
215 Update lids of vendor umad_port.
216 *****************************************************************************/
217static ib_api_status_t update_umad_port(osm_vendor_t * p_vend)
218{
219	umad_port_t port;
220	if (umad_get_port(p_vend->umad_port.ca_name,
221			  p_vend->umad_port.portnum, &port) < 0)
222		return IB_ERROR;
223	p_vend->umad_port.base_lid = port.base_lid;
224	p_vend->umad_port.sm_lid = port.sm_lid;
225	umad_release_port(&port);
226	return IB_SUCCESS;
227}
228
229/*****************************************************************************
230 *****************************************************************************/
231osm_bind_handle_t
232osmv_bind_sa(IN osm_vendor_t * const p_vend,
233	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
234{
235	osm_bind_info_t bind_info;
236	osm_log_t *p_log = p_vend->p_log;
237	osmv_sa_bind_info_t *p_sa_bind_info;
238	cl_status_t cl_status;
239
240	OSM_LOG_ENTER(p_log);
241
242	OSM_LOG(p_log, OSM_LOG_DEBUG,
243		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
244
245	bind_info.port_guid = port_guid;
246	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
247	bind_info.class_version = 2;
248	bind_info.is_responder = FALSE;
249	bind_info.is_trap_processor = FALSE;
250	bind_info.is_report_processor = FALSE;
251	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
252	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
253
254	/* allocate the new sa bind info */
255	p_sa_bind_info =
256	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
257	if (!p_sa_bind_info) {
258		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5505: "
259			"Failed to allocate new bind structure\n");
260		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
261		goto Exit;
262	}
263
264	/* store some important context */
265	p_sa_bind_info->p_log = p_log;
266	p_sa_bind_info->p_mad_pool = p_mad_pool;
267	p_sa_bind_info->p_vendor = p_vend;
268
269	/* Bind to the lower level */
270	p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info);	/* context provided to CBs */
271
272	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
273		free(p_sa_bind_info);
274		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
275		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5506: "
276			"Failed to bind to vendor GSI\n");
277		goto Exit;
278	}
279
280	/* update time umad_port is initilized now */
281	p_sa_bind_info->last_lids_update_sec = time(NULL);
282
283	/* initialize the sync_event */
284	cl_event_construct(&p_sa_bind_info->sync_event);
285	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
286	if (cl_status != CL_SUCCESS) {
287		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5508: "
288			"cl_init_event failed: %s\n", ib_get_err_str(cl_status));
289		free(p_sa_bind_info);
290		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
291	}
292
293Exit:
294	OSM_LOG_EXIT(p_log);
295	return (p_sa_bind_info);
296}
297
298/*****************************************************************************
299 *****************************************************************************/
300
301/****t* OSM Vendor SA Client/osmv_sa_mad_data
302 * NAME
303 *    osmv_sa_mad_data
304 *
305 * DESCRIPTION
306 * Extra fields required to perform a mad query
307 *  This struct is passed to the actual send method
308 *
309 * SYNOPSIS
310 */
311typedef struct _osmv_sa_mad_data {
312	/* MAD data. */
313	uint8_t method;
314	ib_net16_t attr_id;
315	ib_net16_t attr_offset;
316	ib_net32_t attr_mod;
317	ib_net64_t comp_mask;
318	void *p_attr;
319} osmv_sa_mad_data_t;
320/*
321 * method
322 *    The method of the mad to be sent
323 *
324 *  attr_id
325 *     Attribute ID
326 *
327 *  attr_offset
328 *     Offset as defined by RMPP
329 *
330 *  attr_mod
331 *     Attribute modifier
332 *
333 *  comp_mask
334 *     The component mask of the query
335 *
336 *  p_attr
337 *     A pointer to the record of the attribute to be sent.
338 *
339 *****/
340
341/*****************************************************************************
342 *****************************************************************************/
343/* Send a MAD out on the GSI interface */
344static ib_api_status_t
345__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
346		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
347		   IN const osmv_query_req_t * const p_query_req)
348{
349	ib_api_status_t status;
350	ib_mad_t *p_mad_hdr;
351	ib_sa_mad_t *p_sa_mad;
352	osm_madw_t *p_madw;
353	osm_log_t *p_log = p_bind->p_log;
354	static atomic32_t trans_id;
355	boolean_t sync;
356	osmv_query_req_t *p_query_req_copy;
357
358	OSM_LOG_ENTER(p_log);
359
360	/*
361	   since the sm_lid might change we obtain it every send
362	   (actually it is cached in the bind object and refreshed
363	   every 30sec by this proc)
364	 */
365	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
366		status = update_umad_port(p_bind->p_vendor);
367		if (status != IB_SUCCESS) {
368			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
369				"Failed to obtain the SM lid\n");
370			goto Exit;
371		}
372		p_bind->last_lids_update_sec = time(NULL);
373	}
374
375	/* Get a MAD wrapper for the send */
376	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
377				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);
378
379	if (p_madw == NULL) {
380		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
381			"Unable to acquire MAD\n");
382		status = IB_INSUFFICIENT_RESOURCES;
383		goto Exit;
384	}
385
386	/* Initialize the Sent MAD: */
387
388	/* Initialize the MAD buffer for the send operation. */
389	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
390	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
391
392	/* Get a new transaction Id */
393	cl_atomic_inc(&trans_id);
394
395	/* Cleanup the MAD from any residue */
396	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
397
398	/* Initialize the standard MAD header. */
399	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
400			IB_MCLASS_SUBN_ADM,	/* class */
401			(uint8_t) 2,	/* version */
402			p_sa_mad_data->method,	/* method */
403			cl_hton64((uint64_t) trans_id),	/* tid */
404			p_sa_mad_data->attr_id,	/* attr id */
405			p_sa_mad_data->attr_mod	/* attr mod */);
406
407	/* Set the query information. */
408	p_sa_mad->sm_key = p_query_req->sm_key;
409	p_sa_mad->attr_offset = 0;
410	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
411#ifdef DUAL_SIDED_RMPP
412	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
413		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
414#endif
415	if (p_sa_mad->comp_mask) {
416		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
417		       ib_get_attr_size(p_sa_mad_data->attr_offset));
418	}
419
420	/*
421	   Provide the address to send to
422	 */
423	p_madw->mad_addr.dest_lid =
424	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
425	p_madw->mad_addr.addr_type.smi.source_lid =
426	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
427	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
428	p_madw->resp_expected = TRUE;
429	p_madw->fail_msg = CL_DISP_MSGID_NONE;
430
431	/*
432	   Provide MAD context such that the call back will know what to do.
433	   We have to keep the entire request structure so we know the CB.
434	   Since we can not rely on the client to keep it around until
435	   the response - we duplicate it and will later dispose it (in CB).
436	   To store on the MADW we cast it into what opensm has:
437	   p_madw->context.ni_context.node_guid
438	 */
439	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
440	*p_query_req_copy = *p_query_req;
441	p_madw->context.ni_context.node_guid =
442	    (ib_net64_t) (long)p_query_req_copy;
443
444	/* we can support async as well as sync calls */
445	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
446
447	/* send the mad asynchronously */
448	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
449				 p_madw, p_madw->resp_expected);
450
451	/* if synchronous - wait on the event */
452	if (sync) {
453		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
454		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
455		cl_event_reset(&p_bind->sync_event);
456		status = p_madw->status;
457	}
458
459Exit:
460	OSM_LOG_EXIT(p_log);
461	return status;
462}
463
464/*****************************************************************************
465 *****************************************************************************/
466/*
467 * Query the SA based on the user's request.
468 */
469ib_api_status_t
470osmv_query_sa(IN osm_bind_handle_t h_bind,
471	      IN const osmv_query_req_t * const p_query_req)
472{
473	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind;
474	osmv_sa_mad_data_t sa_mad_data;
475	osmv_user_query_t *p_user_query;
476	ib_service_record_t svc_rec;
477	ib_node_record_t node_rec;
478	ib_portinfo_record_t port_info;
479	ib_path_rec_t path_rec;
480#ifdef DUAL_SIDED_RMPP
481	ib_multipath_rec_t multipath_rec;
482	osmv_multipath_req_t *p_mpr_req;
483	int i, j;
484#endif
485	ib_class_port_info_t class_port_info;
486	osm_log_t *p_log = p_bind->p_log;
487	ib_api_status_t status;
488
489	OSM_LOG_ENTER(p_log);
490
491	/* Set the request information. */
492	sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
493	sa_mad_data.attr_mod = 0;
494
495	/* Set the MAD attributes and component mask correctly. */
496	switch (p_query_req->query_type) {
497
498	case OSMV_QUERY_USER_DEFINED:
499		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 USER_DEFINED\n");
500		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
501		if (p_user_query->method)
502			sa_mad_data.method = p_user_query->method;
503		sa_mad_data.attr_offset = p_user_query->attr_offset;
504		sa_mad_data.attr_id = p_user_query->attr_id;
505		sa_mad_data.attr_mod = p_user_query->attr_mod;
506		sa_mad_data.comp_mask = p_user_query->comp_mask;
507		sa_mad_data.p_attr = p_user_query->p_attr;
508		break;
509
510	case OSMV_QUERY_ALL_SVC_RECS:
511		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
512		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
513		sa_mad_data.attr_offset =
514		    ib_get_attr_offset(sizeof(ib_service_record_t));
515		sa_mad_data.comp_mask = 0;
516		sa_mad_data.p_attr = &svc_rec;
517		break;
518
519	case OSMV_QUERY_SVC_REC_BY_NAME:
520		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
521		sa_mad_data.method = IB_MAD_METHOD_GET;
522		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
523		sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
524		sa_mad_data.attr_offset =
525		    ib_get_attr_offset(sizeof(ib_service_record_t));
526		sa_mad_data.p_attr = &svc_rec;
527		memcpy(svc_rec.service_name, p_query_req->p_query_input,
528		       sizeof(ib_svc_name_t));
529		break;
530
531	case OSMV_QUERY_SVC_REC_BY_ID:
532		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_ID\n");
533		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
534		sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
535		sa_mad_data.attr_offset =
536		    ib_get_attr_offset(sizeof(ib_service_record_t));
537		sa_mad_data.p_attr = &svc_rec;
538		svc_rec.service_id =
539		    *(ib_net64_t *) (p_query_req->p_query_input);
540		break;
541
542	case OSMV_QUERY_CLASS_PORT_INFO:
543		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 CLASS_PORT_INFO\n");
544		sa_mad_data.method = IB_MAD_METHOD_GET;
545		sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
546		sa_mad_data.attr_offset =
547		    ib_get_attr_offset(sizeof(ib_class_port_info_t));
548		sa_mad_data.comp_mask = 0;
549		sa_mad_data.p_attr = &class_port_info;
550		break;
551
552	case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
553		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 NODE_REC_BY_NODE_GUID\n");
554		sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
555		sa_mad_data.attr_offset =
556		    ib_get_attr_offset(sizeof(ib_node_record_t));
557		sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
558		sa_mad_data.p_attr = &node_rec;
559		node_rec.node_info.node_guid =
560		    *(ib_net64_t *) (p_query_req->p_query_input);
561		break;
562
563	case OSMV_QUERY_PORT_REC_BY_LID:
564		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID\n");
565		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
566		sa_mad_data.attr_offset =
567		    ib_get_attr_offset(sizeof(ib_portinfo_record_t));
568		sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
569		sa_mad_data.p_attr = &port_info;
570		port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input);
571		break;
572
573	case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
574		sa_mad_data.method = IB_MAD_METHOD_GET;
575		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
576		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID_AND_NUM\n");
577		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
578		sa_mad_data.attr_offset =
579		    ib_get_attr_offset(sizeof(ib_portinfo_record_t));
580		sa_mad_data.comp_mask =
581		    IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
582		sa_mad_data.p_attr = p_user_query->p_attr;
583		break;
584
585	case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
586		sa_mad_data.method = IB_MAD_METHOD_GET;
587		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
588		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
589		sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
590		sa_mad_data.attr_offset =
591		    ib_get_attr_offset(sizeof(ib_vl_arb_table_record_t));
592		sa_mad_data.comp_mask =
593		    IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT |
594		    IB_VLA_COMPMASK_BLOCK;
595		sa_mad_data.p_attr = p_user_query->p_attr;
596		break;
597
598	case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
599		sa_mad_data.method = IB_MAD_METHOD_GET;
600		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
601		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
602		sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
603		sa_mad_data.attr_offset =
604		    ib_get_attr_offset(sizeof(ib_slvl_table_record_t));
605		sa_mad_data.comp_mask =
606		    IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT |
607		    IB_SLVL_COMPMASK_IN_PORT;
608		sa_mad_data.p_attr = p_user_query->p_attr;
609		break;
610
611	case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
612		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_PORT_GUIDS\n");
613		memset(&path_rec, 0, sizeof(ib_path_rec_t));
614		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
615		sa_mad_data.attr_offset =
616		    ib_get_attr_offset(sizeof(ib_path_rec_t));
617		sa_mad_data.comp_mask =
618		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID);
619		sa_mad_data.p_attr = &path_rec;
620		ib_gid_set_default(&path_rec.dgid,
621				   ((osmv_guid_pair_t *) (p_query_req->
622							  p_query_input))->
623				   dest_guid);
624		ib_gid_set_default(&path_rec.sgid,
625				   ((osmv_guid_pair_t *) (p_query_req->
626							  p_query_input))->
627				   src_guid);
628		break;
629
630	case OSMV_QUERY_PATH_REC_BY_GIDS:
631		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_GIDS\n");
632		memset(&path_rec, 0, sizeof(ib_path_rec_t));
633		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
634		sa_mad_data.attr_offset =
635		    ib_get_attr_offset(sizeof(ib_path_rec_t));
636		sa_mad_data.comp_mask =
637		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID);
638		sa_mad_data.p_attr = &path_rec;
639		memcpy(&path_rec.dgid,
640		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
641		       dest_gid, sizeof(ib_gid_t));
642		memcpy(&path_rec.sgid,
643		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
644		       src_gid, sizeof(ib_gid_t));
645		break;
646
647	case OSMV_QUERY_PATH_REC_BY_LIDS:
648		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_LIDS\n");
649		memset(&path_rec, 0, sizeof(ib_path_rec_t));
650		sa_mad_data.method = IB_MAD_METHOD_GET;
651		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
652		sa_mad_data.attr_offset =
653		    ib_get_attr_offset(sizeof(ib_path_rec_t));
654		sa_mad_data.comp_mask =
655		    (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID);
656		sa_mad_data.p_attr = &path_rec;
657		path_rec.dlid =
658		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->
659		    dest_lid;
660		path_rec.slid =
661		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid;
662		break;
663
664	case OSMV_QUERY_UD_MULTICAST_SET:
665		sa_mad_data.method = IB_MAD_METHOD_SET;
666		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
667		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_SET\n");
668		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
669		sa_mad_data.attr_offset =
670		    ib_get_attr_offset(sizeof(ib_member_rec_t));
671		sa_mad_data.comp_mask = p_user_query->comp_mask;
672		sa_mad_data.p_attr = p_user_query->p_attr;
673		break;
674
675	case OSMV_QUERY_UD_MULTICAST_DELETE:
676		sa_mad_data.method = IB_MAD_METHOD_DELETE;
677		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
678		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_DELETE\n");
679		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
680		sa_mad_data.attr_offset =
681		    ib_get_attr_offset(sizeof(ib_member_rec_t));
682		sa_mad_data.comp_mask = p_user_query->comp_mask;
683		sa_mad_data.p_attr = p_user_query->p_attr;
684		break;
685
686#ifdef DUAL_SIDED_RMPP
687	case OSMV_QUERY_MULTIPATH_REC:
688		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 MULTIPATH_REC\n");
689		/* Validate sgid/dgid counts against SA client limit */
690		p_mpr_req = (osmv_multipath_req_t *) p_query_req->p_query_input;
691		if (p_mpr_req->sgid_count + p_mpr_req->dgid_count >
692		    IB_MULTIPATH_MAX_GIDS) {
693			OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 MULTIPATH_REC "
694				"SGID count %d DGID count %d max count %d\n",
695				p_mpr_req->sgid_count, p_mpr_req->dgid_count,
696				IB_MULTIPATH_MAX_GIDS);
697			CL_ASSERT(0);
698			return IB_ERROR;
699		}
700		memset(&multipath_rec, 0, sizeof(ib_multipath_rec_t));
701		sa_mad_data.method = IB_MAD_METHOD_GETMULTI;
702		sa_mad_data.attr_id = IB_MAD_ATTR_MULTIPATH_RECORD;
703		sa_mad_data.attr_offset =
704		    ib_get_attr_offset(sizeof(ib_multipath_rec_t));
705		sa_mad_data.p_attr = &multipath_rec;
706		sa_mad_data.comp_mask = p_mpr_req->comp_mask;
707		multipath_rec.num_path = p_mpr_req->num_path;
708		if (p_mpr_req->reversible)
709			multipath_rec.num_path |= 0x80;
710		else
711			multipath_rec.num_path &= ~0x80;
712		multipath_rec.pkey = p_mpr_req->pkey;
713		ib_multipath_rec_set_sl(&multipath_rec, p_mpr_req->sl);
714		ib_multipath_rec_set_qos_class(&multipath_rec, 0);
715		multipath_rec.independence = p_mpr_req->independence;
716		multipath_rec.sgid_count = p_mpr_req->sgid_count;
717		multipath_rec.dgid_count = p_mpr_req->dgid_count;
718		j = 0;
719		for (i = 0; i < p_mpr_req->sgid_count; i++, j++)
720			multipath_rec.gids[j] = p_mpr_req->gids[j];
721		for (i = 0; i < p_mpr_req->dgid_count; i++, j++)
722			multipath_rec.gids[j] = p_mpr_req->gids[j];
723		break;
724#endif
725
726	default:
727		OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 UNKNOWN\n");
728		CL_ASSERT(0);
729		return IB_ERROR;
730	}
731
732	status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req);
733
734	OSM_LOG_EXIT(p_log);
735	return status;
736}
737