Blame libvendor/osm_vendor_ibumad_sa.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit 13e616
 * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved.
Packit 13e616
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit 13e616
 * Copyright (c) 2009,2010 HNR Consulting. 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
#include <stdlib.h>
Packit 13e616
#include <string.h>
Packit 13e616
#include <sys/time.h>
Packit 13e616
#include <vendor/osm_vendor_api.h>
Packit 13e616
#include <vendor/osm_vendor_sa_api.h>
Packit 13e616
#include <complib/cl_event.h>
Packit 13e616
Packit 13e616
/* this struct is the internal rep of the bind handle */
Packit 13e616
typedef struct _osmv_sa_bind_info {
Packit 13e616
	osm_bind_handle_t h_bind;
Packit 13e616
	osm_log_t *p_log;
Packit 13e616
	osm_vendor_t *p_vendor;
Packit 13e616
	osm_mad_pool_t *p_mad_pool;
Packit 13e616
	cl_event_t sync_event;
Packit 13e616
	time_t last_lids_update_sec;
Packit 13e616
} osmv_sa_bind_info_t;
Packit 13e616
Packit 13e616
/*
Packit 13e616
  Call back on new mad received:
Packit 13e616
Packit 13e616
  We basically only need to set the context of the query.
Packit 13e616
  Or report an error.
Packit 13e616
Packit 13e616
  A pointer to the actual context of the request (a copy of the oriignal
Packit 13e616
  request structure) is attached as the p_madw->context.ni_context.node_guid
Packit 13e616
*/
Packit 13e616
static void
Packit 13e616
__osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
Packit 13e616
		     IN void *bind_context, IN osm_madw_t * p_req_madw)
Packit 13e616
{
Packit 13e616
	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
Packit 13e616
	osmv_query_req_t *p_query_req_copy = NULL;
Packit 13e616
	osmv_query_res_t query_res;
Packit 13e616
	ib_sa_mad_t *p_sa_mad;
Packit 13e616
	ib_net16_t mad_status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_bind->p_log);
Packit 13e616
Packit 13e616
	if (!p_req_madw) {
Packit 13e616
		OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"Ignoring a non-response mad\n");
Packit 13e616
		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* obtain the sent context since we store it during send in the ni_ctx */
Packit 13e616
	p_query_req_copy = (osmv_query_req_t *)
Packit 13e616
            (uintptr_t)(osm_madw_get_ni_context_ptr(p_req_madw)->node_guid);
Packit 13e616
Packit 13e616
	/* provide the context of the original request in the result */
Packit 13e616
	query_res.query_context = p_query_req_copy->query_context;
Packit 13e616
Packit 13e616
	/* provide the resulting madw */
Packit 13e616
	query_res.p_result_madw = p_madw;
Packit 13e616
Packit 13e616
	/* update the req fields */
Packit 13e616
	p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;
Packit 13e616
Packit 13e616
	/* if we got a remote error track it in the status */
Packit 13e616
	mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
Packit 13e616
	if (mad_status != IB_SUCCESS) {
Packit 13e616
		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5501: "
Packit 13e616
			"Remote error: 0x%04X\n", cl_ntoh16(mad_status));
Packit 13e616
		query_res.status = IB_REMOTE_ERROR;
Packit 13e616
	} else
Packit 13e616
		query_res.status = IB_SUCCESS;
Packit 13e616
Packit 13e616
	/* what if we have got back an empty mad ? */
Packit 13e616
	if (!p_madw->mad_size) {
Packit 13e616
		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5502: "
Packit 13e616
			"Got an empty mad\n");
Packit 13e616
		query_res.status = IB_ERROR;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (IB_SUCCESS == mad_status) {
Packit 13e616
Packit 13e616
		/* if we are in not in a method response of an rmpp nature we must get only 1 */
Packit 13e616
		/* HACK: in the future we might need to be smarter for other methods... */
Packit 13e616
		if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
Packit 13e616
			query_res.result_cnt = 1;
Packit 13e616
		} else {
Packit 13e616
#ifndef VENDOR_RMPP_SUPPORT
Packit 13e616
			if (mad_status != IB_SUCCESS)
Packit 13e616
				query_res.result_cnt = 0;
Packit 13e616
			else
Packit 13e616
				query_res.result_cnt = 1;
Packit 13e616
#else
Packit 13e616
			if (ib_get_attr_size(p_sa_mad->attr_offset)) {
Packit 13e616
				/* we used the offset value to calculate the
Packit 13e616
				   number of records in here */
Packit 13e616
				query_res.result_cnt =
Packit 13e616
				    (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) /
Packit 13e616
				    ib_get_attr_size(p_sa_mad->attr_offset);
Packit 13e616
				OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
Packit 13e616
					"Count = %u = %zu / %u (%zu)\n",
Packit 13e616
					query_res.result_cnt,
Packit 13e616
					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
Packit 13e616
					ib_get_attr_size(p_sa_mad->attr_offset),
Packit 13e616
					(p_madw->mad_size -
Packit 13e616
					 IB_SA_MAD_HDR_SIZE) %
Packit 13e616
					ib_get_attr_size(p_sa_mad->attr_offset));
Packit 13e616
			} else
Packit 13e616
				query_res.result_cnt = 0;
Packit 13e616
#endif
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	query_res.query_type = p_query_req_copy->query_type;
Packit 13e616
Packit 13e616
	p_query_req_copy->pfn_query_cb(&query_res);
Packit 13e616
Packit 13e616
	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
Packit 13e616
		cl_event_signal(&p_bind->sync_event);
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
Packit 13e616
	/* free the copied query request if found */
Packit 13e616
	if (p_query_req_copy)
Packit 13e616
		free(p_query_req_copy);
Packit 13e616
Packit 13e616
	/* put back the request madw */
Packit 13e616
	if (p_req_madw)
Packit 13e616
		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_bind->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
  Send Error Callback:
Packit 13e616
Packit 13e616
  Only report the error and get rid of the mad wrapper
Packit 13e616
*/
Packit 13e616
static void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
Packit 13e616
	osmv_query_req_t *p_query_req_copy = NULL;
Packit 13e616
	osmv_query_res_t query_res;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_bind->p_log);
Packit 13e616
Packit 13e616
	/* Obtain the sent context etc */
Packit 13e616
	p_query_req_copy = (osmv_query_req_t *)
Packit 13e616
            (uintptr_t)(osm_madw_get_ni_context_ptr(p_madw)->node_guid);
Packit 13e616
Packit 13e616
	/* provide the context of the original request in the result */
Packit 13e616
	query_res.query_context = p_query_req_copy->query_context;
Packit 13e616
Packit 13e616
	query_res.p_result_madw = p_madw;
Packit 13e616
Packit 13e616
	query_res.status = IB_TIMEOUT;
Packit 13e616
	query_res.result_cnt = 0;
Packit 13e616
Packit 13e616
	query_res.query_type = p_query_req_copy->query_type;
Packit 13e616
Packit 13e616
	p_query_req_copy->pfn_query_cb(&query_res);
Packit 13e616
Packit 13e616
	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
Packit 13e616
		cl_event_signal(&p_bind->sync_event);
Packit 13e616
Packit 13e616
	free(p_query_req_copy);
Packit 13e616
	OSM_LOG_EXIT(p_bind->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*****************************************************************************
Packit 13e616
 Update lids of vendor umad_port.
Packit 13e616
 *****************************************************************************/
Packit 13e616
static ib_api_status_t update_umad_port(osm_vendor_t * p_vend)
Packit 13e616
{
Packit 13e616
	umad_port_t port;
Packit 13e616
	if (umad_get_port(p_vend->umad_port.ca_name,
Packit 13e616
			  p_vend->umad_port.portnum, &port) < 0)
Packit 13e616
		return IB_ERROR;
Packit 13e616
	p_vend->umad_port.base_lid = port.base_lid;
Packit 13e616
	p_vend->umad_port.sm_lid = port.sm_lid;
Packit 13e616
	umad_release_port(&port);
Packit 13e616
	return IB_SUCCESS;
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_bind_handle_t
Packit 13e616
osmv_bind_sa(IN osm_vendor_t * const p_vend,
Packit 13e616
	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	osm_bind_info_t bind_info;
Packit 13e616
	osm_log_t *p_log = p_vend->p_log;
Packit 13e616
	osmv_sa_bind_info_t *p_sa_bind_info;
Packit 13e616
	cl_status_t cl_status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	OSM_LOG(p_log, OSM_LOG_DEBUG,
Packit 13e616
		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
Packit 13e616
Packit 13e616
	bind_info.port_guid = port_guid;
Packit 13e616
	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
Packit 13e616
	bind_info.class_version = 2;
Packit 13e616
	bind_info.is_responder = FALSE;
Packit 13e616
	bind_info.is_trap_processor = FALSE;
Packit 13e616
	bind_info.is_report_processor = FALSE;
Packit 13e616
	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
Packit 13e616
	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
Packit 13e616
	bind_info.timeout = p_vend->timeout;
Packit 13e616
	bind_info.retries = OSM_DEFAULT_RETRY_COUNT;
Packit 13e616
Packit 13e616
	/* allocate the new sa bind info */
Packit 13e616
	p_sa_bind_info =
Packit 13e616
	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
Packit 13e616
	if (!p_sa_bind_info) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5505: "
Packit 13e616
			"Failed to allocate new bind structure\n");
Packit 13e616
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* store some important context */
Packit 13e616
	p_sa_bind_info->p_log = p_log;
Packit 13e616
	p_sa_bind_info->p_mad_pool = p_mad_pool;
Packit 13e616
	p_sa_bind_info->p_vendor = p_vend;
Packit 13e616
Packit 13e616
	/* Bind to the lower level */
Packit 13e616
	p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info);	/* context provided to CBs */
Packit 13e616
Packit 13e616
	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
Packit 13e616
		free(p_sa_bind_info);
Packit 13e616
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5506: "
Packit 13e616
			"Failed to bind to vendor GSI\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* update time umad_port is initialized now */
Packit 13e616
	p_sa_bind_info->last_lids_update_sec = time(NULL);
Packit 13e616
Packit 13e616
	/* initialize the sync_event */
Packit 13e616
	cl_event_construct(&p_sa_bind_info->sync_event);
Packit 13e616
	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
Packit 13e616
	if (cl_status != CL_SUCCESS) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5508: "
Packit 13e616
			"cl_init_event failed: %s\n", ib_get_err_str(cl_status));
Packit 13e616
		free(p_sa_bind_info);
Packit 13e616
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return (p_sa_bind_info);
Packit 13e616
}
Packit 13e616
Packit 13e616
/****t* OSM Vendor SA Client/osmv_sa_mad_data
Packit 13e616
 * NAME
Packit 13e616
 *    osmv_sa_mad_data
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * Extra fields required to perform a mad query
Packit 13e616
 *  This struct is passed to the actual send method
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
typedef struct _osmv_sa_mad_data {
Packit 13e616
	/* MAD data. */
Packit 13e616
	uint8_t method;
Packit 13e616
	ib_net16_t attr_id;
Packit 13e616
	ib_net16_t attr_offset;
Packit 13e616
	ib_net32_t attr_mod;
Packit 13e616
	ib_net64_t comp_mask;
Packit 13e616
	void *p_attr;
Packit 13e616
} osmv_sa_mad_data_t;
Packit 13e616
/*
Packit 13e616
 * method
Packit 13e616
 *    The method of the mad to be sent
Packit 13e616
 *
Packit 13e616
 *  attr_id
Packit 13e616
 *     Attribute ID
Packit 13e616
 *
Packit 13e616
 *  attr_offset
Packit 13e616
 *     Offset as defined by RMPP
Packit 13e616
 *
Packit 13e616
 *  attr_mod
Packit 13e616
 *     Attribute modifier
Packit 13e616
 *
Packit 13e616
 *  comp_mask
Packit 13e616
 *     The component mask of the query
Packit 13e616
 *
Packit 13e616
 *  p_attr
Packit 13e616
 *     A pointer to the record of the attribute to be sent.
Packit 13e616
 *
Packit 13e616
 *****/
Packit 13e616
Packit 13e616
/* Send a MAD out on the GSI interface */
Packit 13e616
static ib_api_status_t
Packit 13e616
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
Packit 13e616
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
Packit 13e616
		   IN const osmv_query_req_t * const p_query_req)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	ib_mad_t *p_mad_hdr;
Packit 13e616
	ib_sa_mad_t *p_sa_mad;
Packit 13e616
	osm_madw_t *p_madw;
Packit 13e616
	osm_log_t *p_log = p_bind->p_log;
Packit 13e616
	static atomic32_t trans_id;
Packit 13e616
	boolean_t sync;
Packit 13e616
	osmv_query_req_t *p_query_req_copy;
Packit 13e616
	uint32_t sa_size;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   since the sm_lid might change we obtain it every send
Packit 13e616
	   (actually it is cached in the bind object and refreshed
Packit 13e616
	   every 30sec by this proc)
Packit 13e616
	 */
Packit 13e616
	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
Packit 13e616
		status = update_umad_port(p_bind->p_vendor);
Packit 13e616
		if (status != IB_SUCCESS) {
Packit 13e616
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
Packit 13e616
				"Failed to obtain the SM lid\n");
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
		p_bind->last_lids_update_sec = time(NULL);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* Get a MAD wrapper for the send */
Packit 13e616
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
Packit 13e616
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);
Packit 13e616
Packit 13e616
	if (p_madw == NULL) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
Packit 13e616
			"Unable to acquire MAD\n");
Packit 13e616
		status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* Initialize the Sent MAD: */
Packit 13e616
Packit 13e616
	/* Initialize the MAD buffer for the send operation. */
Packit 13e616
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
Packit 13e616
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
Packit 13e616
Packit 13e616
	/* Get a new transaction Id */
Packit 13e616
	cl_atomic_inc(&trans_id);
Packit 13e616
Packit 13e616
	/* Cleanup the MAD from any residue */
Packit 13e616
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);
Packit 13e616
Packit 13e616
	/* Initialize the standard MAD header. */
Packit 13e616
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
Packit 13e616
			IB_MCLASS_SUBN_ADM,	/* class */
Packit 13e616
			(uint8_t) 2,	/* version */
Packit 13e616
			p_sa_mad_data->method,	/* method */
Packit 13e616
			cl_hton64((uint64_t) trans_id),	/* tid */
Packit 13e616
			p_sa_mad_data->attr_id,	/* attr id */
Packit 13e616
			p_sa_mad_data->attr_mod	/* attr mod */);
Packit 13e616
Packit 13e616
	/* Set the query information. */
Packit 13e616
	p_sa_mad->sm_key = p_query_req->sm_key;
Packit 13e616
	p_sa_mad->attr_offset = 0;
Packit 13e616
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
Packit 13e616
#ifdef DUAL_SIDED_RMPP
Packit 13e616
	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
Packit 13e616
		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
Packit 13e616
#endif
Packit 13e616
	if (p_sa_mad->comp_mask) {
Packit 13e616
		p_sa_mad_data->attr_offset ? (sa_size = ib_get_attr_size(p_sa_mad_data->attr_offset)) : (sa_size = IB_SA_DATA_SIZE);
Packit 13e616
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr, sa_size);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Provide the address to send to
Packit 13e616
	 */
Packit 13e616
	p_madw->mad_addr.dest_lid =
Packit 13e616
	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
Packit 13e616
	p_madw->mad_addr.addr_type.smi.source_lid =
Packit 13e616
	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
Packit 13e616
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
Packit 13e616
	p_madw->resp_expected = TRUE;
Packit 13e616
	p_madw->fail_msg = CL_DISP_MSGID_NONE;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   add grh
Packit 13e616
	 */
Packit 13e616
	if (p_query_req->with_grh) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "sending sa query with GRH "
Packit 13e616
			"GID 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
Packit 13e616
			cl_ntoh64(p_query_req->gid.unicast.prefix),
Packit 13e616
			cl_ntoh64(p_query_req->gid.unicast.interface_id));
Packit 13e616
		p_madw->mad_addr.addr_type.gsi.global_route = 1;
Packit 13e616
		memset(&p_madw->mad_addr.addr_type.gsi.grh_info, 0,
Packit 13e616
		       sizeof(p_madw->mad_addr.addr_type.gsi.grh_info));
Packit 13e616
		memcpy(&p_madw->mad_addr.addr_type.gsi.grh_info.dest_gid, &(p_query_req->gid), 16);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Provide MAD context such that the call back will know what to do.
Packit 13e616
	   We have to keep the entire request structure so we know the CB.
Packit 13e616
	   Since we can not rely on the client to keep it around until
Packit 13e616
	   the response - we duplicate it and will later dispose it (in CB).
Packit 13e616
	   To store on the MADW we cast it into what opensm has:
Packit 13e616
	   p_madw->context.ni_context.node_guid
Packit 13e616
	 */
Packit 13e616
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
Packit 13e616
	if (!p_query_req_copy) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5511: "
Packit 13e616
			"Unable to acquire memory for query copy\n");
Packit 13e616
		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
Packit 13e616
		status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
	*p_query_req_copy = *p_query_req;
Packit 13e616
	osm_madw_get_ni_context_ptr(p_madw)->node_guid =
Packit 13e616
	    (ib_net64_t) (uintptr_t)p_query_req_copy;
Packit 13e616
Packit 13e616
	/* we can support async as well as sync calls */
Packit 13e616
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
Packit 13e616
Packit 13e616
	/* send the mad asynchronously */
Packit 13e616
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
Packit 13e616
				 p_madw, p_madw->resp_expected);
Packit 13e616
Packit 13e616
	/* if synchronous - wait on the event */
Packit 13e616
	if (sync) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
Packit 13e616
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
Packit 13e616
		cl_event_reset(&p_bind->sync_event);
Packit 13e616
		status = p_madw->status;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return status;
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Query the SA based on the user's request.
Packit 13e616
 */
Packit 13e616
ib_api_status_t
Packit 13e616
osmv_query_sa(IN osm_bind_handle_t h_bind,
Packit 13e616
	      IN const osmv_query_req_t * const p_query_req)
Packit 13e616
{
Packit 13e616
	union {
Packit 13e616
		ib_service_record_t svc_rec;
Packit 13e616
		ib_node_record_t node_rec;
Packit 13e616
		ib_portinfo_record_t port_info;
Packit 13e616
		ib_path_rec_t path_rec;
Packit 13e616
#ifdef DUAL_SIDED_RMPP
Packit 13e616
		ib_multipath_rec_t multipath_rec;
Packit 13e616
#endif
Packit 13e616
		ib_class_port_info_t class_port_info;
Packit 13e616
	} u;
Packit 13e616
	osmv_sa_mad_data_t sa_mad_data;
Packit 13e616
	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind;
Packit 13e616
	osmv_user_query_t *p_user_query;
Packit 13e616
#ifdef DUAL_SIDED_RMPP
Packit 13e616
	osmv_multipath_req_t *p_mpr_req;
Packit 13e616
	int i, j;
Packit 13e616
#endif
Packit 13e616
	osm_log_t *p_log = p_bind->p_log;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	/* Set the request information. */
Packit 13e616
	sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
Packit 13e616
	sa_mad_data.attr_mod = 0;
Packit 13e616
	sa_mad_data.attr_offset = 0;
Packit 13e616
Packit 13e616
	/* Set the MAD attributes and component mask correctly. */
Packit 13e616
	switch (p_query_req->query_type) {
Packit 13e616
Packit 13e616
	case OSMV_QUERY_USER_DEFINED:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 USER_DEFINED\n");
Packit 13e616
		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
Packit 13e616
		if (p_user_query->method)
Packit 13e616
			sa_mad_data.method = p_user_query->method;
Packit 13e616
#ifdef DUAL_SIDED_RMPP
Packit 13e616
		if (sa_mad_data.method == IB_MAD_METHOD_GETMULTI ||
Packit 13e616
		    sa_mad_data.method == IB_MAD_METHOD_GETTRACETABLE)
Packit 13e616
			sa_mad_data.attr_offset = p_user_query->attr_offset;
Packit 13e616
#endif
Packit 13e616
		sa_mad_data.attr_id = p_user_query->attr_id;
Packit 13e616
		sa_mad_data.attr_mod = p_user_query->attr_mod;
Packit 13e616
		sa_mad_data.comp_mask = p_user_query->comp_mask;
Packit 13e616
		sa_mad_data.p_attr = p_user_query->p_attr;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_ALL_SVC_RECS:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = 0;
Packit 13e616
		sa_mad_data.p_attr = &u.svc_rec;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_SVC_REC_BY_NAME:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n");
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GET;
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
Packit 13e616
		sa_mad_data.p_attr = &u.svc_rec;
Packit 13e616
		memcpy(u.svc_rec.service_name, p_query_req->p_query_input,
Packit 13e616
		       sizeof(ib_svc_name_t));
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_SVC_REC_BY_ID:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_ID\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
Packit 13e616
		sa_mad_data.p_attr = &u.svc_rec;
Packit 13e616
		u.svc_rec.service_id =
Packit 13e616
		    *(ib_net64_t *) (p_query_req->p_query_input);
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_CLASS_PORT_INFO:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 CLASS_PORT_INFO\n");
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GET;
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
Packit 13e616
		sa_mad_data.comp_mask = 0;
Packit 13e616
		sa_mad_data.p_attr = &u.class_port_info;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 NODE_REC_BY_NODE_GUID\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
Packit 13e616
		sa_mad_data.p_attr = &u.node_rec;
Packit 13e616
		u.node_rec.node_info.node_guid =
Packit 13e616
		    *(ib_net64_t *) (p_query_req->p_query_input);
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_PORT_REC_BY_LID:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
Packit 13e616
		sa_mad_data.p_attr = &u.port_info;
Packit 13e616
		u.port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input);
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GET;
Packit 13e616
		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID_AND_NUM\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
Packit 13e616
		sa_mad_data.comp_mask =
Packit 13e616
		    IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
Packit 13e616
		sa_mad_data.p_attr = p_user_query->p_attr;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GET;
Packit 13e616
		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
Packit 13e616
		sa_mad_data.comp_mask =
Packit 13e616
		    IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT |
Packit 13e616
		    IB_VLA_COMPMASK_BLOCK;
Packit 13e616
		sa_mad_data.p_attr = p_user_query->p_attr;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GET;
Packit 13e616
		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
Packit 13e616
		sa_mad_data.comp_mask =
Packit 13e616
		    IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT |
Packit 13e616
		    IB_SLVL_COMPMASK_IN_PORT;
Packit 13e616
		sa_mad_data.p_attr = p_user_query->p_attr;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_PORT_GUIDS\n");
Packit 13e616
		memset(&u.path_rec, 0, sizeof(ib_path_rec_t));
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
Packit 13e616
		sa_mad_data.comp_mask =
Packit 13e616
		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH);
Packit 13e616
		u.path_rec.num_path = 0x7f;
Packit 13e616
		sa_mad_data.p_attr = &u.path_rec;
Packit 13e616
		ib_gid_set_default(&u.path_rec.dgid,
Packit 13e616
				   ((osmv_guid_pair_t *) (p_query_req->
Packit 13e616
							  p_query_input))->
Packit 13e616
							  dest_guid);
Packit 13e616
		ib_gid_set_default(&u.path_rec.sgid,
Packit 13e616
				   ((osmv_guid_pair_t *) (p_query_req->
Packit 13e616
							  p_query_input))->
Packit 13e616
							  src_guid);
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_PATH_REC_BY_GIDS:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_GIDS\n");
Packit 13e616
		memset(&u.path_rec, 0, sizeof(ib_path_rec_t));
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
Packit 13e616
		sa_mad_data.comp_mask =
Packit 13e616
		    (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH);
Packit 13e616
		u.path_rec.num_path = 0x7f;
Packit 13e616
		sa_mad_data.p_attr = &u.path_rec;
Packit 13e616
		memcpy(&u.path_rec.dgid,
Packit 13e616
		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
Packit 13e616
					      dest_gid,
Packit 13e616
		       sizeof(ib_gid_t));
Packit 13e616
		memcpy(&u.path_rec.sgid,
Packit 13e616
		       &((osmv_gid_pair_t *) (p_query_req->p_query_input))->
Packit 13e616
					      src_gid,
Packit 13e616
		       sizeof(ib_gid_t));
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_PATH_REC_BY_LIDS:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_LIDS\n");
Packit 13e616
		memset(&u.path_rec, 0, sizeof(ib_path_rec_t));
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GET;
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
Packit 13e616
		sa_mad_data.comp_mask =
Packit 13e616
		    (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID);
Packit 13e616
		sa_mad_data.p_attr = &u.path_rec;
Packit 13e616
		u.path_rec.dlid =
Packit 13e616
		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->dest_lid;
Packit 13e616
		u.path_rec.slid =
Packit 13e616
		    ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_UD_MULTICAST_SET:
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_SET;
Packit 13e616
		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_SET\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = p_user_query->comp_mask;
Packit 13e616
		sa_mad_data.p_attr = p_user_query->p_attr;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case OSMV_QUERY_UD_MULTICAST_DELETE:
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_DELETE;
Packit 13e616
		p_user_query = (osmv_user_query_t *) p_query_req->p_query_input;
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_DELETE\n");
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
Packit 13e616
		sa_mad_data.comp_mask = p_user_query->comp_mask;
Packit 13e616
		sa_mad_data.p_attr = p_user_query->p_attr;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
#ifdef DUAL_SIDED_RMPP
Packit 13e616
	case OSMV_QUERY_MULTIPATH_REC:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 MULTIPATH_REC\n");
Packit 13e616
		/* Validate sgid/dgid counts against SA client limit */
Packit 13e616
		p_mpr_req = (osmv_multipath_req_t *) p_query_req->p_query_input;
Packit 13e616
		if (p_mpr_req->sgid_count + p_mpr_req->dgid_count >
Packit 13e616
		    IB_MULTIPATH_MAX_GIDS) {
Packit 13e616
			OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 MULTIPATH_REC "
Packit 13e616
				"SGID count %d DGID count %d max count %d\n",
Packit 13e616
				p_mpr_req->sgid_count, p_mpr_req->dgid_count,
Packit 13e616
				IB_MULTIPATH_MAX_GIDS);
Packit 13e616
			CL_ASSERT(0);
Packit 13e616
			return IB_ERROR;
Packit 13e616
		}
Packit 13e616
		memset(&u.multipath_rec, 0, sizeof(ib_multipath_rec_t));
Packit 13e616
		sa_mad_data.method = IB_MAD_METHOD_GETMULTI;
Packit 13e616
		sa_mad_data.attr_id = IB_MAD_ATTR_MULTIPATH_RECORD;
Packit 13e616
		sa_mad_data.attr_offset =
Packit 13e616
		    ib_get_attr_offset(sizeof(ib_multipath_rec_t));
Packit 13e616
		sa_mad_data.p_attr = &u.multipath_rec;
Packit 13e616
		sa_mad_data.comp_mask = p_mpr_req->comp_mask;
Packit 13e616
		u.multipath_rec.num_path = p_mpr_req->num_path;
Packit 13e616
		if (p_mpr_req->reversible)
Packit 13e616
			u.multipath_rec.num_path |= 0x80;
Packit 13e616
		else
Packit 13e616
			u.multipath_rec.num_path &= ~0x80;
Packit 13e616
		u.multipath_rec.pkey = p_mpr_req->pkey;
Packit 13e616
		ib_multipath_rec_set_sl(&u.multipath_rec, p_mpr_req->sl);
Packit 13e616
		ib_multipath_rec_set_qos_class(&u.multipath_rec, 0);
Packit 13e616
		u.multipath_rec.independence = p_mpr_req->independence;
Packit 13e616
		u.multipath_rec.sgid_count = p_mpr_req->sgid_count;
Packit 13e616
		u.multipath_rec.dgid_count = p_mpr_req->dgid_count;
Packit 13e616
		j = 0;
Packit 13e616
		for (i = 0; i < p_mpr_req->sgid_count; i++, j++)
Packit 13e616
			u.multipath_rec.gids[j] = p_mpr_req->gids[j];
Packit 13e616
		for (i = 0; i < p_mpr_req->dgid_count; i++, j++)
Packit 13e616
			u.multipath_rec.gids[j] = p_mpr_req->gids[j];
Packit 13e616
		break;
Packit 13e616
#endif
Packit 13e616
Packit 13e616
	default:
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 UNKNOWN\n");
Packit 13e616
		CL_ASSERT(0);
Packit 13e616
		return IB_ERROR;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return status;
Packit 13e616
}