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.
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:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
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.
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
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.
45 Next available error code: 0x300
50 #endif /* HAVE_CONFIG_H */
52 #ifdef OSM_VENDOR_INTF_AL
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>
66 /****s* OpenSM: Vendor AL/osm_al_bind_info_t
71 * Structure containing bind information.
75 typedef struct _osm_al_bind_info {
79 ib_mad_svc_handle_t h_svc;
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;
91 * Pointer to the vendor object.
94 * User's context passed during osm_bind
97 * Handle the QP for this bind.
100 * Handle the QP mad service for this bind.
103 * Port number (within the HCA) of the bound port.
106 * Pool key returned by all for this QP.
109 * Address vector handle used for all directed route SMPs.
114 /**********************************************************************
115 **********************************************************************/
116 inline static ib_api_status_t
117 __osm_al_convert_wcs(IN ib_wc_status_t const wc_status)
123 case IB_WCS_TIMEOUT_RETRY_ERR:
131 /**********************************************************************
132 **********************************************************************/
133 static void __osm_al_ca_err_callback(IN ib_async_event_rec_t * p_async_rec)
135 osm_vendor_t *p_vend = (osm_vendor_t *) p_async_rec->context;
136 OSM_LOG_ENTER(p_vend->p_log);
138 osm_log(p_vend->p_log, OSM_LOG_ERROR,
139 "__osm_al_ca_err_callback: ERR 3B01: "
140 "Event on channel adapter (%s).\n",
141 ib_get_async_event_str(p_async_rec->code));
143 OSM_LOG_EXIT(p_vend->p_log);
146 /**********************************************************************
147 **********************************************************************/
148 static void __osm_al_ca_destroy_callback(IN void *context)
150 osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) context;
151 osm_vendor_t *p_vend = p_bind->p_vend;
152 OSM_LOG_ENTER(p_vend->p_log);
154 osm_log(p_vend->p_log, OSM_LOG_INFO,
155 "__osm_al_ca_destroy_callback: "
156 "Closing local channel adapter.\n");
158 OSM_LOG_EXIT(p_vend->p_log);
161 /**********************************************************************
162 **********************************************************************/
163 static void __osm_al_err_callback(IN ib_async_event_rec_t * p_async_rec)
165 osm_al_bind_info_t *p_bind =
166 (osm_al_bind_info_t *) p_async_rec->context;
167 osm_vendor_t *p_vend = p_bind->p_vend;
168 OSM_LOG_ENTER(p_vend->p_log);
170 osm_log(p_vend->p_log, OSM_LOG_ERROR,
171 "__osm_al_err_callback: ERR 3B02: "
172 "Error on QP (%s).\n",
173 ib_get_async_event_str(p_async_rec->code));
175 OSM_LOG_EXIT(p_vend->p_log);
178 /**********************************************************************
179 **********************************************************************/
181 __osm_al_send_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
183 osm_al_bind_info_t *const p_bind =
184 (osm_al_bind_info_t *) mad_svc_context;
185 osm_vendor_t *const p_vend = p_bind->p_vend;
186 osm_madw_t *const p_madw = (osm_madw_t *) p_elem->context1;
187 osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
190 OSM_LOG_ENTER(p_vend->p_log);
193 CL_ASSERT(p_vw->h_av);
196 Destroy the address vector as necessary.
198 if (p_vw->h_av != p_bind->h_dr_av) {
199 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
200 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
201 "__osm_al_send_callback: "
202 "Destroying av handle %p.\n", p_vw->h_av);
205 ib_destroy_av(p_vw->h_av);
208 p_mad = ib_get_mad_buf(p_elem);
210 if (p_elem->resp_expected) {
212 If the send was unsuccessful, notify the user
213 for MADs that were expecting a response.
214 A NULL mad wrapper parameter is the user's clue
215 that the transaction turned sour.
217 Otherwise, do nothing for successful sends when a
218 reponse is expected. The mad will be returned to the
221 p_madw->status = __osm_al_convert_wcs(p_elem->status);
222 if (p_elem->status != IB_WCS_SUCCESS) {
223 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
224 "__osm_al_send_callback: "
225 "MAD completed with work queue error: %s.\n",
226 ib_get_wc_status_str(p_elem->status));
228 Return any wrappers to the pool that may have been
229 pre-emptively allocated to handle a receive.
231 if (p_vw->p_resp_madw) {
232 osm_mad_pool_put(p_bind->p_osm_pool,
234 p_vw->p_resp_madw = NULL;
237 p_bind->send_err_callback(p_bind->client_context,
241 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
242 "__osm_al_send_callback: "
243 "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",
244 cl_ntoh64(p_mad->trans_id));
245 osm_mad_pool_put(p_bind->p_osm_pool, p_madw);
250 OSM_LOG_EXIT(p_vend->p_log);
253 /**********************************************************************
254 **********************************************************************/
256 __osm_al_rcv_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
258 osm_al_bind_info_t *const p_bind =
259 (osm_al_bind_info_t *) mad_svc_context;
260 osm_vendor_t *const p_vend = p_bind->p_vend;
261 osm_madw_t *p_old_madw;
262 osm_madw_t *p_new_madw;
263 osm_vend_wrap_t *p_old_vw;
264 osm_vend_wrap_t *p_new_vw;
266 osm_mad_addr_t mad_addr;
268 OSM_LOG_ENTER(p_vend->p_log);
270 CL_ASSERT(p_elem->context1 == NULL);
271 CL_ASSERT(p_elem->context2 == NULL);
273 p_new_mad = ib_get_mad_buf(p_elem);
276 In preperation for initializing the new mad wrapper,
277 Initialize the mad_addr structure for the received wire MAD.
279 mad_addr.dest_lid = p_elem->remote_lid;
280 mad_addr.path_bits = p_elem->path_bits;
282 /* TO DO - figure out which #define to use for the 2.5 Gb rate... */
283 mad_addr.static_rate = 0;
285 if (p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
286 p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR) {
287 mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
289 mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
290 mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
291 mad_addr.addr_type.gsi.pkey_ix = p_elem->pkey_index;
292 mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
293 mad_addr.addr_type.gsi.global_route = FALSE;
297 If this MAD is a response to a previous request,
298 then grab our pre-allocated MAD wrapper.
299 Otherwise, allocate a new MAD wrapper.
301 if (ib_mad_is_response(p_new_mad)) {
302 CL_ASSERT(p_elem->send_context1 != NULL);
303 CL_ASSERT(p_elem->send_context2 == NULL);
305 p_old_madw = (osm_madw_t *) p_elem->send_context1;
306 p_old_vw = osm_madw_get_vend_ptr(p_old_madw);
307 p_new_madw = p_old_vw->p_resp_madw;
309 CL_ASSERT(p_new_madw);
311 osm_madw_init(p_new_madw, p_bind, p_elem->size, &mad_addr);
312 osm_madw_set_mad(p_new_madw, p_new_mad);
314 CL_ASSERT(p_elem->send_context1 == NULL);
315 CL_ASSERT(p_elem->send_context2 == NULL);
317 p_new_madw = osm_mad_pool_get_wrapper(p_bind->p_osm_pool,
318 p_bind, p_elem->size,
319 p_new_mad, &mad_addr);
322 CL_ASSERT(p_new_madw);
323 p_new_vw = osm_madw_get_vend_ptr(p_new_madw);
325 p_new_vw->h_bind = p_bind;
326 p_new_vw->size = p_elem->size;
327 p_new_vw->p_elem = p_elem;
329 p_new_vw->p_resp_madw = NULL;
331 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
332 "__osm_al_rcv_callback: "
333 "Calling receive callback function %p.\n",
334 p_bind->rcv_callback);
336 p_bind->rcv_callback(p_new_madw, p_bind->client_context,
337 p_elem->send_context1);
339 OSM_LOG_EXIT(p_vend->p_log);
342 /**********************************************************************
343 **********************************************************************/
345 osm_vendor_init(IN osm_vendor_t * const p_vend,
346 IN osm_log_t * const p_log, IN const uint32_t timeout)
348 ib_api_status_t status;
349 OSM_LOG_ENTER(p_log);
351 p_vend->p_log = p_log;
354 Open our instance of AL.
356 status = ib_open_al(&p_vend->h_al);
357 if (status != IB_SUCCESS) {
358 osm_log(p_vend->p_log, OSM_LOG_ERROR,
359 "osm_vendor_init: ERR 3B03: "
360 "Error opening AL (%s).\n", ib_get_err_str(status));
365 p_vend->timeout = timeout;
372 /**********************************************************************
373 **********************************************************************/
374 osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
375 IN const uint32_t timeout)
377 ib_api_status_t status;
378 osm_vendor_t *p_vend;
380 OSM_LOG_ENTER(p_log);
382 p_vend = malloc(sizeof(*p_vend));
383 if (p_vend == NULL) {
384 osm_log(p_vend->p_log, OSM_LOG_ERROR,
385 "osm_vendor_new: ERR 3B04: "
386 "Unable to allocate vendor object.\n");
390 memset(p_vend, 0, sizeof(*p_vend));
392 status = osm_vendor_init(p_vend, p_log, timeout);
393 if (status != IB_SUCCESS) {
403 /**********************************************************************
404 **********************************************************************/
405 void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
407 /* TO DO - fill this in */
408 ib_close_al((*pp_vend)->h_al);
413 /**********************************************************************
414 **********************************************************************/
415 static ib_api_status_t
416 __osm_ca_info_init(IN osm_vendor_t * const p_vend,
417 IN osm_ca_info_t * const p_ca_info,
418 IN const ib_net64_t ca_guid)
420 ib_api_status_t status;
422 OSM_LOG_ENTER(p_vend->p_log);
424 p_ca_info->guid = ca_guid;
426 if (osm_log_is_active(p_vend->p_log, OSM_LOG_VERBOSE)) {
427 osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
428 "__osm_ca_info_init: "
429 "Querying CA 0x%" PRIx64 ".\n", cl_ntoh64(ca_guid));
432 status = ib_query_ca_by_guid(p_vend->h_al, ca_guid, NULL,
433 &p_ca_info->attr_size);
434 if ((status != IB_INSUFFICIENT_MEMORY) && (status != IB_SUCCESS)) {
435 osm_log(p_vend->p_log, OSM_LOG_ERROR,
436 "__osm_ca_info_init: ERR 3B05: "
437 "Unexpected status getting CA attributes (%s).\n",
438 ib_get_err_str(status));
442 CL_ASSERT(p_ca_info->attr_size);
444 p_ca_info->p_attr = malloc(p_ca_info->attr_size);
445 if (p_ca_info->p_attr == NULL) {
446 osm_log(p_vend->p_log, OSM_LOG_ERROR,
447 "__osm_ca_info_init: ERR 3B06: "
448 "Unable to allocate attribute storage.\n");
452 status = ib_query_ca_by_guid(p_vend->h_al, ca_guid, p_ca_info->p_attr,
453 &p_ca_info->attr_size);
454 if (status != IB_SUCCESS) {
455 osm_log(p_vend->p_log, OSM_LOG_ERROR,
456 "__osm_ca_info_init: ERR 3B07: "
457 "Unexpected status getting CA attributes (%s).\n",
458 ib_get_err_str(status));
463 OSM_LOG_EXIT(p_vend->p_log);
467 /**********************************************************************
468 **********************************************************************/
470 osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
471 IN osm_ca_info_t * const p_ca_info)
473 OSM_LOG_ENTER(p_vend->p_log);
475 if (p_ca_info->p_attr)
476 free(p_ca_info->p_attr);
480 OSM_LOG_EXIT(p_vend->p_log);
483 /**********************************************************************
484 **********************************************************************/
485 osm_ca_info_t *osm_ca_info_new(IN osm_vendor_t * const p_vend,
486 IN const ib_net64_t ca_guid)
488 ib_api_status_t status;
489 osm_ca_info_t *p_ca_info;
491 OSM_LOG_ENTER(p_vend->p_log);
495 p_ca_info = malloc(sizeof(*p_ca_info));
496 if (p_ca_info == NULL)
499 memset(p_ca_info, 0, sizeof(*p_ca_info));
501 status = __osm_ca_info_init(p_vend, p_ca_info, ca_guid);
502 if (status != IB_SUCCESS) {
503 osm_ca_info_destroy(p_vend, p_ca_info);
509 OSM_LOG_EXIT(p_vend->p_log);
513 /**********************************************************************
514 **********************************************************************/
515 static ib_api_status_t
516 __osm_vendor_get_ca_guids(IN osm_vendor_t * const p_vend,
517 IN ib_net64_t ** const p_guids,
518 IN uintn_t * const p_num_guids)
520 ib_api_status_t status;
522 OSM_LOG_ENTER(p_vend->p_log);
525 CL_ASSERT(p_num_guids);
527 status = ib_get_ca_guids(p_vend->h_al, NULL, p_num_guids);
528 if ((status != IB_INSUFFICIENT_MEMORY) && (status != IB_SUCCESS)) {
529 osm_log(p_vend->p_log, OSM_LOG_ERROR,
530 "__osm_vendor_get_ca_guids: ERR 3B08: "
531 "Unexpected status getting CA GUID array (%s).\n",
532 ib_get_err_str(status));
536 if (*p_num_guids == 0) {
537 osm_log(p_vend->p_log, OSM_LOG_ERROR,
538 "__osm_vendor_get_ca_guids: ERR 3B09: "
539 "No available channel adapters.\n");
540 status = IB_INSUFFICIENT_RESOURCES;
544 *p_guids = malloc(*p_num_guids * sizeof(**p_guids));
545 if (*p_guids == NULL) {
546 osm_log(p_vend->p_log, OSM_LOG_ERROR,
547 "__osm_vendor_get_ca_guids: ERR 3B10: "
548 "Unable to allocate CA GUID array.\n");
552 status = ib_get_ca_guids(p_vend->h_al, *p_guids, p_num_guids);
553 CL_ASSERT(*p_num_guids);
555 if (osm_log_is_active(p_vend->p_log, OSM_LOG_VERBOSE)) {
556 osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
557 "__osm_vendor_get_ca_guids: "
558 "Detected %u local channel adapters.\n", *p_num_guids);
562 OSM_LOG_EXIT(p_vend->p_log);
566 /****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
568 * osm_ca_info_get_pi_ptr
571 * Returns a pointer to the port attribute of the specified port
576 static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
578 IN const uint8_t index)
580 return (&p_ca_info->p_attr->p_port_attr[index]);
586 * [in] Pointer to a CA Info object.
589 * [in] Port "index" for which to retrieve the port attribute.
590 * The index is the offset into the ca's internal array
591 * of port attributes.
594 * Returns a pointer to the port attribute of the specified port
602 /**********************************************************************
603 **********************************************************************/
605 osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
606 IN ib_port_attr_t * const p_attr_array,
607 IN uint32_t * const p_num_ports)
609 ib_api_status_t status;
613 uint32_t port_count = 0;
615 uint32_t total_ports = 0;
616 ib_net64_t *p_ca_guid = NULL;
617 osm_ca_info_t *p_ca_info;
619 OSM_LOG_ENTER(p_vend->p_log);
622 CL_ASSERT(p_vend->p_ca_info == NULL);
625 1) Determine the number of CA's
626 2) Allocate an array big enough to hold the ca info objects.
627 3) Call again to retrieve the guids.
629 status = __osm_vendor_get_ca_guids(p_vend, &p_ca_guid, &ca_count);
631 p_vend->p_ca_info = malloc(ca_count * sizeof(*p_vend->p_ca_info));
632 if (p_vend->p_ca_info == NULL) {
633 osm_log(p_vend->p_log, OSM_LOG_ERROR,
634 "osm_vendor_get_all_port_attr: ERR 3B11: "
635 "Unable to allocate CA information array.\n");
639 memset(p_vend->p_ca_info, 0, ca_count * sizeof(*p_vend->p_ca_info));
640 p_vend->ca_count = ca_count;
643 For each CA, retrieve the port info attributes
645 for (ca = 0; ca < ca_count; ca++) {
646 p_ca_info = &p_vend->p_ca_info[ca];
648 status = __osm_ca_info_init(p_vend, p_ca_info, p_ca_guid[ca]);
650 if (status != IB_SUCCESS) {
651 osm_log(p_vend->p_log, OSM_LOG_ERROR,
652 "osm_vendor_get_all_port_attr: ERR 3B12: "
653 "Unable to initialize CA Info object (%s).\n",
654 ib_get_err_str(status));
657 total_ports += osm_ca_info_get_num_ports(p_ca_info);
661 If the user supplied enough storage, return the port guids,
662 otherwise, return the appropriate error.
664 if (*p_num_ports >= total_ports) {
665 for (ca = 0; ca < ca_count; ca++) {
668 p_ca_info = &p_vend->p_ca_info[ca];
670 num_ports = osm_ca_info_get_num_ports(p_ca_info);
672 for (port_num = 0; port_num < num_ports; port_num++) {
673 p_attr_array[port_count] =
674 *__osm_ca_info_get_port_attr_ptr(p_ca_info,
680 status = IB_INSUFFICIENT_MEMORY;
683 *p_num_ports = total_ports;
689 OSM_LOG_EXIT(p_vend->p_log);
693 /**********************************************************************
694 **********************************************************************/
696 osm_vendor_get_ca_guid(IN osm_vendor_t * const p_vend,
697 IN const ib_net64_t port_guid)
701 uint32_t num_guids = 0;
702 osm_ca_info_t *p_ca_info;
705 OSM_LOG_ENTER(p_vend->p_log);
707 CL_ASSERT(port_guid);
709 First, locate the HCA that owns this port.
711 if (p_vend->p_ca_info == NULL) {
713 Initialize the osm_ca_info_t array which allows
714 us to match port GUID to CA.
716 osm_vendor_get_all_port_attr(p_vend, NULL, &num_guids);
719 CL_ASSERT(p_vend->p_ca_info);
720 CL_ASSERT(p_vend->ca_count);
722 for (ca = 0; ca < p_vend->ca_count; ca++) {
723 p_ca_info = &p_vend->p_ca_info[ca];
725 num_ports = osm_ca_info_get_num_ports(p_ca_info);
726 CL_ASSERT(num_ports);
728 for (index = 0; index < num_ports; index++) {
730 osm_ca_info_get_port_guid(p_ca_info, index)) {
731 OSM_LOG_EXIT(p_vend->p_log);
732 return (osm_ca_info_get_ca_guid(p_ca_info));
738 No local CA owns this guid!
740 osm_log(p_vend->p_log, OSM_LOG_ERROR,
741 "osm_vendor_get_ca_guid: ERR 3B13: "
742 "Unable to determine CA guid.\n");
744 OSM_LOG_EXIT(p_vend->p_log);
748 /**********************************************************************
749 **********************************************************************/
751 osm_vendor_get_port_num(IN osm_vendor_t * const p_vend,
752 IN const ib_net64_t port_guid)
756 uint32_t num_guids = 0;
757 osm_ca_info_t *p_ca_info;
760 OSM_LOG_ENTER(p_vend->p_log);
762 CL_ASSERT(port_guid);
764 First, locate the HCA that owns this port.
766 if (p_vend->p_ca_info == NULL) {
768 Initialize the osm_ca_info_t array which allows
769 us to match port GUID to CA.
771 osm_vendor_get_all_port_attr(p_vend, NULL, &num_guids);
774 CL_ASSERT(p_vend->p_ca_info);
775 CL_ASSERT(p_vend->ca_count);
777 for (ca = 0; ca < p_vend->ca_count; ca++) {
778 p_ca_info = &p_vend->p_ca_info[ca];
780 num_ports = osm_ca_info_get_num_ports(p_ca_info);
781 CL_ASSERT(num_ports);
783 for (index = 0; index < num_ports; index++) {
785 osm_ca_info_get_port_guid(p_ca_info, index)) {
786 OSM_LOG_EXIT(p_vend->p_log);
787 return (osm_ca_info_get_port_num
794 No local CA owns this guid!
796 osm_log(p_vend->p_log, OSM_LOG_ERROR,
797 "osm_vendor_get_port_num: ERR 3B30: "
798 "Unable to determine CA guid.\n");
800 OSM_LOG_EXIT(p_vend->p_log);
804 /**********************************************************************
805 **********************************************************************/
806 static ib_api_status_t
807 __osm_vendor_open_ca(IN osm_vendor_t * const p_vend,
808 IN const ib_net64_t port_guid)
811 ib_api_status_t status;
813 OSM_LOG_ENTER(p_vend->p_log);
815 ca_guid = osm_vendor_get_ca_guid(p_vend, port_guid);
817 osm_log(p_vend->p_log, OSM_LOG_ERROR,
818 "__osm_vendor_open_ca: ERR 3B31: "
819 "Bad port GUID value 0x%" PRIx64 ".\n",
820 cl_ntoh64(port_guid));
825 osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
826 "__osm_vendor_open_ca: "
827 "Opening HCA 0x%" PRIx64 ".\n", cl_ntoh64(ca_guid));
829 status = ib_open_ca(p_vend->h_al,
831 __osm_al_ca_err_callback, p_vend, &p_vend->h_ca);
833 if (status != IB_SUCCESS) {
834 osm_log(p_vend->p_log, OSM_LOG_ERROR,
835 "__osm_vendor_open_ca: ERR 3B15: "
836 "Unable to open CA (%s).\n", ib_get_err_str(status));
840 CL_ASSERT(p_vend->h_ca);
842 status = ib_alloc_pd(p_vend->h_ca, IB_PDT_ALIAS, p_vend, &p_vend->h_pd);
844 if (status != IB_SUCCESS) {
845 ib_close_ca(p_vend->h_ca, __osm_al_ca_destroy_callback);
846 osm_log(p_vend->p_log, OSM_LOG_ERROR,
847 "__osm_vendor_open_ca: ERR 3B16: "
848 "Unable to allocate protection domain (%s).\n",
849 ib_get_err_str(status));
853 CL_ASSERT(p_vend->h_pd);
856 OSM_LOG_EXIT(p_vend->p_log);
860 /**********************************************************************
861 **********************************************************************/
863 __osm_vendor_init_av(IN const osm_al_bind_info_t * p_bind,
864 IN ib_av_attr_t * p_av)
866 memset(p_av, 0, sizeof(*p_av));
867 p_av->port_num = p_bind->port_num;
868 p_av->dlid = IB_LID_PERMISSIVE;
871 /**********************************************************************
872 **********************************************************************/
874 osm_vendor_bind(IN osm_vendor_t * const p_vend,
875 IN osm_bind_info_t * const p_user_bind,
876 IN osm_mad_pool_t * const p_mad_pool,
877 IN osm_vend_mad_recv_callback_t mad_recv_callback,
878 IN osm_vend_mad_send_err_callback_t send_err_callback,
881 ib_net64_t port_guid;
882 osm_al_bind_info_t *p_bind = 0;
883 ib_api_status_t status;
884 ib_qp_create_t qp_create;
885 ib_mad_svc_t mad_svc;
888 OSM_LOG_ENTER(p_vend->p_log);
890 CL_ASSERT(p_user_bind);
891 CL_ASSERT(p_mad_pool);
892 CL_ASSERT(mad_recv_callback);
893 CL_ASSERT(send_err_callback);
895 port_guid = p_user_bind->port_guid;
897 osm_log(p_vend->p_log, OSM_LOG_INFO,
899 "Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));
901 if (p_vend->h_ca == 0) {
902 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
904 "Opening CA that owns port 0x%" PRIx64 ".\n",
907 status = __osm_vendor_open_ca(p_vend, port_guid);
908 if (status != IB_SUCCESS) {
909 osm_log(p_vend->p_log, OSM_LOG_ERROR,
910 "osm_vendor_bind: ERR 3B17: "
911 "Unable to Open CA (%s).\n",
912 ib_get_err_str(status));
917 p_bind = malloc(sizeof(*p_bind));
918 if (p_bind == NULL) {
919 osm_log(p_vend->p_log, OSM_LOG_ERROR,
920 "osm_vendor_bind: ERR 3B18: "
921 "Unable to allocate internal bind object.\n");
925 memset(p_bind, 0, sizeof(*p_bind));
926 p_bind->p_vend = p_vend;
927 p_bind->client_context = context;
928 p_bind->port_num = osm_vendor_get_port_num(p_vend, port_guid);
929 p_bind->rcv_callback = mad_recv_callback;
930 p_bind->send_err_callback = send_err_callback;
931 p_bind->p_osm_pool = p_mad_pool;
933 CL_ASSERT(p_bind->port_num);
938 memset(&qp_create, 0, sizeof(qp_create));
940 switch (p_user_bind->mad_class) {
941 case IB_MCLASS_SUBN_LID:
942 case IB_MCLASS_SUBN_DIR:
943 qp_create.qp_type = IB_QPT_QP0_ALIAS;
946 case IB_MCLASS_SUBN_ADM:
948 qp_create.qp_type = IB_QPT_QP1_ALIAS;
952 qp_create.sq_depth = p_user_bind->send_q_size;
953 qp_create.rq_depth = p_user_bind->recv_q_size;
954 qp_create.sq_sge = OSM_AL_SQ_SGE;
955 qp_create.rq_sge = OSM_AL_RQ_SGE;
957 status = ib_get_spl_qp(p_vend->h_pd,
961 __osm_al_err_callback,
962 &p_bind->pool_key, &p_bind->h_qp);
964 if (status != IB_SUCCESS) {
966 osm_log(p_vend->p_log, OSM_LOG_ERROR,
967 "osm_vendor_bind: ERR 3B19: "
968 "Unable to get QP handle (%s).\n",
969 ib_get_err_str(status));
973 CL_ASSERT(p_bind->h_qp);
974 CL_ASSERT(p_bind->pool_key);
976 memset(&mad_svc, 0, sizeof(mad_svc));
978 mad_svc.mad_svc_context = p_bind;
979 mad_svc.pfn_mad_send_cb = __osm_al_send_callback;
980 mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
981 mad_svc.mgmt_class = p_user_bind->mad_class;
982 mad_svc.mgmt_version = p_user_bind->class_version;
983 mad_svc.support_unsol = p_user_bind->is_responder;
984 mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
985 mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
986 mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
987 mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
988 mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
990 status = ib_reg_mad_svc(p_bind->h_qp, &mad_svc, &p_bind->h_svc);
992 if (status != IB_SUCCESS) {
994 osm_log(p_vend->p_log, OSM_LOG_ERROR,
995 "osm_vendor_bind: ERR 3B21: "
996 "Unable to register QP0 MAD service (%s).\n",
997 ib_get_err_str(status));
1001 __osm_vendor_init_av(p_bind, &av);
1003 status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
1004 if (status != IB_SUCCESS) {
1005 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1006 "osm_vendor_bind: ERR 3B22: "
1007 "Unable to create address vector (%s).\n",
1008 ib_get_err_str(status));
1013 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
1014 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1016 "Allocating av handle %p.\n", p_bind->h_dr_av);
1020 OSM_LOG_EXIT(p_vend->p_log);
1021 return ((osm_bind_handle_t) p_bind);
1024 /**********************************************************************
1025 **********************************************************************/
1026 ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
1027 IN const uint32_t mad_size,
1028 IN osm_vend_wrap_t * const p_vw)
1031 osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1032 osm_vendor_t *p_vend = p_bind->p_vend;
1033 ib_api_status_t status;
1035 OSM_LOG_ENTER(p_vend->p_log);
1039 p_vw->size = mad_size;
1040 p_vw->h_bind = h_bind;
1043 Retrieve a MAD element from the pool and give the user direct
1044 access to its buffer.
1046 status = ib_get_mad(p_bind->pool_key, mad_size, &p_vw->p_elem);
1047 if (status != IB_SUCCESS) {
1048 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1049 "osm_vendor_get: ERR 3B25: "
1050 "Unable to acquire MAD (%s).\n",
1051 ib_get_err_str(status));
1057 CL_ASSERT(p_vw->p_elem);
1058 p_mad = ib_get_mad_buf(p_vw->p_elem);
1060 if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
1061 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1063 "Acquired MAD %p, size = %u.\n", p_mad, mad_size);
1067 OSM_LOG_EXIT(p_vend->p_log);
1071 /**********************************************************************
1072 **********************************************************************/
1074 osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
1076 osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1077 osm_vendor_t *p_vend = p_bind->p_vend;
1078 ib_api_status_t status;
1080 OSM_LOG_ENTER(p_vend->p_log);
1083 CL_ASSERT(p_vw->p_elem);
1084 CL_ASSERT(p_vw->h_bind == h_bind);
1086 if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
1087 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1089 "Retiring MAD %p.\n", ib_get_mad_buf(p_vw->p_elem));
1092 status = ib_put_mad(p_vw->p_elem);
1093 if (status != IB_SUCCESS) {
1094 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1095 "osm_vendor_put: ERR 3B26: "
1096 "Unable to retire MAD (%s).\n", ib_get_err_str(status));
1099 OSM_LOG_EXIT(p_vend->p_log);
1102 /**********************************************************************
1103 **********************************************************************/
1105 osm_vendor_send(IN osm_bind_handle_t h_bind,
1106 IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
1108 osm_al_bind_info_t *const p_bind = h_bind;
1109 osm_vendor_t *const p_vend = p_bind->p_vend;
1110 osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
1111 osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
1112 ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
1113 ib_api_status_t status;
1114 ib_mad_element_t *p_elem;
1117 OSM_LOG_ENTER(p_vend->p_log);
1119 CL_ASSERT(p_vw->h_bind == h_bind);
1120 CL_ASSERT(p_vw->p_elem);
1122 p_elem = p_vw->p_elem;
1125 If a response is expected to this MAD, then preallocate
1126 a mad wrapper to contain the wire MAD received in the
1127 response. Allocating a wrapper here allows for easier
1128 failure paths than after we already received the wire mad.
1130 if (resp_expected) {
1132 osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool);
1133 if (p_vw->p_resp_madw == NULL) {
1134 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1135 "osm_vendor_send: ERR 3B27: "
1136 "Unable to allocate MAD wrapper.\n");
1137 status = IB_INSUFFICIENT_RESOURCES;
1141 p_vw->p_resp_madw = NULL;
1144 For all sends other than directed route SM MADs,
1145 acquire an address vector for the destination.
1147 if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
1148 memset(&av, 0, sizeof(av));
1149 av.port_num = p_bind->port_num;
1150 av.dlid = p_mad_addr->dest_lid;
1151 av.static_rate = p_mad_addr->static_rate;
1152 av.path_bits = p_mad_addr->path_bits;
1154 if ((p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
1155 (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR)) {
1156 av.sl = p_mad_addr->addr_type.gsi.service_level;
1158 if (p_mad_addr->addr_type.gsi.global_route) {
1159 av.grh_valid = TRUE;
1161 /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
1165 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
1166 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1168 "av.port_num 0x%X, "
1170 "av.static_rate %d, "
1171 "av.path_bits %d.\n",
1172 av.port_num, cl_ntoh16(av.dlid),
1173 av.static_rate, av.path_bits);
1176 status = ib_create_av(p_vend->h_pd, &av, &p_vw->h_av);
1177 if (status != IB_SUCCESS) {
1178 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1179 "osm_vendor_send: ERR 3B28: "
1180 "Unable to create address vector (%s).\n",
1181 ib_get_err_str(status));
1183 if (p_vw->p_resp_madw)
1184 osm_mad_pool_put(p_bind->p_osm_pool,
1189 if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
1190 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1192 "Allocating av handle %p.\n", p_vw->h_av);
1195 p_vw->h_av = p_bind->h_dr_av;
1198 p_elem->h_av = p_vw->h_av;
1200 p_elem->context1 = p_madw;
1201 p_elem->context2 = NULL;
1203 p_elem->immediate_data = 0;
1204 p_elem->p_grh = NULL;
1205 p_elem->resp_expected = resp_expected;
1206 p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
1208 p_elem->send_opt = IB_SEND_OPT_SIGNALED;
1209 p_elem->timeout_ms = p_vend->timeout;
1211 /* Completion information. */
1212 p_elem->status = 0; /* Not trusting AL */
1214 if ((p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
1215 (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)) {
1216 p_elem->remote_qp = 0;
1217 p_elem->remote_qkey = 0;
1219 p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
1220 p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
1221 osm_log(p_vend->p_log, OSM_LOG_DEBUG,
1223 "remote qp = 0x%X, remote qkey = 0x%X.\n",
1224 cl_ntoh32(p_elem->remote_qp),
1225 cl_ntoh32(p_elem->remote_qkey));
1228 status = ib_send_mad(p_bind->h_svc, p_elem, NULL);
1229 if (status != IB_SUCCESS) {
1230 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1231 "osm_vendor_send: ERR 3B29: "
1232 "Send failed (%s).\n", ib_get_err_str(status));
1233 if (p_vw->p_resp_madw)
1234 osm_mad_pool_put(p_bind->p_osm_pool, p_vw->p_resp_madw);
1239 OSM_LOG_EXIT(p_vend->p_log);
1243 /**********************************************************************
1244 **********************************************************************/
1245 ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
1247 osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1248 osm_vendor_t *p_vend = p_bind->p_vend;
1250 ib_api_status_t status;
1252 OSM_LOG_ENTER(p_vend->p_log);
1255 The only thing we need to do is refresh the directed
1256 route address vector.
1258 __osm_vendor_init_av(p_bind, &av);
1260 status = ib_destroy_av(p_bind->h_dr_av);
1261 if (status != IB_SUCCESS) {
1262 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1263 "osm_vendor_local_lid_change: ERR 3B32: "
1264 "Unable to destroy address vector (%s).\n",
1265 ib_get_err_str(status));
1270 status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
1271 if (status != IB_SUCCESS) {
1272 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1273 "osm_vendor_local_lid_change: ERR 3B33: "
1274 "Unable to create address vector (%s).\n",
1275 ib_get_err_str(status));
1281 OSM_LOG_EXIT(p_vend->p_log);
1285 /**********************************************************************
1286 **********************************************************************/
1287 void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
1289 osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
1290 osm_vendor_t *p_vend = p_bind->p_vend;
1291 ib_api_status_t status;
1292 ib_port_attr_mod_t attr_mod;
1294 OSM_LOG_ENTER(p_vend->p_log);
1296 memset(&attr_mod, 0, sizeof(attr_mod));
1298 attr_mod.cap.sm = is_sm_val;
1300 status = ib_modify_ca(p_vend->h_ca, p_bind->port_num,
1301 IB_CA_MOD_IS_SM, &attr_mod);
1303 if (status != IB_SUCCESS) {
1304 osm_log(p_vend->p_log, OSM_LOG_ERROR,
1305 "osm_vendor_set_sm: ERR 3B34: "
1306 "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
1307 is_sm_val, ib_get_err_str(status));
1310 OSM_LOG_EXIT(p_vend->p_log);
1313 /**********************************************************************
1314 **********************************************************************/
1315 void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
1320 #endif /* OSM_VENDOR_INTF_AL */