Blame opensm/osm_sm_mad_ctrl.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit 13e616
 * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
Packit 13e616
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit 13e616
 * Copyright (c) 2009 HNR Consulting. All rights reserved.
Packit 13e616
 * Copyright (c) 2009 Sun Microsystems, Inc. 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
/*
Packit 13e616
 * Abstract:
Packit 13e616
 *    Implementation of osm_sm_mad_ctrl_t.
Packit 13e616
 * This object represents the SM MAD request controller object.
Packit 13e616
 * This object is part of the opensm family of objects.
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 <string.h>
Packit 13e616
#include <complib/cl_debug.h>
Packit 13e616
#include <iba/ib_types.h>
Packit 13e616
#include <opensm/osm_file_ids.h>
Packit 13e616
#define FILE_ID OSM_FILE_SM_MAD_CTRL_C
Packit 13e616
#include <opensm/osm_sm_mad_ctrl.h>
Packit 13e616
#include <vendor/osm_vendor_api.h>
Packit 13e616
#include <opensm/osm_madw.h>
Packit 13e616
#include <opensm/osm_msgdef.h>
Packit 13e616
#include <opensm/osm_helper.h>
Packit 13e616
#include <opensm/osm_opensm.h>
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_retire_trans_mad
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_retire_trans_mad
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles clean-up of MADs associated with the SM's
Packit 13e616
 * outstanding transactions on the wire.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
Packit 13e616
static void sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
					 IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	uint32_t outstanding;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_madw);
Packit 13e616
	/*
Packit 13e616
	   Return the MAD & wrapper to the pool.
Packit 13e616
	 */
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"Retiring MAD with TID 0x%" PRIx64 "\n",
Packit 13e616
		cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id));
Packit 13e616
Packit 13e616
	osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
Packit 13e616
	outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats);
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n",
Packit 13e616
		p_ctrl->p_stats->qp0_mads_outstanding,
Packit 13e616
		outstanding ? "" : ": wire is clean.");
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/************/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_disp_done_callback
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_disp_done_callback
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function is the Dispatcher callback that indicates
Packit 13e616
 * a received MAD has been processed by the recipient.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data)
Packit 13e616
{
Packit 13e616
	osm_sm_mad_ctrl_t *p_ctrl = context;
Packit 13e616
	osm_madw_t *p_madw = p_data;
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   If the MAD that just finished processing was a response,
Packit 13e616
	   then retire the transaction, since we must have generated
Packit 13e616
	   the request.
Packit 13e616
Packit 13e616
	   Otherwise, retire the transaction if a response was expected,
Packit 13e616
	   as in the case of a send failure. If a response was not expected,
Packit 13e616
	   just put the MAD back in the pool, because the MAD was a query
Packit 13e616
	   from some outside agent, e.g. Get(SMInfo) from another SM.
Packit 13e616
	 */
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
	if (ib_smp_is_response(p_smp)) {
Packit 13e616
		CL_ASSERT(p_madw->resp_expected == FALSE);
Packit 13e616
		sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
Packit 13e616
	} else if (p_madw->resp_expected == TRUE)
Packit 13e616
		sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
Packit 13e616
	else
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/************/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_update_wire_stats
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_update_wire_stats
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * Updates wire stats for outstanding MADs and calls the VL15 poller.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * p_ctrl)
Packit 13e616
{
Packit 13e616
	uint32_t mads_on_wire;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	mads_on_wire =
Packit 13e616
	    cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire);
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"%u SMPs on the wire, %u outstanding\n", mads_on_wire,
Packit 13e616
		p_ctrl->p_stats->qp0_mads_outstanding);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   We can signal the VL15 controller to send another MAD
Packit 13e616
	   if any are waiting for transmission.
Packit 13e616
	 */
Packit 13e616
	osm_vl15_poll(p_ctrl->p_vl15);
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_process_get_resp
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_process_get_resp
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles method GetResp() for received MADs.
Packit 13e616
 * This is the most common path for QP0 MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
					 IN osm_madw_t * p_madw,
Packit 13e616
					 IN void *transaction_context)
Packit 13e616
{
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	cl_status_t status;
Packit 13e616
	osm_madw_t *p_old_madw;
Packit 13e616
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_madw);
Packit 13e616
	CL_ASSERT(transaction_context);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: "
Packit 13e616
			"'D' bit not set in returned SMP\n");
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_old_madw = transaction_context;
Packit 13e616
Packit 13e616
	sm_mad_ctrl_update_wire_stats(p_ctrl);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Copy the MAD Wrapper context from the requesting MAD
Packit 13e616
	   to the new MAD.  This mechanism allows the recipient
Packit 13e616
	   controller to recover its own context regarding this
Packit 13e616
	   MAD transaction.  Once we've copied the context, we
Packit 13e616
	   can return the original MAD to the pool.
Packit 13e616
	 */
Packit 13e616
	osm_madw_copy_context(p_madw, p_old_madw);
Packit 13e616
	osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Note that attr_id (like the rest of the MAD) is in
Packit 13e616
	   network byte order.
Packit 13e616
	 */
Packit 13e616
	switch (p_smp->attr_id) {
Packit 13e616
	case IB_MAD_ATTR_NODE_DESC:
Packit 13e616
		msg_id = OSM_MSG_MAD_NODE_DESC;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_NODE_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_NODE_INFO;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_GUID_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_GUID_INFO;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_SWITCH_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_SWITCH_INFO;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_PORT_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_PORT_INFO;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_LIN_FWD_TBL:
Packit 13e616
		msg_id = OSM_MSG_MAD_LFT;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_MCAST_FWD_TBL:
Packit 13e616
		msg_id = OSM_MSG_MAD_MFT;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_SM_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_SM_INFO;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_SLVL_TABLE:
Packit 13e616
		msg_id = OSM_MSG_MAD_SLVL;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_VL_ARBITRATION:
Packit 13e616
		msg_id = OSM_MSG_MAD_VL_ARB;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_P_KEY_TABLE:
Packit 13e616
		msg_id = OSM_MSG_MAD_PKEY;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_MLNX_EXT_PORT_INFO;
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_ATTR_CLASS_PORT_INFO:
Packit 13e616
	case IB_MAD_ATTR_NOTICE:
Packit 13e616
	case IB_MAD_ATTR_INFORM_INFO:
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: "
Packit 13e616
			"Unsupported attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Post this MAD to the dispatcher for asynchronous
Packit 13e616
	   processing by the appropriate controller.
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
Packit 13e616
		osm_get_disp_msg_str(msg_id));
Packit 13e616
Packit 13e616
	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
Packit 13e616
			      sm_mad_ctrl_disp_done_callback, p_ctrl);
Packit 13e616
Packit 13e616
	if (status != CL_SUCCESS) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: "
Packit 13e616
			"Dispatcher post message failed (%s) for attribute 0x%X (%s)\n",
Packit 13e616
			CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_process_get
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_process_get
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles method Get() for received MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
				    IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	cl_status_t status;
Packit 13e616
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Note that attr_id (like the rest of the MAD) is in
Packit 13e616
	   network byte order.
Packit 13e616
	 */
Packit 13e616
	switch (p_smp->attr_id) {
Packit 13e616
	case IB_MAD_ATTR_SM_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_SM_INFO;
Packit 13e616
		break;
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
Packit 13e616
			"Ignoring SubnGet MAD - unsupported attribute 0x%X\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id));
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Post this MAD to the dispatcher for asynchronous
Packit 13e616
	   processing by the appropriate controller.
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
Packit 13e616
		osm_get_disp_msg_str(msg_id));
Packit 13e616
Packit 13e616
	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
Packit 13e616
			      sm_mad_ctrl_disp_done_callback, p_ctrl);
Packit 13e616
Packit 13e616
	if (status != CL_SUCCESS) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: "
Packit 13e616
			"Dispatcher post message failed (%s)\n",
Packit 13e616
			CL_STATUS_MSG(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 *
Packit 13e616
 * RETURN VALUES
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_process_set
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_process_set
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles method Set() for received MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
				    IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	cl_status_t status;
Packit 13e616
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Note that attr_id (like the rest of the MAD) is in
Packit 13e616
	   network byte order.
Packit 13e616
	 */
Packit 13e616
	switch (p_smp->attr_id) {
Packit 13e616
	case IB_MAD_ATTR_SM_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_SM_INFO;
Packit 13e616
		break;
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: "
Packit 13e616
			"Unsupported attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Post this MAD to the dispatcher for asynchronous
Packit 13e616
	   processing by the appropriate controller.
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
Packit 13e616
		osm_get_disp_msg_str(msg_id));
Packit 13e616
Packit 13e616
	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
Packit 13e616
			      sm_mad_ctrl_disp_done_callback, p_ctrl);
Packit 13e616
Packit 13e616
	if (status != CL_SUCCESS) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: "
Packit 13e616
			"Dispatcher post message failed (%s)\n",
Packit 13e616
			CL_STATUS_MSG(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 *
Packit 13e616
 * RETURN VALUES
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_process_trap
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_process_trap
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles method Trap() for received MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
				     IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	cl_status_t status;
Packit 13e616
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	/* Make sure OpenSM is master. If not - then we should not process the trap */
Packit 13e616
	if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"Received trap but OpenSM is not in MASTER state. "
Packit 13e616
			"Dropping mad\n");
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Note that attr_id (like the rest of the MAD) is in
Packit 13e616
	   network byte order.
Packit 13e616
	 */
Packit 13e616
	switch (p_smp->attr_id) {
Packit 13e616
	case IB_MAD_ATTR_NOTICE:
Packit 13e616
		msg_id = OSM_MSG_MAD_NOTICE;
Packit 13e616
		break;
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: "
Packit 13e616
			"Unsupported attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Post this MAD to the dispatcher for asynchronous
Packit 13e616
	   processing by the appropriate controller.
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
Packit 13e616
		osm_get_disp_msg_str(msg_id));
Packit 13e616
Packit 13e616
	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
Packit 13e616
			      sm_mad_ctrl_disp_done_callback, p_ctrl);
Packit 13e616
Packit 13e616
	if (status != CL_SUCCESS) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: "
Packit 13e616
			"Dispatcher post message failed (%s)\n",
Packit 13e616
			CL_STATUS_MSG(status));
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 *
Packit 13e616
 * RETURN VALUES
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_process_trap_repress
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_process_trap_repress
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles method TrapRepress() for received MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_process_trap_repress(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
					     IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Note that attr_id (like the rest of the MAD) is in
Packit 13e616
	   network byte order.
Packit 13e616
	 */
Packit 13e616
	switch (p_smp->attr_id) {
Packit 13e616
	case IB_MAD_ATTR_NOTICE:
Packit 13e616
		sm_mad_ctrl_update_wire_stats(p_ctrl);
Packit 13e616
		sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
Packit 13e616
		break;
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3105: "
Packit 13e616
			"Unsupported attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		break;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
static void log_rcv_cb_error(osm_log_t *p_log, ib_smp_t *p_smp, ib_net16_t status)
Packit 13e616
{
Packit 13e616
	char buf[BUF_SIZE];
Packit 13e616
	uint32_t i;
Packit 13e616
Packit 13e616
	if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) {
Packit 13e616
		char ipath[IB_SUBNET_PATH_HOPS_MAX * 4];
Packit 13e616
		char rpath[IB_SUBNET_PATH_HOPS_MAX * 4];
Packit 13e616
		int ni = sprintf(ipath, "%d", p_smp->initial_path[0]);
Packit 13e616
		int nr = sprintf(rpath, "%d", p_smp->return_path[0]);
Packit 13e616
		for (i = 1; i <= p_smp->hop_count; i++) {
Packit 13e616
			ni += sprintf(ipath + ni, ",%d", p_smp->initial_path[i]);
Packit 13e616
			nr += sprintf(rpath + nr, ",%d", p_smp->return_path[i]);
Packit 13e616
		}
Packit 13e616
		snprintf(buf, sizeof(buf),
Packit 13e616
			 "\n\t\t\tInitial path: %s Return path: %s",
Packit 13e616
			 ipath, rpath);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3111: "
Packit 13e616
		"Received MAD with error status = 0x%X\n"
Packit 13e616
		"\t\t\t%s(%s), attr_mod 0x%x, TID 0x%" PRIx64 "%s\n",
Packit 13e616
		cl_ntoh16(status), ib_get_sm_method_str(p_smp->method),
Packit 13e616
		ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod),
Packit 13e616
		cl_ntoh64(p_smp->trans_id),
Packit 13e616
		p_smp->mgmt_class == IB_MCLASS_SUBN_DIR ? buf : "");
Packit 13e616
Packit 13e616
	osm_dump_dr_smp_v2(p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 *
Packit 13e616
 * RETURN VALUES
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_rcv_callback
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_rcv_callback
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This is the callback from the transport layer for received MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw,
Packit 13e616
				     IN void *bind_context,
Packit 13e616
				     IN osm_madw_t * p_req_madw)
Packit 13e616
{
Packit 13e616
	osm_sm_mad_ctrl_t *p_ctrl = bind_context;
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	ib_net16_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_madw);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   A MAD was received from the wire, possibly in response to a request.
Packit 13e616
	 */
Packit 13e616
	cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd);
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n",
Packit 13e616
		p_ctrl->p_stats->qp0_mads_rcvd);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	/* if we are closing down simply do nothing */
Packit 13e616
	if (osm_exit_flag) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR,
Packit 13e616
			"Ignoring received mad - since we are exiting\n");
Packit 13e616
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_DEBUG);
Packit 13e616
Packit 13e616
		/* retire the mad or put it back */
Packit 13e616
		if (ib_smp_is_response(p_smp)) {
Packit 13e616
			CL_ASSERT(p_madw->resp_expected == FALSE);
Packit 13e616
			sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
Packit 13e616
		} else if (p_madw->resp_expected == TRUE)
Packit 13e616
			sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
Packit 13e616
		else
Packit 13e616
			osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES))
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_FRAMES);
Packit 13e616
Packit 13e616
	if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
Packit 13e616
		status = ib_smp_get_status(p_smp);
Packit 13e616
	else
Packit 13e616
		status = p_smp->status;
Packit 13e616
Packit 13e616
	if (status != 0)
Packit 13e616
		log_rcv_cb_error(p_ctrl->p_log, p_smp, status);
Packit 13e616
Packit 13e616
	switch (p_smp->method) {
Packit 13e616
	case IB_MAD_METHOD_GET_RESP:
Packit 13e616
		CL_ASSERT(p_req_madw != NULL);
Packit 13e616
		sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw);
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_METHOD_GET:
Packit 13e616
		CL_ASSERT(p_req_madw == NULL);
Packit 13e616
		sm_mad_ctrl_process_get(p_ctrl, p_madw);
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_METHOD_TRAP:
Packit 13e616
		CL_ASSERT(p_req_madw == NULL);
Packit 13e616
		sm_mad_ctrl_process_trap(p_ctrl, p_madw);
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_METHOD_SET:
Packit 13e616
		CL_ASSERT(p_req_madw == NULL);
Packit 13e616
		sm_mad_ctrl_process_set(p_ctrl, p_madw);
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_METHOD_TRAP_REPRESS:
Packit 13e616
		CL_ASSERT(p_req_madw != NULL);
Packit 13e616
		sm_mad_ctrl_process_trap_repress(p_ctrl, p_madw);
Packit 13e616
		break;
Packit 13e616
	case IB_MAD_METHOD_SEND:
Packit 13e616
	case IB_MAD_METHOD_REPORT:
Packit 13e616
	case IB_MAD_METHOD_REPORT_RESP:
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: "
Packit 13e616
			"Unsupported method = 0x%X\n", p_smp->method);
Packit 13e616
		osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 *
Packit 13e616
 * RETURN VALUES
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
/****f* opensm: SM/sm_mad_ctrl_send_err_cb
Packit 13e616
 * NAME
Packit 13e616
 * sm_mad_ctrl_send_err_cb
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This is the callback from the transport layer for send errors
Packit 13e616
 * on MADs that were expecting a response.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sm_mad_ctrl_send_err_cb(IN void *context, IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	osm_sm_mad_ctrl_t *p_ctrl = context;
Packit 13e616
	ib_api_status_t status;
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	CL_ASSERT(p_madw);
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: "
Packit 13e616
		"MAD completed in error (%s): "
Packit 13e616
		"%s(%s), attr_mod 0x%x, TID 0x%" PRIx64 "\n",
Packit 13e616
		ib_get_err_str(p_madw->status),
Packit 13e616
		ib_get_sm_method_str(p_smp->method),
Packit 13e616
		ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod),
Packit 13e616
		cl_ntoh64(p_smp->trans_id));
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   If this was a SubnSet MAD, then this error might indicate a problem
Packit 13e616
	   in configuring the subnet. In this case - need to mark that there was
Packit 13e616
	   such a problem. The subnet will not be up, and the next sweep should
Packit 13e616
	   be a heavy sweep as well.
Packit 13e616
	 */
Packit 13e616
	if (p_smp->method == IB_MAD_METHOD_SET &&
Packit 13e616
	    (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ||
Packit 13e616
	     p_smp->attr_id == IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO ||
Packit 13e616
	     p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
Packit 13e616
	     p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
Packit 13e616
	     p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL ||
Packit 13e616
	     p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE)) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: "
Packit 13e616
			"Set method failed for attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
		p_ctrl->p_subn->subnet_initialization_error = TRUE;
Packit 13e616
	} else if (p_madw->status == IB_TIMEOUT &&
Packit 13e616
		   p_smp->method == IB_MAD_METHOD_GET) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3120: "
Packit 13e616
			"Timeout while getting attribute 0x%X (%s); "
Packit 13e616
			"Possible mis-set mkey?\n",
Packit 13e616
			cl_ntoh16(p_smp->attr_id),
Packit 13e616
			ib_get_sm_attr_str(p_smp->attr_id));
Packit 13e616
	}
Packit 13e616
Packit 13e616
	osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Since we did not get any response we suspect the DR path
Packit 13e616
	   used for the target port.
Packit 13e616
	   Find it and replace it with an alternate path.
Packit 13e616
	   This is true only if the destination lid is not 0xFFFF, since
Packit 13e616
	   then we are aiming for a specific path and not specific destination
Packit 13e616
	   lid.
Packit 13e616
	 */
Packit 13e616
	/* For now - do not add the alternate dr path to the release */
Packit 13e616
#if 0
Packit 13e616
	if (p_madw->mad_addr.dest_lid != 0xFFFF) {
Packit 13e616
		osm_physp_t *p_physp = osm_get_physp_by_mad_addr(p_ctrl->p_log,
Packit 13e616
								 p_ctrl->p_subn,
Packit 13e616
								 &(p_madw->
Packit 13e616
								   mad_addr));
Packit 13e616
		if (!p_physp) {
Packit 13e616
			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: "
Packit 13e616
				"Failed to find the corresponding phys port\n");
Packit 13e616
		} else {
Packit 13e616
			osm_physp_replace_dr_path_with_alternate_dr_path
Packit 13e616
			    (p_ctrl->p_log, p_ctrl->p_subn, p_physp,
Packit 13e616
			     p_madw->h_bind);
Packit 13e616
		}
Packit 13e616
	}
Packit 13e616
#endif
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   An error occurred.  No response was received to a request MAD.
Packit 13e616
	   Retire the original request MAD.
Packit 13e616
	 */
Packit 13e616
	sm_mad_ctrl_update_wire_stats(p_ctrl);
Packit 13e616
Packit 13e616
	if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"Posting Dispatcher message %s\n",
Packit 13e616
			osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
Packit 13e616
Packit 13e616
		status = cl_disp_post(p_ctrl->h_disp,
Packit 13e616
				      osm_madw_get_err_msg(p_madw), p_madw,
Packit 13e616
				      sm_mad_ctrl_disp_done_callback, p_ctrl);
Packit 13e616
		if (status != CL_SUCCESS)
Packit 13e616
			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: "
Packit 13e616
				"Dispatcher post message failed (%s)\n",
Packit 13e616
				CL_STATUS_MSG(status));
Packit 13e616
	} else
Packit 13e616
		/*
Packit 13e616
		   No error message was provided, just retire the MAD.
Packit 13e616
		 */
Packit 13e616
		sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
Packit 13e616
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * PARAMETERS
Packit 13e616
 *
Packit 13e616
 * RETURN VALUES
Packit 13e616
 *
Packit 13e616
 * NOTES
Packit 13e616
 *
Packit 13e616
 * SEE ALSO
Packit 13e616
 *********/
Packit 13e616
Packit 13e616
void osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * p_ctrl)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_ctrl);
Packit 13e616
	memset(p_ctrl, 0, sizeof(*p_ctrl));
Packit 13e616
	p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * p_ctrl)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_ctrl);
Packit 13e616
Packit 13e616
	if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE)
Packit 13e616
		osm_vendor_unbind(p_ctrl->h_bind);
Packit 13e616
	cl_disp_unregister(p_ctrl->h_disp);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_api_status_t osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
				     IN osm_subn_t * p_subn,
Packit 13e616
				     IN osm_mad_pool_t * p_mad_pool,
Packit 13e616
				     IN osm_vl15_t * p_vl15,
Packit 13e616
				     IN osm_vendor_t * p_vendor,
Packit 13e616
				     IN osm_log_t * p_log,
Packit 13e616
				     IN osm_stats_t * p_stats,
Packit 13e616
				     IN cl_plock_t * p_lock,
Packit 13e616
				     IN cl_dispatcher_t * p_disp)
Packit 13e616
{
Packit 13e616
	ib_api_status_t status = IB_SUCCESS;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_log);
Packit 13e616
Packit 13e616
	osm_sm_mad_ctrl_construct(p_ctrl);
Packit 13e616
Packit 13e616
	p_ctrl->p_subn = p_subn;
Packit 13e616
	p_ctrl->p_log = p_log;
Packit 13e616
	p_ctrl->p_disp = p_disp;
Packit 13e616
	p_ctrl->p_mad_pool = p_mad_pool;
Packit 13e616
	p_ctrl->p_vendor = p_vendor;
Packit 13e616
	p_ctrl->p_stats = p_stats;
Packit 13e616
	p_ctrl->p_lock = p_lock;
Packit 13e616
	p_ctrl->p_vl15 = p_vl15;
Packit 13e616
Packit 13e616
	p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL,
Packit 13e616
					  NULL);
Packit 13e616
Packit 13e616
	if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: "
Packit 13e616
			"Dispatcher registration failed\n");
Packit 13e616
		status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_log);
Packit 13e616
	return status;
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_api_status_t osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * p_ctrl,
Packit 13e616
				     IN ib_net64_t port_guid)
Packit 13e616
{
Packit 13e616
	osm_bind_info_t bind_info;
Packit 13e616
	ib_api_status_t status = IB_SUCCESS;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: "
Packit 13e616
			"Multiple binds not allowed\n");
Packit 13e616
		status = IB_ERROR;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	bind_info.class_version = 1;
Packit 13e616
	bind_info.is_report_processor = FALSE;
Packit 13e616
	bind_info.is_responder = TRUE;
Packit 13e616
	bind_info.is_trap_processor = TRUE;
Packit 13e616
	bind_info.mad_class = IB_MCLASS_SUBN_DIR;
Packit 13e616
	bind_info.port_guid = port_guid;
Packit 13e616
	bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
Packit 13e616
	bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
Packit 13e616
	bind_info.timeout = p_ctrl->p_subn->opt.transaction_timeout;
Packit 13e616
	bind_info.retries = p_ctrl->p_subn->opt.transaction_retries;
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
Packit 13e616
		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
Packit 13e616
Packit 13e616
	p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, &bind_info,
Packit 13e616
					 p_ctrl->p_mad_pool,
Packit 13e616
					 sm_mad_ctrl_rcv_callback,
Packit 13e616
					 sm_mad_ctrl_send_err_cb, p_ctrl);
Packit 13e616
Packit 13e616
	if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
Packit 13e616
		status = IB_ERROR;
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3118: "
Packit 13e616
			"Vendor specific bind failed\n");
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
	return status;
Packit 13e616
}