Blame libvendor/osm_vendor_al.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit 13e616
 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
Packit 13e616
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit 13e616
 *
Packit 13e616
 * This software is available to you under a choice of one of two
Packit 13e616
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit 13e616
 * General Public License (GPL) Version 2, available from the file
Packit 13e616
 * COPYING in the main directory of this source tree, or the
Packit 13e616
 * OpenIB.org BSD license below:
Packit 13e616
 *
Packit 13e616
 *     Redistribution and use in source and binary forms, with or
Packit 13e616
 *     without modification, are permitted provided that the following
Packit 13e616
 *     conditions are met:
Packit 13e616
 *
Packit 13e616
 *      - Redistributions of source code must retain the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer.
Packit 13e616
 *
Packit 13e616
 *      - Redistributions in binary form must reproduce the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer in the documentation and/or other materials
Packit 13e616
 *        provided with the distribution.
Packit 13e616
 *
Packit 13e616
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 13e616
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 13e616
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 13e616
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit 13e616
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit 13e616
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 13e616
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit 13e616
 * SOFTWARE.
Packit 13e616
 *
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Abstract:
Packit 13e616
 *    Implementation of osm_req_t.
Packit 13e616
 * This object represents the generic attribute requester.
Packit 13e616
 * This object is part of the opensm family of objects.
Packit 13e616
 *
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
  Next available error code: 0x300
Packit 13e616
*/
Packit 13e616
Packit 13e616
#if HAVE_CONFIG_H
Packit 13e616
#  include <config.h>
Packit 13e616
#endif				/* HAVE_CONFIG_H */
Packit 13e616
Packit 13e616
#ifdef OSM_VENDOR_INTF_AL
Packit 13e616
Packit 13e616
#include <stdlib.h>
Packit 13e616
#include <string.h>
Packit 13e616
#include <complib/cl_qlist.h>
Packit 13e616
#include <complib/cl_thread.h>
Packit 13e616
#include <complib/cl_math.h>
Packit 13e616
#include <complib/cl_debug.h>
Packit 13e616
#include <iba/ib_types.h>
Packit 13e616
#include <opensm/osm_madw.h>
Packit 13e616
#include <opensm/osm_log.h>
Packit 13e616
#include <opensm/osm_mad_pool.h>
Packit 13e616
#include <vendor/osm_vendor_api.h>
Packit 13e616
Packit 13e616
/****s* OpenSM: Vendor AL/osm_al_bind_info_t
Packit 13e616
 * NAME
Packit 13e616
 *   osm_al_bind_info_t
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 *    Structure containing bind information.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
typedef struct _osm_al_bind_info {
Packit 13e616
	osm_vendor_t *p_vend;
Packit 13e616
	void *client_context;
Packit 13e616
	ib_qp_handle_t h_qp;
Packit 13e616
	ib_mad_svc_handle_t h_svc;
Packit 13e616
	uint8_t port_num;
Packit 13e616
	ib_pool_key_t pool_key;
Packit 13e616
	osm_vend_mad_recv_callback_t rcv_callback;
Packit 13e616
	osm_vend_mad_send_err_callback_t send_err_callback;
Packit 13e616
	osm_mad_pool_t *p_osm_pool;
Packit 13e616
	ib_av_handle_t h_dr_av;
Packit 13e616
Packit 13e616
} osm_al_bind_info_t;
Packit 13e616
/*
Packit 13e616
 * FIELDS
Packit 13e616
 * p_vend
Packit 13e616
 *    Pointer to the vendor object.
Packit 13e616
 *
Packit 13e616
 * client_context
Packit 13e616
 *    User's context passed during osm_bind
Packit 13e616
 *
Packit 13e616
 * h_qp
Packit 13e616
 *    Handle the QP for this bind.
Packit 13e616
 *
Packit 13e616
 * h_qp_svc
Packit 13e616
 *    Handle the QP mad service for this bind.
Packit 13e616
 *
Packit 13e616
 * port_num
Packit 13e616
 *    Port number (within the HCA) of the bound port.
Packit 13e616
 *
Packit 13e616
 * pool_key
Packit 13e616
 *    Pool key returned by all for this QP.
Packit 13e616
 *
Packit 13e616
 * h_dr_av
Packit 13e616
 *    Address vector handle used for all directed route SMPs.
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
inline static ib_api_status_t
Packit 13e616
__osm_al_convert_wcs(IN ib_wc_status_t const wc_status)
Packit 13e616
{
Packit 13e616
	switch (wc_status) {
Packit 13e616
	case IB_WCS_SUCCESS:
Packit 13e616
		return (IB_SUCCESS);
Packit 13e616
Packit 13e616
	case IB_WCS_TIMEOUT_RETRY_ERR:
Packit 13e616
		return (IB_TIMEOUT);
Packit 13e616
Packit 13e616
	default:
Packit 13e616
		return (IB_ERROR);
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
static void __osm_al_ca_err_callback(IN ib_async_event_rec_t * p_async_rec)
Packit 13e616
{
Packit 13e616
	osm_vendor_t *p_vend = (osm_vendor_t *) p_async_rec->context;
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
		"__osm_al_ca_err_callback: ERR 3B01: "
Packit 13e616
		"Event on channel adapter (%s).\n",
Packit 13e616
		ib_get_async_event_str(p_async_rec->code));
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
static void __osm_al_ca_destroy_callback(IN void *context)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) context;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_INFO,
Packit 13e616
		"__osm_al_ca_destroy_callback: "
Packit 13e616
		"Closing local channel adapter.\n");
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
static void __osm_al_err_callback(IN ib_async_event_rec_t * p_async_rec)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *p_bind =
Packit 13e616
	    (osm_al_bind_info_t *) p_async_rec->context;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
		"__osm_al_err_callback: ERR 3B02: "
Packit 13e616
		"Error on QP (%s).\n",
Packit 13e616
		ib_get_async_event_str(p_async_rec->code));
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
static void
Packit 13e616
__osm_al_send_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *const p_bind =
Packit 13e616
	    (osm_al_bind_info_t *) mad_svc_context;
Packit 13e616
	osm_vendor_t *const p_vend = p_bind->p_vend;
Packit 13e616
	osm_madw_t *const p_madw = (osm_madw_t *) p_elem->context1;
Packit 13e616
	osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
Packit 13e616
	ib_mad_t *p_mad;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vw);
Packit 13e616
	CL_ASSERT(p_vw->h_av);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Destroy the address vector as necessary.
Packit 13e616
	 */
Packit 13e616
	if (p_vw->h_av != p_bind->h_dr_av) {
Packit 13e616
		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"__osm_al_send_callback: "
Packit 13e616
				"Destroying av handle %p.\n", p_vw->h_av);
Packit 13e616
		}
Packit 13e616
Packit 13e616
		ib_destroy_av(p_vw->h_av);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_mad = ib_get_mad_buf(p_elem);
Packit 13e616
Packit 13e616
	if (p_elem->resp_expected) {
Packit 13e616
		/*
Packit 13e616
		   If the send was unsuccessful, notify the user
Packit 13e616
		   for MADs that were expecting a response.
Packit 13e616
		   A NULL mad wrapper parameter is the user's clue
Packit 13e616
		   that the transaction turned sour.
Packit 13e616
Packit 13e616
		   Otherwise, do nothing for successful sends when a
Packit 13e616
		   reponse is expected.  The mad will be returned to the
Packit 13e616
		   pool later.
Packit 13e616
		 */
Packit 13e616
		p_madw->status = __osm_al_convert_wcs(p_elem->status);
Packit 13e616
		if (p_elem->status != IB_WCS_SUCCESS) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"__osm_al_send_callback: "
Packit 13e616
				"MAD completed with work queue error: %s.\n",
Packit 13e616
				ib_get_wc_status_str(p_elem->status));
Packit 13e616
			/*
Packit 13e616
			   Return any wrappers to the pool that may have been
Packit 13e616
			   pre-emptively allocated to handle a receive.
Packit 13e616
			 */
Packit 13e616
			if (p_vw->p_resp_madw) {
Packit 13e616
				osm_mad_pool_put(p_bind->p_osm_pool,
Packit 13e616
						 p_vw->p_resp_madw);
Packit 13e616
				p_vw->p_resp_madw = NULL;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			p_bind->send_err_callback(p_bind->client_context,
Packit 13e616
						  p_madw);
Packit 13e616
		}
Packit 13e616
	} else {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"__osm_al_send_callback: "
Packit 13e616
			"Returning MAD to pool, TID = 0x%" PRIx64 ".\n",
Packit 13e616
			cl_ntoh64(p_mad->trans_id));
Packit 13e616
		osm_mad_pool_put(p_bind->p_osm_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
static void
Packit 13e616
__osm_al_rcv_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *const p_bind =
Packit 13e616
	    (osm_al_bind_info_t *) mad_svc_context;
Packit 13e616
	osm_vendor_t *const p_vend = p_bind->p_vend;
Packit 13e616
	osm_madw_t *p_old_madw;
Packit 13e616
	osm_madw_t *p_new_madw;
Packit 13e616
	osm_vend_wrap_t *p_old_vw;
Packit 13e616
	osm_vend_wrap_t *p_new_vw;
Packit 13e616
	ib_mad_t *p_new_mad;
Packit 13e616
	osm_mad_addr_t mad_addr;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_elem->context1 == NULL);
Packit 13e616
	CL_ASSERT(p_elem->context2 == NULL);
Packit 13e616
Packit 13e616
	p_new_mad = ib_get_mad_buf(p_elem);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   In preperation for initializing the new mad wrapper,
Packit 13e616
	   Initialize the mad_addr structure for the received wire MAD.
Packit 13e616
	 */
Packit 13e616
	mad_addr.dest_lid = p_elem->remote_lid;
Packit 13e616
	mad_addr.path_bits = p_elem->path_bits;
Packit 13e616
Packit 13e616
	/* TO DO - figure out which #define to use for the 2.5 Gb rate... */
Packit 13e616
	mad_addr.static_rate = 0;
Packit 13e616
Packit 13e616
	if (p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
Packit 13e616
	    p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR) {
Packit 13e616
		mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;
Packit 13e616
	} else {
Packit 13e616
		mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;
Packit 13e616
		mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;
Packit 13e616
		mad_addr.addr_type.gsi.pkey_ix = p_elem->pkey_index;
Packit 13e616
		mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;
Packit 13e616
		mad_addr.addr_type.gsi.global_route = FALSE;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   If this MAD is a response to a previous request,
Packit 13e616
	   then grab our pre-allocated MAD wrapper.
Packit 13e616
	   Otherwise, allocate a new MAD wrapper.
Packit 13e616
	 */
Packit 13e616
	if (ib_mad_is_response(p_new_mad)) {
Packit 13e616
		CL_ASSERT(p_elem->send_context1 != NULL);
Packit 13e616
		CL_ASSERT(p_elem->send_context2 == NULL);
Packit 13e616
Packit 13e616
		p_old_madw = (osm_madw_t *) p_elem->send_context1;
Packit 13e616
		p_old_vw = osm_madw_get_vend_ptr(p_old_madw);
Packit 13e616
		p_new_madw = p_old_vw->p_resp_madw;
Packit 13e616
Packit 13e616
		CL_ASSERT(p_new_madw);
Packit 13e616
Packit 13e616
		osm_madw_init(p_new_madw, p_bind, p_elem->size, &mad_addr);
Packit 13e616
		osm_madw_set_mad(p_new_madw, p_new_mad);
Packit 13e616
	} else {
Packit 13e616
		CL_ASSERT(p_elem->send_context1 == NULL);
Packit 13e616
		CL_ASSERT(p_elem->send_context2 == NULL);
Packit 13e616
Packit 13e616
		p_new_madw = osm_mad_pool_get_wrapper(p_bind->p_osm_pool,
Packit 13e616
						      p_bind, p_elem->size,
Packit 13e616
						      p_new_mad, &mad_addr);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_new_madw);
Packit 13e616
	p_new_vw = osm_madw_get_vend_ptr(p_new_madw);
Packit 13e616
Packit 13e616
	p_new_vw->h_bind = p_bind;
Packit 13e616
	p_new_vw->size = p_elem->size;
Packit 13e616
	p_new_vw->p_elem = p_elem;
Packit 13e616
	p_new_vw->h_av = 0;
Packit 13e616
	p_new_vw->p_resp_madw = NULL;
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"__osm_al_rcv_callback: "
Packit 13e616
		"Calling receive callback function %p.\n",
Packit 13e616
		p_bind->rcv_callback);
Packit 13e616
Packit 13e616
	p_bind->rcv_callback(p_new_madw, p_bind->client_context,
Packit 13e616
			     p_elem->send_context1);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_api_status_t
Packit 13e616
osm_vendor_init(IN osm_vendor_t * const p_vend,
Packit 13e616
		IN osm_log_t * const p_log, IN const uint32_t timeout)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	p_vend->p_log = p_log;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Open our instance of AL.
Packit 13e616
	 */
Packit 13e616
	status = ib_open_al(&p_vend->h_al);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_init: ERR 3B03: "
Packit 13e616
			"Error opening AL (%s).\n", ib_get_err_str(status));
Packit 13e616
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_vend->timeout = timeout;
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
Packit 13e616
			     IN const uint32_t timeout)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	osm_vendor_t *p_vend;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	p_vend = malloc(sizeof(*p_vend));
Packit 13e616
	if (p_vend == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_new: ERR 3B04: "
Packit 13e616
			"Unable to allocate vendor object.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	memset(p_vend, 0, sizeof(*p_vend));
Packit 13e616
Packit 13e616
	status = osm_vendor_init(p_vend, p_log, timeout);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		free(p_vend);
Packit 13e616
		p_vend = NULL;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return (p_vend);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
Packit 13e616
{
Packit 13e616
	/* TO DO - fill this in */
Packit 13e616
	ib_close_al((*pp_vend)->h_al);
Packit 13e616
	free(*pp_vend);
Packit 13e616
	*pp_vend = NULL;
Packit 13e616
}
Packit 13e616
Packit 13e616
static ib_api_status_t
Packit 13e616
__osm_ca_info_init(IN osm_vendor_t * const p_vend,
Packit 13e616
		   IN osm_ca_info_t * const p_ca_info,
Packit 13e616
		   IN const ib_net64_t ca_guid)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	p_ca_info->guid = ca_guid;
Packit 13e616
Packit 13e616
	if (osm_log_is_active(p_vend->p_log, OSM_LOG_VERBOSE)) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
Packit 13e616
			"__osm_ca_info_init: "
Packit 13e616
			"Querying CA 0x%" PRIx64 ".\n", cl_ntoh64(ca_guid));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = ib_query_ca_by_guid(p_vend->h_al, ca_guid, NULL,
Packit 13e616
				     &p_ca_info->attr_size);
Packit 13e616
	if ((status != IB_INSUFFICIENT_MEMORY) && (status != IB_SUCCESS)) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_ca_info_init: ERR 3B05: "
Packit 13e616
			"Unexpected status getting CA attributes (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_ca_info->attr_size);
Packit 13e616
Packit 13e616
	p_ca_info->p_attr = malloc(p_ca_info->attr_size);
Packit 13e616
	if (p_ca_info->p_attr == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_ca_info_init: ERR 3B06: "
Packit 13e616
			"Unable to allocate attribute storage.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = ib_query_ca_by_guid(p_vend->h_al, ca_guid, p_ca_info->p_attr,
Packit 13e616
				     &p_ca_info->attr_size);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_ca_info_init: ERR 3B07: "
Packit 13e616
			"Unexpected status getting CA attributes (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
void
Packit 13e616
osm_ca_info_destroy(IN osm_vendor_t * const p_vend,
Packit 13e616
		    IN osm_ca_info_t * const p_ca_info)
Packit 13e616
{
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	if (p_ca_info->p_attr)
Packit 13e616
		free(p_ca_info->p_attr);
Packit 13e616
Packit 13e616
	free(p_ca_info);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_ca_info_t *osm_ca_info_new(IN osm_vendor_t * const p_vend,
Packit 13e616
			       IN const ib_net64_t ca_guid)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	osm_ca_info_t *p_ca_info;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(ca_guid);
Packit 13e616
Packit 13e616
	p_ca_info = malloc(sizeof(*p_ca_info));
Packit 13e616
	if (p_ca_info == NULL)
Packit 13e616
		goto Exit;
Packit 13e616
Packit 13e616
	memset(p_ca_info, 0, sizeof(*p_ca_info));
Packit 13e616
Packit 13e616
	status = __osm_ca_info_init(p_vend, p_ca_info, ca_guid);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_ca_info_destroy(p_vend, p_ca_info);
Packit 13e616
		p_ca_info = NULL;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (p_ca_info);
Packit 13e616
}
Packit 13e616
Packit 13e616
static ib_api_status_t
Packit 13e616
__osm_vendor_get_ca_guids(IN osm_vendor_t * const p_vend,
Packit 13e616
			  IN ib_net64_t ** const p_guids,
Packit 13e616
			  IN unsigned * const p_num_guids)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_guids);
Packit 13e616
	CL_ASSERT(p_num_guids);
Packit 13e616
Packit 13e616
	status = ib_get_ca_guids(p_vend->h_al, NULL, p_num_guids);
Packit 13e616
	if ((status != IB_INSUFFICIENT_MEMORY) && (status != IB_SUCCESS)) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_get_ca_guids: ERR 3B08: "
Packit 13e616
			"Unexpected status getting CA GUID array (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (*p_num_guids == 0) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_get_ca_guids: ERR 3B09: "
Packit 13e616
			"No available channel adapters.\n");
Packit 13e616
		status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	*p_guids = malloc(*p_num_guids * sizeof(**p_guids));
Packit 13e616
	if (*p_guids == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_get_ca_guids: ERR 3B10: "
Packit 13e616
			"Unable to allocate CA GUID array.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = ib_get_ca_guids(p_vend->h_al, *p_guids, p_num_guids);
Packit 13e616
	CL_ASSERT(*p_num_guids);
Packit 13e616
Packit 13e616
	if (osm_log_is_active(p_vend->p_log, OSM_LOG_VERBOSE)) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
Packit 13e616
			"__osm_vendor_get_ca_guids: "
Packit 13e616
			"Detected %u local channel adapters.\n", *p_num_guids);
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr
Packit 13e616
 * NAME
Packit 13e616
 * osm_ca_info_get_pi_ptr
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * Returns a pointer to the port attribute of the specified port
Packit 13e616
 * owned by this CA.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
Packit 13e616
						       const p_ca_info,
Packit 13e616
						       IN const uint8_t index)
Packit 13e616
{
Packit 13e616
	return (&p_ca_info->p_attr->p_port_attr[index]);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 * p_ca_info
Packit 13e616
 *    [in] Pointer to a CA Info object.
Packit 13e616
 *
Packit 13e616
 * index
Packit 13e616
 *    [in] Port "index" for which to retrieve the port attribute.
Packit 13e616
 *    The index is the offset into the ca's internal array
Packit 13e616
 *    of port attributes.
Packit 13e616
 *
Packit 13e616
 * RETURN VALUE
Packit 13e616
 * Returns a pointer to the port attribute of the specified port
Packit 13e616
 * owned by this CA.
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
ib_api_status_t
Packit 13e616
osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
Packit 13e616
			     IN ib_port_attr_t * const p_attr_array,
Packit 13e616
			     IN uint32_t * const p_num_ports)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	uint32_t ca;
Packit 13e616
	unsigned ca_count;
Packit 13e616
	uint32_t port_count = 0;
Packit 13e616
	uint8_t port_num;
Packit 13e616
	uint32_t total_ports = 0;
Packit 13e616
	ib_net64_t *p_ca_guid = NULL;
Packit 13e616
	osm_ca_info_t *p_ca_info;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vend);
Packit 13e616
	CL_ASSERT(p_vend->p_ca_info == NULL);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   1) Determine the number of CA's
Packit 13e616
	   2) Allocate an array big enough to hold the ca info objects.
Packit 13e616
	   3) Call again to retrieve the guids.
Packit 13e616
	 */
Packit 13e616
	status = __osm_vendor_get_ca_guids(p_vend, &p_ca_guid, &ca_count);
Packit 13e616
Packit 13e616
	p_vend->p_ca_info = malloc(ca_count * sizeof(*p_vend->p_ca_info));
Packit 13e616
	if (p_vend->p_ca_info == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_get_all_port_attr: ERR 3B11: "
Packit 13e616
			"Unable to allocate CA information array.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	memset(p_vend->p_ca_info, 0, ca_count * sizeof(*p_vend->p_ca_info));
Packit 13e616
	p_vend->ca_count = ca_count;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   For each CA, retrieve the port info attributes
Packit 13e616
	 */
Packit 13e616
	for (ca = 0; ca < ca_count; ca++) {
Packit 13e616
		p_ca_info = &p_vend->p_ca_info[ca];
Packit 13e616
Packit 13e616
		status = __osm_ca_info_init(p_vend, p_ca_info, p_ca_guid[ca]);
Packit 13e616
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_get_all_port_attr: ERR 3B12: "
Packit 13e616
				"Unable to initialize CA Info object (%s).\n",
Packit 13e616
				ib_get_err_str(status));
Packit 13e616
		}
Packit 13e616
Packit 13e616
		total_ports += osm_ca_info_get_num_ports(p_ca_info);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   If the user supplied enough storage, return the port guids,
Packit 13e616
	   otherwise, return the appropriate error.
Packit 13e616
	 */
Packit 13e616
	if (*p_num_ports >= total_ports) {
Packit 13e616
		for (ca = 0; ca < ca_count; ca++) {
Packit 13e616
			uint32_t num_ports;
Packit 13e616
Packit 13e616
			p_ca_info = &p_vend->p_ca_info[ca];
Packit 13e616
Packit 13e616
			num_ports = osm_ca_info_get_num_ports(p_ca_info);
Packit 13e616
Packit 13e616
			for (port_num = 0; port_num < num_ports; port_num++) {
Packit 13e616
				p_attr_array[port_count] =
Packit 13e616
				    *__osm_ca_info_get_port_attr_ptr(p_ca_info,
Packit 13e616
								     port_num);
Packit 13e616
				port_count++;
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
	} else {
Packit 13e616
		status = IB_INSUFFICIENT_MEMORY;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	*p_num_ports = total_ports;
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	if (p_ca_guid)
Packit 13e616
		free(p_ca_guid);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_net64_t
Packit 13e616
osm_vendor_get_ca_guid(IN osm_vendor_t * const p_vend,
Packit 13e616
		       IN const ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	uint8_t index;
Packit 13e616
	uint8_t num_ports;
Packit 13e616
	uint32_t num_guids = 0;
Packit 13e616
	osm_ca_info_t *p_ca_info;
Packit 13e616
	uint32_t ca;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(port_guid);
Packit 13e616
	/*
Packit 13e616
	   First, locate the HCA that owns this port.
Packit 13e616
	 */
Packit 13e616
	if (p_vend->p_ca_info == NULL) {
Packit 13e616
		/*
Packit 13e616
		   Initialize the osm_ca_info_t array which allows
Packit 13e616
		   us to match port GUID to CA.
Packit 13e616
		 */
Packit 13e616
		osm_vendor_get_all_port_attr(p_vend, NULL, &num_guids);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vend->p_ca_info);
Packit 13e616
	CL_ASSERT(p_vend->ca_count);
Packit 13e616
Packit 13e616
	for (ca = 0; ca < p_vend->ca_count; ca++) {
Packit 13e616
		p_ca_info = &p_vend->p_ca_info[ca];
Packit 13e616
Packit 13e616
		num_ports = osm_ca_info_get_num_ports(p_ca_info);
Packit 13e616
		CL_ASSERT(num_ports);
Packit 13e616
Packit 13e616
		for (index = 0; index < num_ports; index++) {
Packit 13e616
			if (port_guid ==
Packit 13e616
			    osm_ca_info_get_port_guid(p_ca_info, index)) {
Packit 13e616
				OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
				return (osm_ca_info_get_ca_guid(p_ca_info));
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   No local CA owns this guid!
Packit 13e616
	 */
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
		"osm_vendor_get_ca_guid: ERR 3B13: "
Packit 13e616
		"Unable to determine CA guid.\n");
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (0);
Packit 13e616
}
Packit 13e616
Packit 13e616
uint8_t
Packit 13e616
osm_vendor_get_port_num(IN osm_vendor_t * const p_vend,
Packit 13e616
			IN const ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	uint8_t index;
Packit 13e616
	uint8_t num_ports;
Packit 13e616
	uint32_t num_guids = 0;
Packit 13e616
	osm_ca_info_t *p_ca_info;
Packit 13e616
	uint32_t ca;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(port_guid);
Packit 13e616
	/*
Packit 13e616
	   First, locate the HCA that owns this port.
Packit 13e616
	 */
Packit 13e616
	if (p_vend->p_ca_info == NULL) {
Packit 13e616
		/*
Packit 13e616
		   Initialize the osm_ca_info_t array which allows
Packit 13e616
		   us to match port GUID to CA.
Packit 13e616
		 */
Packit 13e616
		osm_vendor_get_all_port_attr(p_vend, NULL, &num_guids);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vend->p_ca_info);
Packit 13e616
	CL_ASSERT(p_vend->ca_count);
Packit 13e616
Packit 13e616
	for (ca = 0; ca < p_vend->ca_count; ca++) {
Packit 13e616
		p_ca_info = &p_vend->p_ca_info[ca];
Packit 13e616
Packit 13e616
		num_ports = osm_ca_info_get_num_ports(p_ca_info);
Packit 13e616
		CL_ASSERT(num_ports);
Packit 13e616
Packit 13e616
		for (index = 0; index < num_ports; index++) {
Packit 13e616
			if (port_guid ==
Packit 13e616
			    osm_ca_info_get_port_guid(p_ca_info, index)) {
Packit 13e616
				OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
				return (osm_ca_info_get_port_num
Packit 13e616
					(p_ca_info, index));
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   No local CA owns this guid!
Packit 13e616
	 */
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
		"osm_vendor_get_port_num: ERR 3B30: "
Packit 13e616
		"Unable to determine CA guid.\n");
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (0);
Packit 13e616
}
Packit 13e616
Packit 13e616
static ib_api_status_t
Packit 13e616
__osm_vendor_open_ca(IN osm_vendor_t * const p_vend,
Packit 13e616
		     IN const ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	ib_net64_t ca_guid;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	ca_guid = osm_vendor_get_ca_guid(p_vend, port_guid);
Packit 13e616
	if (ca_guid == 0) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_open_ca: ERR 3B31: "
Packit 13e616
			"Bad port GUID value 0x%" PRIx64 ".\n",
Packit 13e616
			cl_ntoh64(port_guid));
Packit 13e616
		status = IB_ERROR;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_VERBOSE,
Packit 13e616
		"__osm_vendor_open_ca: "
Packit 13e616
		"Opening HCA 0x%" PRIx64 ".\n", cl_ntoh64(ca_guid));
Packit 13e616
Packit 13e616
	status = ib_open_ca(p_vend->h_al,
Packit 13e616
			    ca_guid,
Packit 13e616
			    __osm_al_ca_err_callback, p_vend, &p_vend->h_ca);
Packit 13e616
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_open_ca: ERR 3B15: "
Packit 13e616
			"Unable to open CA (%s).\n", ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vend->h_ca);
Packit 13e616
Packit 13e616
	status = ib_alloc_pd(p_vend->h_ca, IB_PDT_ALIAS, p_vend, &p_vend->h_pd);
Packit 13e616
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		ib_close_ca(p_vend->h_ca, __osm_al_ca_destroy_callback);
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_open_ca: ERR 3B16: "
Packit 13e616
			"Unable to allocate protection domain (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vend->h_pd);
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
static void
Packit 13e616
__osm_vendor_init_av(IN const osm_al_bind_info_t * p_bind,
Packit 13e616
		     IN ib_av_attr_t * p_av)
Packit 13e616
{
Packit 13e616
	memset(p_av, 0, sizeof(*p_av));
Packit 13e616
	p_av->port_num = p_bind->port_num;
Packit 13e616
	p_av->dlid = IB_LID_PERMISSIVE;
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_bind_handle_t
Packit 13e616
osm_vendor_bind(IN osm_vendor_t * const p_vend,
Packit 13e616
		IN osm_bind_info_t * const p_user_bind,
Packit 13e616
		IN osm_mad_pool_t * const p_mad_pool,
Packit 13e616
		IN osm_vend_mad_recv_callback_t mad_recv_callback,
Packit 13e616
		IN osm_vend_mad_send_err_callback_t send_err_callback,
Packit 13e616
		IN void *context)
Packit 13e616
{
Packit 13e616
	ib_net64_t port_guid;
Packit 13e616
	osm_al_bind_info_t *p_bind = 0;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	ib_qp_create_t qp_create;
Packit 13e616
	ib_mad_svc_t mad_svc;
Packit 13e616
	ib_av_attr_t av;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_user_bind);
Packit 13e616
	CL_ASSERT(p_mad_pool);
Packit 13e616
	CL_ASSERT(mad_recv_callback);
Packit 13e616
	CL_ASSERT(send_err_callback);
Packit 13e616
Packit 13e616
	port_guid = p_user_bind->port_guid;
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_INFO,
Packit 13e616
		"osm_vendor_bind: "
Packit 13e616
		"Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));
Packit 13e616
Packit 13e616
	if (p_vend->h_ca == 0) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osm_vendor_bind: "
Packit 13e616
			"Opening CA that owns port 0x%" PRIx64 ".\n",
Packit 13e616
			port_guid);
Packit 13e616
Packit 13e616
		status = __osm_vendor_open_ca(p_vend, port_guid);
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_bind: ERR 3B17: "
Packit 13e616
				"Unable to Open CA (%s).\n",
Packit 13e616
				ib_get_err_str(status));
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_bind = malloc(sizeof(*p_bind));
Packit 13e616
	if (p_bind == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3B18: "
Packit 13e616
			"Unable to allocate internal bind object.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	memset(p_bind, 0, sizeof(*p_bind));
Packit 13e616
	p_bind->p_vend = p_vend;
Packit 13e616
	p_bind->client_context = context;
Packit 13e616
	p_bind->port_num = osm_vendor_get_port_num(p_vend, port_guid);
Packit 13e616
	p_bind->rcv_callback = mad_recv_callback;
Packit 13e616
	p_bind->send_err_callback = send_err_callback;
Packit 13e616
	p_bind->p_osm_pool = p_mad_pool;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_bind->port_num);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Get the proper QP.
Packit 13e616
	 */
Packit 13e616
	memset(&qp_create, 0, sizeof(qp_create));
Packit 13e616
Packit 13e616
	switch (p_user_bind->mad_class) {
Packit 13e616
	case IB_MCLASS_SUBN_LID:
Packit 13e616
	case IB_MCLASS_SUBN_DIR:
Packit 13e616
		qp_create.qp_type = IB_QPT_QP0_ALIAS;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MCLASS_SUBN_ADM:
Packit 13e616
	default:
Packit 13e616
		qp_create.qp_type = IB_QPT_QP1_ALIAS;
Packit 13e616
		break;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	qp_create.sq_depth = p_user_bind->send_q_size;
Packit 13e616
	qp_create.rq_depth = p_user_bind->recv_q_size;
Packit 13e616
	qp_create.sq_sge = OSM_AL_SQ_SGE;
Packit 13e616
	qp_create.rq_sge = OSM_AL_RQ_SGE;
Packit 13e616
Packit 13e616
	status = ib_get_spl_qp(p_vend->h_pd,
Packit 13e616
			       port_guid,
Packit 13e616
			       &qp_create,
Packit 13e616
			       p_bind,
Packit 13e616
			       __osm_al_err_callback,
Packit 13e616
			       &p_bind->pool_key, &p_bind->h_qp);
Packit 13e616
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		free(p_bind);
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3B19: "
Packit 13e616
			"Unable to get QP handle (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_bind->h_qp);
Packit 13e616
	CL_ASSERT(p_bind->pool_key);
Packit 13e616
Packit 13e616
	memset(&mad_svc, 0, sizeof(mad_svc));
Packit 13e616
Packit 13e616
	mad_svc.mad_svc_context = p_bind;
Packit 13e616
	mad_svc.pfn_mad_send_cb = __osm_al_send_callback;
Packit 13e616
	mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
Packit 13e616
	mad_svc.mgmt_class = p_user_bind->mad_class;
Packit 13e616
	mad_svc.mgmt_version = p_user_bind->class_version;
Packit 13e616
	mad_svc.support_unsol = p_user_bind->is_responder;
Packit 13e616
	mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
Packit 13e616
	mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
Packit 13e616
	mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
Packit 13e616
	mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
Packit 13e616
	mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;
Packit 13e616
Packit 13e616
	status = ib_reg_mad_svc(p_bind->h_qp, &mad_svc, &p_bind->h_svc);
Packit 13e616
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		free(p_bind);
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3B21: "
Packit 13e616
			"Unable to register QP0 MAD service (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	__osm_vendor_init_av(p_bind, &av;;
Packit 13e616
Packit 13e616
	status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3B22: "
Packit 13e616
			"Unable to create address vector (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osm_vendor_bind: "
Packit 13e616
			"Allocating av handle %p.\n", p_bind->h_dr_av);
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return ((osm_bind_handle_t) p_bind);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
Packit 13e616
			 IN const uint32_t mad_size,
Packit 13e616
			 IN osm_vend_wrap_t * const p_vw)
Packit 13e616
{
Packit 13e616
	ib_mad_t *p_mad;
Packit 13e616
	osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vw);
Packit 13e616
Packit 13e616
	p_vw->size = mad_size;
Packit 13e616
	p_vw->h_bind = h_bind;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Retrieve a MAD element from the pool and give the user direct
Packit 13e616
	   access to its buffer.
Packit 13e616
	 */
Packit 13e616
	status = ib_get_mad(p_bind->pool_key, mad_size, &p_vw->p_elem);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_get: ERR 3B25: "
Packit 13e616
			"Unable to acquire MAD (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
Packit 13e616
		p_mad = NULL;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vw->p_elem);
Packit 13e616
	p_mad = ib_get_mad_buf(p_vw->p_elem);
Packit 13e616
Packit 13e616
	if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osm_vendor_get: "
Packit 13e616
			"Acquired MAD %p, size = %u.\n", p_mad, mad_size);
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (p_mad);
Packit 13e616
}
Packit 13e616
Packit 13e616
void
Packit 13e616
osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vw);
Packit 13e616
	CL_ASSERT(p_vw->p_elem);
Packit 13e616
	CL_ASSERT(p_vw->h_bind == h_bind);
Packit 13e616
Packit 13e616
	if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osm_vendor_put: "
Packit 13e616
			"Retiring MAD %p.\n", ib_get_mad_buf(p_vw->p_elem));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = ib_put_mad(p_vw->p_elem);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_put: ERR 3B26: "
Packit 13e616
			"Unable to retire MAD (%s).\n", ib_get_err_str(status));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_api_status_t
Packit 13e616
osm_vendor_send(IN osm_bind_handle_t h_bind,
Packit 13e616
		IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *const p_bind = h_bind;
Packit 13e616
	osm_vendor_t *const p_vend = p_bind->p_vend;
Packit 13e616
	osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
Packit 13e616
	osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
Packit 13e616
	ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	ib_mad_element_t *p_elem;
Packit 13e616
	ib_av_attr_t av;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vw->h_bind == h_bind);
Packit 13e616
	CL_ASSERT(p_vw->p_elem);
Packit 13e616
Packit 13e616
	p_elem = p_vw->p_elem;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   If a response is expected to this MAD, then preallocate
Packit 13e616
	   a mad wrapper to contain the wire MAD received in the
Packit 13e616
	   response.  Allocating a wrapper here allows for easier
Packit 13e616
	   failure paths than after we already received the wire mad.
Packit 13e616
	 */
Packit 13e616
	if (resp_expected) {
Packit 13e616
		p_vw->p_resp_madw =
Packit 13e616
		    osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool);
Packit 13e616
		if (p_vw->p_resp_madw == NULL) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_send: ERR 3B27: "
Packit 13e616
				"Unable to allocate MAD wrapper.\n");
Packit 13e616
			status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
	} else
Packit 13e616
		p_vw->p_resp_madw = NULL;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   For all sends other than directed route SM MADs,
Packit 13e616
	   acquire an address vector for the destination.
Packit 13e616
	 */
Packit 13e616
	if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
Packit 13e616
		memset(&av, 0, sizeof(av));
Packit 13e616
		av.port_num = p_bind->port_num;
Packit 13e616
		av.dlid = p_mad_addr->dest_lid;
Packit 13e616
		av.static_rate = p_mad_addr->static_rate;
Packit 13e616
		av.path_bits = p_mad_addr->path_bits;
Packit 13e616
Packit 13e616
		if ((p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
Packit 13e616
		    (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR)) {
Packit 13e616
			av.sl = p_mad_addr->addr_type.gsi.service_level;
Packit 13e616
Packit 13e616
			if (p_mad_addr->addr_type.gsi.global_route) {
Packit 13e616
				av.grh_valid = TRUE;
Packit 13e616
				/* ANIL */
Packit 13e616
				/* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
Packit 13e616
		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osm_vendor_send: "
Packit 13e616
				"av.port_num 0x%X, "
Packit 13e616
				"av.dlid 0x%X, "
Packit 13e616
				"av.static_rate   %d, "
Packit 13e616
				"av.path_bits %d.\n",
Packit 13e616
				av.port_num, cl_ntoh16(av.dlid),
Packit 13e616
				av.static_rate, av.path_bits);
Packit 13e616
		}
Packit 13e616
Packit 13e616
		status = ib_create_av(p_vend->h_pd, &av, &p_vw->h_av);
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_send: ERR 3B28: "
Packit 13e616
				"Unable to create address vector (%s).\n",
Packit 13e616
				ib_get_err_str(status));
Packit 13e616
Packit 13e616
			if (p_vw->p_resp_madw)
Packit 13e616
				osm_mad_pool_put(p_bind->p_osm_pool,
Packit 13e616
						 p_vw->p_resp_madw);
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osm_vendor_send: "
Packit 13e616
				"Allocating av handle %p.\n", p_vw->h_av);
Packit 13e616
		}
Packit 13e616
	} else {
Packit 13e616
		p_vw->h_av = p_bind->h_dr_av;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_elem->h_av = p_vw->h_av;
Packit 13e616
Packit 13e616
	p_elem->context1 = p_madw;
Packit 13e616
	p_elem->context2 = NULL;
Packit 13e616
Packit 13e616
	p_elem->immediate_data = 0;
Packit 13e616
	p_elem->p_grh = NULL;
Packit 13e616
	p_elem->resp_expected = resp_expected;
Packit 13e616
	p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
Packit 13e616
Packit 13e616
	p_elem->send_opt = IB_SEND_OPT_SIGNALED;
Packit 13e616
	p_elem->timeout_ms = p_vend->timeout;
Packit 13e616
Packit 13e616
	/* Completion information. */
Packit 13e616
	p_elem->status = 0;	/* Not trusting AL */
Packit 13e616
Packit 13e616
	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
Packit 13e616
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)) {
Packit 13e616
		p_elem->remote_qp = 0;
Packit 13e616
		p_elem->remote_qkey = 0;
Packit 13e616
	} else {
Packit 13e616
		p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
Packit 13e616
		p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osm_vendor_send: "
Packit 13e616
			"remote qp = 0x%X, remote qkey = 0x%X.\n",
Packit 13e616
			cl_ntoh32(p_elem->remote_qp),
Packit 13e616
			cl_ntoh32(p_elem->remote_qkey));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = ib_send_mad(p_bind->h_svc, p_elem, NULL);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_send: ERR 3B29: "
Packit 13e616
			"Send failed (%s).\n", ib_get_err_str(status));
Packit 13e616
		if (p_vw->p_resp_madw)
Packit 13e616
			osm_mad_pool_put(p_bind->p_osm_pool, p_vw->p_resp_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	ib_av_attr_t av;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   The only thing we need to do is refresh the directed
Packit 13e616
	   route address vector.
Packit 13e616
	 */
Packit 13e616
	__osm_vendor_init_av(p_bind, &av;;
Packit 13e616
Packit 13e616
	status = ib_destroy_av(p_bind->h_dr_av);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_local_lid_change: ERR 3B32: "
Packit 13e616
			"Unable to destroy address vector (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_local_lid_change: ERR 3B33: "
Packit 13e616
			"Unable to create address vector (%s).\n",
Packit 13e616
			ib_get_err_str(status));
Packit 13e616
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
Packit 13e616
{
Packit 13e616
	osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	ib_port_attr_mod_t attr_mod;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	memset(&attr_mod, 0, sizeof(attr_mod));
Packit 13e616
Packit 13e616
	attr_mod.cap.sm = is_sm_val;
Packit 13e616
Packit 13e616
	status = ib_modify_ca(p_vend->h_ca, p_bind->port_num,
Packit 13e616
			      IB_CA_MOD_IS_SM, &attr_mod);
Packit 13e616
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_set_sm: ERR 3B34: "
Packit 13e616
			"Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",
Packit 13e616
			is_sm_val, ib_get_err_str(status));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
Packit 13e616
{
Packit 13e616
Packit 13e616
}
Packit 13e616
Packit 13e616
#endif				/* OSM_VENDOR_INTF_AL */