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