Blame libvendor/osm_vendor_ts.c

Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * This software is available to you under a choice of one of two
Packit Service 54dbc3
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit Service 54dbc3
 * General Public License (GPL) Version 2, available from the file
Packit Service 54dbc3
 * COPYING in the main directory of this source tree, or the
Packit Service 54dbc3
 * OpenIB.org BSD license below:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *     Redistribution and use in source and binary forms, with or
Packit Service 54dbc3
 *     without modification, are permitted provided that the following
Packit Service 54dbc3
 *     conditions are met:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions of source code must retain the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions in binary form must reproduce the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer in the documentation and/or other materials
Packit Service 54dbc3
 *        provided with the distribution.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit Service 54dbc3
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service 54dbc3
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit Service 54dbc3
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit Service 54dbc3
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit Service 54dbc3
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 54dbc3
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit Service 54dbc3
 * SOFTWARE.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
#undef __init
Packit Service 54dbc3
#if HAVE_CONFIG_H
Packit Service 54dbc3
#  include <config.h>
Packit Service 54dbc3
#endif				/* HAVE_CONFIG_H */
Packit Service 54dbc3
Packit Service 54dbc3
#include <stdlib.h>
Packit Service 54dbc3
#include <string.h>
Packit Service 54dbc3
#include <vendor/osm_vendor_ts.h>
Packit Service 54dbc3
#include <vendor/osm_vendor_api.h>
Packit Service 54dbc3
#include <vendor/osm_ts_useraccess.h>
Packit Service 54dbc3
#include <opensm/osm_subnet.h>
Packit Service 54dbc3
#include <opensm/osm_opensm.h>
Packit Service 54dbc3
Packit Service 54dbc3
/*
Packit Service 54dbc3
  Since a race can accure on requests. Meaning - a response is received before
Packit Service 54dbc3
  the send_callback is called - we will save both the madw_p and the fact
Packit Service 54dbc3
  whether or not it is a response. A race can occure only on requests that did
Packit Service 54dbc3
  not fail, and then the madw_p will be put back in the pool before the
Packit Service 54dbc3
  callback.
Packit Service 54dbc3
*/
Packit Service 54dbc3
uint64_t __osm_set_wrid_by_p_madw(IN osm_madw_t * p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint64_t wrid = 0;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_madw->p_mad);
Packit Service 54dbc3
Packit Service 54dbc3
	memcpy(&wrid, &p_madw, sizeof(osm_madw_t *));
Packit Service 54dbc3
	wrid = (wrid << 1) |
Packit Service 54dbc3
	    ib_mad_is_response(p_madw->p_mad);
Packit Service 54dbc3
	return wrid;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void
Packit Service 54dbc3
__osm_set_p_madw_and_resp_by_wrid(IN uint64_t wrid,
Packit Service 54dbc3
				  OUT uint8_t * is_resp,
Packit Service 54dbc3
				  OUT osm_madw_t ** pp_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	*is_resp = wrid & 0x0000000000000001;
Packit Service 54dbc3
	wrid = wrid >> 1;
Packit Service 54dbc3
	memcpy(pp_madw, &wrid, sizeof(osm_madw_t *));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * TS MAD to OSM ADDRESS VECTOR
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void
Packit Service 54dbc3
__osm_ts_conv_mad_rcv_desc_to_osm_addr(IN osm_vendor_t * const p_vend,
Packit Service 54dbc3
				       IN struct ib_mad *p_mad,
Packit Service 54dbc3
				       IN uint8_t is_smi,
Packit Service 54dbc3
				       OUT osm_mad_addr_t * p_mad_addr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	p_mad_addr->dest_lid = cl_hton16(p_mad->slid);
Packit Service 54dbc3
	p_mad_addr->static_rate = 0;	/*  HACK - we do not know the rate ! */
Packit Service 54dbc3
	p_mad_addr->path_bits = 0;	/*  HACK - no way to know in TS */
Packit Service 54dbc3
	if (is_smi) {
Packit Service 54dbc3
		/* SMI */
Packit Service 54dbc3
		p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
Packit Service 54dbc3
		p_mad_addr->addr_type.smi.port_num = p_mad->port;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		/* GSI */
Packit Service 54dbc3
		p_mad_addr->addr_type.gsi.remote_qp = p_mad->sqpn;
Packit Service 54dbc3
		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
Packit Service 54dbc3
		p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
Packit Service 54dbc3
		p_mad_addr->addr_type.gsi.service_level = 0;	/*  HACK no way to know */
Packit Service 54dbc3
Packit Service 54dbc3
		p_mad_addr->addr_type.gsi.global_route = FALSE;	/*  HACK no way to know */
Packit Service 54dbc3
		/* copy the GRH data if relevant */
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   if (p_mad_addr->addr_type.gsi.global_route)
Packit Service 54dbc3
		   {
Packit Service 54dbc3
		   p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
Packit Service 54dbc3
		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
Packit Service 54dbc3
		   p_rcv_desc->grh.traffic_class,
Packit Service 54dbc3
		   p_rcv_desc->grh.flow_label);
Packit Service 54dbc3
		   p_mad_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
Packit Service 54dbc3
		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
Packit Service 54dbc3
		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
Packit Service 54dbc3
		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
Packit Service 54dbc3
		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
Packit Service 54dbc3
		   }
Packit Service 54dbc3
		 */
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * OSM ADDR VECTOR TO TS MAD:
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void
Packit Service 54dbc3
__osm_ts_conv_osm_addr_to_ts_addr(IN osm_mad_addr_t * p_mad_addr,
Packit Service 54dbc3
				  IN uint8_t is_smi, OUT struct ib_mad *p_mad)
Packit Service 54dbc3
{
Packit Service 54dbc3
Packit Service 54dbc3
	/* For global destination or Multicast address: */
Packit Service 54dbc3
	p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
Packit Service 54dbc3
	p_mad->sl = 0;
Packit Service 54dbc3
	if (is_smi) {
Packit Service 54dbc3
		p_mad->sqpn = 0;
Packit Service 54dbc3
		p_mad->dqpn = 0;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		p_mad->sqpn = 1;
Packit Service 54dbc3
		p_mad->dqpn = p_mad_addr->addr_type.gsi.remote_qp;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void __osm_vendor_clear_sm(IN osm_bind_handle_t h_bind)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ts_bind_info_t *p_bind = (osm_ts_bind_info_t *) h_bind;
Packit Service 54dbc3
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit Service 54dbc3
	VAPI_ret_t status;
Packit Service 54dbc3
	VAPI_hca_attr_t attr_mod;
Packit Service 54dbc3
	VAPI_hca_attr_mask_t attr_mask;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	memset(&attr_mod, 0, sizeof(attr_mod));
Packit Service 54dbc3
	memset(&attr_mask, 0, sizeof(attr_mask));
Packit Service 54dbc3
Packit Service 54dbc3
	attr_mod.is_sm = FALSE;
Packit Service 54dbc3
	attr_mask = HCA_ATTR_IS_SM;
Packit Service 54dbc3
Packit Service 54dbc3
	status =
Packit Service 54dbc3
	    VAPI_modify_hca_attr(p_bind->hca_hndl, p_bind->port_num, &attr_mod,
Packit Service 54dbc3
				 &attr_mask);
Packit Service 54dbc3
	if (status != VAPI_OK) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"__osm_vendor_clear_sm: ERR 5021: "
Packit Service 54dbc3
			"Unable set 'IS_SM' bit in port attributes (%d).\n",
Packit Service 54dbc3
			status);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * ANY CONSTRUCTION OF THE osm_vendor_t OBJECT
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void osm_vendor_construct(IN osm_vendor_t * const p_vend)
Packit Service 54dbc3
{
Packit Service 54dbc3
	memset(p_vend, 0, sizeof(*p_vend));
Packit Service 54dbc3
	cl_thread_construct(&(p_vend->smi_bind.poller));
Packit Service 54dbc3
	cl_thread_construct(&(p_vend->gsi_bind.poller));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * DEALOCATE osm_vendor_t
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void osm_vendor_destroy(IN osm_vendor_t * const p_vend)
Packit Service 54dbc3
{
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
	osm_transaction_mgr_destroy(p_vend);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Destroy the poller threads */
Packit Service 54dbc3
	/* HACK: can you destroy an un-initialized thread ? */
Packit Service 54dbc3
	pthread_cancel(p_vend->smi_bind.poller.osd.id);
Packit Service 54dbc3
	pthread_cancel(p_vend->gsi_bind.poller.osd.id);
Packit Service 54dbc3
	cl_thread_destroy(&(p_vend->smi_bind.poller));
Packit Service 54dbc3
	cl_thread_destroy(&(p_vend->gsi_bind.poller));
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
DEALLOCATE A POINTER TO osm_vendor_t
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
Packit Service 54dbc3
{
Packit Service 54dbc3
	CL_ASSERT(pp_vend);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_vendor_destroy(*pp_vend);
Packit Service 54dbc3
	free(*pp_vend);
Packit Service 54dbc3
	*pp_vend = NULL;
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 Initializes the vendor:
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
Packit Service 54dbc3
ib_api_status_t
Packit Service 54dbc3
osm_vendor_init(IN osm_vendor_t * const p_vend,
Packit Service 54dbc3
		IN osm_log_t * const p_log, IN const uint32_t timeout)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status = IB_SUCCESS;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_vend->p_log = p_log;
Packit Service 54dbc3
	p_vend->p_transaction_mgr = NULL;
Packit Service 54dbc3
	osm_transaction_mgr_init(p_vend);
Packit Service 54dbc3
	p_vend->timeout = timeout;
Packit Service 54dbc3
Packit Service 54dbc3
	/* we use the file handle to track the binding */
Packit Service 54dbc3
	p_vend->smi_bind.ul_dev_fd = -1;
Packit Service 54dbc3
	p_vend->gsi_bind.ul_dev_fd = -1;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_log);
Packit Service 54dbc3
	return (status);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 *  Create and Initialize osm_vendor_t Object
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
Packit Service 54dbc3
			     IN const uint32_t timeout)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	osm_vendor_t *p_vend;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	p_vend = malloc(sizeof(*p_vend));
Packit Service 54dbc3
	if (p_vend != NULL) {
Packit Service 54dbc3
		memset(p_vend, 0, sizeof(*p_vend));
Packit Service 54dbc3
Packit Service 54dbc3
		status = osm_vendor_init(p_vend, p_log, timeout);
Packit Service 54dbc3
		if (status != IB_SUCCESS) {
Packit Service 54dbc3
			osm_vendor_delete(&p_vend);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_new: ERR 5007: "
Packit Service 54dbc3
			"Fail to allocate vendor object.\n");
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_log);
Packit Service 54dbc3
	return (p_vend);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * TS RCV Thread callback
Packit Service 54dbc3
 * HACK: - we need to make this support arbitrary size mads.
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void
Packit Service 54dbc3
__osm_ts_rcv_callback(IN osm_ts_bind_info_t * p_bind,
Packit Service 54dbc3
		      IN osm_mad_addr_t * p_mad_addr,
Packit Service 54dbc3
		      IN uint32_t mad_size, IN void *p_mad)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	osm_madw_t *p_req_madw = NULL;
Packit Service 54dbc3
	osm_madw_t *p_madw;
Packit Service 54dbc3
	osm_vend_wrap_t *p_new_vw;
Packit Service 54dbc3
	ib_mad_t *p_mad_buf;
Packit Service 54dbc3
	osm_log_t *const p_log = p_bind->p_vend->p_log;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/* if it is a response MAD we mustbe able to get the request */
Packit Service 54dbc3
	if (ib_mad_is_response((ib_mad_t *) p_mad)) {
Packit Service 54dbc3
		/* can we find a matching madw by this payload TID */
Packit Service 54dbc3
		status =
Packit Service 54dbc3
		    osm_transaction_mgr_get_madw_for_tid(p_bind->p_vend,
Packit Service 54dbc3
							 (ib_mad_t *) p_mad,
Packit Service 54dbc3
							 &p_req_madw);
Packit Service 54dbc3
		if (status != IB_SUCCESS) {
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_ts_rcv_callback: ERR 5008: "
Packit Service 54dbc3
				"Error obtaining request madw by TID (%d).\n",
Packit Service 54dbc3
				status);
Packit Service 54dbc3
			p_req_madw = NULL;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		if (p_req_madw == NULL) {
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_ts_rcv_callback: ERR 5009:  "
Packit Service 54dbc3
				"Fail to obtain request madw for receined MAD. Aborting CB.\n");
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* do we have a request ??? */
Packit Service 54dbc3
	if (p_req_madw == NULL) {
Packit Service 54dbc3
Packit Service 54dbc3
		/* if not - get new osm_madw and arrange it. */
Packit Service 54dbc3
		/* create the new madw in the pool */
Packit Service 54dbc3
		p_madw = osm_mad_pool_get(p_bind->p_osm_pool,
Packit Service 54dbc3
					  (osm_bind_handle_t) p_bind,
Packit Service 54dbc3
					  mad_size, p_mad_addr);
Packit Service 54dbc3
		if (p_madw == NULL) {
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_ts_rcv_callback: ERR 5010: "
Packit Service 54dbc3
				"Error request for a new madw.\n");
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
		/* HACK: we cust to avoid the const ??? */
Packit Service 54dbc3
		p_mad_buf = (void *)p_madw->p_mad;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		/* we have the madw defined during the send and stored in the vend_wrap */
Packit Service 54dbc3
		/* we need to make sure the wrapper is correctly init there */
Packit Service 54dbc3
		CL_ASSERT(p_req_madw->vend_wrap.p_resp_madw != 0);
Packit Service 54dbc3
		p_madw = p_req_madw->vend_wrap.p_resp_madw;
Packit Service 54dbc3
Packit Service 54dbc3
		CL_ASSERT(p_madw->h_bind);
Packit Service 54dbc3
		p_mad_buf =
Packit Service 54dbc3
		    osm_vendor_get(p_madw->h_bind, mad_size,
Packit Service 54dbc3
				   &p_madw->vend_wrap);
Packit Service 54dbc3
Packit Service 54dbc3
		if (p_mad_buf == NULL) {
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_ts_rcv_callback: ERR 5011: "
Packit Service 54dbc3
				"Unable to acquire wire MAD.\n");
Packit Service 54dbc3
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/*
Packit Service 54dbc3
		   Finally, attach the wire MAD to this wrapper.
Packit Service 54dbc3
		 */
Packit Service 54dbc3
		osm_madw_set_mad(p_madw, p_mad_buf);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* init some fields of the vendor wrapper */
Packit Service 54dbc3
	p_new_vw = osm_madw_get_vend_ptr(p_madw);
Packit Service 54dbc3
	p_new_vw->h_bind = p_bind;
Packit Service 54dbc3
	p_new_vw->size = mad_size;
Packit Service 54dbc3
	p_new_vw->p_resp_madw = NULL;
Packit Service 54dbc3
	p_new_vw->p_mad_buf = p_mad_buf;
Packit Service 54dbc3
Packit Service 54dbc3
	memcpy(p_new_vw->p_mad_buf, p_mad, mad_size);
Packit Service 54dbc3
Packit Service 54dbc3
	/* attach the buffer to the wrapper */
Packit Service 54dbc3
	p_madw->p_mad = p_mad_buf;
Packit Service 54dbc3
Packit Service 54dbc3
	/* we can also make sure we marked the size and bind on the returned madw */
Packit Service 54dbc3
	p_madw->h_bind = p_new_vw->h_bind;
Packit Service 54dbc3
Packit Service 54dbc3
	/* call the CB */
Packit Service 54dbc3
	(*(osm_vend_mad_recv_callback_t) p_bind->rcv_callback)
Packit Service 54dbc3
	    (p_madw, p_bind->client_context, p_req_madw);
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * TS Send callback : invoked after each send
Packit Service 54dbc3
 *
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void
Packit Service 54dbc3
__osm_ts_send_callback(IN osm_ts_bind_info_t * bind_info_p,
Packit Service 54dbc3
		       IN boolean_t is_resp,
Packit Service 54dbc3
		       IN osm_madw_t * madw_p, IN IB_comp_status_t status)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_log_t *const p_log = bind_info_p->p_vend->p_log;
Packit Service 54dbc3
	osm_vend_wrap_t *p_vw;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_log(p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"__osm_ts_send_callback: INFO 1008: "
Packit Service 54dbc3
		"Handling Send of MADW:%p Is Resp:%d.\n", madw_p, is_resp);
Packit Service 54dbc3
Packit Service 54dbc3
	/* we need to handle requests and responses differently */
Packit Service 54dbc3
	if (is_resp) {
Packit Service 54dbc3
		if (status != IB_COMP_SUCCESS) {
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_ts_send_callback: ERR 5012: "
Packit Service 54dbc3
				"Error Sending Response MADW:%p.\n", madw_p);
Packit Service 54dbc3
		} else {
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"__osm_ts_send_callback: DBG 1008: "
Packit Service 54dbc3
				"Completed Sending Response MADW:%p.\n",
Packit Service 54dbc3
				madw_p);
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* if we are a response - we need to clean it up */
Packit Service 54dbc3
		osm_mad_pool_put(bind_info_p->p_osm_pool, madw_p);
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
Packit Service 54dbc3
		/* this call back is invoked on completion of send - error or not */
Packit Service 54dbc3
		if (status != IB_COMP_SUCCESS) {
Packit Service 54dbc3
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_ts_send_callback: ERR 5013: "
Packit Service 54dbc3
				"Received an Error from IB_MGT Send (%d).\n",
Packit Service 54dbc3
				status);
Packit Service 54dbc3
Packit Service 54dbc3
			p_vw = osm_madw_get_vend_ptr(madw_p);
Packit Service 54dbc3
			CL_ASSERT(p_vw);
Packit Service 54dbc3
Packit Service 54dbc3
			/*
Packit Service 54dbc3
			   Return any wrappers to the pool that may have been
Packit Service 54dbc3
			   pre-emptively allocated to handle a receive.
Packit Service 54dbc3
			 */
Packit Service 54dbc3
			if (p_vw->p_resp_madw) {
Packit Service 54dbc3
				osm_mad_pool_put(bind_info_p->p_osm_pool,
Packit Service 54dbc3
						 p_vw->p_resp_madw);
Packit Service 54dbc3
				p_vw->p_resp_madw = NULL;
Packit Service 54dbc3
			}
Packit Service 54dbc3
Packit Service 54dbc3
			/* invoke the CB */
Packit Service 54dbc3
			(*(osm_vend_mad_send_err_callback_t) bind_info_p->
Packit Service 54dbc3
			 send_err_callback)
Packit Service 54dbc3
			    (bind_info_p->client_context, madw_p);
Packit Service 54dbc3
		} else {
Packit Service 54dbc3
			/* successful request send - do nothing - the response will need the
Packit Service 54dbc3
			   out mad */
Packit Service 54dbc3
			osm_log(p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"__osm_ts_send_callback: DBG 1008: "
Packit Service 54dbc3
				"Completed Sending Request MADW:%p.\n", madw_p);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * Poller thread:
Packit Service 54dbc3
 * Always receive 256byte mads from the devcie file
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void __osm_vendor_ts_poller(IN void *p_ptr)
Packit Service 54dbc3
{
Packit Service 54dbc3
	int ts_ret_code;
Packit Service 54dbc3
	struct ib_mad mad;
Packit Service 54dbc3
	osm_mad_addr_t mad_addr;
Packit Service 54dbc3
	osm_ts_bind_info_t *const p_bind = (osm_ts_bind_info_t *) p_ptr;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_bind->p_vend->p_log);
Packit Service 54dbc3
	/* we set the type of cancelation for this thread */
Packit Service 54dbc3
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
Packit Service 54dbc3
Packit Service 54dbc3
	while (1) {
Packit Service 54dbc3
		/* we read one mad at a time and pass it to the read callback function */
Packit Service 54dbc3
		ts_ret_code = read(p_bind->ul_dev_fd, &mad, sizeof(mad));
Packit Service 54dbc3
		if (ts_ret_code != sizeof(mad)) {
Packit Service 54dbc3
			osm_log(p_bind->p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"__osm_vendor_ts_poller: ERR 5003: "
Packit Service 54dbc3
				"error with read, bytes = %d, errno = %d\n",
Packit Service 54dbc3
				ts_ret_code, errno);
Packit Service 54dbc3
		} else {
Packit Service 54dbc3
			osm_log(p_bind->p_vend->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
				"__osm_vendor_ts_poller: "
Packit Service 54dbc3
				"MAD QPN:%d SLID:0x%04x class:0x%02x "
Packit Service 54dbc3
				"__osm_vendor_ts_poller:0x%02x attr:0x%04x status:0x%04x "
Packit Service 54dbc3
				"__osm_vendor_ts_poller:0x%016" PRIx64 "\n",
Packit Service 54dbc3
				cl_ntoh32(mad.dqpn),
Packit Service 54dbc3
				cl_ntoh16(mad.slid),
Packit Service 54dbc3
				mad.mgmt_class,
Packit Service 54dbc3
				mad.r_method,
Packit Service 54dbc3
				cl_ntoh16(mad.attribute_id),
Packit Service 54dbc3
				cl_ntoh16(mad.status),
Packit Service 54dbc3
				cl_ntoh64(mad.transaction_id));
Packit Service 54dbc3
Packit Service 54dbc3
			/* first arrange an address */
Packit Service 54dbc3
			__osm_ts_conv_mad_rcv_desc_to_osm_addr(p_bind->p_vend,
Packit Service 54dbc3
							       &mad,
Packit Service 54dbc3
							       (((ib_mad_t *) &
Packit Service 54dbc3
								 mad)->
Packit Service 54dbc3
								mgmt_class ==
Packit Service 54dbc3
								IB_MCLASS_SUBN_LID)
Packit Service 54dbc3
							       ||
Packit Service 54dbc3
							       (((ib_mad_t *) &
Packit Service 54dbc3
								 mad)->
Packit Service 54dbc3
								mgmt_class ==
Packit Service 54dbc3
								IB_MCLASS_SUBN_DIR),
Packit Service 54dbc3
							       &mad_addr);
Packit Service 54dbc3
Packit Service 54dbc3
			/* call the receiver callback */
Packit Service 54dbc3
			/* HACK: this should be replaced with a call to the RMPP Assembly ... */
Packit Service 54dbc3
			__osm_ts_rcv_callback(p_bind, &mad_addr, 256, &mad;;
Packit Service 54dbc3
		}
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_bind->p_vend->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * BINDs a callback (rcv and send error) for a given class and method
Packit Service 54dbc3
 * defined by the given:  osm_bind_info_t
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
osm_bind_handle_t
Packit Service 54dbc3
osm_vendor_bind(IN osm_vendor_t * const p_vend,
Packit Service 54dbc3
		IN osm_bind_info_t * const p_user_bind,
Packit Service 54dbc3
		IN osm_mad_pool_t * const p_mad_pool,
Packit Service 54dbc3
		IN osm_vend_mad_recv_callback_t mad_recv_callback,
Packit Service 54dbc3
		IN osm_vend_mad_send_err_callback_t send_err_callback,
Packit Service 54dbc3
		IN void *context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_net64_t port_guid;
Packit Service 54dbc3
	osm_ts_bind_info_t *p_bind = NULL;
Packit Service 54dbc3
	VAPI_hca_hndl_t hca_hndl;
Packit Service 54dbc3
	VAPI_hca_id_t hca_id;
Packit Service 54dbc3
	uint32_t port_num;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
	int device_fd;
Packit Service 54dbc3
	char device_file[16];
Packit Service 54dbc3
	osm_ts_user_mad_filter filter;
Packit Service 54dbc3
	int ts_ioctl_ret;
Packit Service 54dbc3
	int qpn;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_mad_pool);
Packit Service 54dbc3
Packit Service 54dbc3
	port_guid = p_user_bind->port_guid;
Packit Service 54dbc3
Packit Service 54dbc3
	osm_log(p_vend->p_log, OSM_LOG_INFO,
Packit Service 54dbc3
		"osm_vendor_bind: "
Packit Service 54dbc3
		"Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));
Packit Service 54dbc3
Packit Service 54dbc3
	switch (p_user_bind->mad_class) {
Packit Service 54dbc3
	case IB_MCLASS_SUBN_LID:
Packit Service 54dbc3
	case IB_MCLASS_SUBN_DIR:
Packit Service 54dbc3
		p_bind = &(p_vend->smi_bind);
Packit Service 54dbc3
		qpn = 0;
Packit Service 54dbc3
		break;
Packit Service 54dbc3
Packit Service 54dbc3
	case IB_MCLASS_SUBN_ADM:
Packit Service 54dbc3
	default:
Packit Service 54dbc3
		p_bind = &(p_vend->gsi_bind);
Packit Service 54dbc3
		qpn = 1;
Packit Service 54dbc3
		break;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* Make sure we did not previously opened the file */
Packit Service 54dbc3
	if (p_bind->ul_dev_fd >= 0) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_bind: ERR 5004: "
Packit Service 54dbc3
			"Already binded to port %u\n", p_bind->port_num);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	   We need to figure out what is the TS file name to attach to.
Packit Service 54dbc3
	   I guess it is following the index of the port in the table of
Packit Service 54dbc3
	   ports.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
Packit Service 54dbc3
	/* obtain the hca name and port num from the guid */
Packit Service 54dbc3
	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"osm_vendor_bind: "
Packit Service 54dbc3
		"Finding CA and Port that owns port guid 0x%" PRIx64 ".\n",
Packit Service 54dbc3
		cl_ntoh64(port_guid));
Packit Service 54dbc3
	status =
Packit Service 54dbc3
	    osm_vendor_get_guid_ca_and_port(p_vend, port_guid, &hca_hndl,
Packit Service 54dbc3
					    &hca_id, &port_num);
Packit Service 54dbc3
	if (status != IB_SUCCESS) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_bind: ERR 5005: "
Packit Service 54dbc3
			"Fail to find port number of port guid:0x%016" PRIx64
Packit Service 54dbc3
			"\n", port_guid);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* the file name is just /dev/ts_ua0: */
Packit Service 54dbc3
	strcpy(device_file, "/dev/ts_ua0");
Packit Service 54dbc3
Packit Service 54dbc3
	osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
		"osm_vendor_bind: " "Opening TS UL dev file:%s\n", device_file);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Open the file ... */
Packit Service 54dbc3
	device_fd = open(device_file, O_RDWR);
Packit Service 54dbc3
	if (device_fd < 0) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_bind: ERR 5006: "
Packit Service 54dbc3
			"Fail to open TS UL dev file:%s\n", device_file);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* track this bind request info */
Packit Service 54dbc3
	p_bind->ul_dev_fd = device_fd;
Packit Service 54dbc3
	p_bind->port_num = port_num;
Packit Service 54dbc3
	p_bind->p_vend = p_vend;
Packit Service 54dbc3
	p_bind->client_context = context;
Packit Service 54dbc3
	p_bind->rcv_callback = mad_recv_callback;
Packit Service 54dbc3
	p_bind->send_err_callback = send_err_callback;
Packit Service 54dbc3
	p_bind->p_osm_pool = p_mad_pool;
Packit Service 54dbc3
	p_bind->hca_hndl = hca_hndl;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Create the MAD filter on this file handle.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	filter.port = port_num;
Packit Service 54dbc3
Packit Service 54dbc3
	filter.qpn = qpn;
Packit Service 54dbc3
	filter.mgmt_class = p_user_bind->mad_class;
Packit Service 54dbc3
	filter.direction = TS_IB_MAD_DIRECTION_IN;
Packit Service 54dbc3
	filter.mask =
Packit Service 54dbc3
	    TS_IB_MAD_FILTER_DIRECTION |
Packit Service 54dbc3
	    TS_IB_MAD_FILTER_PORT |
Packit Service 54dbc3
	    TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS;
Packit Service 54dbc3
Packit Service 54dbc3
	ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &filter);
Packit Service 54dbc3
	if (ts_ioctl_ret < 0) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_bind: ERR 5014: "
Packit Service 54dbc3
			"Fail to register MAD filter with err:%u\n",
Packit Service 54dbc3
			ts_ioctl_ret);
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* Initialize the listener thread for this port */
Packit Service 54dbc3
	status = cl_thread_init(&p_bind->poller,
Packit Service 54dbc3
				__osm_vendor_ts_poller, p_bind,
Packit Service 54dbc3
				"osm ts poller");
Packit Service 54dbc3
	if (status != IB_SUCCESS)
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
	return ((osm_bind_handle_t) p_bind);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
Get a mad from the lower level.
Packit Service 54dbc3
The osm_vend_wrap_t is a wrapper used to connect the mad to the response.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
Packit Service 54dbc3
			 IN const uint32_t mad_size,
Packit Service 54dbc3
			 IN osm_vend_wrap_t * const p_vw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	ib_mad_t *p_mad;
Packit Service 54dbc3
	osm_ts_bind_info_t *p_bind = (osm_ts_bind_info_t *) h_bind;
Packit Service 54dbc3
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_vw);
Packit Service 54dbc3
Packit Service 54dbc3
	p_vw->size = mad_size;
Packit Service 54dbc3
Packit Service 54dbc3
	/* allocate it */
Packit Service 54dbc3
	p_mad = (ib_mad_t *) malloc(p_vw->size);
Packit Service 54dbc3
	if (p_mad == NULL) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_get: ERR 5022: "
Packit Service 54dbc3
			"Error Obtaining MAD buffer.\n");
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	memset(p_mad, 0, p_vw->size);
Packit Service 54dbc3
Packit Service 54dbc3
	/* track locally */
Packit Service 54dbc3
	p_vw->p_mad_buf = p_mad;
Packit Service 54dbc3
	p_vw->h_bind = h_bind;
Packit Service 54dbc3
	p_vw->p_resp_madw = NULL;
Packit Service 54dbc3
Packit Service 54dbc3
	if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"osm_vendor_get: "
Packit Service 54dbc3
			"Acquired MAD %p, size = %u.\n", p_mad, p_vw->size);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
	return (p_mad);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * Return a MAD by providing it's wrapper object.
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
void
Packit Service 54dbc3
osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ts_bind_info_t *p_bind = (osm_ts_bind_info_t *) h_bind;
Packit Service 54dbc3
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit Service 54dbc3
	osm_madw_t *p_madw;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_vw);
Packit Service 54dbc3
	CL_ASSERT(p_vw->p_mad_buf);
Packit Service 54dbc3
Packit Service 54dbc3
	if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
			"osm_vendor_put: " "Retiring MAD %p.\n",
Packit Service 54dbc3
			p_vw->p_mad_buf);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * We moved the removal of the transaction to immediatly after
Packit Service 54dbc3
	 * it was looked up.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
Packit Service 54dbc3
	/* free the mad but the wrapper is part of the madw object */
Packit Service 54dbc3
	free(p_vw->p_mad_buf);
Packit Service 54dbc3
	p_vw->p_mad_buf = NULL;
Packit Service 54dbc3
	p_madw = PARENT_STRUCT(p_vw, osm_madw_t, vend_wrap);
Packit Service 54dbc3
	p_madw->p_mad = NULL;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
Actually Send a MAD
Packit Service 54dbc3
Packit Service 54dbc3
MADs are buffers of type: struct ib_mad - so they are limited by size.
Packit Service 54dbc3
This is for internal use by osm_vendor_send and the transaction mgr
Packit Service 54dbc3
retry too.
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
ib_api_status_t
Packit Service 54dbc3
osm_ts_send_mad(IN osm_ts_bind_info_t * p_bind, IN osm_madw_t * const p_madw)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_vendor_t *const p_vend = p_bind->p_vend;
Packit Service 54dbc3
	osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
Packit Service 54dbc3
	ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
Packit Service 54dbc3
	struct ib_mad ts_mad;
Packit Service 54dbc3
	int ret;
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Copy the MAD over to the sent mad
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	memcpy(&ts_mad, p_mad, 256);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * For all sends other than directed route SM MADs,
Packit Service 54dbc3
	 * acquire an address vector for the destination.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
Packit Service 54dbc3
		__osm_ts_conv_osm_addr_to_ts_addr(p_mad_addr,
Packit Service 54dbc3
						  p_mad->mgmt_class ==
Packit Service 54dbc3
						  IB_MCLASS_SUBN_LID, &ts_mad);
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		/* is a directed route - we need to construct a permissive address */
Packit Service 54dbc3
		/* we do not need port number since it is part of the mad_hndl */
Packit Service 54dbc3
		ts_mad.dlid = IB_LID_PERMISSIVE;
Packit Service 54dbc3
		ts_mad.slid = IB_LID_PERMISSIVE;
Packit Service 54dbc3
	}
Packit Service 54dbc3
	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
Packit Service 54dbc3
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
Packit Service 54dbc3
		ts_mad.sqpn = 0;
Packit Service 54dbc3
		ts_mad.dqpn = 0;
Packit Service 54dbc3
	} else {
Packit Service 54dbc3
		ts_mad.sqpn = 1;
Packit Service 54dbc3
		ts_mad.dqpn = 1;
Packit Service 54dbc3
	}
Packit Service 54dbc3
	ts_mad.port = p_bind->port_num;
Packit Service 54dbc3
Packit Service 54dbc3
	/* send it */
Packit Service 54dbc3
	ret = write(p_bind->ul_dev_fd, &ts_mad, sizeof(ts_mad));
Packit Service 54dbc3
Packit Service 54dbc3
	if (ret != sizeof(ts_mad)) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_ts_send_mad: ERR 5026: "
Packit Service 54dbc3
			"Error sending mad (%d).\n", ret);
Packit Service 54dbc3
		status = IB_ERROR;
Packit Service 54dbc3
		goto Exit;
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	status = IB_SUCCESS;
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
	return (status);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
Send a MAD through.
Packit Service 54dbc3
Packit Service 54dbc3
What is unclear to me is the need for the setting of all the MAD Wrapper
Packit Service 54dbc3
fields. Seems like the OSM uses these values during it's processing...
Packit Service 54dbc3
**********************************************************************/
Packit Service 54dbc3
ib_api_status_t
Packit Service 54dbc3
osm_vendor_send(IN osm_bind_handle_t h_bind,
Packit Service 54dbc3
		IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ts_bind_info_t *p_bind = (osm_ts_bind_info_t *) h_bind;
Packit Service 54dbc3
	osm_vendor_t *const p_vend = p_bind->p_vend;
Packit Service 54dbc3
	osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
Packit Service 54dbc3
	ib_api_status_t status;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * If a response is expected to this MAD, then preallocate
Packit Service 54dbc3
	 * a mad wrapper to contain the wire MAD received in the
Packit Service 54dbc3
	 * response.  Allocating a wrapper here allows for easier
Packit Service 54dbc3
	 * failure paths than after we already received the wire mad.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (resp_expected == TRUE) {
Packit Service 54dbc3
		/* we track it in the vendor wrapper */
Packit Service 54dbc3
		p_vw->p_resp_madw =
Packit Service 54dbc3
		    osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool);
Packit Service 54dbc3
		if (p_vw->p_resp_madw == NULL) {
Packit Service 54dbc3
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"osm_vendor_send: ERR 5024: "
Packit Service 54dbc3
				"Unable to allocate MAD wrapper.\n");
Packit Service 54dbc3
			status = IB_INSUFFICIENT_RESOURCES;
Packit Service 54dbc3
			goto Exit;
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* put some minimal info on that wrapper */
Packit Service 54dbc3
		((osm_madw_t *) (p_vw->p_resp_madw))->h_bind = h_bind;
Packit Service 54dbc3
Packit Service 54dbc3
		/* we also want to track it in the TID based map */
Packit Service 54dbc3
		status = osm_transaction_mgr_insert_madw((osm_bind_handle_t *)
Packit Service 54dbc3
							 p_bind, p_madw);
Packit Service 54dbc3
		if (status != IB_SUCCESS) {
Packit Service 54dbc3
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
				"osm_vendor_send: ERR 5025: "
Packit Service 54dbc3
				"Error inserting request madw by TID (%d).\n",
Packit Service 54dbc3
				status);
Packit Service 54dbc3
		}
Packit Service 54dbc3
	} else
Packit Service 54dbc3
		p_vw->p_resp_madw = NULL;
Packit Service 54dbc3
Packit Service 54dbc3
	/* do the actual send */
Packit Service 54dbc3
	/* HACK: to be replaced by call to RMPP Segmentation */
Packit Service 54dbc3
	status = osm_ts_send_mad(p_bind, p_madw);
Packit Service 54dbc3
Packit Service 54dbc3
	/* we do not get an asycn callback so call it ourselves */
Packit Service 54dbc3
	/* this will handle all cleanup if neccessary */
Packit Service 54dbc3
	__osm_ts_send_callback(p_bind, !resp_expected, p_madw, status);
Packit Service 54dbc3
Packit Service 54dbc3
Exit:
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
	return (status);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/**********************************************************************
Packit Service 54dbc3
 * the idea here is to change the content of the bind such that it
Packit Service 54dbc3
 * will hold the local address used for sending directed route by the SMA.
Packit Service 54dbc3
 **********************************************************************/
Packit Service 54dbc3
ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_vendor_t *p_vend = ((osm_ts_bind_info_t *) h_bind)->p_vend;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit Service 54dbc3
		"osm_vendor_local_lid_change: DEBUG 2202: " "Change of LID.\n");
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	return (IB_SUCCESS);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
Packit Service 54dbc3
{
Packit Service 54dbc3
	osm_ts_bind_info_t *p_bind = (osm_ts_bind_info_t *) h_bind;
Packit Service 54dbc3
	osm_vendor_t *p_vend = p_bind->p_vend;
Packit Service 54dbc3
	VAPI_ret_t status;
Packit Service 54dbc3
	VAPI_hca_attr_t attr_mod;
Packit Service 54dbc3
	VAPI_hca_attr_mask_t attr_mask;
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_ENTER(p_vend->p_log);
Packit Service 54dbc3
Packit Service 54dbc3
	memset(&attr_mod, 0, sizeof(attr_mod));
Packit Service 54dbc3
	memset(&attr_mask, 0, sizeof(attr_mask));
Packit Service 54dbc3
Packit Service 54dbc3
	attr_mod.is_sm = is_sm_val;
Packit Service 54dbc3
	attr_mask = HCA_ATTR_IS_SM;
Packit Service 54dbc3
Packit Service 54dbc3
	status =
Packit Service 54dbc3
	    VAPI_modify_hca_attr(p_bind->hca_hndl, p_bind->port_num, &attr_mod,
Packit Service 54dbc3
				 &attr_mask);
Packit Service 54dbc3
	if (status != VAPI_OK) {
Packit Service 54dbc3
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit Service 54dbc3
			"osm_vendor_set_sm: ERR 5027: "
Packit Service 54dbc3
			"Unable set 'IS_SM' bit to:%u in port attributes (%d).\n",
Packit Service 54dbc3
			is_sm_val, status);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	OSM_LOG_EXIT(p_vend->p_log);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
Packit Service 54dbc3
{
Packit Service 54dbc3
Packit Service 54dbc3
}