xref: /NextBSD/contrib/ofed/management/opensm/libvendor/osm_vendor_mlx_sa.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
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 <complib/cl_debug.h>
43 #include <complib/cl_timer.h>
44 #include <complib/cl_event.h>
45 #include <vendor/osm_vendor_api.h>
46 #include <vendor/osm_vendor_sa_api.h>
47 
48 /*****************************************************************************
49  *****************************************************************************/
50 
51 /* this struct is the internal rep of the bind handle */
52 typedef struct _osmv_sa_bind_info {
53 	osm_bind_handle_t h_bind;
54 	osm_log_t *p_log;
55 	osm_vendor_t *p_vendor;
56 	osm_mad_pool_t *p_mad_pool;
57 	uint64_t port_guid;
58 	cl_event_t sync_event;
59 	uint64_t last_lids_update_sec;
60 	uint16_t lid;
61 	uint16_t sm_lid;
62 } osmv_sa_bind_info_t;
63 
64 /*****************************************************************************
65  *****************************************************************************/
66 
67 /*
68   Call back on new mad received:
69 
70   We basically only need to set the context of the query.
71   Or report an error.
72 
73   A pointer to the actual context of the request (a copy of the oriignal
74   request structure) is attached as the p_madw->context.ni_context.node_guid
75 */
76 void
__osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,IN void * bind_context,IN osm_madw_t * p_req_madw)77 __osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
78 		     IN void *bind_context, IN osm_madw_t * p_req_madw)
79 {
80 	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
81 	osmv_query_req_t *p_query_req_copy = NULL;
82 	osmv_query_res_t query_res;
83 	ib_sa_mad_t *p_sa_mad;
84 	ib_net16_t mad_status;
85 
86 	OSM_LOG_ENTER(p_bind->p_log);
87 
88 	if (!p_req_madw) {
89 		osm_log(p_bind->p_log, OSM_LOG_DEBUG,
90 			"__osmv_sa_mad_rcv_cb: "
91 			"Ignoring a non-response mad\n");
92 		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
93 		goto Exit;
94 	}
95 
96 	/* obtain the sent context */
97 	p_query_req_copy =
98 	    (osmv_query_req_t *) (p_req_madw->context.arb_context.context1);
99 
100 	/* provide the context of the original request in the result */
101 	query_res.query_context = p_query_req_copy->query_context;
102 
103 	/* provide the resulting madw */
104 	query_res.p_result_madw = p_madw;
105 
106 	/* update the req fields */
107 	p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;
108 
109 	/* if we got a remote error track it in the status */
110 	mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
111 	if (mad_status != IB_SUCCESS) {
112 		osm_log(p_bind->p_log, OSM_LOG_ERROR,
113 			"__osmv_sa_mad_rcv_cb: ERR 0501: "
114 			"Remote error:0x%04X .\n", mad_status);
115 		query_res.status = IB_REMOTE_ERROR;
116 	} else {
117 		query_res.status = IB_SUCCESS;
118 	}
119 
120 	/* what if we have got back an empty mad ? */
121 	if (!p_madw->mad_size) {
122 		osm_log(p_bind->p_log, OSM_LOG_ERROR,
123 			"__osmv_sa_mad_rcv_cb: ERR 0502: "
124 			"Got an empty mad.\n");
125 		query_res.status = IB_ERROR;
126 	}
127 
128 	if (IB_SUCCESS == mad_status) {
129 
130 		/* if we are in not in a method response of an rmpp nature we must get only 1 */
131 		/* HACK: in the future we might need to be smarter for other methods... */
132 		if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
133 			query_res.result_cnt = 1;
134 		} else {
135 #ifndef VENDOR_RMPP_SUPPORT
136 			if (mad_status != IB_SUCCESS)
137 				query_res.result_cnt = 0;
138 			else
139 				query_res.result_cnt = 1;
140 #else
141 			/* we used the offset value to calculate the number of
142 			   records in here */
143 			if (ib_get_attr_size(p_sa_mad->attr_offset) == 0) {
144 				query_res.result_cnt = 0;
145 				osm_log(p_bind->p_log, OSM_LOG_DEBUG,
146 					"__osmv_sa_mad_rcv_cb: Count = 0\n");
147 			}
148 			else {
149 				query_res.result_cnt = (uintn_t)
150 					((p_madw->mad_size - IB_SA_MAD_HDR_SIZE) /
151 					 ib_get_attr_size(p_sa_mad->attr_offset));
152 				osm_log(p_bind->p_log, OSM_LOG_DEBUG,
153 					"__osmv_sa_mad_rcv_cb: "
154 					"Count = %u = %zu / %u (%zu)\n",
155 					query_res.result_cnt,
156 					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
157 					ib_get_attr_size(p_sa_mad->attr_offset),
158 					(p_madw->mad_size - IB_SA_MAD_HDR_SIZE) %
159 					ib_get_attr_size(p_sa_mad->attr_offset));
160 			}
161 #endif
162 		}
163 	}
164 
165 	query_res.query_type = p_query_req_copy->query_type;
166 
167 	p_query_req_copy->pfn_query_cb(&query_res);
168 
169 	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
170 		cl_event_signal(&p_bind->sync_event);
171 
172 Exit:
173 
174 	/* free the copied query request if found */
175 	if (p_query_req_copy)
176 		free(p_query_req_copy);
177 
178 	/* put back the request madw */
179 	if (p_req_madw)
180 		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
181 
182 	OSM_LOG_EXIT(p_bind->p_log);
183 }
184 
185 /*****************************************************************************
186  ****************************************************************************/
187 /*
188   Send Error Callback:
189 
190   Only report the error and get rid of the mad wrapper
191 */
__osmv_sa_mad_err_cb(IN void * bind_context,IN osm_madw_t * p_madw)192 void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
193 {
194 	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
195 	osmv_query_req_t *p_query_req_copy = NULL;
196 	osmv_query_res_t query_res;
197 
198 	OSM_LOG_ENTER(p_bind->p_log);
199 
200 	/* Obtain the sent context etc */
201 	p_query_req_copy =
202 	    (osmv_query_req_t *) (p_madw->context.arb_context.context1);
203 
204 	/* provide the context of the original request in the result */
205 	query_res.query_context = p_query_req_copy->query_context;
206 
207 	query_res.p_result_madw = p_madw;
208 
209 	query_res.status = IB_TIMEOUT;
210 	query_res.result_cnt = 0;
211 	query_res.p_result_madw->status = IB_TIMEOUT;
212 	p_madw->status = IB_TIMEOUT;
213 	query_res.query_type = p_query_req_copy->query_type;
214 
215 	p_query_req_copy->pfn_query_cb(&query_res);
216 
217 	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
218 		cl_event_signal(&p_bind->sync_event);
219 
220 	if (p_query_req_copy)
221 		free(p_query_req_copy);
222 	OSM_LOG_EXIT(p_bind->p_log);
223 }
224 
225 /*****************************************************************************
226  This routine needs to be invoked on every send - since the SM LID and Local
227  lid might change. To do that without any major perfoermance impact we cache
228  the results and time they were obtained. Refresh only twice a minute.
229  To avoid the need to use statics and risk a race - we require the refresh time
230  to be stored in the context of the results. Also this coveres cases were
231  we query for multiple guids.
232  *****************************************************************************/
233 ib_api_status_t
__osmv_get_lid_and_sm_lid_by_port_guid(IN osm_vendor_t * const p_vend,IN ib_net64_t port_guid,IN OUT uint64_t * p_lids_update_time_sec,OUT uint16_t * lid,OUT uint16_t * sm_lid)234 __osmv_get_lid_and_sm_lid_by_port_guid(IN osm_vendor_t * const p_vend,
235 				       IN ib_net64_t port_guid,
236 				       IN OUT uint64_t * p_lids_update_time_sec,
237 				       OUT uint16_t * lid,
238 				       OUT uint16_t * sm_lid)
239 {
240 
241 	ib_api_status_t status;
242 	ib_port_attr_t *p_attr_array;
243 	uint32_t num_ports;
244 	uint32_t port_num;
245 
246 	OSM_LOG_ENTER(p_vend->p_log);
247 
248 	/* use prevous values if current time is close enough to previous query */
249 	if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30) {
250 		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
251 			"__osmv_get_lid_and_sm_lid_by_port_guid: "
252 			"Using previously stored lid:0x%04x sm_lid:0x%04x\n",
253 			*lid, *sm_lid);
254 		status = IB_SUCCESS;
255 		goto Exit;
256 	}
257 
258 	/* obtain the number of available ports */
259 	num_ports = 0;
260 	status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports);
261 	if (status != IB_INSUFFICIENT_MEMORY) {
262 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
263 			"__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: "
264 			"expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n",
265 			ib_get_err_str(status)
266 		    );
267 		status = IB_ERROR;
268 		goto Exit;
269 	}
270 
271 	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
272 		"__osmv_get_lid_and_sm_lid_by_port_guid: "
273 		"Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n",
274 		num_ports, cl_ntoh64(port_guid)
275 	    );
276 
277 	/* allocate the attributes */
278 	p_attr_array =
279 	    (ib_port_attr_t *) malloc(sizeof(ib_port_attr_t) * num_ports);
280 
281 	/* obtain the attributes */
282 	status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports);
283 	if (status != IB_SUCCESS) {
284 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
285 			"__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
286 			"Fail to get port attributes (error: %s)\n",
287 			ib_get_err_str(status)
288 		    );
289 		free(p_attr_array);
290 		goto Exit;
291 	}
292 
293 	status = IB_ERROR;
294 	/* find the port requested in the list */
295 	for (port_num = 0; (port_num < num_ports) && (status == IB_ERROR);
296 	     port_num++) {
297 		if (p_attr_array[port_num].port_guid == port_guid) {
298 			*lid = p_attr_array[port_num].lid;
299 			*sm_lid = p_attr_array[port_num].sm_lid;
300 			*p_lids_update_time_sec = cl_get_time_stamp_sec();
301 			status = IB_SUCCESS;
302 			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
303 				"__osmv_get_lid_and_sm_lid_by_port_guid: "
304 				"Found guid:0x%016" PRIx64 " with idx:%d\n",
305 				cl_ntoh64(port_guid), port_num);
306 		}
307 	}
308 
309 	free(p_attr_array);
310 
311 Exit:
312 	OSM_LOG_EXIT(p_vend->p_log);
313 	return (status);
314 }
315 
316 /*****************************************************************************
317  *****************************************************************************/
318 osm_bind_handle_t
osmv_bind_sa(IN osm_vendor_t * const p_vend,IN osm_mad_pool_t * const p_mad_pool,IN ib_net64_t port_guid)319 osmv_bind_sa(IN osm_vendor_t * const p_vend,
320 	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
321 {
322 	osm_bind_info_t bind_info;
323 	osm_log_t *p_log = p_vend->p_log;
324 	ib_api_status_t status = IB_SUCCESS;
325 	osmv_sa_bind_info_t *p_sa_bind_info;
326 	cl_status_t cl_status;
327 
328 	OSM_LOG_ENTER(p_log);
329 
330 	osm_log(p_log, OSM_LOG_DEBUG,
331 		"osmv_bind_sa: "
332 		"Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));
333 
334 	bind_info.port_guid = port_guid;
335 	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
336 	bind_info.class_version = 2;
337 	bind_info.is_responder = TRUE;
338 	bind_info.is_trap_processor = FALSE;
339 	bind_info.is_report_processor = TRUE;
340 	bind_info.send_q_size = 256;
341 	bind_info.recv_q_size = 256;
342 
343 	/* allocate the new sa bind info */
344 	p_sa_bind_info =
345 	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
346 	if (!p_sa_bind_info) {
347 		osm_log(p_log, OSM_LOG_ERROR,
348 			"osmv_bind_sa: ERR 0505: "
349 			"Fail to allocate new bidn structure\n");
350 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
351 		goto Exit;
352 	}
353 
354 	/* store some important context */
355 	p_sa_bind_info->p_log = p_log;
356 	p_sa_bind_info->port_guid = port_guid;
357 	p_sa_bind_info->p_mad_pool = p_mad_pool;
358 	p_sa_bind_info->p_vendor = p_vend;
359 	p_sa_bind_info->last_lids_update_sec = 0;
360 
361 	/* Bind to the lower level */
362 	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 */
363 
364 	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
365 		free(p_sa_bind_info);
366 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
367 		osm_log(p_log, OSM_LOG_ERROR,
368 			"osmv_bind_sa: ERR 0506: "
369 			"Fail to bind to vendor SMI.\n");
370 		goto Exit;
371 	}
372 
373 	/* obtain the sm_lid from the vendor */
374 	status =
375 	    __osmv_get_lid_and_sm_lid_by_port_guid(p_vend, port_guid,
376 						   &p_sa_bind_info->
377 						   last_lids_update_sec,
378 						   &p_sa_bind_info->lid,
379 						   &p_sa_bind_info->sm_lid);
380 	if (status != IB_SUCCESS) {
381 		free(p_sa_bind_info);
382 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
383 		osm_log(p_log, OSM_LOG_ERROR,
384 			"osmv_bind_sa: ERR 0507: "
385 			"Fail to obtain the sm lid.\n");
386 		goto Exit;
387 	}
388 
389 	/* initialize the sync_event */
390 	cl_event_construct(&p_sa_bind_info->sync_event);
391 	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
392 	if (cl_status != CL_SUCCESS) {
393 		osm_log(p_log, OSM_LOG_ERROR,
394 			"osmv_bind_sa: ERR 0508: "
395 			"cl_init_event failed: %s\n", ib_get_err_str(cl_status)
396 		    );
397 		free(p_sa_bind_info);
398 		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
399 	}
400 
401 Exit:
402 	OSM_LOG_EXIT(p_log);
403 	return (p_sa_bind_info);
404 }
405 
406 /*****************************************************************************
407  *****************************************************************************/
408 
409 /****t* OSM Vendor SA Client/osmv_sa_mad_data
410  * NAME
411  *    osmv_sa_mad_data
412  *
413  * DESCRIPTION
414  * Extra fields required to perform a mad query
415  *  This struct is passed to the actual send method
416  *
417  * SYNOPSIS
418  */
419 typedef struct _osmv_sa_mad_data {
420 	/* MAD data. */
421 	uint8_t method;
422 	ib_net16_t attr_id;
423 	ib_net16_t attr_offset;
424 	ib_net32_t attr_mod;
425 	ib_net64_t comp_mask;
426 	void *p_attr;
427 } osmv_sa_mad_data_t;
428 /*
429  * method
430  *    The method of the mad to be sent
431  *
432  *  attr_id
433  *     Attribute ID
434  *
435  *  attr_offset
436  *     Offset as defined by RMPP
437  *
438  *  attr_mod
439  *     Attribute modifier
440  *
441  *  comp_mask
442  *     The component mask of the query
443  *
444  *  p_attr
445  *     A pointer to the record of the attribute to be sent.
446  *
447  *****/
448 
449 /*****************************************************************************
450  *****************************************************************************/
451 /* Send a MAD out on the GSI interface */
452 ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,IN const osmv_sa_mad_data_t * const p_sa_mad_data,IN const osmv_query_req_t * const p_query_req)453 __osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
454 		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
455 		   IN const osmv_query_req_t * const p_query_req)
456 {
457 	ib_api_status_t status;
458 	ib_mad_t *p_mad_hdr;
459 	ib_sa_mad_t *p_sa_mad;
460 	osm_madw_t *p_madw;
461 	osm_log_t *p_log = p_bind->p_log;
462 	static atomic32_t trans_id;
463 	boolean_t sync;
464 	osmv_query_req_t *p_query_req_copy;
465 
466 	OSM_LOG_ENTER(p_log);
467 
468 	/*
469 	   since the sm_lid might change we obtain it every send
470 	   (actually it is cached in the bind object and refreshed
471 	   every 30sec by this proc )
472 	 */
473 	status =
474 	    __osmv_get_lid_and_sm_lid_by_port_guid(p_bind->p_vendor,
475 						   p_bind->port_guid,
476 						   &p_bind->
477 						   last_lids_update_sec,
478 						   &p_bind->lid,
479 						   &p_bind->sm_lid);
480 	if (status != IB_SUCCESS) {
481 		osm_log(p_log, OSM_LOG_ERROR,
482 			"__osmv_send_sa_req: ERR 0509: "
483 			"Fail to obtain the sm lid.\n");
484 		goto Exit;
485 	}
486 
487 	/* Get a MAD wrapper for the send */
488 	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
489 				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);
490 
491 	if (p_madw == NULL) {
492 		osm_log(p_log, OSM_LOG_ERROR,
493 			"__osmv_send_sa_req: ERR 0510: "
494 			"Unable to acquire MAD.\n");
495 		status = IB_INSUFFICIENT_RESOURCES;
496 		goto Exit;
497 	}
498 
499 	/* Initialize the Sent MAD: */
500 
501 	/* Initialize the MAD buffer for the send operation. */
502 	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
503 	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
504 
505 	/* Get a new transaction Id */
506 	cl_atomic_inc(&trans_id);
507 
508 	/* Cleanup the MAD from any residue */
509 	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
510 
511 	/* Initialize the standard MAD header. */
512 	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
513 			IB_MCLASS_SUBN_ADM,	/* class */
514 			(uint8_t) 2,	/* version */
515 			p_sa_mad_data->method,	/* method */
516 			cl_hton64((uint64_t) trans_id),	/* tid */
517 			p_sa_mad_data->attr_id,	/* attr id */
518 			p_sa_mad_data->attr_mod	/* attr mod */
519 	    );
520 
521 	/* Set the query information. */
522 	p_sa_mad->sm_key = p_query_req->sm_key;
523 	p_sa_mad->attr_offset = 0;
524 	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
525 	if (p_sa_mad->comp_mask) {
526 		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
527 		       ib_get_attr_size(p_sa_mad_data->attr_offset));
528 	}
529 
530 	/*
531 	   Provide the address to send to
532 	 */
533 	/* Patch to handle IBAL - host order , where it should take destination lid in network order */
534 #ifdef OSM_VENDOR_INTF_AL
535 	p_madw->mad_addr.dest_lid = p_bind->sm_lid;
536 #else
537 	p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
538 #endif
539 	p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->lid);
540 	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
541 	p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
542 	p_madw->mad_addr.addr_type.gsi.pkey_ix = 0;
543 	p_madw->resp_expected = TRUE;
544 	p_madw->fail_msg = CL_DISP_MSGID_NONE;
545 
546 	/*
547 	   Provide MAD context such that the call back will know what to do.
548 	   We have to keep the entire request structure so we know the CB.
549 	   Since we can not rely on the client to keep it arroud until
550 	   the response - we duplicate it and will later dispose it (in CB).
551 	   To store on the MADW we cast it into what opensm has:
552 	   p_madw->context.arb_context.context1
553 	 */
554 	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
555 	*p_query_req_copy = *p_query_req;
556 	p_madw->context.arb_context.context1 = p_query_req_copy;
557 
558 	/* we can support async as well as sync calls */
559 	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
560 
561 	/* send the mad asynchronously */
562 	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
563 				 p_madw, p_madw->resp_expected);
564 
565 	/* if synchronous - wait on the event */
566 	if (sync) {
567 		osm_log(p_log, OSM_LOG_DEBUG,
568 			"__osmv_send_sa_req: " "Waiting for async event.\n");
569 		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
570 		cl_event_reset(&p_bind->sync_event);
571 		status = p_madw->status;
572 	}
573 
574 Exit:
575 	OSM_LOG_EXIT(p_log);
576 	return status;
577 }
578 
579 /*****************************************************************************
580  *****************************************************************************/
581 /*
582  * Query the SA based on the user's request.
583  */
584 ib_api_status_t
osmv_query_sa(IN osm_bind_handle_t h_bind,IN const osmv_query_req_t * const p_query_req)585 osmv_query_sa(IN osm_bind_handle_t h_bind,
586 	      IN const osmv_query_req_t * const p_query_req)
587 {
588 	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind;
589 	osmv_sa_mad_data_t sa_mad_data;
590 	osmv_user_query_t *p_user_query;
591 	ib_service_record_t svc_rec;
592 	ib_node_record_t node_rec;
593 	ib_portinfo_record_t port_info;
594 	ib_path_rec_t path_rec;
595 	ib_class_port_info_t class_port_info;
596 	osm_log_t *p_log = p_bind->p_log;
597 	ib_api_status_t status;
598 
599 	OSM_LOG_ENTER(p_log);
600 
601 	/* Set the request information. */
602 	sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
603 	sa_mad_data.attr_mod = 0;
604 
605 	/* Set the MAD attributes and component mask correctly. */
606 	switch (p_query_req->query_type) {
607 
608 	case OSMV_QUERY_USER_DEFINED:
609 		osm_log(p_log, OSM_LOG_DEBUG,
610 			"osmv_query_sa DBG:001 %s", "USER_DEFINED\n");
611 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
612 		if (p_user_query->method)
613 			sa_mad_data.method = p_user_query->method;
614 		sa_mad_data.attr_offset = p_user_query->attr_offset;
615 		sa_mad_data.attr_id = p_user_query->attr_id;
616 		sa_mad_data.attr_mod = p_user_query->attr_mod;
617 		sa_mad_data.comp_mask = p_user_query->comp_mask;
618 		sa_mad_data.p_attr = p_user_query->p_attr;
619 		break;
620 
621 	case OSMV_QUERY_ALL_SVC_RECS:
622 		osm_log(p_log, OSM_LOG_DEBUG,
623 			"osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n");
624 		sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
625 		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
626 		sa_mad_data.attr_offset =
627 		    ib_get_attr_offset(sizeof(ib_service_record_t));
628 		sa_mad_data.comp_mask = 0;
629 		sa_mad_data.p_attr = &svc_rec;
630 		break;
631 
632 	case OSMV_QUERY_SVC_REC_BY_NAME:
633 		osm_log(p_log, OSM_LOG_DEBUG,
634 			"osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n");
635 		sa_mad_data.method = IB_MAD_METHOD_GET;
636 		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
637 		sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
638 		sa_mad_data.attr_offset =
639 		    ib_get_attr_offset(sizeof(ib_service_record_t));
640 		sa_mad_data.p_attr = &svc_rec;
641 		memcpy(svc_rec.service_name, p_query_req->p_query_input,
642 		       sizeof(ib_svc_name_t));
643 		break;
644 
645 	case OSMV_QUERY_SVC_REC_BY_ID:
646 		osm_log(p_log, OSM_LOG_DEBUG,
647 			"osmv_query_sa DBG:001 %s", "SVC_REC_BY_ID\n");
648 		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
649 		sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
650 		sa_mad_data.attr_offset =
651 		    ib_get_attr_offset(sizeof(ib_service_record_t));
652 		sa_mad_data.p_attr = &svc_rec;
653 		svc_rec.service_id =
654 		    *(ib_net64_t *) (p_query_req->p_query_input);
655 		break;
656 
657 	case OSMV_QUERY_CLASS_PORT_INFO:
658 		osm_log(p_log, OSM_LOG_DEBUG,
659 			"osmv_query_sa DBG:001 %s", "CLASS_PORT_INFO\n");
660 		sa_mad_data.method = IB_MAD_METHOD_GET;
661 		sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
662 		sa_mad_data.attr_offset =
663 		    ib_get_attr_offset(sizeof(ib_class_port_info_t));
664 		sa_mad_data.comp_mask = 0;
665 		sa_mad_data.p_attr = &class_port_info;
666 
667 		break;
668 
669 	case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
670 		osm_log(p_log, OSM_LOG_DEBUG,
671 			"osmv_query_sa DBG:001 %s", "NODE_REC_BY_NODE_GUID\n");
672 		sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
673 		sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
674 		sa_mad_data.attr_offset =
675 		    ib_get_attr_offset(sizeof(ib_node_record_t));
676 		sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
677 		sa_mad_data.p_attr = &node_rec;
678 		node_rec.node_info.node_guid =
679 		    *(ib_net64_t *) (p_query_req->p_query_input);
680 
681 		break;
682 
683 	case OSMV_QUERY_PORT_REC_BY_LID:
684 		osm_log(p_log, OSM_LOG_DEBUG,
685 			"osmv_query_sa DBG:001 %s", "PORT_REC_BY_LID\n");
686 		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
687 		sa_mad_data.attr_offset =
688 		    ib_get_attr_offset(sizeof(ib_portinfo_record_t));
689 		sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
690 		sa_mad_data.p_attr = &port_info;
691 		port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input);
692 		break;
693 
694 	case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
695 		sa_mad_data.method = IB_MAD_METHOD_GET;
696 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
697 		osm_log(p_log, OSM_LOG_DEBUG,
698 			"osmv_query_sa DBG:001 %s",
699 			"PORT_REC_BY_LID_AND_NUM\n");
700 		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
701 		sa_mad_data.attr_offset =
702 		    ib_get_attr_offset(sizeof(ib_portinfo_record_t));
703 		sa_mad_data.comp_mask =
704 		    IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
705 		sa_mad_data.p_attr = p_user_query->p_attr;
706 		break;
707 
708 	case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
709 		sa_mad_data.method = IB_MAD_METHOD_GET;
710 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
711 		osm_log(p_log, OSM_LOG_DEBUG,
712 			"osmv_query_sa DBG:001 %s",
713 			"OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
714 		sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
715 		sa_mad_data.attr_offset =
716 		    ib_get_attr_offset(sizeof(ib_vl_arb_table_record_t));
717 		sa_mad_data.comp_mask =
718 		    IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT |
719 		    IB_VLA_COMPMASK_BLOCK;
720 		sa_mad_data.p_attr = p_user_query->p_attr;
721 		break;
722 
723 	case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
724 		sa_mad_data.method = IB_MAD_METHOD_GET;
725 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
726 		osm_log(p_log, OSM_LOG_DEBUG,
727 			"osmv_query_sa DBG:001 %s",
728 			"OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
729 		sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
730 		sa_mad_data.attr_offset =
731 		    ib_get_attr_offset(sizeof(ib_slvl_table_record_t));
732 		sa_mad_data.comp_mask =
733 		    IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT |
734 		    IB_SLVL_COMPMASK_IN_PORT;
735 		sa_mad_data.p_attr = p_user_query->p_attr;
736 		break;
737 
738 	case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
739 		osm_log(p_log, OSM_LOG_DEBUG,
740 			"osmv_query_sa DBG:001 %s", "PATH_REC_BY_PORT_GUIDS\n");
741 		memset(&path_rec, 0, sizeof(ib_path_rec_t));
742 		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
743 		sa_mad_data.attr_offset =
744 		    ib_get_attr_offset(sizeof(ib_path_rec_t));
745 		sa_mad_data.comp_mask =
746 		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID);
747 		sa_mad_data.p_attr = &path_rec;
748 		ib_gid_set_default(&path_rec.dgid,
749 				   ((osmv_guid_pair_t *) (p_query_req->
750 							  p_query_input))->
751 				   dest_guid);
752 		ib_gid_set_default(&path_rec.sgid,
753 				   ((osmv_guid_pair_t *) (p_query_req->
754 							  p_query_input))->
755 				   src_guid);
756 		break;
757 
758 	case OSMV_QUERY_PATH_REC_BY_GIDS:
759 		osm_log(p_log, OSM_LOG_DEBUG,
760 			"osmv_query_sa DBG:001 %s", "PATH_REC_BY_GIDS\n");
761 		memset(&path_rec, 0, sizeof(ib_path_rec_t));
762 		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
763 		sa_mad_data.attr_offset =
764 		    ib_get_attr_offset(sizeof(ib_path_rec_t));
765 		sa_mad_data.comp_mask =
766 		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID);
767 		sa_mad_data.p_attr = &path_rec;
768 		memcpy(&path_rec.dgid,
769 		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
770 		       dest_gid, sizeof(ib_gid_t));
771 		memcpy(&path_rec.sgid,
772 		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
773 		       src_gid, sizeof(ib_gid_t));
774 		break;
775 
776 	case OSMV_QUERY_PATH_REC_BY_LIDS:
777 		osm_log(p_log, OSM_LOG_DEBUG,
778 			"osmv_query_sa DBG:001 %s", "PATH_REC_BY_LIDS\n");
779 		memset(&path_rec, 0, sizeof(ib_path_rec_t));
780 		sa_mad_data.method = IB_MAD_METHOD_GET;
781 		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
782 		sa_mad_data.attr_offset =
783 		    ib_get_attr_offset(sizeof(ib_path_rec_t));
784 		sa_mad_data.comp_mask =
785 		    (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID);
786 		sa_mad_data.p_attr = &path_rec;
787 		path_rec.dlid =
788 		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->
789 		    dest_lid;
790 		path_rec.slid =
791 		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid;
792 		break;
793 
794 	case OSMV_QUERY_UD_MULTICAST_SET:
795 		sa_mad_data.method = IB_MAD_METHOD_SET;
796 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
797 		osm_log(p_log, OSM_LOG_DEBUG,
798 			"osmv_query_sa DBG:001 %s",
799 			"OSMV_QUERY_UD_MULTICAST_SET\n");
800 		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
801 		sa_mad_data.attr_offset =
802 		    ib_get_attr_offset(sizeof(ib_member_rec_t));
803 		sa_mad_data.comp_mask = p_user_query->comp_mask;
804 		sa_mad_data.p_attr = p_user_query->p_attr;
805 		break;
806 
807 	case OSMV_QUERY_UD_MULTICAST_DELETE:
808 		sa_mad_data.method = IB_MAD_METHOD_DELETE;
809 		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
810 		osm_log(p_log, OSM_LOG_DEBUG,
811 			"osmv_query_sa DBG:001 %s",
812 			"OSMV_QUERY_UD_MULTICAST_DELETE\n");
813 		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
814 		sa_mad_data.attr_offset =
815 		    ib_get_attr_offset(sizeof(ib_member_rec_t));
816 		sa_mad_data.comp_mask = p_user_query->comp_mask;
817 		sa_mad_data.p_attr = p_user_query->p_attr;
818 		break;
819 
820 	default:
821 		osm_log(p_log, OSM_LOG_ERROR,
822 			"osmv_query_sa DBG:001 %s", "UNKNOWN\n");
823 		CL_ASSERT(0);
824 		return IB_ERROR;
825 	}
826 
827 	status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req);
828 
829 	OSM_LOG_EXIT(p_log);
830 	return status;
831 }
832 
833 /*****************************************************************************
834  *****************************************************************************/
835