]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/opensm/libvendor/osm_vendor_al.c
MFV r346563:
[FreeBSD/FreeBSD.git] / contrib / ofed / opensm / libvendor / osm_vendor_al.c
1 /*
2  * Copyright (c) 2004-2009 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 /*
37  * Abstract:
38  *    Implementation of osm_req_t.
39  * This object represents the generic attribute requester.
40  * This object is part of the opensm family of objects.
41  *
42  */
43
44 /*
45   Next available error code: 0x300
46 */
47
48 #if HAVE_CONFIG_H
49 #  include <config.h>
50 #endif                          /* HAVE_CONFIG_H */
51
52 #ifdef OSM_VENDOR_INTF_AL
53
54 #include <stdlib.h>
55 #include <string.h>
56 #include <complib/cl_qlist.h>
57 #include <complib/cl_thread.h>
58 #include <complib/cl_math.h>
59 #include <complib/cl_debug.h>
60 #include <iba/ib_types.h>
61 #include <opensm/osm_madw.h>
62 #include <opensm/osm_log.h>
63 #include <opensm/osm_mad_pool.h>
64 #include <vendor/osm_vendor_api.h>
65
66 /****s* OpenSM: Vendor AL/osm_al_bind_info_t
67  * NAME
68  *   osm_al_bind_info_t
69  *
70  * DESCRIPTION
71  *    Structure containing bind information.
72  *
73  * SYNOPSIS
74  */
75 typedef struct _osm_al_bind_info {
76         osm_vendor_t *p_vend;
77         void *client_context;
78         ib_qp_handle_t h_qp;
79         ib_mad_svc_handle_t h_svc;
80         uint8_t port_num;
81         ib_pool_key_t pool_key;
82         osm_vend_mad_recv_callback_t rcv_callback;
83         osm_vend_mad_send_err_callback_t send_err_callback;
84         osm_mad_pool_t *p_osm_pool;
85         ib_av_handle_t h_dr_av;
86
87 } osm_al_bind_info_t;
88 /*
89  * FIELDS
90  * p_vend
91  *    Pointer to the vendor object.
92  *
93  * client_context
94  *    User's context passed during osm_bind
95  *
96  * h_qp
97  *    Handle the QP for this bind.
98  *
99  * h_qp_svc
100  *    Handle the QP mad service for this bind.
101  *
102  * port_num
103  *    Port number (within the HCA) of the bound port.
104  *
105  * pool_key
106  *    Pool key returned by all for this QP.
107  *
108  * h_dr_av
109  *    Address vector handle used for all directed route SMPs.
110  *
111  * SEE ALSO
112  *********/
113
114 inline static ib_api_status_t
115 __osm_al_convert_wcs(IN ib_wc_status_t const wc_status)
116 {
117         switch (wc_status) {
118         case IB_WCS_SUCCESS:
119                 return (IB_SUCCESS);
120
121         case IB_WCS_TIMEOUT_RETRY_ERR:
122                 return (IB_TIMEOUT);
123
124         default:
125                 return (IB_ERROR);
126         }
127 }
128
129 static void __osm_al_ca_err_callback(IN ib_async_event_rec_t * p_async_rec)
130 {
131         osm_vendor_t *p_vend = (osm_vendor_t *) p_async_rec->context;
132         OSM_LOG_ENTER(p_vend->p_log);
133
134         osm_log(p_vend->p_log, OSM_LOG_ERROR,
135                 "__osm_al_ca_err_callback: ERR 3B01: "
136                 "Event on channel adapter (%s).\n",
137                 ib_get_async_event_str(p_async_rec->code));
138
139         OSM_LOG_EXIT(p_vend->p_log);
140 }
141
142 static void __osm_al_ca_destroy_callback(IN void *context)
143 {
144         osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) context;
145         osm_vendor_t *p_vend = p_bind->p_vend;
146         OSM_LOG_ENTER(p_vend->p_log);
147
148         osm_log(p_vend->p_log, OSM_LOG_INFO,
149                 "__osm_al_ca_destroy_callback: "
150                 "Closing local channel adapter.\n");
151
152         OSM_LOG_EXIT(p_vend->p_log);
153 }
154
155 static void __osm_al_err_callback(IN ib_async_event_rec_t * p_async_rec)
156 {
157         osm_al_bind_info_t *p_bind =
158             (osm_al_bind_info_t *) p_async_rec->context;
159         osm_vendor_t *p_vend = p_bind->p_vend;
160         OSM_LOG_ENTER(p_vend->p_log);
161
162         osm_log(p_vend->p_log, OSM_LOG_ERROR,
163                 "__osm_al_err_callback: ERR 3B02: "
164                 "Error on QP (%s).\n",
165                 ib_get_async_event_str(p_async_rec->code));
166
167         OSM_LOG_EXIT(p_vend->p_log);
168 }
169
170 static void
171 __osm_al_send_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
172 {
173         osm_al_bind_info_t *const p_bind =
174             (osm_al_bind_info_t *) mad_svc_context;
175         osm_vendor_t *const p_vend = p_bind->p_vend;
176         osm_madw_t *const p_madw = (osm_madw_t *) p_elem->context1;
177         osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
178         ib_mad_t *p_mad;
179
180         OSM_LOG_ENTER(p_vend->p_log);
181
182         CL_ASSERT(p_vw);
183         CL_ASSERT(p_vw->h_av);
184
185         /*
186            Destroy the address vector as necessary.
187          */
188         if (p_vw->h_av != p_bind->h_dr_av) {
189                 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
190                         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
191                                 "__osm_al_send_callback: "
192                                 "Destroying av handle %p.\n", p_vw->h_av);
193                 }
194
195                 ib_destroy_av(p_vw->h_av);
196         }
197
198         p_mad = ib_get_mad_buf(p_elem);
199
200         if (p_elem->resp_expected) {
201                 /*
202                    If the send was unsuccessful, notify the user
203                    for MADs that were expecting a response.
204                    A NULL mad wrapper parameter is the user's clue
205                    that the transaction turned sour.
206
207                    Otherwise, do nothing for successful sends when a
208                    reponse is expected.  The mad will be returned to the
209                    pool later.
210                  */
211                 p_madw->status = __osm_al_convert_wcs(p_elem->status);
212                 if (p_elem->status != IB_WCS_SUCCESS) {
213                         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
214                                 "__osm_al_send_callback: "
215                                 "MAD completed with work queue error: %s.\n",
216                                 ib_get_wc_status_str(p_elem->status));
217                         /*
218                            Return any wrappers to the pool that may have been
219                            pre-emptively allocated to handle a receive.
220                          */
221                         if (p_vw->p_resp_madw) {
222                                 osm_mad_pool_put(p_bind->p_osm_pool,
223                                                  p_vw->p_resp_madw);
224                                 p_vw->p_resp_madw = NULL;
225                         }
226
227                         p_bind->send_err_callback(p_bind->client_context,
228                                                   p_madw);
229                 }
230         } else {
231                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
232                         "__osm_al_send_callback: "
233                         "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",
234                         cl_ntoh64(p_mad->trans_id));
235                 osm_mad_pool_put(p_bind->p_osm_pool, p_madw);
236                 goto Exit;
237         }
238
239 Exit:
240         OSM_LOG_EXIT(p_vend->p_log);
241 }
242
243 static void
244 __osm_al_rcv_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
245 {
246         osm_al_bind_info_t *const p_bind =
247             (osm_al_bind_info_t *) mad_svc_context;
248         osm_vendor_t *const p_vend = p_bind->p_vend;
249         osm_madw_t *p_old_madw;
250         osm_madw_t *p_new_madw;
251         osm_vend_wrap_t *p_old_vw;
252         osm_vend_wrap_t *p_new_vw;
253         ib_mad_t *p_new_mad;
254         osm_mad_addr_t mad_addr;
255
256         OSM_LOG_ENTER(p_vend->p_log);
257
258         CL_ASSERT(p_elem->context1 == NULL);
259         CL_ASSERT(p_elem->context2 == NULL);
260
261         p_new_mad = ib_get_mad_buf(p_elem);
262
263         /*
264            In preperation for initializing the new mad wrapper,
265            Initialize the mad_addr structure for the received wire MAD.
266          */
267         mad_addr.dest_lid = p_elem->remote_lid;
268         mad_addr.path_bits = p_elem->path_bits;
269
270         /* TO DO - figure out which #define to use for the 2.5 Gb rate... */
271         mad_addr.static_rate = 0;
272
273         if (p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
274             p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR) {
275                 mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
276         } else {
277                 mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
278                 mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
279                 mad_addr.addr_type.gsi.pkey_ix = p_elem->pkey_index;
280                 mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
281                 mad_addr.addr_type.gsi.global_route = FALSE;
282         }
283
284         /*
285            If this MAD is a response to a previous request,
286            then grab our pre-allocated MAD wrapper.
287            Otherwise, allocate a new MAD wrapper.
288          */
289         if (ib_mad_is_response(p_new_mad)) {
290                 CL_ASSERT(p_elem->send_context1 != NULL);
291                 CL_ASSERT(p_elem->send_context2 == NULL);
292
293                 p_old_madw = (osm_madw_t *) p_elem->send_context1;
294                 p_old_vw = osm_madw_get_vend_ptr(p_old_madw);
295                 p_new_madw = p_old_vw->p_resp_madw;
296
297                 CL_ASSERT(p_new_madw);
298
299                 osm_madw_init(p_new_madw, p_bind, p_elem->size, &mad_addr);
300                 osm_madw_set_mad(p_new_madw, p_new_mad);
301         } else {
302                 CL_ASSERT(p_elem->send_context1 == NULL);
303                 CL_ASSERT(p_elem->send_context2 == NULL);
304
305                 p_new_madw = osm_mad_pool_get_wrapper(p_bind->p_osm_pool,
306                                                       p_bind, p_elem->size,
307                                                       p_new_mad, &mad_addr);
308         }
309
310         CL_ASSERT(p_new_madw);
311         p_new_vw = osm_madw_get_vend_ptr(p_new_madw);
312
313         p_new_vw->h_bind = p_bind;
314         p_new_vw->size = p_elem->size;
315         p_new_vw->p_elem = p_elem;
316         p_new_vw->h_av = 0;
317         p_new_vw->p_resp_madw = NULL;
318
319         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
320                 "__osm_al_rcv_callback: "
321                 "Calling receive callback function %p.\n",
322                 p_bind->rcv_callback);
323
324         p_bind->rcv_callback(p_new_madw, p_bind->client_context,
325                              p_elem->send_context1);
326
327         OSM_LOG_EXIT(p_vend->p_log);
328 }
329
330 ib_api_status_t
331 osm_vendor_init(IN osm_vendor_t * const p_vend,
332                 IN osm_log_t * const p_log, IN const uint32_t timeout)
333 {
334         ib_api_status_t status;
335         OSM_LOG_ENTER(p_log);
336
337         p_vend->p_log = p_log;
338
339         /*
340            Open our instance of AL.
341          */
342         status = ib_open_al(&p_vend->h_al);
343         if (status != IB_SUCCESS) {
344                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
345                         "osm_vendor_init: ERR 3B03: "
346                         "Error opening AL (%s).\n", ib_get_err_str(status));
347
348                 goto Exit;
349         }
350
351         p_vend->timeout = timeout;
352
353 Exit:
354         OSM_LOG_EXIT(p_log);
355         return (status);
356 }
357
358 osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
359                              IN const uint32_t timeout)
360 {
361         ib_api_status_t status;
362         osm_vendor_t *p_vend;
363
364         OSM_LOG_ENTER(p_log);
365
366         p_vend = malloc(sizeof(*p_vend));
367         if (p_vend == NULL) {
368                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
369                         "osm_vendor_new: ERR 3B04: "
370                         "Unable to allocate vendor object.\n");
371                 goto Exit;
372         }
373
374         memset(p_vend, 0, sizeof(*p_vend));
375
376         status = osm_vendor_init(p_vend, p_log, timeout);
377         if (status != IB_SUCCESS) {
378                 free(p_vend);
379                 p_vend = NULL;
380         }
381
382 Exit:
383         OSM_LOG_EXIT(p_log);
384         return (p_vend);
385 }
386
387 void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
388 {
389         /* TO DO - fill this in */
390         ib_close_al((*pp_vend)->h_al);
391         free(*pp_vend);
392         *pp_vend = NULL;
393 }
394
395 static ib_api_status_t
396 __osm_ca_info_init(IN osm_vendor_t * const p_vend,
397                    IN osm_ca_info_t * const p_ca_info,
398                    IN const ib_net64_t ca_guid)
399 {
400         ib_api_status_t status;
401
402         OSM_LOG_ENTER(p_vend->p_log);
403
404         p_ca_info->guid = ca_guid;
405
406         if (osm_log_is_active(p_vend->p_log, OSM_LOG_VERBOSE)) {
407                 osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
408                         "__osm_ca_info_init: "
409                         "Querying CA 0x%" PRIx64 ".\n", cl_ntoh64(ca_guid));
410         }
411
412         status = ib_query_ca_by_guid(p_vend->h_al, ca_guid, NULL,
413                                      &p_ca_info->attr_size);
414         if ((status != IB_INSUFFICIENT_MEMORY) && (status != IB_SUCCESS)) {
415                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
416                         "__osm_ca_info_init: ERR 3B05: "
417                         "Unexpected status getting CA attributes (%s).\n",
418                         ib_get_err_str(status));
419                 goto Exit;
420         }
421
422         CL_ASSERT(p_ca_info->attr_size);
423
424         p_ca_info->p_attr = malloc(p_ca_info->attr_size);
425         if (p_ca_info->p_attr == NULL) {
426                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
427                         "__osm_ca_info_init: ERR 3B06: "
428                         "Unable to allocate attribute storage.\n");
429                 goto Exit;
430         }
431
432         status = ib_query_ca_by_guid(p_vend->h_al, ca_guid, p_ca_info->p_attr,
433                                      &p_ca_info->attr_size);
434         if (status != IB_SUCCESS) {
435                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
436                         "__osm_ca_info_init: ERR 3B07: "
437                         "Unexpected status getting CA attributes (%s).\n",
438                         ib_get_err_str(status));
439                 goto Exit;
440         }
441
442 Exit:
443         OSM_LOG_EXIT(p_vend->p_log);
444         return (status);
445 }
446
447 void
448 osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
449                     IN osm_ca_info_t * const p_ca_info)
450 {
451         OSM_LOG_ENTER(p_vend->p_log);
452
453         if (p_ca_info->p_attr)
454                 free(p_ca_info->p_attr);
455
456         free(p_ca_info);
457
458         OSM_LOG_EXIT(p_vend->p_log);
459 }
460
461 osm_ca_info_t *osm_ca_info_new(IN osm_vendor_t * const p_vend,
462                                IN const ib_net64_t ca_guid)
463 {
464         ib_api_status_t status;
465         osm_ca_info_t *p_ca_info;
466
467         OSM_LOG_ENTER(p_vend->p_log);
468
469         CL_ASSERT(ca_guid);
470
471         p_ca_info = malloc(sizeof(*p_ca_info));
472         if (p_ca_info == NULL)
473                 goto Exit;
474
475         memset(p_ca_info, 0, sizeof(*p_ca_info));
476
477         status = __osm_ca_info_init(p_vend, p_ca_info, ca_guid);
478         if (status != IB_SUCCESS) {
479                 osm_ca_info_destroy(p_vend, p_ca_info);
480                 p_ca_info = NULL;
481                 goto Exit;
482         }
483
484 Exit:
485         OSM_LOG_EXIT(p_vend->p_log);
486         return (p_ca_info);
487 }
488
489 static ib_api_status_t
490 __osm_vendor_get_ca_guids(IN osm_vendor_t * const p_vend,
491                           IN ib_net64_t ** const p_guids,
492                           IN unsigned * const p_num_guids)
493 {
494         ib_api_status_t status;
495
496         OSM_LOG_ENTER(p_vend->p_log);
497
498         CL_ASSERT(p_guids);
499         CL_ASSERT(p_num_guids);
500
501         status = ib_get_ca_guids(p_vend->h_al, NULL, p_num_guids);
502         if ((status != IB_INSUFFICIENT_MEMORY) && (status != IB_SUCCESS)) {
503                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
504                         "__osm_vendor_get_ca_guids: ERR 3B08: "
505                         "Unexpected status getting CA GUID array (%s).\n",
506                         ib_get_err_str(status));
507                 goto Exit;
508         }
509
510         if (*p_num_guids == 0) {
511                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
512                         "__osm_vendor_get_ca_guids: ERR 3B09: "
513                         "No available channel adapters.\n");
514                 status = IB_INSUFFICIENT_RESOURCES;
515                 goto Exit;
516         }
517
518         *p_guids = malloc(*p_num_guids * sizeof(**p_guids));
519         if (*p_guids == NULL) {
520                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
521                         "__osm_vendor_get_ca_guids: ERR 3B10: "
522                         "Unable to allocate CA GUID array.\n");
523                 goto Exit;
524         }
525
526         status = ib_get_ca_guids(p_vend->h_al, *p_guids, p_num_guids);
527         CL_ASSERT(*p_num_guids);
528
529         if (osm_log_is_active(p_vend->p_log, OSM_LOG_VERBOSE)) {
530                 osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
531                         "__osm_vendor_get_ca_guids: "
532                         "Detected %u local channel adapters.\n", *p_num_guids);
533         }
534
535 Exit:
536         OSM_LOG_EXIT(p_vend->p_log);
537         return (status);
538 }
539
540 /****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
541  * NAME
542  * osm_ca_info_get_pi_ptr
543  *
544  * DESCRIPTION
545  * Returns a pointer to the port attribute of the specified port
546  * owned by this CA.
547  *
548  * SYNOPSIS
549  */
550 static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
551                                                        const p_ca_info,
552                                                        IN const uint8_t index)
553 {
554         return (&p_ca_info->p_attr->p_port_attr[index]);
555 }
556
557 /*
558  * PARAMETERS
559  * p_ca_info
560  *    [in] Pointer to a CA Info object.
561  *
562  * index
563  *    [in] Port "index" for which to retrieve the port attribute.
564  *    The index is the offset into the ca's internal array
565  *    of port attributes.
566  *
567  * RETURN VALUE
568  * Returns a pointer to the port attribute of the specified port
569  * owned by this CA.
570  *
571  * NOTES
572  *
573  * SEE ALSO
574  *********/
575
576 ib_api_status_t
577 osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
578                              IN ib_port_attr_t * const p_attr_array,
579                              IN uint32_t * const p_num_ports)
580 {
581         ib_api_status_t status;
582
583         uint32_t ca;
584         unsigned ca_count;
585         uint32_t port_count = 0;
586         uint8_t port_num;
587         uint32_t total_ports = 0;
588         ib_net64_t *p_ca_guid = NULL;
589         osm_ca_info_t *p_ca_info;
590
591         OSM_LOG_ENTER(p_vend->p_log);
592
593         CL_ASSERT(p_vend);
594         CL_ASSERT(p_vend->p_ca_info == NULL);
595
596         /*
597            1) Determine the number of CA's
598            2) Allocate an array big enough to hold the ca info objects.
599            3) Call again to retrieve the guids.
600          */
601         status = __osm_vendor_get_ca_guids(p_vend, &p_ca_guid, &ca_count);
602
603         p_vend->p_ca_info = malloc(ca_count * sizeof(*p_vend->p_ca_info));
604         if (p_vend->p_ca_info == NULL) {
605                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
606                         "osm_vendor_get_all_port_attr: ERR 3B11: "
607                         "Unable to allocate CA information array.\n");
608                 goto Exit;
609         }
610
611         memset(p_vend->p_ca_info, 0, ca_count * sizeof(*p_vend->p_ca_info));
612         p_vend->ca_count = ca_count;
613
614         /*
615            For each CA, retrieve the port info attributes
616          */
617         for (ca = 0; ca < ca_count; ca++) {
618                 p_ca_info = &p_vend->p_ca_info[ca];
619
620                 status = __osm_ca_info_init(p_vend, p_ca_info, p_ca_guid[ca]);
621
622                 if (status != IB_SUCCESS) {
623                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
624                                 "osm_vendor_get_all_port_attr: ERR 3B12: "
625                                 "Unable to initialize CA Info object (%s).\n",
626                                 ib_get_err_str(status));
627                 }
628
629                 total_ports += osm_ca_info_get_num_ports(p_ca_info);
630         }
631
632         /*
633            If the user supplied enough storage, return the port guids,
634            otherwise, return the appropriate error.
635          */
636         if (*p_num_ports >= total_ports) {
637                 for (ca = 0; ca < ca_count; ca++) {
638                         uint32_t num_ports;
639
640                         p_ca_info = &p_vend->p_ca_info[ca];
641
642                         num_ports = osm_ca_info_get_num_ports(p_ca_info);
643
644                         for (port_num = 0; port_num < num_ports; port_num++) {
645                                 p_attr_array[port_count] =
646                                     *__osm_ca_info_get_port_attr_ptr(p_ca_info,
647                                                                      port_num);
648                                 port_count++;
649                         }
650                 }
651         } else {
652                 status = IB_INSUFFICIENT_MEMORY;
653         }
654
655         *p_num_ports = total_ports;
656
657 Exit:
658         if (p_ca_guid)
659                 free(p_ca_guid);
660
661         OSM_LOG_EXIT(p_vend->p_log);
662         return (status);
663 }
664
665 ib_net64_t
666 osm_vendor_get_ca_guid(IN osm_vendor_t * const p_vend,
667                        IN const ib_net64_t port_guid)
668 {
669         uint8_t index;
670         uint8_t num_ports;
671         uint32_t num_guids = 0;
672         osm_ca_info_t *p_ca_info;
673         uint32_t ca;
674
675         OSM_LOG_ENTER(p_vend->p_log);
676
677         CL_ASSERT(port_guid);
678         /*
679            First, locate the HCA that owns this port.
680          */
681         if (p_vend->p_ca_info == NULL) {
682                 /*
683                    Initialize the osm_ca_info_t array which allows
684                    us to match port GUID to CA.
685                  */
686                 osm_vendor_get_all_port_attr(p_vend, NULL, &num_guids);
687         }
688
689         CL_ASSERT(p_vend->p_ca_info);
690         CL_ASSERT(p_vend->ca_count);
691
692         for (ca = 0; ca < p_vend->ca_count; ca++) {
693                 p_ca_info = &p_vend->p_ca_info[ca];
694
695                 num_ports = osm_ca_info_get_num_ports(p_ca_info);
696                 CL_ASSERT(num_ports);
697
698                 for (index = 0; index < num_ports; index++) {
699                         if (port_guid ==
700                             osm_ca_info_get_port_guid(p_ca_info, index)) {
701                                 OSM_LOG_EXIT(p_vend->p_log);
702                                 return (osm_ca_info_get_ca_guid(p_ca_info));
703                         }
704                 }
705         }
706
707         /*
708            No local CA owns this guid!
709          */
710         osm_log(p_vend->p_log, OSM_LOG_ERROR,
711                 "osm_vendor_get_ca_guid: ERR 3B13: "
712                 "Unable to determine CA guid.\n");
713
714         OSM_LOG_EXIT(p_vend->p_log);
715         return (0);
716 }
717
718 uint8_t
719 osm_vendor_get_port_num(IN osm_vendor_t * const p_vend,
720                         IN const ib_net64_t port_guid)
721 {
722         uint8_t index;
723         uint8_t num_ports;
724         uint32_t num_guids = 0;
725         osm_ca_info_t *p_ca_info;
726         uint32_t ca;
727
728         OSM_LOG_ENTER(p_vend->p_log);
729
730         CL_ASSERT(port_guid);
731         /*
732            First, locate the HCA that owns this port.
733          */
734         if (p_vend->p_ca_info == NULL) {
735                 /*
736                    Initialize the osm_ca_info_t array which allows
737                    us to match port GUID to CA.
738                  */
739                 osm_vendor_get_all_port_attr(p_vend, NULL, &num_guids);
740         }
741
742         CL_ASSERT(p_vend->p_ca_info);
743         CL_ASSERT(p_vend->ca_count);
744
745         for (ca = 0; ca < p_vend->ca_count; ca++) {
746                 p_ca_info = &p_vend->p_ca_info[ca];
747
748                 num_ports = osm_ca_info_get_num_ports(p_ca_info);
749                 CL_ASSERT(num_ports);
750
751                 for (index = 0; index < num_ports; index++) {
752                         if (port_guid ==
753                             osm_ca_info_get_port_guid(p_ca_info, index)) {
754                                 OSM_LOG_EXIT(p_vend->p_log);
755                                 return (osm_ca_info_get_port_num
756                                         (p_ca_info, index));
757                         }
758                 }
759         }
760
761         /*
762            No local CA owns this guid!
763          */
764         osm_log(p_vend->p_log, OSM_LOG_ERROR,
765                 "osm_vendor_get_port_num: ERR 3B30: "
766                 "Unable to determine CA guid.\n");
767
768         OSM_LOG_EXIT(p_vend->p_log);
769         return (0);
770 }
771
772 static ib_api_status_t
773 __osm_vendor_open_ca(IN osm_vendor_t * const p_vend,
774                      IN const ib_net64_t port_guid)
775 {
776         ib_net64_t ca_guid;
777         ib_api_status_t status;
778
779         OSM_LOG_ENTER(p_vend->p_log);
780
781         ca_guid = osm_vendor_get_ca_guid(p_vend, port_guid);
782         if (ca_guid == 0) {
783                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
784                         "__osm_vendor_open_ca: ERR 3B31: "
785                         "Bad port GUID value 0x%" PRIx64 ".\n",
786                         cl_ntoh64(port_guid));
787                 status = IB_ERROR;
788                 goto Exit;
789         }
790
791         osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
792                 "__osm_vendor_open_ca: "
793                 "Opening HCA 0x%" PRIx64 ".\n", cl_ntoh64(ca_guid));
794
795         status = ib_open_ca(p_vend->h_al,
796                             ca_guid,
797                             __osm_al_ca_err_callback, p_vend, &p_vend->h_ca);
798
799         if (status != IB_SUCCESS) {
800                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
801                         "__osm_vendor_open_ca: ERR 3B15: "
802                         "Unable to open CA (%s).\n", ib_get_err_str(status));
803                 goto Exit;
804         }
805
806         CL_ASSERT(p_vend->h_ca);
807
808         status = ib_alloc_pd(p_vend->h_ca, IB_PDT_ALIAS, p_vend, &p_vend->h_pd);
809
810         if (status != IB_SUCCESS) {
811                 ib_close_ca(p_vend->h_ca, __osm_al_ca_destroy_callback);
812                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
813                         "__osm_vendor_open_ca: ERR 3B16: "
814                         "Unable to allocate protection domain (%s).\n",
815                         ib_get_err_str(status));
816                 goto Exit;
817         }
818
819         CL_ASSERT(p_vend->h_pd);
820
821 Exit:
822         OSM_LOG_EXIT(p_vend->p_log);
823         return (status);
824 }
825
826 static void
827 __osm_vendor_init_av(IN const osm_al_bind_info_t * p_bind,
828                      IN ib_av_attr_t * p_av)
829 {
830         memset(p_av, 0, sizeof(*p_av));
831         p_av->port_num = p_bind->port_num;
832         p_av->dlid = IB_LID_PERMISSIVE;
833 }
834
835 osm_bind_handle_t
836 osm_vendor_bind(IN osm_vendor_t * const p_vend,
837                 IN osm_bind_info_t * const p_user_bind,
838                 IN osm_mad_pool_t * const p_mad_pool,
839                 IN osm_vend_mad_recv_callback_t mad_recv_callback,
840                 IN osm_vend_mad_send_err_callback_t send_err_callback,
841                 IN void *context)
842 {
843         ib_net64_t port_guid;
844         osm_al_bind_info_t *p_bind = 0;
845         ib_api_status_t status;
846         ib_qp_create_t qp_create;
847         ib_mad_svc_t mad_svc;
848         ib_av_attr_t av;
849
850         OSM_LOG_ENTER(p_vend->p_log);
851
852         CL_ASSERT(p_user_bind);
853         CL_ASSERT(p_mad_pool);
854         CL_ASSERT(mad_recv_callback);
855         CL_ASSERT(send_err_callback);
856
857         port_guid = p_user_bind->port_guid;
858
859         osm_log(p_vend->p_log, OSM_LOG_INFO,
860                 "osm_vendor_bind: "
861                 "Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));
862
863         if (p_vend->h_ca == 0) {
864                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
865                         "osm_vendor_bind: "
866                         "Opening CA that owns port 0x%" PRIx64 ".\n",
867                         port_guid);
868
869                 status = __osm_vendor_open_ca(p_vend, port_guid);
870                 if (status != IB_SUCCESS) {
871                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
872                                 "osm_vendor_bind: ERR 3B17: "
873                                 "Unable to Open CA (%s).\n",
874                                 ib_get_err_str(status));
875                         goto Exit;
876                 }
877         }
878
879         p_bind = malloc(sizeof(*p_bind));
880         if (p_bind == NULL) {
881                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
882                         "osm_vendor_bind: ERR 3B18: "
883                         "Unable to allocate internal bind object.\n");
884                 goto Exit;
885         }
886
887         memset(p_bind, 0, sizeof(*p_bind));
888         p_bind->p_vend = p_vend;
889         p_bind->client_context = context;
890         p_bind->port_num = osm_vendor_get_port_num(p_vend, port_guid);
891         p_bind->rcv_callback = mad_recv_callback;
892         p_bind->send_err_callback = send_err_callback;
893         p_bind->p_osm_pool = p_mad_pool;
894
895         CL_ASSERT(p_bind->port_num);
896
897         /*
898            Get the proper QP.
899          */
900         memset(&qp_create, 0, sizeof(qp_create));
901
902         switch (p_user_bind->mad_class) {
903         case IB_MCLASS_SUBN_LID:
904         case IB_MCLASS_SUBN_DIR:
905                 qp_create.qp_type = IB_QPT_QP0_ALIAS;
906                 break;
907
908         case IB_MCLASS_SUBN_ADM:
909         default:
910                 qp_create.qp_type = IB_QPT_QP1_ALIAS;
911                 break;
912         }
913
914         qp_create.sq_depth = p_user_bind->send_q_size;
915         qp_create.rq_depth = p_user_bind->recv_q_size;
916         qp_create.sq_sge = OSM_AL_SQ_SGE;
917         qp_create.rq_sge = OSM_AL_RQ_SGE;
918
919         status = ib_get_spl_qp(p_vend->h_pd,
920                                port_guid,
921                                &qp_create,
922                                p_bind,
923                                __osm_al_err_callback,
924                                &p_bind->pool_key, &p_bind->h_qp);
925
926         if (status != IB_SUCCESS) {
927                 free(p_bind);
928                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
929                         "osm_vendor_bind: ERR 3B19: "
930                         "Unable to get QP handle (%s).\n",
931                         ib_get_err_str(status));
932                 goto Exit;
933         }
934
935         CL_ASSERT(p_bind->h_qp);
936         CL_ASSERT(p_bind->pool_key);
937
938         memset(&mad_svc, 0, sizeof(mad_svc));
939
940         mad_svc.mad_svc_context = p_bind;
941         mad_svc.pfn_mad_send_cb = __osm_al_send_callback;
942         mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
943         mad_svc.mgmt_class = p_user_bind->mad_class;
944         mad_svc.mgmt_version = p_user_bind->class_version;
945         mad_svc.support_unsol = p_user_bind->is_responder;
946         mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
947         mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
948         mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
949         mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
950         mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
951
952         status = ib_reg_mad_svc(p_bind->h_qp, &mad_svc, &p_bind->h_svc);
953
954         if (status != IB_SUCCESS) {
955                 free(p_bind);
956                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
957                         "osm_vendor_bind: ERR 3B21: "
958                         "Unable to register QP0 MAD service (%s).\n",
959                         ib_get_err_str(status));
960                 goto Exit;
961         }
962
963         __osm_vendor_init_av(p_bind, &av);
964
965         status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
966         if (status != IB_SUCCESS) {
967                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
968                         "osm_vendor_bind: ERR 3B22: "
969                         "Unable to create address vector (%s).\n",
970                         ib_get_err_str(status));
971
972                 goto Exit;
973         }
974
975         if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
976                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
977                         "osm_vendor_bind: "
978                         "Allocating av handle %p.\n", p_bind->h_dr_av);
979         }
980
981 Exit:
982         OSM_LOG_EXIT(p_vend->p_log);
983         return ((osm_bind_handle_t) p_bind);
984 }
985
986 ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
987                          IN const uint32_t mad_size,
988                          IN osm_vend_wrap_t * const p_vw)
989 {
990         ib_mad_t *p_mad;
991         osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
992         osm_vendor_t *p_vend = p_bind->p_vend;
993         ib_api_status_t status;
994
995         OSM_LOG_ENTER(p_vend->p_log);
996
997         CL_ASSERT(p_vw);
998
999         p_vw->size = mad_size;
1000         p_vw->h_bind = h_bind;
1001
1002         /*
1003            Retrieve a MAD element from the pool and give the user direct
1004            access to its buffer.
1005          */
1006         status = ib_get_mad(p_bind->pool_key, mad_size, &p_vw->p_elem);
1007         if (status != IB_SUCCESS) {
1008                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1009                         "osm_vendor_get: ERR 3B25: "
1010                         "Unable to acquire MAD (%s).\n",
1011                         ib_get_err_str(status));
1012
1013                 p_mad = NULL;
1014                 goto Exit;
1015         }
1016
1017         CL_ASSERT(p_vw->p_elem);
1018         p_mad = ib_get_mad_buf(p_vw->p_elem);
1019
1020         if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
1021                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1022                         "osm_vendor_get: "
1023                         "Acquired MAD %p, size = %u.\n", p_mad, mad_size);
1024         }
1025
1026 Exit:
1027         OSM_LOG_EXIT(p_vend->p_log);
1028         return (p_mad);
1029 }
1030
1031 void
1032 osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
1033 {
1034         osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1035         osm_vendor_t *p_vend = p_bind->p_vend;
1036         ib_api_status_t status;
1037
1038         OSM_LOG_ENTER(p_vend->p_log);
1039
1040         CL_ASSERT(p_vw);
1041         CL_ASSERT(p_vw->p_elem);
1042         CL_ASSERT(p_vw->h_bind == h_bind);
1043
1044         if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
1045                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1046                         "osm_vendor_put: "
1047                         "Retiring MAD %p.\n", ib_get_mad_buf(p_vw->p_elem));
1048         }
1049
1050         status = ib_put_mad(p_vw->p_elem);
1051         if (status != IB_SUCCESS) {
1052                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1053                         "osm_vendor_put: ERR 3B26: "
1054                         "Unable to retire MAD (%s).\n", ib_get_err_str(status));
1055         }
1056
1057         OSM_LOG_EXIT(p_vend->p_log);
1058 }
1059
1060 ib_api_status_t
1061 osm_vendor_send(IN osm_bind_handle_t h_bind,
1062                 IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
1063 {
1064         osm_al_bind_info_t *const p_bind = h_bind;
1065         osm_vendor_t *const p_vend = p_bind->p_vend;
1066         osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
1067         osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
1068         ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
1069         ib_api_status_t status;
1070         ib_mad_element_t *p_elem;
1071         ib_av_attr_t av;
1072
1073         OSM_LOG_ENTER(p_vend->p_log);
1074
1075         CL_ASSERT(p_vw->h_bind == h_bind);
1076         CL_ASSERT(p_vw->p_elem);
1077
1078         p_elem = p_vw->p_elem;
1079
1080         /*
1081            If a response is expected to this MAD, then preallocate
1082            a mad wrapper to contain the wire MAD received in the
1083            response.  Allocating a wrapper here allows for easier
1084            failure paths than after we already received the wire mad.
1085          */
1086         if (resp_expected) {
1087                 p_vw->p_resp_madw =
1088                     osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool);
1089                 if (p_vw->p_resp_madw == NULL) {
1090                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
1091                                 "osm_vendor_send: ERR 3B27: "
1092                                 "Unable to allocate MAD wrapper.\n");
1093                         status = IB_INSUFFICIENT_RESOURCES;
1094                         goto Exit;
1095                 }
1096         } else
1097                 p_vw->p_resp_madw = NULL;
1098
1099         /*
1100            For all sends other than directed route SM MADs,
1101            acquire an address vector for the destination.
1102          */
1103         if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
1104                 memset(&av, 0, sizeof(av));
1105                 av.port_num = p_bind->port_num;
1106                 av.dlid = p_mad_addr->dest_lid;
1107                 av.static_rate = p_mad_addr->static_rate;
1108                 av.path_bits = p_mad_addr->path_bits;
1109
1110                 if ((p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
1111                     (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR)) {
1112                         av.sl = p_mad_addr->addr_type.gsi.service_level;
1113
1114                         if (p_mad_addr->addr_type.gsi.global_route) {
1115                                 av.grh_valid = TRUE;
1116                                 /* ANIL */
1117                                 /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
1118                         }
1119                 }
1120
1121                 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
1122                         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1123                                 "osm_vendor_send: "
1124                                 "av.port_num 0x%X, "
1125                                 "av.dlid 0x%X, "
1126                                 "av.static_rate   %d, "
1127                                 "av.path_bits %d.\n",
1128                                 av.port_num, cl_ntoh16(av.dlid),
1129                                 av.static_rate, av.path_bits);
1130                 }
1131
1132                 status = ib_create_av(p_vend->h_pd, &av, &p_vw->h_av);
1133                 if (status != IB_SUCCESS) {
1134                         osm_log(p_vend->p_log, OSM_LOG_ERROR,
1135                                 "osm_vendor_send: ERR 3B28: "
1136                                 "Unable to create address vector (%s).\n",
1137                                 ib_get_err_str(status));
1138
1139                         if (p_vw->p_resp_madw)
1140                                 osm_mad_pool_put(p_bind->p_osm_pool,
1141                                                  p_vw->p_resp_madw);
1142                         goto Exit;
1143                 }
1144
1145                 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
1146                         osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1147                                 "osm_vendor_send: "
1148                                 "Allocating av handle %p.\n", p_vw->h_av);
1149                 }
1150         } else {
1151                 p_vw->h_av = p_bind->h_dr_av;
1152         }
1153
1154         p_elem->h_av = p_vw->h_av;
1155
1156         p_elem->context1 = p_madw;
1157         p_elem->context2 = NULL;
1158
1159         p_elem->immediate_data = 0;
1160         p_elem->p_grh = NULL;
1161         p_elem->resp_expected = resp_expected;
1162         p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
1163
1164         p_elem->send_opt = IB_SEND_OPT_SIGNALED;
1165         p_elem->timeout_ms = p_vend->timeout;
1166
1167         /* Completion information. */
1168         p_elem->status = 0;     /* Not trusting AL */
1169
1170         if ((p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
1171             (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)) {
1172                 p_elem->remote_qp = 0;
1173                 p_elem->remote_qkey = 0;
1174         } else {
1175                 p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
1176                 p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
1177                 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1178                         "osm_vendor_send: "
1179                         "remote qp = 0x%X, remote qkey = 0x%X.\n",
1180                         cl_ntoh32(p_elem->remote_qp),
1181                         cl_ntoh32(p_elem->remote_qkey));
1182         }
1183
1184         status = ib_send_mad(p_bind->h_svc, p_elem, NULL);
1185         if (status != IB_SUCCESS) {
1186                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1187                         "osm_vendor_send: ERR 3B29: "
1188                         "Send failed (%s).\n", ib_get_err_str(status));
1189                 if (p_vw->p_resp_madw)
1190                         osm_mad_pool_put(p_bind->p_osm_pool, p_vw->p_resp_madw);
1191                 goto Exit;
1192         }
1193
1194 Exit:
1195         OSM_LOG_EXIT(p_vend->p_log);
1196         return (status);
1197 }
1198
1199 ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
1200 {
1201         osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1202         osm_vendor_t *p_vend = p_bind->p_vend;
1203         ib_av_attr_t av;
1204         ib_api_status_t status;
1205
1206         OSM_LOG_ENTER(p_vend->p_log);
1207
1208         /*
1209            The only thing we need to do is refresh the directed
1210            route address vector.
1211          */
1212         __osm_vendor_init_av(p_bind, &av);
1213
1214         status = ib_destroy_av(p_bind->h_dr_av);
1215         if (status != IB_SUCCESS) {
1216                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1217                         "osm_vendor_local_lid_change: ERR 3B32: "
1218                         "Unable to destroy address vector (%s).\n",
1219                         ib_get_err_str(status));
1220
1221                 goto Exit;
1222         }
1223
1224         status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
1225         if (status != IB_SUCCESS) {
1226                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1227                         "osm_vendor_local_lid_change: ERR 3B33: "
1228                         "Unable to create address vector (%s).\n",
1229                         ib_get_err_str(status));
1230
1231                 goto Exit;
1232         }
1233
1234 Exit:
1235         OSM_LOG_EXIT(p_vend->p_log);
1236         return (status);
1237 }
1238
1239 void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
1240 {
1241         osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1242         osm_vendor_t *p_vend = p_bind->p_vend;
1243         ib_api_status_t status;
1244         ib_port_attr_mod_t attr_mod;
1245
1246         OSM_LOG_ENTER(p_vend->p_log);
1247
1248         memset(&attr_mod, 0, sizeof(attr_mod));
1249
1250         attr_mod.cap.sm = is_sm_val;
1251
1252         status = ib_modify_ca(p_vend->h_ca, p_bind->port_num,
1253                               IB_CA_MOD_IS_SM, &attr_mod);
1254
1255         if (status != IB_SUCCESS) {
1256                 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1257                         "osm_vendor_set_sm: ERR 3B34: "
1258                         "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
1259                         is_sm_val, ib_get_err_str(status));
1260         }
1261
1262         OSM_LOG_EXIT(p_vend->p_log);
1263 }
1264
1265 void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
1266 {
1267
1268 }
1269
1270 #endif                          /* OSM_VENDOR_INTF_AL */