]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/libvendor/osm_vendor_mlx_sa.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / libvendor / osm_vendor_mlx_sa.c
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
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 */
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
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
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
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
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  *****************************************************************************/