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