Blame libvendor/osm_vendor_ts.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
#undef __init
Packit 13e616
#if HAVE_CONFIG_H
Packit 13e616
#  include <config.h>
Packit 13e616
#endif				/* HAVE_CONFIG_H */
Packit 13e616
Packit 13e616
#include <stdlib.h>
Packit 13e616
#include <string.h>
Packit 13e616
#include <vendor/osm_vendor_ts.h>
Packit 13e616
#include <vendor/osm_vendor_api.h>
Packit 13e616
#include <vendor/osm_ts_useraccess.h>
Packit 13e616
#include <opensm/osm_subnet.h>
Packit 13e616
#include <opensm/osm_opensm.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
Packit 13e616
  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
 * TS MAD to OSM ADDRESS VECTOR
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_ts_conv_mad_rcv_desc_to_osm_addr(IN osm_vendor_t * const p_vend,
Packit 13e616
				       IN struct ib_mad *p_mad,
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 = cl_hton16(p_mad->slid);
Packit 13e616
	p_mad_addr->static_rate = 0;	/*  HACK - we do not know the rate ! */
Packit 13e616
	p_mad_addr->path_bits = 0;	/*  HACK - no way to know in TS */
Packit 13e616
	if (is_smi) {
Packit 13e616
		/* SMI */
Packit 13e616
		p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
Packit 13e616
		p_mad_addr->addr_type.smi.port_num = p_mad->port;
Packit 13e616
	} else {
Packit 13e616
		/* GSI */
Packit 13e616
		p_mad_addr->addr_type.gsi.remote_qp = p_mad->sqpn;
Packit 13e616
		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
Packit 13e616
		p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
Packit 13e616
		p_mad_addr->addr_type.gsi.service_level = 0;	/*  HACK no way to know */
Packit 13e616
Packit 13e616
		p_mad_addr->addr_type.gsi.global_route = FALSE;	/*  HACK no way to know */
Packit 13e616
		/* copy the GRH data if relevant */
Packit 13e616
		/*
Packit 13e616
		   if (p_mad_addr->addr_type.gsi.global_route)
Packit 13e616
		   {
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.IP_version,
Packit 13e616
		   p_rcv_desc->grh.traffic_class,
Packit 13e616
		   p_rcv_desc->grh.flow_label);
Packit 13e616
		   p_mad_addr->addr_type.gsi.grh_info.hop_limit =  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
/**********************************************************************
Packit 13e616
 * OSM ADDR VECTOR TO TS MAD:
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_ts_conv_osm_addr_to_ts_addr(IN osm_mad_addr_t * p_mad_addr,
Packit 13e616
				  IN uint8_t is_smi, OUT struct ib_mad *p_mad)
Packit 13e616
{
Packit 13e616
Packit 13e616
	/* For global destination or Multicast address: */
Packit 13e616
	p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
Packit 13e616
	p_mad->sl = 0;
Packit 13e616
	if (is_smi) {
Packit 13e616
		p_mad->sqpn = 0;
Packit 13e616
		p_mad->dqpn = 0;
Packit 13e616
	} else {
Packit 13e616
		p_mad->sqpn = 1;
Packit 13e616
		p_mad->dqpn = p_mad_addr->addr_type.gsi.remote_qp;
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_ts_bind_info_t *p_bind = (osm_ts_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 5021: "
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
	cl_thread_construct(&(p_vend->smi_bind.poller));
Packit 13e616
	cl_thread_construct(&(p_vend->gsi_bind.poller));
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_LOG_ENTER(p_vend->p_log);
Packit 13e616
	osm_transaction_mgr_destroy(p_vend);
Packit 13e616
Packit 13e616
	/* Destroy the poller threads */
Packit 13e616
	/* HACK: can you destroy an un-initialized thread ? */
Packit 13e616
	pthread_cancel(p_vend->smi_bind.poller.osd.id);
Packit 13e616
	pthread_cancel(p_vend->gsi_bind.poller.osd.id);
Packit 13e616
	cl_thread_destroy(&(p_vend->smi_bind.poller));
Packit 13e616
	cl_thread_destroy(&(p_vend->gsi_bind.poller));
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
 Initializes the vendor:
Packit 13e616
**********************************************************************/
Packit 13e616
Packit 13e616
ib_api_status_t
Packit 13e616
osm_vendor_init(IN osm_vendor_t * const p_vend,
Packit 13e616
		IN osm_log_t * const p_log, IN const uint32_t timeout)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status = IB_SUCCESS;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	p_vend->p_log = p_log;
Packit 13e616
	p_vend->p_transaction_mgr = NULL;
Packit 13e616
	osm_transaction_mgr_init(p_vend);
Packit 13e616
	p_vend->timeout = timeout;
Packit 13e616
Packit 13e616
	/* we use the file handle to track the binding */
Packit 13e616
	p_vend->smi_bind.ul_dev_fd = -1;
Packit 13e616
	p_vend->gsi_bind.ul_dev_fd = -1;
Packit 13e616
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
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 5007: "
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
 * TS RCV Thread callback
Packit 13e616
 * HACK: - we need to make this support arbitrary size mads.
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_ts_rcv_callback(IN osm_ts_bind_info_t * p_bind,
Packit 13e616
		      IN osm_mad_addr_t * p_mad_addr,
Packit 13e616
		      IN uint32_t mad_size, IN void *p_mad)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	osm_madw_t *p_req_madw = NULL;
Packit 13e616
	osm_madw_t *p_madw;
Packit 13e616
	osm_vend_wrap_t *p_new_vw;
Packit 13e616
	ib_mad_t *p_mad_buf;
Packit 13e616
	osm_log_t *const p_log = p_bind->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 *) p_mad)) {
Packit 13e616
		/* can we find a matching madw by this payload TID */
Packit 13e616
		status =
Packit 13e616
		    osm_transaction_mgr_get_madw_for_tid(p_bind->p_vend,
Packit 13e616
							 (ib_mad_t *) p_mad,
Packit 13e616
							 &p_req_madw);
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_ts_rcv_callback: ERR 5008: "
Packit 13e616
				"Error obtaining request madw by TID (%d).\n",
Packit 13e616
				status);
Packit 13e616
			p_req_madw = NULL;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		if (p_req_madw == NULL) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_ts_rcv_callback: ERR 5009:  "
Packit 13e616
				"Fail to obtain request madw for receined MAD. Aborting CB.\n");
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* do we have a request ??? */
Packit 13e616
	if (p_req_madw == NULL) {
Packit 13e616
Packit 13e616
		/* if not - get new osm_madw and arrange it. */
Packit 13e616
		/* create the new madw in the pool */
Packit 13e616
		p_madw = osm_mad_pool_get(p_bind->p_osm_pool,
Packit 13e616
					  (osm_bind_handle_t) p_bind,
Packit 13e616
					  mad_size, p_mad_addr);
Packit 13e616
		if (p_madw == NULL) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_ts_rcv_callback: ERR 5010: "
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
		p_mad_buf = (void *)p_madw->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(p_req_madw->vend_wrap.p_resp_madw != 0);
Packit 13e616
		p_madw = p_req_madw->vend_wrap.p_resp_madw;
Packit 13e616
Packit 13e616
		CL_ASSERT(p_madw->h_bind);
Packit 13e616
		p_mad_buf =
Packit 13e616
		    osm_vendor_get(p_madw->h_bind, mad_size,
Packit 13e616
				   &p_madw->vend_wrap);
Packit 13e616
Packit 13e616
		if (p_mad_buf == NULL) {
Packit 13e616
			osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_ts_rcv_callback: ERR 5011: "
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(p_madw, p_mad_buf);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* init some fields of the vendor wrapper */
Packit 13e616
	p_new_vw = osm_madw_get_vend_ptr(p_madw);
Packit 13e616
	p_new_vw->h_bind = p_bind;
Packit 13e616
	p_new_vw->size = mad_size;
Packit 13e616
	p_new_vw->p_resp_madw = NULL;
Packit 13e616
	p_new_vw->p_mad_buf = p_mad_buf;
Packit 13e616
Packit 13e616
	memcpy(p_new_vw->p_mad_buf, p_mad, mad_size);
Packit 13e616
Packit 13e616
	/* attach the buffer to the wrapper */
Packit 13e616
	p_madw->p_mad = p_mad_buf;
Packit 13e616
Packit 13e616
	/* we can also make sure we marked the size and bind on the returned madw */
Packit 13e616
	p_madw->h_bind = p_new_vw->h_bind;
Packit 13e616
Packit 13e616
	/* call the CB */
Packit 13e616
	(*(osm_vend_mad_recv_callback_t) p_bind->rcv_callback)
Packit 13e616
	    (p_madw, p_bind->client_context, p_req_madw);
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * TS Send callback : invoked after each send
Packit 13e616
 *
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osm_ts_send_callback(IN osm_ts_bind_info_t * bind_info_p,
Packit 13e616
		       IN boolean_t is_resp,
Packit 13e616
		       IN osm_madw_t * madw_p, IN IB_comp_status_t status)
Packit 13e616
{
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
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	osm_log(p_log, OSM_LOG_DEBUG,
Packit 13e616
		"__osm_ts_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_ts_send_callback: ERR 5012: "
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_ts_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_ts_send_callback: ERR 5013: "
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
			(*(osm_vend_mad_send_err_callback_t) bind_info_p->
Packit 13e616
			 send_err_callback)
Packit 13e616
			    (bind_info_p->client_context, 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_ts_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
 * Poller thread:
Packit 13e616
 * Always receive 256byte mads from the devcie file
Packit 13e616
 **********************************************************************/
Packit 13e616
void __osm_vendor_ts_poller(IN void *p_ptr)
Packit 13e616
{
Packit 13e616
	int ts_ret_code;
Packit 13e616
	struct ib_mad mad;
Packit 13e616
	osm_mad_addr_t mad_addr;
Packit 13e616
	osm_ts_bind_info_t *const p_bind = (osm_ts_bind_info_t *) p_ptr;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_bind->p_vend->p_log);
Packit 13e616
	/* we set the type of cancelation for this thread */
Packit 13e616
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
Packit 13e616
Packit 13e616
	while (1) {
Packit 13e616
		/* we read one mad at a time and pass it to the read callback function */
Packit 13e616
		ts_ret_code = read(p_bind->ul_dev_fd, &mad, sizeof(mad));
Packit 13e616
		if (ts_ret_code != sizeof(mad)) {
Packit 13e616
			osm_log(p_bind->p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"__osm_vendor_ts_poller: ERR 5003: "
Packit 13e616
				"error with read, bytes = %d, errno = %d\n",
Packit 13e616
				ts_ret_code, errno);
Packit 13e616
		} else {
Packit 13e616
			osm_log(p_bind->p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"__osm_vendor_ts_poller: "
Packit 13e616
				"MAD QPN:%d SLID:0x%04x class:0x%02x "
Packit 13e616
				"__osm_vendor_ts_poller:0x%02x attr:0x%04x status:0x%04x "
Packit 13e616
				"__osm_vendor_ts_poller:0x%016" PRIx64 "\n",
Packit 13e616
				cl_ntoh32(mad.dqpn),
Packit 13e616
				cl_ntoh16(mad.slid),
Packit 13e616
				mad.mgmt_class,
Packit 13e616
				mad.r_method,
Packit 13e616
				cl_ntoh16(mad.attribute_id),
Packit 13e616
				cl_ntoh16(mad.status),
Packit 13e616
				cl_ntoh64(mad.transaction_id));
Packit 13e616
Packit 13e616
			/* first arrange an address */
Packit 13e616
			__osm_ts_conv_mad_rcv_desc_to_osm_addr(p_bind->p_vend,
Packit 13e616
							       &mad,
Packit 13e616
							       (((ib_mad_t *) &
Packit 13e616
								 mad)->
Packit 13e616
								mgmt_class ==
Packit 13e616
								IB_MCLASS_SUBN_LID)
Packit 13e616
							       ||
Packit 13e616
							       (((ib_mad_t *) &
Packit 13e616
								 mad)->
Packit 13e616
								mgmt_class ==
Packit 13e616
								IB_MCLASS_SUBN_DIR),
Packit 13e616
							       &mad_addr);
Packit 13e616
Packit 13e616
			/* call the receiver callback */
Packit 13e616
			/* HACK: this should be replaced with a call to the RMPP Assembly ... */
Packit 13e616
			__osm_ts_rcv_callback(p_bind, &mad_addr, 256, &mad;;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_bind->p_vend->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_ts_bind_info_t *p_bind = NULL;
Packit 13e616
	VAPI_hca_hndl_t hca_hndl;
Packit 13e616
	VAPI_hca_id_t hca_id;
Packit 13e616
	uint32_t port_num;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	int device_fd;
Packit 13e616
	char device_file[16];
Packit 13e616
	osm_ts_user_mad_filter filter;
Packit 13e616
	int ts_ioctl_ret;
Packit 13e616
	int qpn;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_mad_pool);
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
	switch (p_user_bind->mad_class) {
Packit 13e616
	case IB_MCLASS_SUBN_LID:
Packit 13e616
	case IB_MCLASS_SUBN_DIR:
Packit 13e616
		p_bind = &(p_vend->smi_bind);
Packit 13e616
		qpn = 0;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MCLASS_SUBN_ADM:
Packit 13e616
	default:
Packit 13e616
		p_bind = &(p_vend->gsi_bind);
Packit 13e616
		qpn = 1;
Packit 13e616
		break;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* Make sure we did not previously opened the file */
Packit 13e616
	if (p_bind->ul_dev_fd >= 0) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 5004: "
Packit 13e616
			"Already binded to port %u\n", p_bind->port_num);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   We need to figure out what is the TS file name to attach to.
Packit 13e616
	   I guess it is following the index of the port in the table of
Packit 13e616
	   ports.
Packit 13e616
	 */
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
		cl_ntoh64(port_guid));
Packit 13e616
	status =
Packit 13e616
	    osm_vendor_get_guid_ca_and_port(p_vend, port_guid, &hca_hndl,
Packit 13e616
					    &hca_id, &port_num);
Packit 13e616
	if (status != IB_SUCCESS) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 5005: "
Packit 13e616
			"Fail to find port number of port guid:0x%016" PRIx64
Packit 13e616
			"\n", port_guid);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* the file name is just /dev/ts_ua0: */
Packit 13e616
	strcpy(device_file, "/dev/ts_ua0");
Packit 13e616
Packit 13e616
	osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
		"osm_vendor_bind: " "Opening TS UL dev file:%s\n", device_file);
Packit 13e616
Packit 13e616
	/* Open the file ... */
Packit 13e616
	device_fd = open(device_file, O_RDWR);
Packit 13e616
	if (device_fd < 0) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 5006: "
Packit 13e616
			"Fail to open TS UL dev file:%s\n", device_file);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* track this bind request info */
Packit 13e616
	p_bind->ul_dev_fd = device_fd;
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
	p_bind->hca_hndl = hca_hndl;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Create the MAD filter on this file handle.
Packit 13e616
	 */
Packit 13e616
	filter.port = port_num;
Packit 13e616
Packit 13e616
	filter.qpn = qpn;
Packit 13e616
	filter.mgmt_class = p_user_bind->mad_class;
Packit 13e616
	filter.direction = TS_IB_MAD_DIRECTION_IN;
Packit 13e616
	filter.mask =
Packit 13e616
	    TS_IB_MAD_FILTER_DIRECTION |
Packit 13e616
	    TS_IB_MAD_FILTER_PORT |
Packit 13e616
	    TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS;
Packit 13e616
Packit 13e616
	ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &filter);
Packit 13e616
	if (ts_ioctl_ret < 0) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_bind: ERR 5014: "
Packit 13e616
			"Fail to register MAD filter with err:%u\n",
Packit 13e616
			ts_ioctl_ret);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* Initialize the listener thread for this port */
Packit 13e616
	status = cl_thread_init(&p_bind->poller,
Packit 13e616
				__osm_vendor_ts_poller, p_bind,
Packit 13e616
				"osm ts poller");
Packit 13e616
	if (status != IB_SUCCESS)
Packit 13e616
		goto Exit;
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 *p_mad;
Packit 13e616
	osm_ts_bind_info_t *p_bind = (osm_ts_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
Packit 13e616
	p_vw->size = mad_size;
Packit 13e616
Packit 13e616
	/* allocate it */
Packit 13e616
	p_mad = (ib_mad_t *) malloc(p_vw->size);
Packit 13e616
	if (p_mad == NULL) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_vendor_get: ERR 5022: "
Packit 13e616
			"Error Obtaining MAD buffer.\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	memset(p_mad, 0, p_vw->size);
Packit 13e616
Packit 13e616
	/* track locally */
Packit 13e616
	p_vw->p_mad_buf = p_mad;
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", p_mad, p_vw->size);
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (p_mad);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
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_ts_bind_info_t *p_bind = (osm_ts_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->p_mad_buf);
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->p_mad_buf);
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->p_mad_buf);
Packit 13e616
	p_vw->p_mad_buf = 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
MADs are buffers of type: struct ib_mad - so they are limited by size.
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_ts_send_mad(IN osm_ts_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_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
	struct ib_mad ts_mad;
Packit 13e616
	int ret;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * Copy the MAD over to the sent mad
Packit 13e616
	 */
Packit 13e616
	memcpy(&ts_mad, p_mad, 256);
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_ts_conv_osm_addr_to_ts_addr(p_mad_addr,
Packit 13e616
						  p_mad->mgmt_class ==
Packit 13e616
						  IB_MCLASS_SUBN_LID, &ts_mad);
Packit 13e616
	} else {
Packit 13e616
		/* is a directed route - we need to construct a permissive address */
Packit 13e616
		/* we do not need port number since it is part of the mad_hndl */
Packit 13e616
		ts_mad.dlid = IB_LID_PERMISSIVE;
Packit 13e616
		ts_mad.slid = IB_LID_PERMISSIVE;
Packit 13e616
	}
Packit 13e616
	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
Packit 13e616
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
Packit 13e616
		ts_mad.sqpn = 0;
Packit 13e616
		ts_mad.dqpn = 0;
Packit 13e616
	} else {
Packit 13e616
		ts_mad.sqpn = 1;
Packit 13e616
		ts_mad.dqpn = 1;
Packit 13e616
	}
Packit 13e616
	ts_mad.port = p_bind->port_num;
Packit 13e616
Packit 13e616
	/* send it */
Packit 13e616
	ret = write(p_bind->ul_dev_fd, &ts_mad, sizeof(ts_mad));
Packit 13e616
Packit 13e616
	if (ret != sizeof(ts_mad)) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osm_ts_send_mad: ERR 5026: "
Packit 13e616
			"Error sending mad (%d).\n", ret);
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_ts_bind_info_t *p_bind = (osm_ts_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 5024: "
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 5025: "
Packit 13e616
				"Error inserting request madw by TID (%d).\n",
Packit 13e616
				status);
Packit 13e616
		}
Packit 13e616
	} else
Packit 13e616
		p_vw->p_resp_madw = NULL;
Packit 13e616
Packit 13e616
	/* do the actual send */
Packit 13e616
	/* HACK: to be replaced by call to RMPP Segmentation */
Packit 13e616
	status = osm_ts_send_mad(p_bind, p_madw);
Packit 13e616
Packit 13e616
	/* we do not get an asycn callback so call it ourselves */
Packit 13e616
	/* this will handle all cleanup if neccessary */
Packit 13e616
	__osm_ts_send_callback(p_bind, !resp_expected, p_madw, status);
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_ts_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_ts_bind_info_t *p_bind = (osm_ts_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 5027: "
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
}