Blame libvendor/osm_vendor_mtl.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2008 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
#if HAVE_CONFIG_H
Packit 13e616
#  include <config.h>
Packit 13e616
#endif				/* HAVE_CONFIG_H */
Packit 13e616
Packit 13e616
#ifdef OSM_VENDOR_INTF_MTL
Packit 13e616
Packit 13e616
#include <stdlib.h>
Packit 13e616
#include <string.h>
Packit 13e616
#include <opensm/osm_helper.h>
Packit 13e616
#include <opensm/osm_log.h>
Packit 13e616
/* HACK - I do not know how to prevent complib from loading kernel H files */
Packit 13e616
#undef __init
Packit 13e616
#include <vendor/osm_vendor_mtl.h>
Packit 13e616
#include <vendor/osm_vendor_api.h>
Packit 13e616
#include <opensm/osm_subnet.h>
Packit 13e616
#include <opensm/osm_opensm.h>
Packit 13e616
#include <vendor/osm_vendor_mtl_transaction_mgr.h>
Packit 13e616
#include <vendor/osm_mtl_bind.h>
Packit 13e616
Packit 13e616
/*
Packit 13e616
  Since a race can accure on requests. Meaning - a response is received before
Packit 13e616
  the send_callback is called - we will save both the madw_p and the fact
Packit 13e616
  whether or not it is a response. A race can occure only on requests that did
Packit 13e616
  not fail, and then the madw_p will be put back in the pool before the callback.
Packit 13e616
*/
Packit 13e616
uint64_t __osm_set_wrid_by_p_madw(IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	uint64_t wrid = 0;
Packit 13e616
Packit 13e616
	CL_ASSERT(p_madw->p_mad);
Packit 13e616
Packit 13e616
	memcpy(&wrid, &p_madw, sizeof(osm_madw_t *));
Packit 13e616
	wrid = (wrid << 1) |
Packit 13e616
	    ib_mad_is_response(p_madw->p_mad);
Packit 13e616
	return wrid;
Packit 13e616
}
Packit 13e616
Packit 13e616
void
Packit 13e616
__osm_set_p_madw_and_resp_by_wrid(IN uint64_t wrid,
Packit 13e616
				  OUT uint8_t * is_resp,
Packit 13e616
				  OUT osm_madw_t ** pp_madw)
Packit 13e616
{
Packit 13e616
	*is_resp = wrid & 0x0000000000000001;
Packit 13e616
	wrid = wrid >> 1;
Packit 13e616
	memcpy(pp_madw, &wrid, sizeof(osm_madw_t *));
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * IB_MGT to OSM ADDRESS VECTOR
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_mtl_conv_ibmgt_rcv_desc_to_osm_addr(IN osm_vendor_t * const p_vend,
Packit 13e616
					  IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
Packit 13e616
					  IN uint8_t is_smi,
Packit 13e616
					  OUT osm_mad_addr_t * p_mad_addr)
Packit 13e616
{
Packit 13e616
	/*  p_mad_addr->dest_lid = p_osm->subn.sm_base_lid; - for resp we use the dest lid ... */
Packit 13e616
	p_mad_addr->dest_lid = cl_hton16(p_rcv_desc->remote_lid);
Packit 13e616
	p_mad_addr->static_rate = 0;	/*  HACK - we do not  know the rate ! */
Packit 13e616
	p_mad_addr->path_bits = p_rcv_desc->local_path_bits;
Packit 13e616
	if (is_smi) {
Packit 13e616
		/* SMI */
Packit 13e616
		p_mad_addr->addr_type.smi.source_lid =
Packit 13e616
		    cl_hton16(p_rcv_desc->remote_lid);
Packit 13e616
		p_mad_addr->addr_type.smi.port_num = 99;	/*  HACK - if used - should fail */
Packit 13e616
	} else {
Packit 13e616
		/* GSI */
Packit 13e616
		/* seems to me there is a IBMGT bug reversing the QPN ... */
Packit 13e616
		/* Does IBMGT supposed to provide the QPN is network or HOST ? */
Packit 13e616
		p_mad_addr->addr_type.gsi.remote_qp = cl_hton32(p_rcv_desc->qp);
Packit 13e616
Packit 13e616
		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
Packit 13e616
		/*  we do have the p_mad_addr->pkey_ix but how to get the PKey by index ? */
Packit 13e616
		/*  the only way seems to be to use VAPI_query_hca_pkey_tbl and obtain */
Packit 13e616
		/*  the full PKey table - than go by the index. */
Packit 13e616
		/*  since this does not seem reasonable to me I simply use the default */
Packit 13e616
		/*  There is a TAVOR limitation that only one P_KEY is supported per  */
Packit 13e616
		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
Packit 13e616
		p_mad_addr->addr_type.gsi.pkey_ix = 0;
Packit 13e616
		p_mad_addr->addr_type.gsi.service_level = p_rcv_desc->sl;
Packit 13e616
Packit 13e616
		p_mad_addr->addr_type.gsi.global_route = p_rcv_desc->grh_flag;
Packit 13e616
		/* copy the GRH data if relevant */
Packit 13e616
		if (p_mad_addr->addr_type.gsi.global_route) {
Packit 13e616
			p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
Packit 13e616
			    ib_grh_set_ver_class_flow(p_rcv_desc->grh.
Packit 13e616
						      IP_version,
Packit 13e616
						      p_rcv_desc->grh.
Packit 13e616
						      traffic_class,
Packit 13e616
						      p_rcv_desc->grh.
Packit 13e616
						      flow_label);
Packit 13e616
			p_mad_addr->addr_type.gsi.grh_info.hop_limit =
Packit 13e616
			    p_rcv_desc->grh.hop_limit;
Packit 13e616
			memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
Packit 13e616
			       &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
Packit 13e616
			memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
Packit 13e616
			       p_rcv_desc->grh.dgid, sizeof(ib_net64_t));
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * OSM ADDR VECTOR TO IB_MGT
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_mtl_conv_osm_addr_to_ibmgt_addr(IN osm_mad_addr_t * p_mad_addr,
Packit 13e616
				      IN uint8_t is_smi, OUT IB_ud_av_t * p_av)
Packit 13e616
{
Packit 13e616
Packit 13e616
	/* For global destination or Multicast address: */
Packit 13e616
	u_int8_t ver;
Packit 13e616
Packit 13e616
	memset(p_av, 0, sizeof(IB_ud_av_t));
Packit 13e616
Packit 13e616
	p_av->src_path_bits = p_mad_addr->path_bits;
Packit 13e616
	p_av->static_rate = p_mad_addr->static_rate;
Packit 13e616
	p_av->dlid = cl_ntoh16(p_mad_addr->dest_lid);
Packit 13e616
Packit 13e616
	if (is_smi) {
Packit 13e616
		p_av->sl = 0;	/*  Just to note we use 0 here. */
Packit 13e616
	} else {
Packit 13e616
		p_av->sl = p_mad_addr->addr_type.gsi.service_level;
Packit 13e616
		p_av->grh_flag = p_mad_addr->addr_type.gsi.global_route;
Packit 13e616
Packit 13e616
		if (p_mad_addr->addr_type.gsi.global_route) {
Packit 13e616
			ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi.
Packit 13e616
						  grh_info.ver_class_flow, &ver,
Packit 13e616
						  &p_av->traffic_class,
Packit 13e616
						  &p_av->flow_label);
Packit 13e616
			p_av->hop_limit =
Packit 13e616
			    p_mad_addr->addr_type.gsi.grh_info.hop_limit;
Packit 13e616
			p_av->sgid_index = 0;	/*  we always use source GID 0 */
Packit 13e616
			memcpy(&p_av->dgid,
Packit 13e616
			       &p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
Packit 13e616
			       sizeof(ib_net64_t));
Packit 13e616
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
void __osm_vendor_clear_sm(IN osm_bind_handle_t h_bind)
Packit 13e616
{
Packit 13e616
	osm_mtl_bind_info_t *p_bind = (osm_mtl_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	VAPI_ret_t status;
Packit 13e616
	VAPI_hca_attr_t attr_mod;
Packit 13e616
	VAPI_hca_attr_mask_t attr_mask;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	memset(&attr_mod, 0, sizeof(attr_mod));
Packit 13e616
	memset(&attr_mask, 0, sizeof(attr_mask));
Packit 13e616
Packit 13e616
	attr_mod.is_sm = FALSE;
Packit 13e616
	attr_mask = HCA_ATTR_IS_SM;
Packit 13e616
Packit 13e616
	status =
Packit 13e616
	    VAPI_modify_hca_attr(p_bind->hca_hndl, p_bind->port_num, &attr_mod,
Packit 13e616
				 &attr_mask);
Packit 13e616
	if (status != VAPI_OK) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_vendor_clear_sm: ERR 3C21: "
Packit 13e616
			"Unable set 'IS_SM' bit in port attributes (%d).\n",
Packit 13e616
			status);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * ANY CONSTRUCTION OF THE osm_vendor_t OBJECT
Packit 13e616
 **********************************************************************/
Packit 13e616
void osm_vendor_construct(IN osm_vendor_t * const p_vend)
Packit 13e616
{
Packit 13e616
	memset(p_vend, 0, sizeof(*p_vend));
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * DEALOCATE osm_vendor_t
Packit 13e616
 **********************************************************************/
Packit 13e616
void osm_vendor_destroy(IN osm_vendor_t * const p_vend)
Packit 13e616
{
Packit 13e616
	osm_vendor_mgt_bind_t *vendor_mgt_bind_p;
Packit 13e616
	IB_MGT_ret_t mgt_ret;
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	if (p_vend->h_al != NULL) {
Packit 13e616
		vendor_mgt_bind_p = (osm_vendor_mgt_bind_t *) p_vend->h_al;
Packit 13e616
		if (vendor_mgt_bind_p->gsi_init) {
Packit 13e616
Packit 13e616
			/* un register the class */
Packit 13e616
			/* HACK WE ASSUME WE ONLY GOT SA CLASS REGISTERD ON GSI !!! */
Packit 13e616
			mgt_ret =
Packit 13e616
			    IB_MGT_unbind_gsi_class(vendor_mgt_bind_p->
Packit 13e616
						    gsi_mads_hdl,
Packit 13e616
						    IB_MCLASS_SUBN_ADM);
Packit 13e616
			if (mgt_ret != IB_MGT_OK) {
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_destroy: ERR 3C03: "
Packit 13e616
					"Fail to unbind the SA class.\n");
Packit 13e616
			}
Packit 13e616
Packit 13e616
			/* un bind the handle */
Packit 13e616
			if (IB_MGT_release_handle
Packit 13e616
			    (vendor_mgt_bind_p->gsi_mads_hdl) != IB_MGT_OK) {
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_destroy: ERR 3C02: "
Packit 13e616
					"Fail to unbind the SA GSI handle.\n");
Packit 13e616
			}
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osm_vendor_destroy: DBG 1002: "
Packit 13e616
				"Unbind the GSI handles.\n");
Packit 13e616
		}
Packit 13e616
		if (vendor_mgt_bind_p->smi_init) {
Packit 13e616
			/* first - clear the IS_SM in the capability mask */
Packit 13e616
			__osm_vendor_clear_sm((osm_bind_handle_t)
Packit 13e616
					      (vendor_mgt_bind_p->smi_p_bind));
Packit 13e616
Packit 13e616
			/* un register the class */
Packit 13e616
			mgt_ret =
Packit 13e616
			    IB_MGT_unbind_sm(vendor_mgt_bind_p->smi_mads_hdl);
Packit 13e616
			if (mgt_ret != IB_MGT_OK) {
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_destroy: ERR 3C04: "
Packit 13e616
					"Fail to unbind the SM class.\n");
Packit 13e616
			}
Packit 13e616
Packit 13e616
			/* un bind the handle */
Packit 13e616
			if (IB_MGT_release_handle
Packit 13e616
			    (vendor_mgt_bind_p->smi_mads_hdl) != IB_MGT_OK) {
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_destroy: ERR 3C05: "
Packit 13e616
					"Fail to unbind the SMI handle.\n");
Packit 13e616
			}
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osm_vendor_destroy: DBG 1003: "
Packit 13e616
				"Unbind the SMI handles.\n");
Packit 13e616
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
	osm_transaction_mgr_destroy(p_vend);
Packit 13e616
	/*  __osm_mtl_destroy_tid_mad_map( p_vend ); */
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
DEALLOCATE A POINTER TO osm_vendor_t
Packit 13e616
**********************************************************************/
Packit 13e616
void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(pp_vend);
Packit 13e616
Packit 13e616
	osm_vendor_destroy(*pp_vend);
Packit 13e616
	free(*pp_vend);
Packit 13e616
	*pp_vend = NULL;
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * This proc actuall binds the handle to the lower level.
Packit 13e616
 *
Packit 13e616
 * We might have here as a result a casting of our struct to the ib_al_handle_t
Packit 13e616
 *
Packit 13e616
 * Q: Do we need 2 of those - one for MSI and one for GSI ?
Packit 13e616
 * A: Yes! We should be able to do the SA too. So we need a struct!
Packit 13e616
 *
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
	osm_vendor_mgt_bind_t *ib_mgt_hdl_p;
Packit 13e616
	ib_api_status_t status = IB_SUCCESS;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	p_vend->p_log = p_log;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * HACK: We need no handle. Assuming the driver is up.
Packit 13e616
	 */
Packit 13e616
	ib_mgt_hdl_p = (osm_vendor_mgt_bind_t *)
Packit 13e616
	    malloc(sizeof(osm_vendor_mgt_bind_t));
Packit 13e616
	if (ib_mgt_hdl_p == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_init: ERR 3C06: "
Packit 13e616
			"Fail to allocate vendor mgt handle.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	ib_mgt_hdl_p->smi_init = FALSE;
Packit 13e616
	ib_mgt_hdl_p->gsi_init = FALSE;
Packit 13e616
	/* cast it into the ib_al_handle_t h_al */
Packit 13e616
	p_vend->h_al = (ib_al_handle_t) ib_mgt_hdl_p;
Packit 13e616
	p_vend->p_transaction_mgr = NULL;
Packit 13e616
	osm_transaction_mgr_init(p_vend);
Packit 13e616
	/*  p_vend->madw_by_tid_map_p = NULL; */
Packit 13e616
	/*  __osm_mtl_init_tid_mad_map( p_vend ); */
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
/**********************************************************************
Packit 13e616
 *  Create and Initialize osm_vendor_t Object
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
	CL_ASSERT(p_log);
Packit 13e616
Packit 13e616
	p_vend = malloc(sizeof(*p_vend));
Packit 13e616
	if (p_vend != NULL) {
Packit 13e616
		memset(p_vend, 0, sizeof(*p_vend));
Packit 13e616
		status = osm_vendor_init(p_vend, p_log, timeout);
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			osm_vendor_delete(&p_vend);
Packit 13e616
		}
Packit 13e616
	} else {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_new: ERR 3C07: "
Packit 13e616
			"Fail to allocate vendor object.\n");
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return (p_vend);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * IB_MGT RCV callback
Packit 13e616
 *
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_mtl_rcv_callback(IN IB_MGT_mad_hndl_t mad_hndl,
Packit 13e616
		       IN void *private_ctx_p,
Packit 13e616
		       IN void *payload_p,
Packit 13e616
		       IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p)
Packit 13e616
{
Packit 13e616
	IB_MGT_ret_t status;
Packit 13e616
	osm_mtl_bind_info_t *bind_info_p = private_ctx_p;
Packit 13e616
	osm_madw_t *req_madw_p = NULL;
Packit 13e616
	osm_madw_t *madw_p;
Packit 13e616
	osm_vend_wrap_t *p_new_vw;
Packit 13e616
	osm_mad_addr_t mad_addr;
Packit 13e616
	ib_mad_t *mad_buf_p;
Packit 13e616
	osm_log_t *const p_log = bind_info_p->p_vend->p_log;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	/* if it is a response MAD we mustbe able to get the request */
Packit 13e616
	if (ib_mad_is_response((ib_mad_t *) payload_p)) {
Packit 13e616
		/* can we find a matching madw by this payload TID */
Packit 13e616
		status =
Packit 13e616
		    osm_transaction_mgr_get_madw_for_tid(bind_info_p->p_vend,
Packit 13e616
							 (ib_mad_t *) payload_p,
Packit 13e616
							 &req_madw_p);
Packit 13e616
		if (status != IB_MGT_OK) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_mtl_rcv_callback: ERR 3C08: "
Packit 13e616
				"Error obtaining request madw by TID (%d).\n",
Packit 13e616
				status);
Packit 13e616
			req_madw_p = NULL;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		if (req_madw_p == NULL) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_mtl_rcv_callback: ERR 3C09:  "
Packit 13e616
				"Fail to obtain request madw for received MAD.(method=%X attr=%X) Aborting CB.\n",
Packit 13e616
				((ib_mad_t *) payload_p)->method,
Packit 13e616
				cl_ntoh16(((ib_mad_t *) payload_p)->attr_id)
Packit 13e616
Packit 13e616
			    );
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* do we have a request ??? */
Packit 13e616
	if (req_madw_p == NULL) {
Packit 13e616
Packit 13e616
		/* first arrange an address */
Packit 13e616
		__osm_mtl_conv_ibmgt_rcv_desc_to_osm_addr(bind_info_p->p_vend,
Packit 13e616
							  rcv_remote_info_p,
Packit 13e616
							  (((ib_mad_t *)
Packit 13e616
							    payload_p)->
Packit 13e616
							   mgmt_class ==
Packit 13e616
							   IB_MCLASS_SUBN_LID)
Packit 13e616
							  || (((ib_mad_t *)
Packit 13e616
							       payload_p)->
Packit 13e616
							      mgmt_class ==
Packit 13e616
							      IB_MCLASS_SUBN_DIR),
Packit 13e616
							  &mad_addr);
Packit 13e616
Packit 13e616
		osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
			"__osm_mtl_rcv_callback: : "
Packit 13e616
			"Received MAD from QP:%X.\n",
Packit 13e616
			cl_ntoh32(mad_addr.addr_type.gsi.remote_qp)
Packit 13e616
		    );
Packit 13e616
Packit 13e616
		/* if not - get new osm_madw and arrange it. */
Packit 13e616
		/* create the new madw in the pool */
Packit 13e616
		madw_p = osm_mad_pool_get(bind_info_p->p_osm_pool,
Packit 13e616
					  (osm_bind_handle_t) bind_info_p,
Packit 13e616
					  MAD_BLOCK_SIZE, &mad_addr);
Packit 13e616
		if (madw_p == NULL) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_mtl_rcv_callback: ERR 3C10: "
Packit 13e616
				"Error request for a new madw.\n");
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
		/* HACK: we cust to avoid the const ??? */
Packit 13e616
		mad_buf_p = (void *)madw_p->p_mad;
Packit 13e616
	} else {
Packit 13e616
		/* we have the madw defined during the send and stored in the vend_wrap */
Packit 13e616
		/* we need to make sure the wrapper is correctly init there */
Packit 13e616
		CL_ASSERT(req_madw_p->vend_wrap.p_resp_madw != 0);
Packit 13e616
		madw_p = req_madw_p->vend_wrap.p_resp_madw;
Packit 13e616
Packit 13e616
		/* HACK: we do not Support RMPP */
Packit 13e616
		CL_ASSERT(madw_p->h_bind);
Packit 13e616
		mad_buf_p =
Packit 13e616
		    osm_vendor_get(madw_p->h_bind, MAD_BLOCK_SIZE,
Packit 13e616
				   &madw_p->vend_wrap);
Packit 13e616
Packit 13e616
		if (mad_buf_p == NULL) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_mtl_rcv_callback: ERR 3C11: "
Packit 13e616
				"Unable to acquire wire MAD.\n");
Packit 13e616
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/*
Packit 13e616
		   Finally, attach the wire MAD to this wrapper.
Packit 13e616
		 */
Packit 13e616
		osm_madw_set_mad(madw_p, mad_buf_p);
Packit 13e616
Packit 13e616
		/* also we need to handle the size of the mad since we did not init ... */
Packit 13e616
		madw_p->mad_size = MAD_BLOCK_SIZE;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* init some fields of the vendor wrapper */
Packit 13e616
	p_new_vw = osm_madw_get_vend_ptr(madw_p);
Packit 13e616
	p_new_vw->h_bind = bind_info_p;
Packit 13e616
	p_new_vw->size = MAD_BLOCK_SIZE;
Packit 13e616
	p_new_vw->p_resp_madw = NULL;
Packit 13e616
	p_new_vw->mad_buf_p = mad_buf_p;
Packit 13e616
Packit 13e616
	/* HACK: We do not support RMPP in receiving MADS */
Packit 13e616
	memcpy(p_new_vw->mad_buf_p, payload_p, MAD_BLOCK_SIZE);
Packit 13e616
Packit 13e616
	/* attach the buffer to the wrapper */
Packit 13e616
	madw_p->p_mad = mad_buf_p;
Packit 13e616
Packit 13e616
	/* we can also make sure we marked the size and bind on the returned madw */
Packit 13e616
	madw_p->h_bind = p_new_vw->h_bind;
Packit 13e616
Packit 13e616
	/* call the CB */
Packit 13e616
	(*bind_info_p->rcv_callback) (madw_p, bind_info_p->client_context,
Packit 13e616
				      req_madw_p);
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * IB_MGT Send callback : invoked after each send
Packit 13e616
 *
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_mtl_send_callback(IN IB_MGT_mad_hndl_t mad_hndl,
Packit 13e616
			IN u_int64_t wrid,
Packit 13e616
			IN IB_comp_status_t status, IN void *private_ctx_p)
Packit 13e616
{
Packit 13e616
	osm_madw_t *madw_p;
Packit 13e616
	osm_mtl_bind_info_t *bind_info_p =
Packit 13e616
	    (osm_mtl_bind_info_t *) private_ctx_p;
Packit 13e616
	osm_log_t *const p_log = bind_info_p->p_vend->p_log;
Packit 13e616
	osm_vend_wrap_t *p_vw;
Packit 13e616
	uint8_t is_resp;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	/* obtain the madp from the wrid */
Packit 13e616
	__osm_set_p_madw_and_resp_by_wrid(wrid, &is_resp, &madw_p);
Packit 13e616
Packit 13e616
	osm_log(p_log, OSM_LOG_DEBUG,
Packit 13e616
		"__osm_mtl_send_callback: INFO 1008: "
Packit 13e616
		"Handling Send of MADW:%p Is Resp:%d.\n", madw_p, is_resp);
Packit 13e616
Packit 13e616
	/* we need to handle requests and responses differently */
Packit 13e616
	if (is_resp) {
Packit 13e616
		if (status != IB_COMP_SUCCESS) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_mtl_send_callback: ERR 3C12: "
Packit 13e616
				"Error Sending Response MADW:%p.\n", madw_p);
Packit 13e616
		} else {
Packit 13e616
			osm_log(p_log, OSM_LOG_DEBUG,
Packit 13e616
				"__osm_mtl_send_callback: DBG 1008: "
Packit 13e616
				"Completed Sending Response MADW:%p.\n",
Packit 13e616
				madw_p);
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* if we are a response - we need to clean it up */
Packit 13e616
		osm_mad_pool_put(bind_info_p->p_osm_pool, madw_p);
Packit 13e616
	} else {
Packit 13e616
Packit 13e616
		/* this call back is invoked on completion of send - error or not */
Packit 13e616
		if (status != IB_COMP_SUCCESS) {
Packit 13e616
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_mtl_send_callback: ERR 3C13: "
Packit 13e616
				"Received an Error from IB_MGT Send (%d).\n",
Packit 13e616
				status);
Packit 13e616
Packit 13e616
			p_vw = osm_madw_get_vend_ptr(madw_p);
Packit 13e616
			CL_ASSERT(p_vw);
Packit 13e616
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(bind_info_p->p_osm_pool,
Packit 13e616
						 p_vw->p_resp_madw);
Packit 13e616
				p_vw->p_resp_madw = NULL;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			/* invoke the CB */
Packit 13e616
			(*bind_info_p->send_err_callback) (bind_info_p->
Packit 13e616
							   client_context,
Packit 13e616
							   madw_p);
Packit 13e616
		} else {
Packit 13e616
			/* successful request send - do nothing - the response will need the
Packit 13e616
			   out mad */
Packit 13e616
			osm_log(p_log, OSM_LOG_DEBUG,
Packit 13e616
				"__osm_mtl_send_callback: DBG 1008: "
Packit 13e616
				"Completed Sending Request MADW:%p.\n", madw_p);
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * BINDs a callback (rcv and send error) for a given class and method
Packit 13e616
 * defined by the given:  osm_bind_info_t
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_mtl_bind_info_t *p_bind = NULL;
Packit 13e616
	VAPI_hca_hndl_t hca_hndl;
Packit 13e616
	VAPI_hca_id_t hca_id;
Packit 13e616
	IB_MGT_mad_type_t mad_type;
Packit 13e616
	uint32_t port_num;
Packit 13e616
	osm_vendor_mgt_bind_t *ib_mgt_hdl_p;
Packit 13e616
	IB_MGT_ret_t mgt_ret;
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
	/* cast back the AL handle to vendor mgt bind */
Packit 13e616
	ib_mgt_hdl_p = (osm_vendor_mgt_bind_t *) p_vend->h_al;
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
	/* obtain the hca name and port num from the guid */
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"osm_vendor_bind: "
Packit 13e616
		"Finding CA and Port that owns port guid 0x%" PRIx64 ".\n",
Packit 13e616
		port_guid);
Packit 13e616
Packit 13e616
	mgt_ret =
Packit 13e616
	    osm_vendor_get_guid_ca_and_port(p_vend, port_guid, &hca_hndl,
Packit 13e616
					    &hca_id, &port_num);
Packit 13e616
	if (mgt_ret != IB_MGT_OK) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3C14: "
Packit 13e616
			"Unable to obtain CA and port (%d).\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* create the bind object tracking this binding */
Packit 13e616
	p_bind = (osm_mtl_bind_info_t *) malloc(sizeof(osm_mtl_bind_info_t));
Packit 13e616
	memset(p_bind, 0, sizeof(osm_mtl_bind_info_t));
Packit 13e616
	if (p_bind == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3C15: "
Packit 13e616
			"Unable to allocate internal bind object.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* track this bind request info */
Packit 13e616
	memcpy(p_bind->hca_id, hca_id, sizeof(VAPI_hca_id_t));
Packit 13e616
	p_bind->port_num = port_num;
Packit 13e616
	p_bind->p_vend = p_vend;
Packit 13e616
	p_bind->client_context = context;
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 CLASS
Packit 13e616
	 */
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
		mad_type = IB_MGT_SMI;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MCLASS_SUBN_ADM:
Packit 13e616
	default:
Packit 13e616
		mad_type = IB_MGT_GSI;
Packit 13e616
		break;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* we split here - based on the type of MADS GSI / SMI */
Packit 13e616
	/* HACK: we only support one class registration per SMI/GSI !!! */
Packit 13e616
	if (mad_type == IB_MGT_SMI) {
Packit 13e616
		/*
Packit 13e616
		 *  SMI CASE
Packit 13e616
		 */
Packit 13e616
Packit 13e616
		/* we do not need to bind the handle if already available */
Packit 13e616
		if (ib_mgt_hdl_p->smi_init == FALSE) {
Packit 13e616
Packit 13e616
			/* First we have to reg and get the handle for the mad */
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_bind: "
Packit 13e616
				"Binding to IB_MGT SMI of %s port %u\n", hca_id,
Packit 13e616
				port_num);
Packit 13e616
Packit 13e616
			mgt_ret =
Packit 13e616
			    IB_MGT_get_handle(hca_id, port_num, IB_MGT_SMI,
Packit 13e616
					      &(ib_mgt_hdl_p->smi_mads_hdl));
Packit 13e616
			if (IB_MGT_OK != mgt_ret) {
Packit 13e616
				free(p_bind);
Packit 13e616
				p_bind = NULL;
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_bind: ERR 3C16: "
Packit 13e616
					"Error obtaining IB_MGT handle to SMI.\n");
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			/* bind it */
Packit 13e616
			mgt_ret = IB_MGT_bind_sm(ib_mgt_hdl_p->smi_mads_hdl);
Packit 13e616
			if (IB_MGT_OK != mgt_ret) {
Packit 13e616
				free(p_bind);
Packit 13e616
				p_bind = NULL;
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_bind: ERR 3C17: "
Packit 13e616
					"Error binding IB_MGT handle to SM.\n");
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			ib_mgt_hdl_p->smi_init = TRUE;
Packit 13e616
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* attach to this bind info */
Packit 13e616
		p_bind->mad_hndl = ib_mgt_hdl_p->smi_mads_hdl;
Packit 13e616
		ib_mgt_hdl_p->smi_p_bind = p_bind;
Packit 13e616
Packit 13e616
		/* now register the callback */
Packit 13e616
		mgt_ret = IB_MGT_reg_cb(p_bind->mad_hndl,
Packit 13e616
					&__osm_mtl_rcv_callback,
Packit 13e616
					p_bind,
Packit 13e616
					&__osm_mtl_send_callback,
Packit 13e616
					p_bind,
Packit 13e616
					IB_MGT_RCV_CB_MASK |
Packit 13e616
					IB_MGT_SEND_CB_MASK);
Packit 13e616
Packit 13e616
	} else {
Packit 13e616
		/*
Packit 13e616
		 *  GSI CASE
Packit 13e616
		 */
Packit 13e616
Packit 13e616
		if (ib_mgt_hdl_p->gsi_init == FALSE) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_bind: " "Binding to IB_MGT GSI\n");
Packit 13e616
Packit 13e616
			/* First we have to reg and get the handle for the mad */
Packit 13e616
			mgt_ret =
Packit 13e616
			    IB_MGT_get_handle(hca_id, port_num, IB_MGT_GSI,
Packit 13e616
					      &(ib_mgt_hdl_p->gsi_mads_hdl));
Packit 13e616
			if (IB_MGT_OK != mgt_ret) {
Packit 13e616
				free(p_bind);
Packit 13e616
				p_bind = NULL;
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_bind: ERR 3C20: "
Packit 13e616
					"Error obtaining IB_MGT handle to GSI.\n");
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			/* bind it */
Packit 13e616
			mgt_ret =
Packit 13e616
			    IB_MGT_bind_gsi_class(ib_mgt_hdl_p->gsi_mads_hdl,
Packit 13e616
						  p_user_bind->mad_class);
Packit 13e616
			if (IB_MGT_OK != mgt_ret) {
Packit 13e616
				free(p_bind);
Packit 13e616
				p_bind = NULL;
Packit 13e616
				osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osm_vendor_bind: ERR 3C22: "
Packit 13e616
					"Error binding IB_MGT handle to GSI.\n");
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			ib_mgt_hdl_p->gsi_init = TRUE;
Packit 13e616
Packit 13e616
			/* attach to this bind info */
Packit 13e616
			p_bind->mad_hndl = ib_mgt_hdl_p->gsi_mads_hdl;
Packit 13e616
Packit 13e616
			/* now register the callback */
Packit 13e616
			mgt_ret = IB_MGT_reg_cb(p_bind->mad_hndl,
Packit 13e616
						&__osm_mtl_rcv_callback,
Packit 13e616
						p_bind,
Packit 13e616
						&__osm_mtl_send_callback,
Packit 13e616
						p_bind,
Packit 13e616
						IB_MGT_RCV_CB_MASK |
Packit 13e616
						IB_MGT_SEND_CB_MASK);
Packit 13e616
Packit 13e616
		} else {
Packit 13e616
			/* we can use the existing handle */
Packit 13e616
			p_bind->mad_hndl = ib_mgt_hdl_p->gsi_mads_hdl;
Packit 13e616
			mgt_ret = IB_MGT_OK;
Packit 13e616
		}
Packit 13e616
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (IB_MGT_OK != mgt_ret) {
Packit 13e616
		free(p_bind);
Packit 13e616
		p_bind = NULL;
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 3C23: "
Packit 13e616
			"Error binding IB_MGT CB (%d).\n", mgt_ret);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* HACK: Do we need to initialize an address vector ???? */
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
/**********************************************************************
Packit 13e616
Get a mad from the lower level.
Packit 13e616
The osm_vend_wrap_t is a wrapper used to connect the mad to the response.
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 *mad_p;
Packit 13e616
	osm_mtl_bind_info_t *p_bind = (osm_mtl_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_vw);
Packit 13e616
	/* HACK: We know we can not send through IB_MGT */
Packit 13e616
	CL_ASSERT(mad_size <= MAD_BLOCK_SIZE);
Packit 13e616
Packit 13e616
	/* IB_MGT assumes it is 256 - we must follow */
Packit 13e616
	p_vw->size = MAD_BLOCK_SIZE;
Packit 13e616
Packit 13e616
	/* allocate it */
Packit 13e616
	mad_p = (ib_mad_t *) malloc(p_vw->size);
Packit 13e616
	if (mad_p == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_get: ERR 3C24: "
Packit 13e616
			"Error Obtaining MAD buffer.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	memset(mad_p, 0, p_vw->size);
Packit 13e616
Packit 13e616
	/* track locally */
Packit 13e616
	p_vw->mad_buf_p = mad_p;
Packit 13e616
	p_vw->h_bind = h_bind;
Packit 13e616
	p_vw->p_resp_madw = NULL;
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", mad_p, p_vw->size);
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (mad_p);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * Return a MAD by providing it's wrapper object.
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_mtl_bind_info_t *p_bind = (osm_mtl_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	osm_madw_t *p_madw;
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->mad_buf_p);
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: " "Retiring MAD %p.\n",
Packit 13e616
			p_vw->mad_buf_p);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * We moved the removal of the transaction to immediatly after
Packit 13e616
	 * it was looked up.
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	/* free the mad but the wrapper is part of the madw object */
Packit 13e616
	free(p_vw->mad_buf_p);
Packit 13e616
	p_vw->mad_buf_p = NULL;
Packit 13e616
	p_madw = PARENT_STRUCT(p_vw, osm_madw_t, vend_wrap);
Packit 13e616
	p_madw->p_mad = NULL;
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
Actually Send a MAD
Packit 13e616
Packit 13e616
This is for internal use by osm_vendor_send and the transaction mgr
Packit 13e616
retry too.
Packit 13e616
**********************************************************************/
Packit 13e616
ib_api_status_t
Packit 13e616
osm_mtl_send_mad(IN osm_mtl_bind_info_t * p_bind, IN osm_madw_t * const p_madw)
Packit 13e616
{
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_MGT_ret_t mgt_res;
Packit 13e616
	IB_ud_av_t av;
Packit 13e616
	uint64_t wrid;
Packit 13e616
	uint32_t qpn;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
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
		__osm_mtl_conv_osm_addr_to_ibmgt_addr(p_mad_addr,
Packit 13e616
						      p_mad->mgmt_class ==
Packit 13e616
						      IB_MCLASS_SUBN_LID, &av;;
Packit 13e616
	} else {
Packit 13e616
		/* is a directed route - we need to construct a permissive address */
Packit 13e616
		memset(&av, 0, sizeof(av));
Packit 13e616
		/* we do not need port number since it is part of the mad_hndl */
Packit 13e616
		av.dlid = IB_LID_PERMISSIVE;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	wrid = __osm_set_wrid_by_p_madw(p_madw);
Packit 13e616
Packit 13e616
	/* send it */
Packit 13e616
	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
Packit 13e616
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
Packit 13e616
Packit 13e616
		/* SMI CASE */
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_mtl_send_mad: "
Packit 13e616
				"av.dlid 0x%X, "
Packit 13e616
				"av.static_rate %d, "
Packit 13e616
				"av.path_bits %d.\n",
Packit 13e616
				cl_ntoh16(av.dlid), av.static_rate,
Packit 13e616
				av.src_path_bits);
Packit 13e616
		}
Packit 13e616
Packit 13e616
		mgt_res = IB_MGT_send_mad(p_bind->mad_hndl, p_mad,	/*  actual payload */
Packit 13e616
					  &av,	/*  address vector */
Packit 13e616
					  wrid,	/*  casting the mad wrapper pointer for err cb */
Packit 13e616
					  p_vend->timeout);
Packit 13e616
Packit 13e616
	} else {
Packit 13e616
		/* GSI CASE - Support Remote QP */
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_mtl_send_mad: "
Packit 13e616
				"av.dlid 0x%X, av.static_rate %d, "
Packit 13e616
				"av.path_bits %d, remote qp: 0x%06X \n",
Packit 13e616
				av.dlid,
Packit 13e616
				av.static_rate,
Packit 13e616
				av.src_path_bits,
Packit 13e616
				cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp)
Packit 13e616
			    );
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* IBMGT have a bug sending to a QP not 1 -
Packit 13e616
		   the QPN must be in network order except when it qpn 1 ... */
Packit 13e616
		qpn = cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp);
Packit 13e616
Packit 13e616
		mgt_res = IB_MGT_send_mad_to_qp(p_bind->mad_hndl, p_mad,	/*  actual payload */
Packit 13e616
						&av,	/* address vector */
Packit 13e616
						wrid,	/* casting the mad wrapper pointer for err cb */
Packit 13e616
						p_vend->timeout, qpn);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (mgt_res != IB_MGT_OK) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_mtl_send_mad: ERR 3C26: "
Packit 13e616
			"Error sending mad (%d).\n", mgt_res);
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
		status = IB_ERROR;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = IB_SUCCESS;
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
Send a MAD through.
Packit 13e616
Packit 13e616
What is unclear to me is the need for the setting of all the MAD Wrapper
Packit 13e616
fields. Seems like the OSM uses these values during it's processing...
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_mtl_bind_info_t *const p_bind = (osm_mtl_bind_info_t *) 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
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
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 == TRUE) {
Packit 13e616
		/* we track it in the vendor wrapper */
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 3C27: "
Packit 13e616
				"Unable to allocate MAD wrapper.\n");
Packit 13e616
			status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* put some minimal info on that wrapper */
Packit 13e616
		((osm_madw_t *) (p_vw->p_resp_madw))->h_bind = h_bind;
Packit 13e616
Packit 13e616
		/* we also want to track it in the TID based map */
Packit 13e616
		status = osm_transaction_mgr_insert_madw((osm_bind_handle_t)
Packit 13e616
							 p_bind, p_madw);
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osm_vendor_send: ERR 3C25: "
Packit 13e616
				"Error inserting request madw by TID (%d).\n",
Packit 13e616
				status);
Packit 13e616
		}
Packit 13e616
Packit 13e616
	} else
Packit 13e616
		p_vw->p_resp_madw = NULL;
Packit 13e616
Packit 13e616
	/* do the actual send */
Packit 13e616
	status = osm_mtl_send_mad(p_bind, p_madw);
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * the idea here is to change the content of the bind such that it
Packit 13e616
 * will hold the local address used for sending directed route by the SMA.
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_vendor_t *p_vend = ((osm_mtl_bind_info_t *) h_bind)->p_vend;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"osm_vendor_local_lid_change: DEBUG 2202: " "Change of LID.\n");
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
Packit 13e616
	return (IB_SUCCESS);
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_mtl_bind_info_t *p_bind = (osm_mtl_bind_info_t *) h_bind;
Packit 13e616
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit 13e616
	VAPI_ret_t status;
Packit 13e616
	VAPI_hca_attr_t attr_mod;
Packit 13e616
	VAPI_hca_attr_mask_t attr_mask;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	memset(&attr_mod, 0, sizeof(attr_mod));
Packit 13e616
	memset(&attr_mask, 0, sizeof(attr_mask));
Packit 13e616
Packit 13e616
	attr_mod.is_sm = is_sm_val;
Packit 13e616
	attr_mask = HCA_ATTR_IS_SM;
Packit 13e616
Packit 13e616
	status =
Packit 13e616
	    VAPI_modify_hca_attr(p_bind->hca_hndl, p_bind->port_num, &attr_mod,
Packit 13e616
				 &attr_mask);
Packit 13e616
	if (status != VAPI_OK) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_set_sm: ERR 3C28: "
Packit 13e616
			"Unable set 'IS_SM' bit to:%u in port attributes (%d).\n",
Packit 13e616
			is_sm_val, 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_TEST */