Blame opensm/osm_sa_mad_ctrl.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 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
 * Copyright (c) 2009 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
/*
Packit 13e616
 * Abstract:
Packit 13e616
 *    Implementation of osm_sa_mad_ctrl_t.
Packit 13e616
 * This object is part of the SA object.
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_SA_MAD_CTRL_C
Packit 13e616
#include <vendor/osm_vendor_api.h>
Packit 13e616
#include <opensm/osm_sa_mad_ctrl.h>
Packit 13e616
#include <opensm/osm_msgdef.h>
Packit 13e616
#include <opensm/osm_helper.h>
Packit 13e616
#include <opensm/osm_sa.h>
Packit 13e616
#include <opensm/osm_opensm.h>
Packit 13e616
Packit 13e616
/****f* opensm: SA/sa_mad_ctrl_disp_done_callback
Packit 13e616
 * NAME
Packit 13e616
 * sa_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 sa_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data)
Packit 13e616
{
Packit 13e616
	osm_sa_mad_ctrl_t *p_ctrl = context;
Packit 13e616
	osm_madw_t *p_madw = p_data;
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_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
}
Packit 13e616
Packit 13e616
/************/
Packit 13e616
Packit 13e616
/****f* opensm: SA/sa_mad_ctrl_process
Packit 13e616
 * NAME
Packit 13e616
 * sa_mad_ctrl_process
Packit 13e616
 *
Packit 13e616
 * DESCRIPTION
Packit 13e616
 * This function handles known methods for received MADs.
Packit 13e616
 *
Packit 13e616
 * SYNOPSIS
Packit 13e616
 */
Packit 13e616
static void sa_mad_ctrl_process(IN osm_sa_mad_ctrl_t * p_ctrl,
Packit 13e616
				IN osm_madw_t * p_madw,
Packit 13e616
				IN boolean_t is_get_request)
Packit 13e616
{
Packit 13e616
	ib_sa_mad_t *p_sa_mad;
Packit 13e616
	cl_disp_reg_handle_t h_disp;
Packit 13e616
	cl_status_t status;
Packit 13e616
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
Packit 13e616
	uint64_t last_dispatched_msg_queue_time_msec;
Packit 13e616
	uint32_t num_messages;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   If the dispatcher is showing us that it is overloaded
Packit 13e616
	   there is no point in placing the request in. We should instead
Packit 13e616
	   provide immediate response - IB_RESOURCE_BUSY
Packit 13e616
	   But how do we know?
Packit 13e616
	   The dispatcher reports back the number of outstanding messages and
Packit 13e616
	   the time the last message stayed in the queue.
Packit 13e616
	   HACK: Actually, we cannot send a mad from within the receive callback;
Packit 13e616
	   thus - we will just drop it.
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	if (!is_get_request && p_ctrl->p_set_disp) {
Packit 13e616
		h_disp = p_ctrl->h_set_disp;
Packit 13e616
		goto SKIP_QUEUE_CHECK;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	h_disp = p_ctrl->h_disp;
Packit 13e616
	cl_disp_get_queue_status(h_disp, &num_messages,
Packit 13e616
				 &last_dispatched_msg_queue_time_msec);
Packit 13e616
Packit 13e616
	if (num_messages > 1 && p_ctrl->p_subn->opt.max_msg_fifo_timeout &&
Packit 13e616
	    last_dispatched_msg_queue_time_msec >
Packit 13e616
	    p_ctrl->p_subn->opt.max_msg_fifo_timeout) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_INFO,
Packit 13e616
			/*             "Responding BUSY status since the dispatcher is already" */
Packit 13e616
			"Dropping MAD since the dispatcher is already"
Packit 13e616
			" overloaded with %u messages and queue time of:"
Packit 13e616
			"%" PRIu64 "[msec]\n",
Packit 13e616
			num_messages, last_dispatched_msg_queue_time_msec);
Packit 13e616
Packit 13e616
		/* send a busy response */
Packit 13e616
		/* osm_sa_send_error(p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY); */
Packit 13e616
Packit 13e616
		/* return the request to the pool */
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
SKIP_QUEUE_CHECK:
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_sa_mad->attr_id) {
Packit 13e616
	case IB_MAD_ATTR_CLASS_PORT_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_CLASS_PORT_INFO;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_NODE_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_NODE_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_PORTINFO_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_PORTINFO_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_LINK_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_LINK_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_SMINFO_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_SMINFO_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_SERVICE_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_SERVICE_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_PATH_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_PATH_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_MCMEMBER_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_MCMEMBER_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_INFORM_INFO:
Packit 13e616
		msg_id = OSM_MSG_MAD_INFORM_INFO;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_VLARB_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_VL_ARB_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_SLVL_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_PKEY_TBL_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_LFT_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_LFT_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_GUIDINFO_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_GUIDINFO_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_INFORM_INFO_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_SWITCH_INFO_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_ATTR_MFT_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_MFT_RECORD;
Packit 13e616
		break;
Packit 13e616
Packit 13e616
#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
Packit 13e616
	case IB_MAD_ATTR_MULTIPATH_RECORD:
Packit 13e616
		msg_id = OSM_MSG_MAD_MULTIPATH_RECORD;
Packit 13e616
		break;
Packit 13e616
#endif
Packit 13e616
Packit 13e616
	default:
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A01: "
Packit 13e616
			"Unsupported attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh16(p_sa_mad->attr_id),
Packit 13e616
			ib_get_sa_attr_str(p_sa_mad->attr_id));
Packit 13e616
		osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_ERROR);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (msg_id != CL_DISP_MSGID_NONE) {
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,
Packit 13e616
			"Posting Dispatcher message %s\n",
Packit 13e616
			osm_get_disp_msg_str(msg_id));
Packit 13e616
Packit 13e616
		status = cl_disp_post(h_disp, msg_id, p_madw,
Packit 13e616
				      sa_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 1A02: "
Packit 13e616
				"Dispatcher post message failed (%s) for attribute 0x%X (%s)\n",
Packit 13e616
				CL_STATUS_MSG(status),
Packit 13e616
				cl_ntoh16(p_sa_mad->attr_id),
Packit 13e616
				ib_get_sa_attr_str(p_sa_mad->attr_id));
Packit 13e616
Packit 13e616
			osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
			goto Exit;
Packit 13e616
		}
Packit 13e616
	} else {
Packit 13e616
		/*
Packit 13e616
		   There is an unknown MAD attribute type for which there is
Packit 13e616
		   no recipient.  Simply retire the MAD here.
Packit 13e616
		 */
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
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: SA/sa_mad_ctrl_rcv_callback
Packit 13e616
 * NAME
Packit 13e616
 * sa_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 sa_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, IN void *context,
Packit 13e616
				     IN osm_madw_t * p_req_madw)
Packit 13e616
{
Packit 13e616
	osm_sa_mad_ctrl_t *p_ctrl = context;
Packit 13e616
	ib_sa_mad_t *p_sa_mad;
Packit 13e616
	boolean_t is_get_request = FALSE;
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->sa_mads_rcvd);
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
Packit 13e616
		"%u SA MADs received\n", p_ctrl->p_stats->sa_mads_rcvd);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * C15-0.1.3 requires not responding to any MAD if the SM is
Packit 13e616
	 * not in active state!
Packit 13e616
	 * We will not respond if the sm_state is not MASTER, or if the
Packit 13e616
	 * first_time_master_sweep flag (of the subnet) is TRUE - this
Packit 13e616
	 * flag indicates that the master still didn't finish its first
Packit 13e616
	 * sweep, so the subnet is not up and stable yet.
Packit 13e616
	 */
Packit 13e616
	if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
Packit 13e616
			"Received SA MAD while SM not MASTER. MAD ignored\n");
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
	if (p_ctrl->p_subn->first_time_master_sweep == TRUE) {
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
Packit 13e616
			"Received SA MAD while SM in first sweep. MAD ignored\n");
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
Packit 13e616
Packit 13e616
	if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES))
Packit 13e616
		osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_FRAMES);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	 * C15-0.1.5 - Table 185: SA Header - p884
Packit 13e616
	 * SM_key should be either 0 or match the current SM_Key
Packit 13e616
	 * otherwise discard the MAD.
Packit 13e616
	 */
Packit 13e616
	if (p_sa_mad->sm_key != 0 &&
Packit 13e616
	    p_sa_mad->sm_key != p_ctrl->p_subn->opt.sa_key) {
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A04: "
Packit 13e616
			"Non-Zero MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%"
Packit 13e616
			PRIx64 "; SA MAD ignored for method 0x%X attribute 0x%X (%s)\n",
Packit 13e616
			cl_ntoh64(p_sa_mad->sm_key),
Packit 13e616
			cl_ntoh64(p_ctrl->p_subn->opt.sa_key),
Packit 13e616
			p_sa_mad->method, cl_ntoh16(p_sa_mad->attr_id),
Packit 13e616
			ib_get_sa_attr_str(p_sa_mad->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
	switch (p_sa_mad->method) {
Packit 13e616
	case IB_MAD_METHOD_REPORT_RESP:
Packit 13e616
		/* we do not really do anything with report responses -
Packit 13e616
		   just retire the transaction */
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
Packit 13e616
			"Received Report Response. Retiring the transaction\n");
Packit 13e616
Packit 13e616
		if (p_req_madw)
Packit 13e616
			osm_mad_pool_put(p_ctrl->p_mad_pool, p_req_madw);
Packit 13e616
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	case IB_MAD_METHOD_GET:
Packit 13e616
	case IB_MAD_METHOD_GETTABLE:
Packit 13e616
#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
Packit 13e616
	case IB_MAD_METHOD_GETMULTI:
Packit 13e616
#endif
Packit 13e616
		is_get_request = TRUE;
Packit 13e616
	case IB_MAD_METHOD_SET:
Packit 13e616
	case IB_MAD_METHOD_DELETE:
Packit 13e616
		/* if we are closing down simply do nothing */
Packit 13e616
		if (osm_exit_flag)
Packit 13e616
			osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
Packit 13e616
		else
Packit 13e616
			sa_mad_ctrl_process(p_ctrl, p_madw, is_get_request);
Packit 13e616
		break;
Packit 13e616
Packit 13e616
	default:
Packit 13e616
		cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
Packit 13e616
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A05: "
Packit 13e616
			"Unsupported method = 0x%X\n", p_sa_mad->method);
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: SA/sa_mad_ctrl_send_err_callback
Packit 13e616
 * NAME
Packit 13e616
 * sa_mad_ctrl_send_err_callback
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 sa_mad_ctrl_send_err_callback(IN void *context,
Packit 13e616
					  IN osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	osm_sa_mad_ctrl_t *p_ctrl = context;
Packit 13e616
	cl_status_t status;
Packit 13e616
Packit 13e616
	OSM_LOG_ENTER(p_ctrl->p_log);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   We should never be here since the SA never originates a request.
Packit 13e616
	   Unless we generated a Report(Notice)
Packit 13e616
	 */
Packit 13e616
Packit 13e616
	CL_ASSERT(p_madw);
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A06: "
Packit 13e616
		"MAD completed in error (%s): "
Packit 13e616
		"%s(%s), attr_mod 0x%x, LID %u, TID 0x%" PRIx64 "\n",
Packit 13e616
		ib_get_err_str(p_madw->status),
Packit 13e616
		ib_get_sa_method_str(p_madw->p_mad->method),
Packit 13e616
		ib_get_sa_attr_str(p_madw->p_mad->attr_id),
Packit 13e616
		cl_ntoh32(p_madw->p_mad->attr_mod),
Packit 13e616
		cl_ntoh16(p_madw->mad_addr.dest_lid),
Packit 13e616
		cl_ntoh64(p_madw->p_mad->trans_id));
Packit 13e616
Packit 13e616
	osm_dump_sa_mad_v2(p_ctrl->p_log, osm_madw_get_sa_mad_ptr(p_madw),
Packit 13e616
			   FILE_ID, OSM_LOG_ERROR);
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
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
		if (p_ctrl->p_set_disp &&
Packit 13e616
		    (p_madw->p_mad->method == IB_MAD_METHOD_SET ||
Packit 13e616
		     p_madw->p_mad->method == IB_MAD_METHOD_DELETE))
Packit 13e616
			status = cl_disp_post(p_ctrl->h_set_disp,
Packit 13e616
					      osm_madw_get_err_msg(p_madw),
Packit 13e616
					      p_madw,
Packit 13e616
					      sa_mad_ctrl_disp_done_callback,
Packit 13e616
					      p_ctrl);
Packit 13e616
		else
Packit 13e616
			status = cl_disp_post(p_ctrl->h_disp,
Packit 13e616
					      osm_madw_get_err_msg(p_madw),
Packit 13e616
					      p_madw,
Packit 13e616
					      sa_mad_ctrl_disp_done_callback,
Packit 13e616
					      p_ctrl);
Packit 13e616
		if (status != CL_SUCCESS) {
Packit 13e616
			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A07: "
Packit 13e616
				"Dispatcher post message failed (%s)\n",
Packit 13e616
				CL_STATUS_MSG(status));
Packit 13e616
		}
Packit 13e616
	} else			/* No error message was provided, just retire the MAD. */
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
 * 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_sa_mad_ctrl_construct(IN osm_sa_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
	p_ctrl->h_set_disp = CL_DISP_INVALID_HANDLE;
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_sa_mad_ctrl_destroy(IN osm_sa_mad_ctrl_t * p_ctrl)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_ctrl);
Packit 13e616
	cl_disp_unregister(p_ctrl->h_disp);
Packit 13e616
	cl_disp_unregister(p_ctrl->h_set_disp);
Packit 13e616
}
Packit 13e616
Packit 13e616
ib_api_status_t osm_sa_mad_ctrl_init(IN osm_sa_mad_ctrl_t * p_ctrl,
Packit 13e616
				     IN osm_sa_t * sa,
Packit 13e616
				     IN osm_mad_pool_t * p_mad_pool,
Packit 13e616
				     IN osm_vendor_t * p_vendor,
Packit 13e616
				     IN osm_subn_t * p_subn,
Packit 13e616
				     IN osm_log_t * p_log,
Packit 13e616
				     IN osm_stats_t * p_stats,
Packit 13e616
				     IN cl_dispatcher_t * p_disp,
Packit 13e616
				     IN cl_dispatcher_t * p_set_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_sa_mad_ctrl_construct(p_ctrl);
Packit 13e616
Packit 13e616
	p_ctrl->sa = sa;
Packit 13e616
	p_ctrl->p_log = p_log;
Packit 13e616
	p_ctrl->p_disp = p_disp;
Packit 13e616
	p_ctrl->p_set_disp = p_set_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_subn = p_subn;
Packit 13e616
Packit 13e616
	p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL,
Packit 13e616
					  p_ctrl);
Packit 13e616
Packit 13e616
	if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
Packit 13e616
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A08: "
Packit 13e616
			"Dispatcher registration failed\n");
Packit 13e616
		status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	if (p_set_disp) {
Packit 13e616
		p_ctrl->h_set_disp =
Packit 13e616
		    cl_disp_register(p_set_disp, CL_DISP_MSGID_NONE, NULL,
Packit 13e616
				     p_ctrl);
Packit 13e616
Packit 13e616
		if (p_ctrl->h_set_disp == CL_DISP_INVALID_HANDLE) {
Packit 13e616
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A0A: "
Packit 13e616
				"SA set dispatcher registration failed\n");
Packit 13e616
			status = IB_INSUFFICIENT_RESOURCES;
Packit 13e616
			goto Exit;
Packit 13e616
		}
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_sa_mad_ctrl_bind(IN osm_sa_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 1A09: "
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 = 2;
Packit 13e616
	bind_info.is_responder = TRUE;
Packit 13e616
	bind_info.is_report_processor = FALSE;
Packit 13e616
	bind_info.is_trap_processor = FALSE;
Packit 13e616
	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
Packit 13e616
	bind_info.port_guid = port_guid;
Packit 13e616
	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
Packit 13e616
	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
Packit 13e616
	bind_info.timeout = p_ctrl->sa->p_subn->opt.transaction_timeout;
Packit 13e616
	bind_info.retries = p_ctrl->sa->p_subn->opt.transaction_retries;
Packit 13e616
Packit 13e616
	OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
Packit 13e616
		"Binding to port GUID 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
					 sa_mad_ctrl_rcv_callback,
Packit 13e616
					 sa_mad_ctrl_send_err_callback, 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 1A10: "
Packit 13e616
			"Vendor specific bind failed (%s)\n",
Packit 13e616
			ib_get_err_str(status));
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
}
Packit 13e616
Packit 13e616
ib_api_status_t osm_sa_mad_ctrl_unbind(IN osm_sa_mad_ctrl_t * p_ctrl)
Packit 13e616
{
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 1A11: "
Packit 13e616
			"No previous bind\n");
Packit 13e616
		status = IB_ERROR;
Packit 13e616
		goto Exit;
Packit 13e616
	}
Packit 13e616
Packit 13e616
	osm_vendor_unbind(p_ctrl->h_bind);
Packit 13e616
Exit:
Packit 13e616
	OSM_LOG_EXIT(p_ctrl->p_log);
Packit 13e616
	return status;
Packit 13e616
}