Blame libvendor/osm_vendor_mlx_ibmgt.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
/*  AUTHOR                 Edward Bortnikov
Packit 13e616
 *
Packit 13e616
 *  DESCRIPTION
Packit 13e616
 *     The lower-level MAD transport interface implementation
Packit 13e616
 *     that allows sending a single MAD/receiving a callback
Packit 13e616
 *     when a single MAD is received.
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 <ib_mgt.h>
Packit 13e616
#include <complib/cl_event.h>
Packit 13e616
#include <vendor/osm_vendor_mlx_transport.h>
Packit 13e616
#include <vendor/osm_vendor_mlx_dispatcher.h>
Packit 13e616
#include <opensm/osm_log.h>
Packit 13e616
Packit 13e616
typedef struct _osmv_IBMGT_transport_mgr_ {
Packit 13e616
	IB_MGT_mad_type_t mad_type;
Packit 13e616
	uint8_t mgmt_class;	/* for gsi */
Packit 13e616
	/* for communication between send call back and send mad */
Packit 13e616
	boolean_t is_send_ok;
Packit 13e616
	cl_event_t send_done;
Packit 13e616
} osmv_IBMGT_transport_mgr_t;
Packit 13e616
Packit 13e616
typedef struct _osmv_IBMGT_transport_info_ {
Packit 13e616
	IB_MGT_mad_hndl_t smi_h;
Packit 13e616
	cl_qlist_t *p_smi_list;
Packit 13e616
Packit 13e616
	IB_MGT_mad_hndl_t gsi_h;
Packit 13e616
	/* holds bind object list for every binded mgmt class */
Packit 13e616
	cl_qlist_t *gsi_mgmt_lists[15];
Packit 13e616
} osmv_IBMGT_transport_info_t;
Packit 13e616
Packit 13e616
static void
Packit 13e616
__osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
Packit 13e616
				  IN uint8_t is_smi,
Packit 13e616
				  OUT osm_mad_addr_t * p_mad_addr);
Packit 13e616
Packit 13e616
static void
Packit 13e616
__osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr,
Packit 13e616
				    IN uint8_t is_smi, OUT IB_ud_av_t * p_av);
Packit 13e616
Packit 13e616
void
Packit 13e616
__osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl,
Packit 13e616
		     IN u_int64_t wrid,
Packit 13e616
		     IN IB_comp_status_t status, IN void *private_ctx_p);
Packit 13e616
Packit 13e616
void
Packit 13e616
__osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl,
Packit 13e616
		    IN void *private_ctx_p,
Packit 13e616
		    IN void *payload_p,
Packit 13e616
		    IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p);
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * NAME
Packit 13e616
 *   osmv_transport_init
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 *   Setup the MAD transport infrastructure (filters, callbacks etc).
Packit 13e616
 */
Packit 13e616
Packit 13e616
ib_api_status_t
Packit 13e616
osmv_transport_init(IN osm_bind_info_t * p_info,
Packit 13e616
		    IN char hca_id[VENDOR_HCA_MAXNAMES],
Packit 13e616
		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
Packit 13e616
{
Packit 13e616
	ib_api_status_t st = IB_SUCCESS;
Packit 13e616
	IB_MGT_ret_t ret;
Packit 13e616
	IB_MGT_mad_type_t mad_type;
Packit 13e616
	osmv_IBMGT_transport_mgr_t *p_mgr;
Packit 13e616
	osmv_IBMGT_transport_info_t *p_tpot_info;
Packit 13e616
	cl_list_obj_t *p_obj = NULL;
Packit 13e616
	osm_log_t *p_log = p_bo->p_vendor->p_log;
Packit 13e616
	int i;
Packit 13e616
Packit 13e616
	UNUSED_PARAM(hca_idx);
Packit 13e616
Packit 13e616
	/* if first bind, allocate tranport_info at vendor */
Packit 13e616
	if (NULL == p_bo->p_vendor->p_transport_info) {
Packit 13e616
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osmv_transport_init: first bind() for the vendor\n");
Packit 13e616
		p_bo->p_vendor->p_transport_info
Packit 13e616
		    = (osmv_IBMGT_transport_info_t *)
Packit 13e616
		    malloc(sizeof(osmv_IBMGT_transport_info_t));
Packit 13e616
		if (NULL == p_bo->p_vendor->p_transport_info) {
Packit 13e616
			return IB_INSUFFICIENT_MEMORY;
Packit 13e616
		}
Packit 13e616
		memset(p_bo->p_vendor->p_transport_info, 0,
Packit 13e616
		       sizeof(osmv_IBMGT_transport_info_t));
Packit 13e616
		p_tpot_info =
Packit 13e616
		    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->
Packit 13e616
						     p_transport_info);
Packit 13e616
Packit 13e616
		p_tpot_info->smi_h = 0xffffffff;
Packit 13e616
		p_tpot_info->p_smi_list = NULL;
Packit 13e616
Packit 13e616
		p_tpot_info->gsi_h = 0xffffffff;
Packit 13e616
		for (i = 0; i < 15; i++) {
Packit 13e616
Packit 13e616
			p_tpot_info->gsi_mgmt_lists[i] = NULL;
Packit 13e616
		}
Packit 13e616
Packit 13e616
	} else {
Packit 13e616
Packit 13e616
		p_tpot_info =
Packit 13e616
		    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->
Packit 13e616
						     p_transport_info);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* Initialize the magic_ptr to the pointer of the p_bo info.
Packit 13e616
	   This will be used to signal when the object is being destroyed, so no
Packit 13e616
	   real action will be done then. */
Packit 13e616
	p_bo->magic_ptr = p_bo;
Packit 13e616
Packit 13e616
	/* allocate transport mgr */
Packit 13e616
	p_mgr = malloc(sizeof(osmv_IBMGT_transport_mgr_t));
Packit 13e616
	if (NULL == p_mgr) {
Packit 13e616
		free(p_tpot_info);
Packit 13e616
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osmv_transport_init: ERR 7201: " "alloc failed \n");
Packit 13e616
		return IB_INSUFFICIENT_MEMORY;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	memset(p_mgr, 0, sizeof(osmv_IBMGT_transport_mgr_t));
Packit 13e616
Packit 13e616
	p_bo->p_transp_mgr = p_mgr;
Packit 13e616
Packit 13e616
	switch (p_info->mad_class) {
Packit 13e616
	case IB_MCLASS_SUBN_LID:
Packit 13e616
	case IB_MCLASS_SUBN_DIR:
Packit 13e616
		mad_type = IB_MGT_SMI;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MCLASS_SUBN_ADM:
Packit 13e616
	default:
Packit 13e616
		mad_type = IB_MGT_GSI;
Packit 13e616
		break;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* we only support one class registration per SMI/GSI !!! */
Packit 13e616
	switch (mad_type) {
Packit 13e616
	case IB_MGT_SMI:
Packit 13e616
		/* we do not need to bind the handle if already available */
Packit 13e616
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osmv_transport_init: SMI bind\n");
Packit 13e616
Packit 13e616
		if (p_tpot_info->smi_h == 0xffffffff) {
Packit 13e616
			ret = IB_MGT_get_handle(hca_id,
Packit 13e616
						p_bo->port_num,
Packit 13e616
						IB_MGT_SMI,
Packit 13e616
						&(p_tpot_info->smi_h));
Packit 13e616
			if (IB_MGT_OK != ret) {
Packit 13e616
				osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_init: ERR 7202: "
Packit 13e616
					"IB_MGT_get_handle for smi failed \n");
Packit 13e616
				st = IB_ERROR;
Packit 13e616
				free(p_mgr);
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osmv_transport_init: got smi handle:%d \n",
Packit 13e616
				p_tpot_info->smi_h);
Packit 13e616
Packit 13e616
			ret = IB_MGT_bind_sm(p_tpot_info->smi_h);
Packit 13e616
			if (IB_MGT_OK != ret) {
Packit 13e616
				osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_init: ERR 7203: "
Packit 13e616
					"IB_MGT_bind_sm failed \n");
Packit 13e616
				st = IB_ERROR;
Packit 13e616
				free(p_mgr);
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			/* init smi list */
Packit 13e616
			p_tpot_info->p_smi_list = malloc(sizeof(cl_qlist_t));
Packit 13e616
			if (NULL == p_tpot_info->p_smi_list) {
Packit 13e616
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_init: ERR 7204: "
Packit 13e616
					"alloc failed \n");
Packit 13e616
				IB_MGT_unbind_sm(p_tpot_info->smi_h);
Packit 13e616
				IB_MGT_release_handle(p_tpot_info->smi_h);
Packit 13e616
				free(p_mgr);
Packit 13e616
				return IB_INSUFFICIENT_MEMORY;
Packit 13e616
			}
Packit 13e616
			memset(p_tpot_info->p_smi_list, 0, sizeof(cl_qlist_t));
Packit 13e616
			cl_qlist_init(p_tpot_info->p_smi_list);
Packit 13e616
Packit 13e616
			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osmv_transport_init: before reg_cb\n");
Packit 13e616
			ret = IB_MGT_reg_cb(p_tpot_info->smi_h,
Packit 13e616
					    &__osmv_IBMGT_rcv_cb,
Packit 13e616
					    p_bo,
Packit 13e616
					    &__osmv_IBMGT_send_cb,
Packit 13e616
					    p_tpot_info->p_smi_list,
Packit 13e616
					    IB_MGT_RCV_CB_MASK |
Packit 13e616
					    IB_MGT_SEND_CB_MASK);
Packit 13e616
			if (ret != IB_SUCCESS) {
Packit 13e616
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_init: ERR 7205: "
Packit 13e616
					"reg_cb failed with return code:%x \n",
Packit 13e616
					ret);
Packit 13e616
				IB_MGT_unbind_sm(p_tpot_info->smi_h);
Packit 13e616
				IB_MGT_release_handle(p_tpot_info->smi_h);
Packit 13e616
				free(p_tpot_info->p_smi_list);
Packit 13e616
				free(p_mgr);
Packit 13e616
				st = IB_ERROR;
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
		}
Packit 13e616
		/* insert to list of smi's - for raising callbacks later on */
Packit 13e616
		p_obj = malloc(sizeof(cl_list_obj_t));
Packit 13e616
		if (p_obj)
Packit 13e616
			memset(p_obj, 0, sizeof(cl_list_obj_t));
Packit 13e616
		cl_qlist_set_obj(p_obj, p_bo);
Packit 13e616
		cl_qlist_insert_tail(p_tpot_info->p_smi_list,
Packit 13e616
				     &p_obj->list_item);
Packit 13e616
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MGT_GSI:
Packit 13e616
		/* we do not need to bind the handle if already available */
Packit 13e616
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"osmv_transport_init: ERR 7206: GSI bind\n");
Packit 13e616
		if (p_tpot_info->gsi_h == 0xffffffff) {
Packit 13e616
			ret = IB_MGT_get_handle(hca_id,
Packit 13e616
						p_bo->port_num,
Packit 13e616
						IB_MGT_GSI,
Packit 13e616
						&(p_tpot_info->gsi_h));
Packit 13e616
			if (IB_MGT_OK != ret) {
Packit 13e616
				osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_init: ERR 7207: "
Packit 13e616
					"IB_MGT_get_handle for gsi failed \n");
Packit 13e616
				st = IB_ERROR;
Packit 13e616
				free(p_mgr);
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* this mgmt class was not binded yet */
Packit 13e616
		if (p_tpot_info->gsi_mgmt_lists[p_info->mad_class] == NULL) {
Packit 13e616
			ret =
Packit 13e616
			    IB_MGT_bind_gsi_class(p_tpot_info->gsi_h,
Packit 13e616
						  p_info->mad_class);
Packit 13e616
			if (IB_MGT_OK != ret) {
Packit 13e616
				osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_init: ERR 7208: "
Packit 13e616
					"IB_MGT_bind_gsi_class failed \n");
Packit 13e616
				st = IB_ERROR;
Packit 13e616
				free(p_mgr);
Packit 13e616
				goto Exit;
Packit 13e616
			}
Packit 13e616
Packit 13e616
			p_tpot_info->gsi_mgmt_lists[p_info->mad_class] =
Packit 13e616
			    malloc(sizeof(cl_qlist_t));
Packit 13e616
			if (NULL ==
Packit 13e616
			    p_tpot_info->gsi_mgmt_lists[p_info->mad_class]) {
Packit 13e616
				IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
Packit 13e616
							p_info->mad_class);
Packit 13e616
				free(p_mgr);
Packit 13e616
				return IB_INSUFFICIENT_MEMORY;
Packit 13e616
			}
Packit 13e616
			memset(p_tpot_info->gsi_mgmt_lists[p_info->mad_class],
Packit 13e616
			       0, sizeof(cl_qlist_t));
Packit 13e616
			cl_qlist_init(p_tpot_info->
Packit 13e616
				      gsi_mgmt_lists[p_info->mad_class]);
Packit 13e616
		}
Packit 13e616
		/* insert to list of smi's - for raising callbacks later on */
Packit 13e616
		p_obj = malloc(sizeof(cl_list_obj_t));
Packit 13e616
		if (p_obj)
Packit 13e616
			memset(p_obj, 0, sizeof(cl_list_obj_t));
Packit 13e616
		cl_qlist_set_obj(p_obj, p_bo);
Packit 13e616
		cl_qlist_insert_tail(p_tpot_info->
Packit 13e616
				     gsi_mgmt_lists[p_info->mad_class],
Packit 13e616
				     &p_obj->list_item);
Packit 13e616
Packit 13e616
		p_mgr->mgmt_class = p_info->mad_class;
Packit 13e616
		ret = IB_MGT_reg_cb(p_tpot_info->gsi_h,
Packit 13e616
				    &__osmv_IBMGT_rcv_cb,
Packit 13e616
				    p_bo,
Packit 13e616
				    &__osmv_IBMGT_send_cb,
Packit 13e616
				    p_bo,
Packit 13e616
				    IB_MGT_RCV_CB_MASK | IB_MGT_SEND_CB_MASK);
Packit 13e616
Packit 13e616
		if (ret != IB_SUCCESS) {
Packit 13e616
			IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
Packit 13e616
						p_mgr->mgmt_class);
Packit 13e616
			free(p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class]);
Packit 13e616
			free(p_mgr);
Packit 13e616
			st = IB_ERROR;
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	default:
Packit 13e616
		osm_log(p_log, OSM_LOG_ERROR,
Packit 13e616
			"osmv_transport_init: ERR 7209: unrecognized mgmt class \n");
Packit 13e616
		st = IB_ERROR;
Packit 13e616
		free(p_mgr);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"osmv_transport_init: GSI bind\n");
Packit 13e616
	cl_event_construct(&p_mgr->send_done);
Packit 13e616
	cl_event_init(&p_mgr->send_done, TRUE);
Packit 13e616
	p_mgr->is_send_ok = FALSE;
Packit 13e616
	p_mgr->mad_type = mad_type;
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	/* OSM_LOG_EXIT(p_log ); */
Packit 13e616
	return (ib_api_status_t) st;
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * NAME
Packit 13e616
 *   osmv_transport_send_mad
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 *   Send a single MAD (256 byte)
Packit 13e616
 */
Packit 13e616
Packit 13e616
ib_api_status_t
Packit 13e616
osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
Packit 13e616
			IN void *p_ib_mad, IN const osm_mad_addr_t * p_mad_addr)
Packit 13e616
{
Packit 13e616
Packit 13e616
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
Packit 13e616
	osmv_IBMGT_transport_info_t *p_tpot_info =
Packit 13e616
	    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info);
Packit 13e616
	osm_vendor_t const *p_vend = p_bo->p_vendor;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	IB_ud_av_t av;
Packit 13e616
	IB_MGT_ret_t ret;
Packit 13e616
	ib_mad_t *p_mad = p_ib_mad;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_vend->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_bo->p_vendor->p_transport_info);
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
		__osmv_IBMGT_osm_addr_to_ibmgt_addr(p_mad_addr,
Packit 13e616
						    p_mad->mgmt_class ==
Packit 13e616
						    IB_MCLASS_SUBN_LID, &av;;
Packit 13e616
	} else {
Packit 13e616
		/* is a directed route - we need to construct a permissive address */
Packit 13e616
		memset(&av, 0, sizeof(av));
Packit 13e616
		/* we do not need port number since it is part of the mad_hndl */
Packit 13e616
		av.dlid = IB_LID_PERMISSIVE;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* send it */
Packit 13e616
	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
Packit 13e616
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
Packit 13e616
Packit 13e616
		/* SMI CASE */
Packit 13e616
		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osmv_transport_mad_send: "
Packit 13e616
				"av.dlid:0x%X, "
Packit 13e616
				"av.static_rate:%d, "
Packit 13e616
				"av.path_bits:%d.\n",
Packit 13e616
				cl_ntoh16(av.dlid), av.static_rate,
Packit 13e616
				av.src_path_bits);
Packit 13e616
		}
Packit 13e616
Packit 13e616
		ret = IB_MGT_send_mad(p_tpot_info->smi_h, p_mad,	/*  actual payload */
Packit 13e616
				      &av,	/*  address vector */
Packit 13e616
				      (u_int64_t) CAST_P2LONG(p_bo),
Packit 13e616
				      IB_MGT_DEFAULT_SEND_TIME);
Packit 13e616
	} else {
Packit 13e616
		/* GSI CASE - Support Remote QP */
Packit 13e616
		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
Packit 13e616
				"osmv_transport_mad_send: "
Packit 13e616
				"av.dlid:0x%X, av.static_rate:%d, av.path_bits:%d, remote qp:%d \n",
Packit 13e616
				cl_ntoh16(av.dlid), av.static_rate,
Packit 13e616
				av.src_path_bits,
Packit 13e616
				cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp)
Packit 13e616
			    );
Packit 13e616
		}
Packit 13e616
Packit 13e616
		ret = IB_MGT_send_mad_to_qp(p_tpot_info->gsi_h, p_mad,	/*  actual payload */
Packit 13e616
					    &av,	/*  address vector */
Packit 13e616
					    (u_int64_t) CAST_P2LONG(p_bo),
Packit 13e616
					    IB_MGT_DEFAULT_SEND_TIME,
Packit 13e616
					    cl_ntoh32(p_mad_addr->addr_type.gsi.
Packit 13e616
						      remote_qp));
Packit 13e616
Packit 13e616
	}
Packit 13e616
Packit 13e616
	status = IB_SUCCESS;
Packit 13e616
	if (ret != IB_MGT_OK) {
Packit 13e616
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
			"osmv_transport_mad_send: ERR 7210: "
Packit 13e616
			"Error sending mad (%d).\n", ret);
Packit 13e616
		status = IB_ERROR;
Packit 13e616
	} else {
Packit 13e616
		osmv_IBMGT_transport_mgr_t *p_mgr =
Packit 13e616
		    (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr);
Packit 13e616
Packit 13e616
		/* Let the others work when I am sleeping ... */
Packit 13e616
		osmv_txn_unlock(p_bo);
Packit 13e616
Packit 13e616
		cl_event_wait_on(&(p_mgr->send_done), 0xffffffff, TRUE);
Packit 13e616
Packit 13e616
		/* Re-acquire the lock */
Packit 13e616
		osmv_txn_lock(p_bo);
Packit 13e616
Packit 13e616
		if (TRUE == p_bo->is_closing) {
Packit 13e616
Packit 13e616
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
Packit 13e616
				"osmv_transport_mad_send: ERR 7211: "
Packit 13e616
				"The handle %p is being unbound, cannot send.\n",
Packit 13e616
				h_bind);
Packit 13e616
			status = IB_ERROR;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		if (p_mgr->is_send_ok == FALSE) {
Packit 13e616
			status = IB_ERROR;
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_vend->p_log);
Packit 13e616
	return (status);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osmv_transport_done(IN const osm_bind_handle_t h_bind)
Packit 13e616
{
Packit 13e616
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
Packit 13e616
	osm_log_t *p_log = p_bo->p_vendor->p_log;
Packit 13e616
	osmv_IBMGT_transport_mgr_t *p_mgr;
Packit 13e616
	osmv_IBMGT_transport_info_t *p_tpot_info;
Packit 13e616
	IB_MGT_ret_t ret;
Packit 13e616
	cl_list_obj_t *p_obj = NULL;
Packit 13e616
	cl_list_item_t *p_item, *p_item_tmp;
Packit 13e616
	int i;
Packit 13e616
	cl_qlist_t *p_list = NULL;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_bo);
Packit 13e616
Packit 13e616
	/* First of all - zero out the magic_ptr, so if a callback is called -
Packit 13e616
	   it'll know that we are currently closing down, and will not handle the
Packit 13e616
	   mad. */
Packit 13e616
	p_bo->magic_ptr = 0;
Packit 13e616
Packit 13e616
	p_mgr = (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr);
Packit 13e616
	p_tpot_info =
Packit 13e616
	    (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info);
Packit 13e616
Packit 13e616
	switch (p_mgr->mad_type) {
Packit 13e616
	case IB_MGT_SMI:
Packit 13e616
		p_list = p_tpot_info->p_smi_list;
Packit 13e616
Packit 13e616
		/* remove from the bindings list */
Packit 13e616
		p_item = cl_qlist_head(p_list);
Packit 13e616
		while (p_item != cl_qlist_end(p_list)) {
Packit 13e616
			p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
Packit 13e616
			if (cl_qlist_obj(p_obj) == h_bind) {
Packit 13e616
				break;
Packit 13e616
			}
Packit 13e616
			p_item_tmp = cl_qlist_next(p_item);
Packit 13e616
			p_item = p_item_tmp;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		CL_ASSERT(p_item != cl_qlist_end(p_list));
Packit 13e616
		cl_qlist_remove_item(p_list, p_item);
Packit 13e616
		if (p_obj)
Packit 13e616
			free(p_obj);
Packit 13e616
Packit 13e616
		/* no one is binded to smi anymore - we can free the list, unbind & realease the hndl */
Packit 13e616
		if (cl_is_qlist_empty(p_list) == TRUE) {
Packit 13e616
			free(p_list);
Packit 13e616
			p_list = NULL;
Packit 13e616
Packit 13e616
			ret = IB_MGT_unbind_sm(p_tpot_info->smi_h);
Packit 13e616
			if (ret != IB_MGT_OK) {
Packit 13e616
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_done: ERR 7212: "
Packit 13e616
					"Failed to unbind sm\n");
Packit 13e616
			}
Packit 13e616
Packit 13e616
			ret = IB_MGT_release_handle(p_tpot_info->smi_h);
Packit 13e616
			if (ret != IB_MGT_OK) {
Packit 13e616
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_done: ERR 7213: "
Packit 13e616
					"Failed to release smi handle\n");
Packit 13e616
			}
Packit 13e616
			p_tpot_info->smi_h = 0xffffffff;
Packit 13e616
		}
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MGT_GSI:
Packit 13e616
		p_list = p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class];
Packit 13e616
		/* remove from the bindings list */
Packit 13e616
		p_item = cl_qlist_head(p_list);
Packit 13e616
		while (p_item != cl_qlist_end(p_list)) {
Packit 13e616
			p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
Packit 13e616
			if (cl_qlist_obj(p_obj) == h_bind) {
Packit 13e616
				break;
Packit 13e616
			}
Packit 13e616
			p_item_tmp = cl_qlist_next(p_item);
Packit 13e616
			p_item = p_item_tmp;
Packit 13e616
		}
Packit 13e616
Packit 13e616
		CL_ASSERT(p_item != cl_qlist_end(p_list));
Packit 13e616
		cl_qlist_remove_item(p_list, p_item);
Packit 13e616
		if (p_obj)
Packit 13e616
			free(p_obj);
Packit 13e616
Packit 13e616
		/* no one is binded to this class anymore - we can free the list and unbind this class */
Packit 13e616
		if (cl_is_qlist_empty(p_list) == TRUE) {
Packit 13e616
			free(p_list);
Packit 13e616
			p_list = NULL;
Packit 13e616
Packit 13e616
			ret =
Packit 13e616
			    IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h,
Packit 13e616
						    p_mgr->mgmt_class);
Packit 13e616
			if (ret != IB_MGT_OK) {
Packit 13e616
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_done: ERR 7214: "
Packit 13e616
					"Failed to unbind gsi class\n");
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
Packit 13e616
		/* all the mgmt classes are unbinded - release gsi handle */
Packit 13e616
		for (i = 0; i < 15; i++) {
Packit 13e616
			if (p_tpot_info->gsi_mgmt_lists[i] != NULL) {
Packit 13e616
				break;
Packit 13e616
			}
Packit 13e616
		}
Packit 13e616
Packit 13e616
		if (i == 15) {
Packit 13e616
			ret = IB_MGT_release_handle(p_tpot_info->gsi_h);
Packit 13e616
			if (ret != IB_MGT_OK) {
Packit 13e616
				osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
Packit 13e616
					"osmv_transport_done: ERR 7215: "
Packit 13e616
					"Failed to release gsi handle\n");
Packit 13e616
			}
Packit 13e616
			p_tpot_info->gsi_h = 0xffffffff;
Packit 13e616
		}
Packit 13e616
	}			/* end switch */
Packit 13e616
Packit 13e616
	free(p_mgr);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * IB_MGT Receive callback : invoked after each receive
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl,
Packit 13e616
		    IN void *private_ctx_p,
Packit 13e616
		    IN void *payload_p,
Packit 13e616
		    IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p)
Packit 13e616
{
Packit 13e616
	osmv_bind_obj_t *p_bo;
Packit 13e616
	osm_mad_addr_t mad_addr;
Packit 13e616
	cl_list_item_t *p_item;
Packit 13e616
	cl_list_obj_t *p_obj;
Packit 13e616
	cl_qlist_t *p_list;
Packit 13e616
	ib_mad_t *p_mad = (ib_mad_t *) payload_p;
Packit 13e616
	osm_vendor_t *p_vendor;
Packit 13e616
	osmv_IBMGT_transport_info_t *p_tinfo;
Packit 13e616
Packit 13e616
	__osmv_IBMGT_rcv_desc_to_osm_addr(rcv_remote_info_p,
Packit 13e616
					  ((p_mad->mgmt_class ==
Packit 13e616
					    IB_MCLASS_SUBN_LID)
Packit 13e616
					   || (p_mad->mgmt_class ==
Packit 13e616
					       IB_MCLASS_SUBN_DIR)), &mad_addr);
Packit 13e616
Packit 13e616
	/* different handling of SMI and GSI */
Packit 13e616
	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) ||
Packit 13e616
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) {
Packit 13e616
		/* SMI CASE */
Packit 13e616
		p_bo = (osmv_bind_obj_t *) private_ctx_p;
Packit 13e616
		/* Make sure the p_bo object is still relevant */
Packit 13e616
		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
Packit 13e616
			return;
Packit 13e616
Packit 13e616
		p_vendor = p_bo->p_vendor;
Packit 13e616
		p_tinfo =
Packit 13e616
		    (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info;
Packit 13e616
		p_list = p_tinfo->p_smi_list;
Packit 13e616
	} else {
Packit 13e616
		/* GSI CASE */
Packit 13e616
		p_bo = (osmv_bind_obj_t *) private_ctx_p;
Packit 13e616
		/* Make sure the p_bo object is still relevant */
Packit 13e616
		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
Packit 13e616
			return;
Packit 13e616
Packit 13e616
		p_vendor = p_bo->p_vendor;
Packit 13e616
		p_tinfo =
Packit 13e616
		    (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info;
Packit 13e616
		p_list = p_tinfo->gsi_mgmt_lists[p_mad->mgmt_class];
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/* go over the bindings list and send the mad, one of them will accept it,
Packit 13e616
	   the others will drope
Packit 13e616
	 */
Packit 13e616
	p_item = cl_qlist_head(p_list);
Packit 13e616
	while (p_item != cl_qlist_end(p_list)) {
Packit 13e616
		p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
Packit 13e616
		p_bo = cl_qlist_obj(p_obj);
Packit 13e616
		/* give upper layer the mad */
Packit 13e616
		osmv_dispatch_mad((osm_bind_handle_t) p_bo, payload_p,
Packit 13e616
				  &mad_addr);
Packit 13e616
		/* Make sure the p_bo object is still relevant */
Packit 13e616
		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
Packit 13e616
			return;
Packit 13e616
Packit 13e616
		p_item = cl_qlist_next(p_item);
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * IB_MGT Send callback : invoked after each send
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl,
Packit 13e616
		     IN u_int64_t wrid,
Packit 13e616
		     IN IB_comp_status_t status, IN void *private_ctx_p)
Packit 13e616
{
Packit 13e616
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) CAST_P2LONG(wrid);
Packit 13e616
Packit 13e616
	osmv_IBMGT_transport_mgr_t *p_mgr =
Packit 13e616
	    (osmv_IBMGT_transport_mgr_t *) p_bo->p_transp_mgr;
Packit 13e616
Packit 13e616
	/* Make sure the p_bo object is still relevant */
Packit 13e616
	if (p_bo->magic_ptr != p_bo)
Packit 13e616
		return;
Packit 13e616
Packit 13e616
	/* we assume that each send on a bind object is synchronized, and no paralel sends
Packit 13e616
	   from diffrent threads with same object can be made */
Packit 13e616
	if (status == IB_COMP_SUCCESS) {
Packit 13e616
		p_mgr->is_send_ok = TRUE;
Packit 13e616
	} else
Packit 13e616
		p_mgr->is_send_ok = FALSE;
Packit 13e616
	cl_event_signal(&p_mgr->send_done);
Packit 13e616
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * IB_MGT to OSM ADDRESS VECTOR
Packit 13e616
 **********************************************************************/
Packit 13e616
static void
Packit 13e616
__osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc,
Packit 13e616
				  IN uint8_t is_smi,
Packit 13e616
				  OUT osm_mad_addr_t * p_mad_addr)
Packit 13e616
{
Packit 13e616
	/*  p_mad_addr->dest_lid = p_osm->subn.sm_base_lid; - for resp we use the dest lid ... */
Packit 13e616
	p_mad_addr->dest_lid = cl_hton16(p_rcv_desc->remote_lid);
Packit 13e616
	p_mad_addr->static_rate = 0;	/*  HACK - we do not  know the rate ! */
Packit 13e616
	p_mad_addr->path_bits = p_rcv_desc->local_path_bits;
Packit 13e616
	/* Clear the grh any way to avoid unset fields */
Packit 13e616
	memset(&p_mad_addr->addr_type.gsi.grh_info, 0,
Packit 13e616
	       sizeof(p_mad_addr->addr_type.gsi.grh_info));
Packit 13e616
Packit 13e616
	if (is_smi) {
Packit 13e616
		/* SMI */
Packit 13e616
		p_mad_addr->addr_type.smi.source_lid =
Packit 13e616
		    cl_hton16(p_rcv_desc->remote_lid);
Packit 13e616
		p_mad_addr->addr_type.smi.port_num = 99;	/*  HACK - if used - should fail */
Packit 13e616
	} else {
Packit 13e616
		/* GSI */
Packit 13e616
		/* seems to me there is a IBMGT bug reversing the QPN ... */
Packit 13e616
		/* Does IBMGT supposed to provide the QPN is network or HOST ? */
Packit 13e616
		p_mad_addr->addr_type.gsi.remote_qp = cl_hton32(p_rcv_desc->qp);
Packit 13e616
Packit 13e616
		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
Packit 13e616
		/*  we do have the p_mad_addr->pkey_ix but how to get the PKey by index ? */
Packit 13e616
		/*  the only way seems to be to use VAPI_query_hca_pkey_tbl and obtain */
Packit 13e616
		/*  the full PKey table - than go by the index. */
Packit 13e616
		/*  since this does not seem reasonable to me I simply use the default */
Packit 13e616
		/*  There is a TAVOR limitation that only one P_KEY is supported per  */
Packit 13e616
		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
Packit 13e616
		p_mad_addr->addr_type.gsi.pkey_ix = 0;
Packit 13e616
		p_mad_addr->addr_type.gsi.service_level = p_rcv_desc->sl;
Packit 13e616
Packit 13e616
		p_mad_addr->addr_type.gsi.global_route = p_rcv_desc->grh_flag;
Packit 13e616
		/* copy the GRH data if relevant */
Packit 13e616
		if (p_mad_addr->addr_type.gsi.global_route) {
Packit 13e616
			p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
Packit 13e616
			    ib_grh_set_ver_class_flow(p_rcv_desc->grh.
Packit 13e616
						      IP_version,
Packit 13e616
						      p_rcv_desc->grh.
Packit 13e616
						      traffic_class,
Packit 13e616
						      p_rcv_desc->grh.
Packit 13e616
						      flow_label);
Packit 13e616
			p_mad_addr->addr_type.gsi.grh_info.hop_limit =
Packit 13e616
			    p_rcv_desc->grh.hop_limit;
Packit 13e616
			memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
Packit 13e616
			       &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
Packit 13e616
			memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
Packit 13e616
			       p_rcv_desc->grh.dgid, sizeof(ib_net64_t));
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 * OSM ADDR VECTOR TO IB_MGT
Packit 13e616
 **********************************************************************/
Packit 13e616
void
Packit 13e616
__osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr,
Packit 13e616
				    IN uint8_t is_smi, OUT IB_ud_av_t * p_av)
Packit 13e616
{
Packit 13e616
Packit 13e616
	/* For global destination or Multicast address: */
Packit 13e616
	u_int8_t ver;
Packit 13e616
Packit 13e616
	memset(p_av, 0, sizeof(IB_ud_av_t));
Packit 13e616
Packit 13e616
	p_av->src_path_bits = p_mad_addr->path_bits;
Packit 13e616
	p_av->static_rate = p_mad_addr->static_rate;
Packit 13e616
	p_av->dlid = cl_ntoh16(p_mad_addr->dest_lid);
Packit 13e616
Packit 13e616
	if (is_smi) {
Packit 13e616
		p_av->sl = 0;	/*  Just to note we use 0 here. */
Packit 13e616
	} else {
Packit 13e616
		p_av->sl = p_mad_addr->addr_type.gsi.service_level;
Packit 13e616
		p_av->grh_flag = p_mad_addr->addr_type.gsi.global_route;
Packit 13e616
Packit 13e616
		if (p_mad_addr->addr_type.gsi.global_route) {
Packit 13e616
			ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi.
Packit 13e616
						  grh_info.ver_class_flow, &ver,
Packit 13e616
						  &p_av->traffic_class,
Packit 13e616
						  &p_av->flow_label);
Packit 13e616
			p_av->hop_limit =
Packit 13e616
			    p_mad_addr->addr_type.gsi.grh_info.hop_limit;
Packit 13e616
			p_av->sgid_index = 0;	/*  we always use source GID 0 */
Packit 13e616
			memcpy(&p_av->dgid,
Packit 13e616
			       &p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
Packit 13e616
			       sizeof(ib_net64_t));
Packit 13e616
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
}