Blame Esm/ib/src/pm/pm/pm_dispatch.c

Packit 5ea288
/* BEGIN_ICS_COPYRIGHT7 ****************************************
Packit 5ea288
Packit Service 6899a0
Copyright (c) 2015-2020, Intel Corporation
Packit 5ea288
Packit 5ea288
Redistribution and use in source and binary forms, with or without
Packit 5ea288
modification, are permitted provided that the following conditions are met:
Packit 5ea288
Packit 5ea288
    * Redistributions of source code must retain the above copyright notice,
Packit 5ea288
      this list of conditions and the following disclaimer.
Packit 5ea288
    * Redistributions in binary form must reproduce the above copyright
Packit 5ea288
      notice, this list of conditions and the following disclaimer in the
Packit 5ea288
      documentation and/or other materials provided with the distribution.
Packit 5ea288
    * Neither the name of Intel Corporation nor the names of its contributors
Packit 5ea288
      may be used to endorse or promote products derived from this software
Packit 5ea288
      without specific prior written permission.
Packit 5ea288
Packit 5ea288
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 5ea288
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 5ea288
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 5ea288
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit 5ea288
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 5ea288
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit 5ea288
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit 5ea288
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit 5ea288
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 5ea288
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 5ea288
Packit 5ea288
** END_ICS_COPYRIGHT7   ****************************************/
Packit 5ea288
Packit 5ea288
/* [ICS VERSION STRING: unknown] */
Packit 5ea288
Packit 5ea288
#include "sm_l.h"
Packit 5ea288
#include "pm_l.h"
Packit 5ea288
#include <iba/ibt.h>
Packit 5ea288
#include "pm_topology.h"
Packit 5ea288
#include "sm_dbsync.h"
Packit 5ea288
#include <limits.h>
Packit 5ea288
#include "if3.h"
Packit 5ea288
Packit 5ea288
// Dispatcher Design.
Packit 5ea288
// The dispatcher has 4 primary entry points:
Packit 5ea288
// PmSweepAllPortCounters - used by PMEngine to start a sweep
Packit 5ea288
// DispatchNodeCallback - callback when a Node level single packet response or timeout
Packit 5ea288
// DispatchPacketCallback - callback when a Node level multi-packet response or timeout
Packit 5ea288
//
Packit 5ea288
// Each entry point is responsible for progressing the PM sweep.
Packit 5ea288
// They do this by ensuring the configured number of parallel nodes and ports
Packit 5ea288
// per node are in progress.  As such a single call could issue one or
Packit 5ea288
// more packets.  Each call must hence be diligent in trying to find work to
Packit 5ea288
// be done, especially if a given port or node is now done.
Packit 5ea288
//
Packit 5ea288
// Each call returns:
Packit 5ea288
// 	VSTATUS_OK - as much work as possible is in progress
Packit 5ea288
// 				- typically indicates new work was started.  Could also
Packit 5ea288
// 					indicate that while a port finished on a node, and there
Packit 5ea288
// 					are no other ports to start, there are other ports not yet
Packit 5ea288
// 					done so we can't start anything else
Packit 5ea288
// 	VSTATUS_NOT_FOUND - did not start any new work
Packit 5ea288
// 	other - assorted errors from low level routines, did not start any new work
Packit 5ea288
//
Packit 5ea288
// One complicating factor is when send's fail immediately.  This is atypical
Packit 5ea288
// but could be caused by problems in the IB stack or perhaps if the local
Packit 5ea288
// port is down.  In this case, the call will continue to try and find other
Packit 5ea288
// work.  Send failures could be transient or perhaps due to a simple problem
Packit 5ea288
// like a duplicate TID.
Packit 5ea288
//
Packit 5ea288
// Each entry point starts from a different perspective (fabric, node or port)
Packit 5ea288
// and tries to find work.  It does this by checking state for the node/port
Packit 5ea288
// it is focused on, and if there is no more work to be done for that node/port
Packit 5ea288
// it must advance to a different node/port.  Once the last port on a device is
Packit 5ea288
// completed, it must advance to a different node, until there are no nodes left
Packit 5ea288
// or until all the possible work is started.
Packit 5ea288
//
Packit 5ea288
// The walking to new Nodes is done only in these three routines.  As such
Packit 5ea288
// when the processing of a given Node or Port is completed, these callers
Packit 5ea288
// will try to start work on the next node available (and may conclude there is
Packit 5ea288
// no new work to be started)
Packit 5ea288
//
Packit 5ea288
// A special case is the rare case of a Send call failing.
Packit 5ea288
// The present approach is for the callback to immediately try to find other
Packit 5ea288
// work (B below).
Packit 5ea288
// An alternative approach is to ignore the Send failure and let the
Packit 5ea288
// cs_context aging and timeout mechanisms handle it (A below)
Packit 5ea288
// This is a trade-off between:
Packit 5ea288
// A. Increasing the PM sweep time when some or all sends fail
Packit 5ea288
// B. spending more time in a callback to search/try more work
Packit 5ea288
Packit 5ea288
static Status_t DispatchNextPacket(Pm_t *pm, PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket);
Packit 5ea288
Packit 5ea288
static uint8 DispatcherStartSweepAllPorts(Pm_t *pm, PmDispatcherNode_t *dispnode);
Packit 5ea288
Packit 5ea288
static Status_t DispatchNextNode(Pm_t *pm, PmDispatcherNode_t *dispnode);
Packit 5ea288
Packit 5ea288
static Status_t DispatchNodeNextStep(Pm_t *pm, PmNode_t *pmnodep, PmDispatcherNode_t *dispnode);
Packit 5ea288
static Status_t DispatchPacketNextStep(Pm_t *pm, PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket);
Packit 5ea288
Packit 5ea288
static void DispatchPacketCallback(cntxt_entry_t *entry, Status_t status, void *data, Mai_t *mad);
Packit 5ea288
static void DispatchNodeCallback(cntxt_entry_t *entry, Status_t status, void *data, Mai_t *mad);
Packit 5ea288
Packit 5ea288
static void DispatchPacketDone(Pm_t *pm, PmDispatcherPacket_t *disppacket);
Packit 5ea288
static void DispatchNodeDone(Pm_t *pm, PmDispatcherNode_t *dispnode); 
Packit 5ea288
Packit 5ea288
int MergePortIntoPacket(Pm_t *pm, PmDispatcherNode_t *dispnode, PmPort_t *pmportp, PmDispatcherPacket_t *disppacket);
Packit 5ea288
Packit 5ea288
size_t CalculatePortInPacket(PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket);
Packit 5ea288
Packit 5ea288
#define CHECK_NEED_CLEAR(dispnode, portNum) \
Packit 5ea288
	((dispnode)->info.needClear[(portNum)/64] & ((uint64)1 << ((portNum) % 64)))
Packit 5ea288
Packit 5ea288
#define SET_NEED_CLEAR(dispnode, portNum) \
Packit 5ea288
	(dispnode)->info.needClear[(portNum)/64] |= ((uint64)1 << ((portNum) % 64))
Packit 5ea288
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
// Utility routines
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
Packit 5ea288
static void PmFailNodeQuery(cntxt_entry_t *entry, PmDispatcherNode_t *dispnode, uint8 method, uint16 aid)
Packit 5ea288
{
Packit 5ea288
	dispnode->info.u.s.failed = 1;
Packit 5ea288
	PmFailNode(dispnode->pm, dispnode->info.pmnodep, PM_QUERY_STATUS_FAIL_QUERY, method, aid);
Packit 5ea288
	if (entry)
Packit 5ea288
		cs_cntxt_retire_nolock( entry, &dispnode->pm->Dispatcher.cntx  );
Packit 5ea288
	DispatchNodeDone(dispnode->pm, dispnode);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmFailPacketClear(cntxt_entry_t *entry, PmDispatcherPacket_t *disppacket, uint8 method, uint16 aid)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherNode_t *dispnode = disppacket->dispnode;
Packit 5ea288
Packit 5ea288
	dispnode->info.u.s.failed = 1;
Packit 5ea288
	PmFailPacket(dispnode->pm, disppacket, PM_QUERY_STATUS_FAIL_CLEAR, method, aid);
Packit 5ea288
	if (entry)
Packit 5ea288
		cs_cntxt_retire_nolock( entry, &dispnode->pm->Dispatcher.cntx  );
Packit 5ea288
	DispatchPacketDone(dispnode->pm, disppacket);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmFailPacketQuery(cntxt_entry_t *entry, PmDispatcherPacket_t *disppacket, uint8 method, uint16 aid)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherNode_t *dispnode = disppacket->dispnode;
Packit 5ea288
Packit 5ea288
	dispnode->info.u.s.failed = 1;
Packit 5ea288
	PmFailPacket(dispnode->pm, disppacket, PM_QUERY_STATUS_FAIL_QUERY, method, aid);
Packit 5ea288
	if (entry)
Packit 5ea288
		cs_cntxt_retire_nolock( entry, &dispnode->pm->Dispatcher.cntx  );
Packit 5ea288
	DispatchPacketDone(dispnode->pm, disppacket);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmNodeMadFail(Mai_t *mad, PmNode_t *pmnodep)
Packit 5ea288
{
Packit 5ea288
	IB_LOG_WARN_FMT(__func__, "PMA response for %s(%s) with bad status: 0x%x From %.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		StlPmMadMethodToText(mad->base.method), StlPmMadAttributeToText(mad->base.aid), mad->base.status,
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmMadFailNodeQuery(cntxt_entry_t *entry, Mai_t *mad, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	PmNodeMadFail(mad, dispnode->info.pmnodep);
Packit 5ea288
	PmFailNodeQuery(entry, dispnode, mad->base.method, mad->base.aid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmPacketMadFail(Mai_t *mad, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
#ifndef VIEO_TRACE_DISABLED
Packit 5ea288
	PmNode_t *pmnodep = disppacket->dispnode->info.pmnodep;
Packit 5ea288
Packit 5ea288
	IB_LOG_WARN_FMT(__func__, "PMA response for %s(%s) with bad status: 0x%x From %.*s Guid "FMT_U64" LID 0x%x Ports %u",
Packit 5ea288
		StlPmMadMethodToText(mad->base.method), StlPmMadAttributeToText(mad->base.aid), mad->base.status,
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, (mad->base.amod >> 24) & 0xFF);
Packit 5ea288
#endif
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmMadFailPacketQuery(cntxt_entry_t *entry, Mai_t *mad, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	PmPacketMadFail(mad, disppacket);
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, mad->base.method, mad->base.aid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmNodeMadAttrWrong(Mai_t *mad, PmNode_t *pmnodep)
Packit 5ea288
{
Packit 5ea288
	IB_LOG_WARN_FMT(__func__, "PMA response for %s(%s) with wrong Attr: 0x%x From %.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		StlPmMadMethodToText(mad->base.method), StlPmMadAttributeToText(mad->base.aid), mad->base.aid,
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmMadAttrWrongNodeQuery(cntxt_entry_t *entry, Mai_t *mad, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	PmNodeMadAttrWrong(mad, dispnode->info.pmnodep);
Packit 5ea288
	PmFailNodeQuery(entry, dispnode, mad->base.method, mad->base.aid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmNodeMadSelectWrong(Mai_t *mad, PmNode_t *pmnodep)
Packit 5ea288
{
Packit 5ea288
	IB_LOG_WARN_FMT(__func__, "PMA response for %s(%s) with wrong Port/VL Select From %.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		StlPmMadMethodToText(mad->base.method), StlPmMadAttributeToText(mad->base.aid),
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmMadAttrWrongPacketQuery(cntxt_entry_t *entry, Mai_t *mad, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	PmNodeMadAttrWrong(mad, disppacket->dispnode->info.pmnodep);
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, mad->base.method, mad->base.aid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
static void PmMadSelectWrongPacketQuery(cntxt_entry_t *entry, Mai_t *mad, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	PmNodeMadSelectWrong(mad, disppacket->dispnode->info.pmnodep);
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, mad->base.method, mad->base.aid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// Dispatcher Perf globals
Packit 5ea288
static PmDispPerfMap_t g_pm_disp_perf_map[] = {
Packit 5ea288
	{ STL_PM_ATTRIB_ID_CLASS_PORTINFO,      STL_NODE_FI, MMTHD_GET, offsetof(PmDispatcherPerf_t, hfi_get_cpi) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_CLASS_PORTINFO,      STL_NODE_SW, MMTHD_GET, offsetof(PmDispatcherPerf_t, sw_get_cpi) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_PORT_STATUS,         STL_NODE_FI, MMTHD_GET, offsetof(PmDispatcherPerf_t, hfi_get_cntrs) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS,  STL_NODE_SW, MMTHD_GET, offsetof(PmDispatcherPerf_t, sw_get_data_cntrs) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS, STL_NODE_SW, MMTHD_GET, offsetof(PmDispatcherPerf_t, sw_get_error_cntrs) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS,   STL_NODE_FI, MMTHD_SET, offsetof(PmDispatcherPerf_t, hfi_clr_cntrs) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS,   STL_NODE_SW, MMTHD_SET, offsetof(PmDispatcherPerf_t, sw_clr_cntrs) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_ERROR_INFO,          STL_NODE_FI, MMTHD_GET, offsetof(PmDispatcherPerf_t, hfi_get_error_info) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_ERROR_INFO,          STL_NODE_SW, MMTHD_GET, offsetof(PmDispatcherPerf_t, sw_get_error_info) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_ERROR_INFO,          STL_NODE_FI, MMTHD_SET, offsetof(PmDispatcherPerf_t, hfi_set_error_info) },
Packit 5ea288
	{ STL_PM_ATTRIB_ID_ERROR_INFO,          STL_NODE_SW, MMTHD_SET, offsetof(PmDispatcherPerf_t, sw_set_error_info) },
Packit 5ea288
	{ 0 }
Packit 5ea288
};
Packit 5ea288
Packit 5ea288
// Dispatcher Perf Functions
Packit 5ea288
void PmDispatcherPerfInit(PmDispatcherPerf_t *perf)
Packit 5ea288
{
Packit 5ea288
	memset(perf, 0, sizeof(PmDispatcherPerf_t));
Packit 5ea288
	g_pmDebugPerf = pm_config.pm_debug_perf;
Packit 5ea288
}
Packit 5ea288
static PmDispatcherPerfPhase_t *PmDispatcherPerfGetPhase(Pm_t *pm, uint16_t aid, uint8_t node_type, uint8_t method)
Packit 5ea288
{
Packit 5ea288
	int i;
Packit 5ea288
	for (i = 0; g_pm_disp_perf_map[i].phase_aid; i++) {
Packit 5ea288
		if (g_pm_disp_perf_map[i].phase_aid == aid
Packit 5ea288
			&& g_pm_disp_perf_map[i].phase_node_type == node_type
Packit 5ea288
			&& g_pm_disp_perf_map[i].phase_method == method)
Packit 5ea288
		{
Packit 5ea288
			return (PmDispatcherPerfPhase_t *)(((size_t)&pm->Dispatcher.perf_stats) + g_pm_disp_perf_map[i].phase_offset);
Packit 5ea288
		}
Packit 5ea288
	}
Packit 5ea288
	return NULL;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
void PmDispatcherPerfCalcStart(Pm_t *pm, Mai_t *mad, PmNode_t *pmnodep)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherPerfPhase_t *phase = PmDispatcherPerfGetPhase(pm, mad->base.aid, pmnodep->nodeType, mad->base.method);
Packit 5ea288
	if (phase && phase->phase_start == 0) {
Packit 5ea288
		(void)vs_time_get(&phase->phase_start);
Packit 5ea288
		phase->min_roundtrip_time = (uint64_t )-1;
Packit 5ea288
	}
Packit 5ea288
}
Packit 5ea288
void PmDispatcherPerfCalcPost(Pm_t *pm, Mai_t *mad, cntxt_entry_t *entry, PmNode_t *pmnodep)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherPerfPhase_t *phase = PmDispatcherPerfGetPhase(pm, mad->base.aid, pmnodep->nodeType, entry->mad.base.method);
Packit 5ea288
	uint64_t roundtrip = mad->intime - entry->tstamp;
Packit 5ea288
	if (phase == NULL) return;
Packit 5ea288
Packit 5ea288
	/* Update end phase time (last packet received) */
Packit 5ea288
	phase->phase_end = mad->intime;
Packit 5ea288
	phase->phase_count++;
Packit 5ea288
	if (roundtrip < phase->min_roundtrip_time) {
Packit 5ea288
		phase->min_roundtrip_time = roundtrip;
Packit 5ea288
	}
Packit 5ea288
	if (roundtrip > phase->max_roundtrip_time) {
Packit 5ea288
		phase->max_roundtrip_time = roundtrip;
Packit 5ea288
	}
Packit 5ea288
	phase->sum_roundtrip_time += roundtrip;
Packit 5ea288
}
Packit 5ea288
static void PmDispatcherPerfEndHelper(PmDispatcherPerfPhase_t *phase, const char *phase_str)
Packit 5ea288
{
Packit 5ea288
	uint64_t avg_roundtrip_time = 0;
Packit 5ea288
Packit 5ea288
	if (phase->phase_count > 0) {
Packit 5ea288
		avg_roundtrip_time = phase->sum_roundtrip_time / phase->phase_count;
Packit 5ea288
	}
Packit 5ea288
	IB_LOG_INFINI_INFO_FMT("PmDispatcherPerf", "%s, %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64,
Packit 5ea288
		phase_str, phase->phase_count, (phase->phase_end - phase->phase_start),
Packit 5ea288
		avg_roundtrip_time, phase->min_roundtrip_time, phase->max_roundtrip_time);
Packit 5ea288
	avg_roundtrip_time = 0;
Packit 5ea288
}
Packit 5ea288
void PmDispatcherPerfEnd(Pm_t *pm)
Packit 5ea288
{
Packit 5ea288
	int i;
Packit 5ea288
	char phase_desc[64];
Packit 5ea288
	PmDispatcherPerfPhase_t *phase;
Packit 5ea288
	IB_LOG_INFINI_INFO_FMT("PmDispatcherPerf", "Phase, NodeType, Pkt Count, Phase Time, RoundTrip (avg), RT (min), RT (max)");
Packit 5ea288
Packit 5ea288
	for (i = 0; g_pm_disp_perf_map[i].phase_aid; i++) {
Packit 5ea288
		phase = PmDispatcherPerfGetPhase(pm, g_pm_disp_perf_map[i].phase_aid,
Packit 5ea288
			g_pm_disp_perf_map[i].phase_node_type, g_pm_disp_perf_map[i].phase_method);
Packit 5ea288
		if (phase) {
Packit 5ea288
			snprintf(phase_desc, 64, "%s(%s), %s",
Packit 5ea288
				StlPmMadMethodToText(g_pm_disp_perf_map[i].phase_method),
Packit 5ea288
				StlPmMadAttributeToText(g_pm_disp_perf_map[i].phase_aid),
Packit 5ea288
				StlNodeTypeToText(g_pm_disp_perf_map[i].phase_node_type));
Packit 5ea288
			PmDispatcherPerfEndHelper(phase, phase_desc);
Packit 5ea288
		}
Packit 5ea288
	}
Packit 5ea288
	IB_LOG_INFINI_INFO_FMT("Total DispatchCallback", "%"PRIu64,
Packit 5ea288
		pm->Dispatcher.perf_stats.callback_calc_time);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// Copy port counters in STL_PORT_STATUS_RSP to port counters as referenced
Packit 5ea288
//   by PmDispatcherPort_t.pPortImage->StlPortCounters/StlVLPortCounters
Packit 5ea288
static void PmCopyPortStatus(STL_PORT_STATUS_RSP *madp, PmDispatcherPacket_t * disppacket)
Packit 5ea288
{
Packit 5ea288
	uint32 vl, i, vlSelMask;
Packit 5ea288
	size_t size_counters;
Packit 5ea288
	PmCompositePortCounters_t * pCounters = &disppacket->DispPorts[0].pPortImage->StlPortCounters;
Packit 5ea288
	PmCompositeVLCounters_t * pVlCounters = &disppacket->DispPorts[0].pPortImage->StlVLPortCounters[0];
Packit 5ea288
	PmCompositePortCounters_t * pCountersPrev;
Packit 5ea288
#ifndef VIEO_TRACE_DISABLED
Packit 5ea288
	PmPort_t *pmportp = disppacket->DispPorts[0].pmportp;
Packit 5ea288
	PmNode_t *pmnodep = pmportp->pmnodep;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG4_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x Port %u",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, pmportp->portNum);
Packit 5ea288
#endif
Packit 5ea288
Packit 5ea288
	size_counters = (size_t)&madp->UncorrectableErrors - (size_t)&madp->PortXmitData + 1;
Packit 5ea288
	memcpy( &pCounters->PortXmitData, &madp->PortXmitData, size_counters );
Packit 5ea288
	pCounters->lq.s.LinkQualityIndicator = madp->lq.s.LinkQualityIndicator;
Packit 5ea288
Packit 5ea288
	for (vl = 0, i = 0, vlSelMask = madp->VLSelectMask; (vl < STL_MAX_VLS) && vlSelMask;
Packit 5ea288
			vl++, vlSelMask >>= 1) {
Packit 5ea288
		if (vlSelMask & 0x1) {
Packit 5ea288
			memcpy( &pVlCounters[vl_to_idx(vl)], &madp->VLs[i++], sizeof(struct _vls_pctrs) );
Packit 5ea288
		}
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	pCountersPrev = disppacket->DispPorts[0].pPortImagePrev ?
Packit 5ea288
		&disppacket->DispPorts[0].pPortImagePrev->StlPortCounters : NULL;
Packit 5ea288
	if (isErrorInfoNeeded(disppacket->dispnode->pm, pCounters, pCountersPrev)) {
Packit 5ea288
		disppacket->DispPorts[0].dispNodeSwPort->flags.s.NeedsErrorInfo = 1;
Packit 5ea288
		disppacket->dispnode->info.u.s.needErrorInfo = 1;
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
}	// End of PmCopyPortStatus()
Packit 5ea288
// Copy data port counters in STL_DATA_PORT_COUNTERS_RSP to port counters
Packit 5ea288
//   as referenced by disppacket; VLSelectMask has been checked == 0 if
Packit 5ea288
//   process_vl_counters == 0
Packit 5ea288
static void PmCopyDataPortCounters(STL_DATA_PORT_COUNTERS_RSP *madp, PmDispatcherPacket_t * disppacket)
Packit 5ea288
{
Packit 5ea288
	uint32 i, vl, j, vlSelMask;
Packit 5ea288
	size_t size_counters, size_port;
Packit 5ea288
	STL_DATA_PORT_COUNTERS_RSP * respp = madp;
Packit 5ea288
	PmCompositePortCounters_t * pCounters;
Packit 5ea288
	PmCompositeVLCounters_t * pVlCounters;
Packit 5ea288
	PmDispatcherNode_t * dispnode = disppacket->dispnode;
Packit 5ea288
	PmDispatcherPort_t * dispport;
Packit 5ea288
#ifndef VIEO_TRACE_DISABLED
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG4_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3] "FMT_U64" VLSelectMask 0x%08x",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, madp->PortSelectMask[3], madp->VLSelectMask);
Packit 5ea288
#endif
Packit 5ea288
Packit 5ea288
	size_port = CalculatePortInPacket(dispnode, disppacket);
Packit 5ea288
	size_counters = (size_t)&madp->Port->PortErrorCounterSummary - (size_t)&madp->Port->PortXmitData;
Packit 5ea288
Packit 5ea288
	// Copy DataPortCounters
Packit 5ea288
	for (i = 0; i < disppacket->numPorts; i++) {
Packit 5ea288
		dispport = &disppacket->DispPorts[i];
Packit 5ea288
		pCounters = &dispport->pPortImage->StlPortCounters;
Packit 5ea288
		pVlCounters = &dispport->pPortImage->StlVLPortCounters[0];
Packit 5ea288
		pCounters->lq.s.LinkQualityIndicator = respp->Port->lq.s.LinkQualityIndicator;
Packit 5ea288
Packit 5ea288
		memcpy(&pCounters->PortXmitData, &respp->Port->PortXmitData, size_counters);
Packit 5ea288
		for ( vl = 0, j = 0, vlSelMask = madp->VLSelectMask; (vl < STL_MAX_VLS) && vlSelMask;
Packit 5ea288
				vl++, vlSelMask >>= 1 ) {
Packit 5ea288
			if (vlSelMask & 0x1) {
Packit 5ea288
				memcpy( &pVlCounters[vl_to_idx(vl)],
Packit 5ea288
					&respp->Port->VLs[j++], sizeof(struct _vls_dpctrs) );
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
		dispport->pPortImage->u.s.gotDataCntrs = 1;
Packit 5ea288
		// Get Error if sum is non-zero and previous image is invalid
Packit 5ea288
		//  OR get Error if previous image is valid and
Packit 5ea288
		//       previous sum is different than current sum
Packit 5ea288
		if ((respp->Port->PortErrorCounterSummary != 0 && dispport->pPortImagePrev == NULL)
Packit 5ea288
			|| (dispport->pPortImagePrev
Packit 5ea288
				&& (PM_PORT_ERROR_SUMMARY(dispport->pPortImagePrev,
Packit 5ea288
					StlResolutionToShift(pm_config.resolution.LocalLinkIntegrity, RES_ADDER_LLI),
Packit 5ea288
					StlResolutionToShift(pm_config.resolution.LinkErrorRecovery, RES_ADDER_LER)
Packit 5ea288
					) != respp->Port->PortErrorCounterSummary) ) )
Packit 5ea288
		{
Packit 5ea288
			dispport->dispNodeSwPort->flags.s.NeedsError = 1;
Packit 5ea288
			disppacket->dispnode->info.u.s.needError = 1;
Packit 5ea288
		} else if (dispport->pPortImagePrev == NULL
Packit 5ea288
			&& isErrorInfoNeeded(disppacket->dispnode->pm, pCounters, NULL))
Packit 5ea288
		{
Packit 5ea288
			// If the previous Image is invalid get ErrorInfo if to be safe
Packit 5ea288
			disppacket->dispnode->info.u.s.needErrorInfo = 1;
Packit 5ea288
			dispport->dispNodeSwPort->flags.s.NeedsErrorInfo = 1;
Packit 5ea288
		}
Packit 5ea288
Packit 5ea288
		respp = (STL_DATA_PORT_COUNTERS_RSP *)((uint8 *)respp + size_port);
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
}	// End of PmCopyDataPortCounters()
Packit 5ea288
Packit 5ea288
// Copy error port counters in STL_ERROR_PORT_COUNTERS_RSP to port counters
Packit 5ea288
//   as referenced by disppacket; VLSelectMask has been checked == 0 if
Packit 5ea288
//   process_vl_counters == 0
Packit 5ea288
static void PmCopyErrorPortCounters(STL_ERROR_PORT_COUNTERS_RSP *madp, PmDispatcherPacket_t * disppacket)
Packit 5ea288
{
Packit 5ea288
	uint32 i, vl, j, vlSelMask;
Packit 5ea288
	size_t size_port, size_counters;
Packit 5ea288
Packit 5ea288
	STL_ERROR_PORT_COUNTERS_RSP * respp = madp;
Packit 5ea288
	PmCompositePortCounters_t * pCounters;
Packit 5ea288
	PmCompositeVLCounters_t * pVlCounters;
Packit 5ea288
	PmCompositePortCounters_t * pCountersPrev;
Packit 5ea288
	PmDispatcherPort_t * dispport;
Packit 5ea288
#ifndef VIEO_TRACE_DISABLED
Packit 5ea288
	PmNode_t *pmnodep = disppacket->dispnode->info.pmnodep;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG4_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3] "FMT_U64" VLSelectMask 0x%08x",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, madp->PortSelectMask[3], madp->VLSelectMask);
Packit 5ea288
#endif
Packit 5ea288
Packit 5ea288
	size_port = CalculatePortInPacket(disppacket->dispnode, disppacket);
Packit 5ea288
	size_counters = (size_t)&madp->Port->UncorrectableErrors - (size_t)&madp->Port->PortRcvConstraintErrors + 1;
Packit 5ea288
Packit 5ea288
	// Copy ErrorPortCounters
Packit 5ea288
	for (i = 0; i < disppacket->numPorts; i++) {
Packit 5ea288
		dispport = &disppacket->DispPorts[i];
Packit 5ea288
		pCounters = &dispport->pPortImage->StlPortCounters;
Packit 5ea288
		pVlCounters = &dispport->pPortImage->StlVLPortCounters[0];
Packit 5ea288
Packit 5ea288
		memcpy(&pCounters->PortRcvConstraintErrors, &respp->Port->PortRcvConstraintErrors, size_counters);
Packit 5ea288
		for (vl = 0, j = 0, vlSelMask = madp->VLSelectMask; (vl < STL_MAX_VLS) && vlSelMask;
Packit 5ea288
				vl++, vlSelMask >>= 1) {
Packit 5ea288
			if (vlSelMask & 0x1) {
Packit 5ea288
				pVlCounters[vl_to_idx(vl)].PortVLXmitDiscards = respp->Port->VLs[j++].PortVLXmitDiscards;
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
		dispport->pPortImage->u.s.gotErrorCntrs = 1;
Packit 5ea288
		pCountersPrev = dispport->pPortImagePrev ?
Packit 5ea288
			&dispport->pPortImagePrev->StlPortCounters : NULL;
Packit 5ea288
		if (isErrorInfoNeeded(disppacket->dispnode->pm, pCounters, pCountersPrev)) {
Packit 5ea288
			dispport->dispNodeSwPort->flags.s.NeedsErrorInfo = 1;
Packit 5ea288
			disppacket->dispnode->info.u.s.needErrorInfo = 1;
Packit 5ea288
		}
Packit 5ea288
Packit 5ea288
		respp = (STL_ERROR_PORT_COUNTERS_RSP *)((uint8 *)respp + size_port);
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
}	// End of PmCopyErrorPortCounters()
Packit 5ea288
Packit 5ea288
static void PmCopyErrorInfo(STL_ERROR_INFO_RSP *madp, PmDispatcherPacket_t * disppacket)
Packit 5ea288
{
Packit 5ea288
	uint32 i;
Packit 5ea288
Packit 5ea288
	PmCompositeErrorInfo_t * pErrorInfo;
Packit 5ea288
	PmDispatcherPort_t * dispport;
Packit 5ea288
#ifndef VIEO_TRACE_DISABLED
Packit 5ea288
	PmNode_t *pmnodep = disppacket->dispnode->info.pmnodep;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG4_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3] "FMT_U64"",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, madp->PortSelectMask[3]);
Packit 5ea288
#endif
Packit 5ea288
Packit 5ea288
	// Copy ErrorInfo
Packit 5ea288
	for (i = 0; i < disppacket->numPorts; i++) {
Packit 5ea288
		dispport = &disppacket->DispPorts[i];
Packit 5ea288
		pErrorInfo = &dispport->pPortImage->ErrorInfo;
Packit 5ea288
Packit 5ea288
		memcpy(pErrorInfo, &madp->Port[i], sizeof(PmCompositeErrorInfo_t));
Packit 5ea288
Packit 5ea288
		if (isErrorInfoStatusSet(pErrorInfo)) {
Packit 5ea288
			dispport->pPortImage->u.s.gotErrorInfo = 1; // We go an ErrorInfo with Status Set
Packit 5ea288
Packit 5ea288
			dispport->dispNodeSwPort->flags.s.NeedsClearErrorInfo = 1;
Packit 5ea288
			disppacket->dispnode->info.u.s.needClearErrorInfo = 1;
Packit 5ea288
		}
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
}	// End of PmCopyErrorInfo()
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
// PMA Outbound Mad processing
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
Packit 5ea288
static void PmSetMadAddressAndTid(Pm_t *pm, PmNode_t *pmnodep, cntxt_entry_t *entry)
Packit 5ea288
{
Packit 5ea288
	entry->mad.addrInfo.sl = pmnodep->sl;
Packit 5ea288
	entry->mad.addrInfo.slid = pm->pm_slid;
Packit 5ea288
	entry->mad.addrInfo.dlid =pmnodep->dlid;	// always set,used by redirect retry
Packit 5ea288
	entry->mad.addrInfo.pkey = pmnodep->pkey;
Packit 5ea288
	entry->mad.addrInfo.destqp = pmnodep->qpn;
Packit 5ea288
	entry->mad.addrInfo.qkey = pmnodep->qkey;
Packit 5ea288
Packit 5ea288
	(void) mai_alloc_tid(hpma, MAD_CV_PERF, &entry->mad.base.tid);
Packit 5ea288
	IB_LOG_DEBUG2LX("send MAD tid:", entry->mad.base.tid);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// returns NULL if unable to allocate an entry.  Since entry pool is pre-sized
Packit 5ea288
// errors allocating the entry are unexpected.
Packit 5ea288
static cntxt_entry_t *PmInitMad(Pm_t *pm, PmNode_t *pmnodep,
Packit 5ea288
			uint8 method, uint32 attr, uint32 modifier)
Packit 5ea288
{
Packit 5ea288
    cntxt_entry_t *entry=NULL;
Packit 5ea288
Packit 5ea288
    if ((entry = cs_cntxt_get_nolock(NULL, &pm->Dispatcher.cntx, FALSE)) == NULL) {
Packit 5ea288
        // could not get a context
Packit 5ea288
        IB_LOG_ERROR0("Error allocating an PM async send/rcv context");
Packit 5ea288
        //cntxt_cb(NULL, VSTATUS_BAD, cntxt_data, NULL);
Packit 5ea288
		return NULL;	// let caller handle it, doing a callback could be recursive and cause a deep stack
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	STL_BasicMadInit(&entry->mad, MAD_CV_PERF, method, attr, modifier,
Packit 5ea288
					pm->pm_slid, pmnodep->dlid, pmnodep->sl);
Packit 5ea288
Packit 5ea288
	PmSetMadAddressAndTid(pm, pmnodep, entry);
Packit 5ea288
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		PmDispatcherPerfCalcStart(pm, &entry->mad, pmnodep);
Packit 5ea288
	}
Packit 5ea288
	return entry;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// caller must retire entry on failure
Packit 5ea288
static __inline Status_t PmDispatcherSend(Pm_t *pm, cntxt_entry_t *entry)
Packit 5ea288
{
Packit 5ea288
	// Alternative for send failures is to ignore them and let timeout fire
Packit 5ea288
	// (void)cs_cntxt_send_mad_nolock (entry, &pm->Dispatcher.cntx);
Packit 5ea288
	// return VSTATUS_OK;
Packit 5ea288
    return cs_cntxt_send_mad_nolock (entry, &pm->Dispatcher.cntx);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// on success a Get(ClassPortInfo) has been sent and Dispatcher.cntx is
Packit 5ea288
// ready to process the response
Packit 5ea288
// On failure, no request nor context entry is outstanding.
Packit 5ea288
static Status_t PmSendGetClassPortInfo(Pm_t *pm, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
Packit 5ea288
    INCREMENT_PM_COUNTER(pmCounterGetClassPortInfo);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_GET, STL_PM_ATTRIB_ID_CLASS_PORTINFO, 0);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = 0;
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchNodeCallback, dispnode);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailNodeQuery(entry, dispnode, MMTHD_GET, STL_PM_ATTRIB_ID_CLASS_PORTINFO);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
void setPortSelectMask(uint64 *selectMask, uint8 portNum, boolean clear)
Packit 5ea288
{
Packit 5ea288
	// selectMask points to an array of 4 uint64s representing sel mask
Packit 5ea288
Packit 5ea288
	int index;
Packit 5ea288
    if (clear) memset(&selectMask[0], 0, 4 * sizeof(uint64));
Packit 5ea288
Packit 5ea288
	// find index
Packit 5ea288
	index = (3 - (portNum / 64));
Packit 5ea288
Packit 5ea288
	selectMask[index] |= (uint64)(1) << (portNum - (64 * (3 - index)));
Packit 5ea288
Packit 5ea288
	return;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// on success a Set(PortCounters) has been sent and Dispatcher.cntx is
Packit 5ea288
// ready to process the response
Packit 5ea288
// On failure, no request nor context entry is outstanding.
Packit 5ea288
static Status_t PmSendClearPortStatus(Pm_t *pm, PmDispatcherNode_t *dispnode,
Packit 5ea288
                                        PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	STL_CLEAR_PORT_STATUS *p;
Packit 5ea288
Packit 5ea288
	// only called if we successfully got port counters
Packit 5ea288
	DEBUG_ASSERT(disppacket->DispPorts[0].pPortImage->u.s.gotDataCntrs || disppacket->DispPorts[0].pPortImage->u.s.gotErrorCntrs);
Packit 5ea288
Packit 5ea288
	INCREMENT_PM_COUNTER(pmCounterSetClearPortStatus);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_SET, STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS, 1 << 24);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = sizeof(STL_CLEAR_PORT_STATUS);
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
	p = (STL_CLEAR_PORT_STATUS *)&entry->mad.data;
Packit 5ea288
	memset(p, 0, sizeof(STL_CLEAR_PORT_STATUS));
Packit 5ea288
	memcpy(p->PortSelectMask, disppacket->PortSelectMask, STL_PORT_SELECTMASK_SIZE);
Packit 5ea288
	p->CounterSelectMask.AsReg32 = disppacket->DispPorts[0].pPortImage->clearSelectMask.AsReg32;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3] "FMT_U64" SelMask 0x%04x",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, p->PortSelectMask[3], p->CounterSelectMask.AsReg32);
Packit 5ea288
Packit 5ea288
	BSWAP_STL_CLEAR_PORT_STATUS_REQ(p);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchPacketCallback, disppacket);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailPacketClear(entry, disppacket, MMTHD_SET, STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// on success a Get(PortStatus) has been sent and Dispatcher.cntx is
Packit 5ea288
// ready to process the response
Packit 5ea288
// On failure, no request nor context entry is outstanding.
Packit 5ea288
static Status_t PmSendGetPortStatus(Pm_t *pm, PmDispatcherNode_t *dispnode,
Packit 5ea288
                                    PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	STL_PORT_STATUS_REQ *p;
Packit 5ea288
Packit 5ea288
	INCREMENT_PM_COUNTER(pmCounterGetPortStatus);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_GET, STL_PM_ATTRIB_ID_PORT_STATUS, (disppacket->numPorts) << 24);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = sizeof(STL_PORT_STATUS_REQ);
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
	p = (STL_PORT_STATUS_REQ *)entry->mad.data;
Packit 5ea288
	p->PortNumber = disppacket->DispPorts[0].pmportp->portNum;
Packit 5ea288
	p->VLSelectMask = disppacket->VLSelectMask;
Packit 5ea288
	memset(p->Reserved, 0, sizeof(p->Reserved));
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x Port %d",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, disppacket->DispPorts[0].pmportp->portNum);
Packit 5ea288
Packit 5ea288
	BSWAP_STL_PORT_STATUS_REQ(p);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchPacketCallback, disppacket);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, MMTHD_GET, STL_PM_ATTRIB_ID_PORT_STATUS);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
Packit 5ea288
}	// End of PmSendGetPortStatus()
Packit 5ea288
Packit 5ea288
// on success a Get(DataPortCounters) has been sent and Dispatcher.cntx is
Packit 5ea288
// ready to process the response
Packit 5ea288
// On failure, no request nor context entry is outstanding.
Packit 5ea288
static Status_t PmSendGetDataPortCounters(Pm_t *pm, PmDispatcherNode_t *dispnode,
Packit 5ea288
                                          PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	STL_DATA_PORT_COUNTERS_REQ *p;
Packit 5ea288
Packit 5ea288
	INCREMENT_PM_COUNTER(pmCounterGetDataPortCounters);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_GET, STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS, (disppacket->numPorts) << 24);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = sizeof(STL_DATA_PORT_COUNTERS_REQ);
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
	p = (STL_DATA_PORT_COUNTERS_REQ *)entry->mad.data;
Packit 5ea288
	memcpy(p->PortSelectMask, disppacket->PortSelectMask, STL_PORT_SELECTMASK_SIZE);
Packit 5ea288
	p->VLSelectMask = disppacket->VLSelectMask;
Packit 5ea288
	p->res.s.LocalLinkIntegrityResolution = StlResolutionToShift(pm_config.resolution.LocalLinkIntegrity, RES_ADDER_LLI);
Packit 5ea288
	p->res.s.LinkErrorRecoveryResolution = StlResolutionToShift(pm_config.resolution.LinkErrorRecovery, RES_ADDER_LER);
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3]: "FMT_U64,
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, p->PortSelectMask[3]);
Packit 5ea288
Packit 5ea288
	BSWAP_STL_DATA_PORT_COUNTERS_REQ(p);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchPacketCallback, disppacket);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, MMTHD_GET, STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
Packit 5ea288
}	// End of PmSendGetDataPortCounters()
Packit 5ea288
Packit 5ea288
// on success a Get(ErrorPortCounters) has been sent and Dispatcher.cntx is
Packit 5ea288
// ready to process the response
Packit 5ea288
// On failure, no request nor context entry is outstanding.
Packit 5ea288
static Status_t PmSendGetErrorPortCounters(Pm_t *pm, PmDispatcherNode_t *dispnode,
Packit 5ea288
                                           PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	STL_ERROR_PORT_COUNTERS_REQ *p;
Packit 5ea288
Packit 5ea288
	INCREMENT_PM_COUNTER(pmCounterGetErrorPortCounters);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_GET, STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS, (disppacket->numPorts) << 24);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = sizeof(STL_ERROR_PORT_COUNTERS_REQ);
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
	p = (STL_ERROR_PORT_COUNTERS_REQ *)entry->mad.data;
Packit 5ea288
	memcpy(p->PortSelectMask, disppacket->PortSelectMask, STL_PORT_SELECTMASK_SIZE);
Packit 5ea288
	p->VLSelectMask = disppacket->VLSelectMask;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3]: "FMT_U64" VLSelectMask 0x%08x",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, p->PortSelectMask[3], p->VLSelectMask);
Packit 5ea288
Packit 5ea288
	BSWAP_STL_ERROR_PORT_COUNTERS_REQ(p);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchPacketCallback, disppacket);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, MMTHD_GET, STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
Packit 5ea288
}	// End of PmSendGetErrorPortCounters()
Packit 5ea288
Packit 5ea288
Packit 5ea288
static Status_t PmSendGetErrorInfo(Pm_t *pm, PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	STL_ERROR_INFO_REQ *p;
Packit 5ea288
Packit 5ea288
	INCREMENT_PM_COUNTER(pmCounterGetErrorInfo);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_GET, STL_PM_ATTRIB_ID_ERROR_INFO, (disppacket->numPorts) << 24);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = sizeof(STL_ERROR_INFO_REQ);
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
	p = (STL_ERROR_INFO_REQ *)entry->mad.data;
Packit 5ea288
	memcpy(p->PortSelectMask, disppacket->PortSelectMask, STL_PORT_SELECTMASK_SIZE);
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3]: "FMT_U64"",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, p->PortSelectMask[3]);
Packit 5ea288
Packit 5ea288
	BSWAP_STL_ERROR_INFO_REQ(p);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchPacketCallback, disppacket);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailPacketQuery(entry, disppacket, MMTHD_GET, STL_PM_ATTRIB_ID_ERROR_INFO);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
Packit 5ea288
}	// End of PmSendGetErrorInfo()
Packit 5ea288
static Status_t PmSendClearErrorInfo(Pm_t *pm, PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	cntxt_entry_t *entry;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	STL_ERROR_INFO_REQ *p;
Packit 5ea288
Packit 5ea288
	INCREMENT_PM_COUNTER(pmCounterSetErrorInfo);
Packit 5ea288
	entry = PmInitMad(pm, pmnodep, MMTHD_SET, STL_PM_ATTRIB_ID_ERROR_INFO, (disppacket->numPorts) << 24);
Packit 5ea288
	if (! entry)
Packit 5ea288
		goto fail;
Packit 5ea288
Packit 5ea288
	entry->mad.datasize = sizeof(STL_ERROR_INFO_REQ);
Packit 5ea288
	// fill in rest of entry->mad.data as needed
Packit 5ea288
	p = (STL_ERROR_INFO_REQ *)entry->mad.data;
Packit 5ea288
	memcpy(p->PortSelectMask, disppacket->PortSelectMask, STL_PORT_SELECTMASK_SIZE);
Packit 5ea288
	p->ErrorInfoSelectMask.AsReg32 = IB_UINT32_MAX;
Packit 5ea288
	p->ErrorInfoSelectMask.s.Reserved = 0;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG1_FMT(__func__, "%.*s Guid "FMT_U64" LID 0x%x PortSelectMask[3]: "FMT_U64"",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, p->PortSelectMask[3]);
Packit 5ea288
Packit 5ea288
	BSWAP_STL_ERROR_INFO_REQ(p);
Packit 5ea288
Packit 5ea288
	cs_cntxt_set_callback(entry, DispatchPacketCallback, disppacket);
Packit 5ea288
	if (VSTATUS_OK ==  PmDispatcherSend(pm, entry))
Packit 5ea288
		return VSTATUS_OK;
Packit 5ea288
fail:
Packit 5ea288
	PmFailPacketClear(entry, disppacket, MMTHD_SET, STL_PM_ATTRIB_ID_ERROR_INFO);
Packit 5ea288
	return VSTATUS_NOT_FOUND;	// no work started
Packit 5ea288
Packit 5ea288
}	// End of PmSendGetErrorInfo()
Packit 5ea288
static void DispatchPacketDone(Pm_t *pm, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherNode_t *dispnode = disppacket->dispnode;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		(int)sizeof(dispnode->info.pmnodep->nodeDesc.NodeString), dispnode->info.pmnodep->nodeDesc.NodeString,
Packit 5ea288
		dispnode->info.pmnodep->NodeGUID, dispnode->info.pmnodep->dlid);
Packit 5ea288
Packit 5ea288
	DEBUG_ASSERT(dispnode->info.state != PM_DISP_NODE_DONE);
Packit 5ea288
	// if dispport->failed,
Packit 5ea288
	// 		then already incremented pm->Image[pm->SweepIndex].NoRespPorts
Packit 5ea288
	dispnode->info.numOutstandingPackets--;
Packit 5ea288
	//Cleanup DispPacket
Packit 5ea288
	memset(disppacket->PortSelectMask, 0, sizeof(uint64)*4);
Packit 5ea288
	disppacket->numPorts = 0;
Packit 5ea288
	vs_pool_free(&pm_pool, (void *)disppacket->DispPorts);
Packit 5ea288
	disppacket->DispPorts = NULL;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
// PM Packet Processing State Machine
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
Packit 5ea288
// cs_send_mad callback for all operations against multiple ports
Packit 5ea288
static void DispatchPacketCallback(cntxt_entry_t *entry, Status_t status, void *data, Mai_t *mad)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherPacket_t *disppacket = (PmDispatcherPacket_t *)data;
Packit 5ea288
	PmDispatcherNode_t *dispnode = disppacket->dispnode;
Packit 5ea288
	PmDispatcherPort_t *dispport;
Packit 5ea288
	STL_CLEAR_PORT_STATUS *clearPortStatusMad;
Packit 5ea288
	uint64_t sTime, eTime;
Packit 5ea288
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		(void)vs_time_get(&sTime);
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG3_FMT( __func__,"%.*s Guid "FMT_U64" LID 0x%x NodeState %u Ports %u PortSelectMask[3] "FMT_U64,
Packit 5ea288
		(int)sizeof(dispnode->info.pmnodep->nodeDesc.NodeString), dispnode->info.pmnodep->nodeDesc.NodeString,
Packit 5ea288
		dispnode->info.pmnodep->NodeGUID, dispnode->info.pmnodep->dlid, dispnode->info.state,
Packit 5ea288
		disppacket->numPorts, disppacket->PortSelectMask[3] );
Packit 5ea288
Packit 5ea288
	switch (dispnode->info.state) {
Packit 5ea288
	case PM_DISP_NODE_GET_DATACOUNTERS:
Packit 5ea288
		if (dispnode->info.pmnodep->nodeType == STL_NODE_FI) {
Packit 5ea288
			if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
				PmFailPacketQuery(entry, disppacket, (mad ? mad->base.method : MMTHD_GET),
Packit 5ea288
								  (mad ? mad->base.aid : STL_PM_ATTRIB_ID_PORT_STATUS) );
Packit 5ea288
				goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
			} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
				PmMadFailPacketQuery(entry, mad, disppacket);
Packit 5ea288
				goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
			} else {
Packit 5ea288
				// process port status
Packit 5ea288
				{
Packit 5ea288
					STL_PORT_STATUS_RSP *portStatusMad = (STL_PORT_STATUS_RSP *)&mad->data;
Packit 5ea288
					BSWAP_STL_PORT_STATUS_RSP(portStatusMad);
Packit 5ea288
					PmCopyPortStatus(portStatusMad, disppacket);
Packit 5ea288
				}
Packit 5ea288
				dispport = &disppacket->DispPorts[0];
Packit 5ea288
				dispport->pPortImage->u.s.gotDataCntrs = 1;
Packit 5ea288
				dispport->pPortImage->u.s.gotErrorCntrs = 1;
Packit 5ea288
			}
Packit 5ea288
		} else if (dispnode->info.pmnodep->nodeType == STL_NODE_SW) {
Packit 5ea288
			if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
				PmFailPacketQuery(entry, disppacket, (mad ? mad->base.method : MMTHD_GET),
Packit 5ea288
					(mad ? mad->base.aid : STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS) );
Packit 5ea288
Packit 5ea288
				goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
			} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
				PmMadFailPacketQuery(entry, mad, disppacket);
Packit 5ea288
				goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
			}
Packit 5ea288
			{
Packit 5ea288
				if (mad->base.aid != STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS) {
Packit 5ea288
					PmMadAttrWrongPacketQuery(entry, mad, disppacket);
Packit 5ea288
					goto nextpacket;    // PacketDone called on Fail
Packit 5ea288
				}
Packit 5ea288
				STL_DATA_PORT_COUNTERS_RSP *dataPortCountersMad = (STL_DATA_PORT_COUNTERS_RSP *)&mad->data;
Packit 5ea288
				BSWAP_STL_DATA_PORT_COUNTERS_RSP(dataPortCountersMad);
Packit 5ea288
Packit 5ea288
				if ((memcmp(dataPortCountersMad->PortSelectMask, disppacket->PortSelectMask, sizeof(uint64)*4) != 0) ||
Packit 5ea288
					(dataPortCountersMad->VLSelectMask != disppacket->VLSelectMask)) {
Packit 5ea288
					PmMadSelectWrongPacketQuery(entry, mad, disppacket);
Packit 5ea288
					goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
				}
Packit 5ea288
				// Process Data Port Counters MAD
Packit 5ea288
				PmCopyDataPortCounters(dataPortCountersMad, disppacket);
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
		break;
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORCOUNTERS:
Packit 5ea288
		if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
Packit 5ea288
			PmFailPacketQuery(entry, disppacket, (mad ? mad->base.method : MMTHD_GET),
Packit 5ea288
					(mad ? mad->base.aid : STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS) );
Packit 5ea288
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
		} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
			PmMadFailPacketQuery(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
		}
Packit 5ea288
Packit 5ea288
		{
Packit 5ea288
			if (mad->base.aid != STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS) {
Packit 5ea288
				PmMadAttrWrongPacketQuery(entry, mad, disppacket);
Packit 5ea288
				goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
			}
Packit 5ea288
Packit 5ea288
			STL_ERROR_PORT_COUNTERS_RSP *errorPortCountersMad = (STL_ERROR_PORT_COUNTERS_RSP *)&mad->data;
Packit 5ea288
			BSWAP_STL_ERROR_PORT_COUNTERS_RSP(errorPortCountersMad);
Packit 5ea288
Packit 5ea288
			if ((memcmp(errorPortCountersMad->PortSelectMask, disppacket->PortSelectMask, sizeof(uint64)*4) != 0) ||
Packit 5ea288
				(errorPortCountersMad->VLSelectMask != disppacket->VLSelectMask)) {
Packit 5ea288
				PmMadSelectWrongPacketQuery(entry, mad, disppacket);
Packit 5ea288
				goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
			}
Packit 5ea288
			// process error port counters
Packit 5ea288
			PmCopyErrorPortCounters(errorPortCountersMad, disppacket);
Packit 5ea288
		}
Packit 5ea288
		break;
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_CLR_PORT_STATUS:
Packit 5ea288
		// we only get here if we successfully got counters
Packit 5ea288
		// we already tabulated, so on failure we simply do not set the Clear
Packit 5ea288
		// flags in the pCounters.  Hence next sweep will assume we didn't clear
Packit 5ea288
		//DEBUG_ASSERT(dispport->pCounters->flags & PM_PORT_GOT_COUNTERS);
Packit 5ea288
		if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
			PmFailPacketClear(entry, disppacket, (mad ? mad->base.method : MMTHD_SET),
Packit 5ea288
					(mad ? mad->base.aid : STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS) );
Packit 5ea288
			goto nextpacket;
Packit 5ea288
#if 0
Packit 5ea288
		} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
			PmMadFailPacketClear(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
		} else if (mad->base.aid != PM_ATTRIB_ID_PORT_COUNTERS) {
Packit 5ea288
			PmMadAttrWrongPacketClear(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
#endif
Packit 5ea288
		} else {
Packit 5ea288
			dispport = &disppacket->DispPorts[0];
Packit 5ea288
			uint32 select = dispport->pPortImage->clearSelectMask.AsReg32;
Packit 5ea288
			clearPortStatusMad = (STL_CLEAR_PORT_STATUS *)&mad->data;
Packit 5ea288
			BSWAP_STL_CLEAR_PORT_STATUS_REQ(clearPortStatusMad);
Packit 5ea288
			if ((memcmp(clearPortStatusMad->PortSelectMask, disppacket->PortSelectMask, sizeof(uint64)*4) != 0) ||
Packit 5ea288
				(clearPortStatusMad->CounterSelectMask.AsReg32 != select)) {
Packit 5ea288
				PmFailPacketClear(entry, disppacket, (mad ? mad->base.method : 0), (mad ? mad->base.aid : 0));
Packit 5ea288
				goto nextpacket;
Packit 5ea288
			}
Packit 5ea288
			// process clear port counters
Packit 5ea288
			//PmClearSelectedPortCounters(dispnode->pm, disppacket);
Packit 5ea288
		}
Packit 5ea288
		break;
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORINFO:
Packit 5ea288
		if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
			PmFailPacketQuery(entry, disppacket, (mad ? mad->base.method : MMTHD_GET),
Packit 5ea288
				(mad ? mad->base.aid : STL_PM_ATTRIB_ID_ERROR_INFO));
Packit 5ea288
			goto nextpacket;
Packit 5ea288
		} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
			PmMadFailPacketQuery(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
		} else if (mad->base.aid != STL_PM_ATTRIB_ID_ERROR_INFO) {
Packit 5ea288
			PmMadAttrWrongPacketQuery(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
		} else {
Packit 5ea288
			STL_ERROR_INFO_RSP *errorInfoMad = (STL_ERROR_INFO_RSP *)&mad->data;
Packit 5ea288
			BSWAP_STL_ERROR_INFO_RSP(errorInfoMad);
Packit 5ea288
Packit 5ea288
			PmCopyErrorInfo(errorInfoMad, disppacket);
Packit 5ea288
		}
Packit 5ea288
		break;
Packit 5ea288
	case PM_DISP_NODE_CLR_ERRORINFO:
Packit 5ea288
		if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
			PmFailPacketClear(entry, disppacket, (mad ? mad->base.method : MMTHD_SET),
Packit 5ea288
					(mad ? mad->base.aid : STL_PM_ATTRIB_ID_ERROR_INFO) );
Packit 5ea288
			goto nextpacket;
Packit 5ea288
#if 0
Packit 5ea288
		} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
			PmMadFailPacketClear(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
		} else if (mad->base.aid != STL_PM_ATTRIB_ID_ERROR_INFO) {
Packit 5ea288
			PmMadAttrWrongPacketClear(entry, mad, disppacket);
Packit 5ea288
			goto nextpacket;	// PacketDone called on Fail
Packit 5ea288
#endif
Packit 5ea288
		} else {
Packit 5ea288
			dispport = &disppacket->DispPorts[0];
Packit 5ea288
			STL_ERROR_INFO_REQ *clearErrorInfoMad = (STL_ERROR_INFO_REQ *)&mad->data;
Packit 5ea288
			BSWAP_STL_ERROR_INFO_REQ(clearErrorInfoMad);
Packit 5ea288
			if (memcmp(clearErrorInfoMad->PortSelectMask, disppacket->PortSelectMask, sizeof(uint64)*4) != 0) {
Packit 5ea288
				PmFailPacketClear(entry, disppacket, (mad ? mad->base.method : 0), (mad ? mad->base.aid : 0));
Packit 5ea288
				goto nextpacket;
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
		break;
Packit 5ea288
	default:
Packit 5ea288
		ASSERT(0);	// or log error
Packit 5ea288
	}    // End of switch (dispnode->info.state)
Packit 5ea288
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		PmDispatcherPerfCalcPost(dispnode->pm, mad, entry, dispnode->info.pmnodep);
Packit 5ea288
	}
Packit 5ea288
	cs_cntxt_retire_nolock( entry, &dispnode->pm->Dispatcher.cntx  );
Packit 5ea288
Packit 5ea288
	DispatchPacketDone(dispnode->pm, disppacket);
Packit 5ea288
Packit 5ea288
nextpacket:
Packit 5ea288
Packit 5ea288
	if (VSTATUS_OK == DispatchNextPacket(dispnode->pm, dispnode, disppacket))
Packit 5ea288
		goto done;
Packit 5ea288
Packit 5ea288
	if (dispnode->info.numOutstandingPackets)
Packit 5ea288
		goto done;
Packit 5ea288
Packit 5ea288
	// all Ports Done
Packit 5ea288
	if (VSTATUS_OK == DispatchNodeNextStep(dispnode->pm, dispnode->info.pmnodep, dispnode))
Packit 5ea288
		goto done;
Packit 5ea288
Packit 5ea288
	// if NodeNextStep returns ! OK, then Node will be done
Packit 5ea288
	DEBUG_ASSERT(dispnode->info.state == PM_DISP_NODE_DONE);
Packit 5ea288
Packit 5ea288
	// loops til finds a node or none left, wake main thread if all done
Packit 5ea288
	(void)DispatchNextNode(dispnode->pm, dispnode);
Packit 5ea288
done:
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		(void)vs_time_get(&eTime);
Packit 5ea288
		dispnode->pm->Dispatcher.perf_stats.callback_calc_time += (eTime - sTime);
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
}	// End of DispatchPacketCallback()
Packit 5ea288
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
// PM Node Processing State Machine
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
Packit 5ea288
extern Pm_t g_pmSweepData;
Packit 5ea288
// Compare function used by qsort() to sort active ports for data counters
Packit 5ea288
// return n < 0 for a < b   
Packit 5ea288
//        n = 0 for a == b  
Packit 5ea288
//        n > 0 for a > b   
Packit 5ea288
int PmDispatcherSwitchPortDataCompare(const void *a, const void *b)
Packit 5ea288
{
Packit 5ea288
	// First Level Compare: NULL check -> Decending 
Packit 5ea288
	PmDispatcherSwitchPort_t *A = (PmDispatcherSwitchPort_t *)a;
Packit 5ea288
	PmDispatcherSwitchPort_t *B = (PmDispatcherSwitchPort_t *)b;
Packit 5ea288
    
Packit 5ea288
	if (A->flags.s.Skip && B->flags.s.Skip)		return 0;
Packit 5ea288
	if (A->flags.s.Skip)						return 1;
Packit 5ea288
	if (B->flags.s.Skip)						return -1;
Packit 5ea288
	if (g_pmSweepData.pmFlags & STL_PM_PROCESS_VL_COUNTERS) {
Packit 5ea288
		// Second Level Compare: numVLs -> Decending
Packit 5ea288
		if (A->NumVLs < B->NumVLs) return 1;
Packit 5ea288
		if (A->NumVLs > B->NumVLs) return -1;
Packit 5ea288
Packit 5ea288
		// Third Level Compare: VLSelectMask -> Ascending
Packit 5ea288
		if (A->VLSelectMask < B->VLSelectMask) return -1;
Packit 5ea288
		if (A->VLSelectMask > B->VLSelectMask) return 1;
Packit 5ea288
	}
Packit 5ea288
	return 0;
Packit 5ea288
}	// End of PmDispatcherSwitchPortDataCompare()
Packit 5ea288
Packit 5ea288
// Compare function used by qsort() to sort active ports for error counters
Packit 5ea288
// return n < 0 for a < b   
Packit 5ea288
//        n = 0 for a == b  
Packit 5ea288
//        n > 0 for a > b   
Packit 5ea288
int PmDispatcherSwitchPortErrorCompare(const void *a, const void *b)
Packit 5ea288
{
Packit 5ea288
	// First Level Compare: NULL check -> Decending 
Packit 5ea288
	PmDispatcherSwitchPort_t *A = (PmDispatcherSwitchPort_t *)a;
Packit 5ea288
	PmDispatcherSwitchPort_t *B = (PmDispatcherSwitchPort_t *)b;
Packit 5ea288
    
Packit 5ea288
	if (A->flags.s.Skip && B->flags.s.Skip)					return 0;
Packit 5ea288
	if (A->flags.s.Skip)									return 1;
Packit 5ea288
	if (B->flags.s.Skip)									return -1;
Packit 5ea288
	if (A->flags.s.NeedsError && B->flags.s.NeedsError)		return 0;
Packit 5ea288
    if (A->flags.s.NeedsError)							return -1;
Packit 5ea288
    if (B->flags.s.NeedsError)							return 1;
Packit 5ea288
	if (g_pmSweepData.pmFlags & STL_PM_PROCESS_VL_COUNTERS) {
Packit 5ea288
        // Second Level Compare: numVLs -> Decending
Packit 5ea288
        if (A->NumVLs < B->NumVLs) return 1;
Packit 5ea288
        if (A->NumVLs > B->NumVLs) return -1;
Packit 5ea288
Packit 5ea288
		// Third Level Compare: VLSelectMask -> Ascending
Packit 5ea288
        if (A->VLSelectMask < B->VLSelectMask) return -1;
Packit 5ea288
        if (A->VLSelectMask > B->VLSelectMask) return 1;
Packit 5ea288
    }
Packit 5ea288
    return 0;
Packit 5ea288
}	// End of PmDispatcherSwitchPortErrorCompare()
Packit 5ea288
Packit 5ea288
// Compare function used by qsort() to sort active ports for clear counters
Packit 5ea288
// return n < 0 for a < b   
Packit 5ea288
//        n = 0 for a == b  
Packit 5ea288
//        n > 0 for a > b   
Packit 5ea288
int PmDispatcherSwitchPortClearCompare(const void *a, const void *b)
Packit 5ea288
{
Packit 5ea288
	// First Level Compare: NULL check -> Decending 
Packit 5ea288
	PmDispatcherSwitchPort_t *A = (PmDispatcherSwitchPort_t *)a;
Packit 5ea288
	PmDispatcherSwitchPort_t *B = (PmDispatcherSwitchPort_t *)b;
Packit 5ea288
    
Packit 5ea288
	if (A->flags.s.Skip && B->flags.s.Skip)					return 0;
Packit 5ea288
	if (A->flags.s.Skip)									return 1;
Packit 5ea288
	if (B->flags.s.Skip)                                  return -1;
Packit 5ea288
	if (A->flags.s.NeedsClear && B->flags.s.NeedsClear)		return 0;
Packit 5ea288
    if (A->flags.s.NeedsClear)							return -1;
Packit 5ea288
    if (B->flags.s.NeedsClear)							return 1;
Packit 5ea288
Packit 5ea288
    return 0;
Packit 5ea288
}	// End of PmDispatcherSwitchPortClearCompare()
Packit 5ea288
int PmDispatcherSwitchPortErrorInfoCompare(const void *a, const void *b)
Packit 5ea288
{
Packit 5ea288
	// First Level Compare: NULL check -> Decending
Packit 5ea288
	PmDispatcherSwitchPort_t *A = (PmDispatcherSwitchPort_t *)a;
Packit 5ea288
	PmDispatcherSwitchPort_t *B = (PmDispatcherSwitchPort_t *)b;
Packit 5ea288
Packit 5ea288
	if (A->flags.s.Skip && B->flags.s.Skip)                     return 0;
Packit 5ea288
	if (A->flags.s.Skip)                                        return 1;
Packit 5ea288
	if (B->flags.s.Skip)                                        return -1;
Packit 5ea288
	if (A->flags.s.NeedsErrorInfo && B->flags.s.NeedsErrorInfo) return 0;
Packit 5ea288
	if (A->flags.s.NeedsErrorInfo)                              return -1;
Packit 5ea288
	if (B->flags.s.NeedsErrorInfo)                              return 1;
Packit 5ea288
Packit 5ea288
    return 0;
Packit 5ea288
}	// End of PmDispatcherSwitchPortErrorInfoCompare()
Packit 5ea288
int PmDispatcherSwitchPortErrorInfoClearCompare(const void *a, const void *b)
Packit 5ea288
{
Packit 5ea288
	// First Level Compare: NULL check -> Decending
Packit 5ea288
	PmDispatcherSwitchPort_t *A = (PmDispatcherSwitchPort_t *)a;
Packit 5ea288
	PmDispatcherSwitchPort_t *B = (PmDispatcherSwitchPort_t *)b;
Packit 5ea288
Packit 5ea288
	if (A->flags.s.Skip && B->flags.s.Skip)                           return 0;
Packit 5ea288
	if (A->flags.s.Skip)                                              return 1;
Packit 5ea288
	if (B->flags.s.Skip)                                              return -1;
Packit 5ea288
	if (A->flags.s.NeedsClearErrorInfo && B->flags.s.NeedsClearErrorInfo) return 0;
Packit 5ea288
	if (A->flags.s.NeedsClearErrorInfo)                               return -1;
Packit 5ea288
	if (B->flags.s.NeedsClearErrorInfo)                               return 1;
Packit 5ea288
Packit 5ea288
    return 0;
Packit 5ea288
}	// End of PmDispatcherSwitchPortErrorInfoClearCompare()
Packit 5ea288
Packit 5ea288
// Compare function used by qsort() to sort DispPorts array in disppacket struct
Packit 5ea288
// return n < 0 for a < b
Packit 5ea288
//        n = 0 for a == b
Packit 5ea288
//        n > 0 for a > b
Packit 5ea288
int PmDispatcherPortNumCompare(const void *a, const void *b)
Packit 5ea288
{
Packit 5ea288
	// First Level Compare: NULL check -> Decending
Packit 5ea288
	PmDispatcherPort_t *A = (PmDispatcherPort_t *)a;
Packit 5ea288
	PmDispatcherPort_t *B = (PmDispatcherPort_t *)b;
Packit 5ea288
Packit 5ea288
	return (A->pmportp->portNum - B->pmportp->portNum);
Packit 5ea288
}	// End of PmDispatcherPortNumCompare()
Packit 5ea288
Packit 5ea288
// start processing of a node
Packit 5ea288
// returns OK if a node was dispatched, returns NOT_FOUND if none dispatched
Packit 5ea288
static Status_t DispatchNode(Pm_t *pm, PmNode_t *pmnodep, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid);
Packit 5ea288
Packit 5ea288
	memset(&dispnode->info, 0, sizeof(dispnode->info));
Packit 5ea288
	dispnode->info.pmnodep = pmnodep;
Packit 5ea288
	dispnode->info.numPorts = ((pmnodep->nodeType == STL_NODE_SW) ? pmnodep->numPorts + 1 : 1);
Packit 5ea288
	pm->Dispatcher.numOutstandingNodes++;
Packit 5ea288
	return DispatchNodeNextStep(pm, pmnodep, dispnode);
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// Continue processing of a node, use when 1st start processing and on
Packit 5ea288
// callbacks to advance to next state/operation on the node
Packit 5ea288
// return:
Packit 5ea288
// 	OK - next packet inflight
Packit 5ea288
// 	VSTATUS_NOT_FOUND - no more work needed/possible, NodeDone called
Packit 5ea288
static Status_t DispatchNodeNextStep(Pm_t *pm, PmNode_t *pmnodep, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	uint8 ret;
Packit 5ea288
	int i, j;
Packit 5ea288
	size_t size;
Packit 5ea288
	Status_t status;
Packit 5ea288
    uint32 VlSelectMask;
Packit 5ea288
	uint32 clearCounterSelect;
Packit 5ea288
	PmPort_t *pmportp;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x NodeState %u",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, dispnode->info.state);
Packit 5ea288
Packit 5ea288
	switch (dispnode->info.state) {
Packit 5ea288
	case PM_DISP_NODE_NONE:
Packit 5ea288
		if (! pmnodep->u.s.PmaGotClassPortInfo) {
Packit 5ea288
			dispnode->info.state = PM_DISP_NODE_CLASS_INFO;
Packit 5ea288
			return PmSendGetClassPortInfo(pm, dispnode);
Packit 5ea288
		}
Packit 5ea288
	case PM_DISP_NODE_CLASS_INFO:
Packit 5ea288
		dispnode->info.state = PM_DISP_NODE_GET_DATACOUNTERS;
Packit 5ea288
        // Allocate activePorts[]
Packit 5ea288
		size = sizeof(PmDispatcherSwitchPort_t) * dispnode->info.numPorts;
Packit 5ea288
Packit 5ea288
        status = vs_pool_alloc(&pm_pool, size, (void *)&dispnode->info.activePorts);
Packit 5ea288
        if (status != VSTATUS_OK || !dispnode->info.activePorts) {
Packit 5ea288
            IB_LOG_ERROR_FMT(__func__, "PM: Failed to allocate Dispatcher activePorts for Node:%.*s status:%u",
Packit 5ea288
                (int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString, status);
Packit 5ea288
            return VSTATUS_NOT_FOUND;
Packit 5ea288
        }
Packit 5ea288
        memset(dispnode->info.activePorts, 0, size);
Packit 5ea288
 
Packit 5ea288
		// Initialize activePorts[] for DataPortCounters
Packit 5ea288
		for (i = 0; i < dispnode->info.numPorts; i++) { 
Packit 5ea288
Packit 5ea288
			if (pmnodep->nodeType == STL_NODE_SW) {
Packit 5ea288
				pmportp = pmnodep->up.swPorts[i];
Packit 5ea288
			} else {
Packit 5ea288
				pmportp = pmnodep->up.caPortp;
Packit 5ea288
			}
Packit 5ea288
			if ( !(pmportp) || !(pmportp->Image[pm->SweepIndex].u.s.active) /* || !(pmportp->u.s.PmaAvoid) */) {
Packit 5ea288
				
Packit 5ea288
				dispnode->info.activePorts[i].portNum = 0xFF;
Packit 5ea288
				dispnode->info.activePorts[i].flags.s.Skip = 1;
Packit 5ea288
				continue;
Packit 5ea288
			}
Packit 5ea288
			dispnode->info.activePorts[i].portNum = pmportp->portNum;
Packit 5ea288
			dispnode->info.activePorts[i].flags.AsReg8 = 0;
Packit 5ea288
Packit 5ea288
			if (pm->pmFlags & STL_PM_PROCESS_VL_COUNTERS) {
Packit 5ea288
				dispnode->info.activePorts[i].VLSelectMask = pmportp->Image[pm->SweepIndex].vlSelectMask;
Packit 5ea288
				for ( j = 0, VlSelectMask = dispnode->info.activePorts[i].VLSelectMask;
Packit 5ea288
						j < STL_MAX_VLS; j++, VlSelectMask >>= 1 ) 
Packit 5ea288
					if (VlSelectMask & 0x1)
Packit 5ea288
						dispnode->info.activePorts[i].NumVLs++;
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
Packit 5ea288
		dispnode->info.nextPort = dispnode->info.activePorts;
Packit 5ea288
        
Packit 5ea288
		// Sort activePorts[], ordering by number of VLs and VLSelectMask;
Packit 5ea288
		//  shift non-active ports to the end
Packit 5ea288
		if (dispnode->info.numPorts > 1) {
Packit 5ea288
			qsort( dispnode->info.activePorts, (size_t)dispnode->info.numPorts,
Packit 5ea288
				sizeof(PmDispatcherSwitchPort_t), PmDispatcherSwitchPortDataCompare );
Packit 5ea288
		}
Packit 5ea288
Packit 5ea288
		for (i = 0; i < dispnode->info.numPorts; i++) {
Packit 5ea288
			IB_LOG_DEBUG4_FMT( __func__,"%.*s Post-qsort: activePorts[%d]: numVLs %u portNum %u flags 0x%02x VLSelect 0x%08x",
Packit 5ea288
				(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString, i,
Packit 5ea288
				dispnode->info.activePorts[i].NumVLs, dispnode->info.activePorts[i].portNum, 
Packit 5ea288
				dispnode->info.activePorts[i].flags.AsReg8, dispnode->info.activePorts[i].VLSelectMask);
Packit 5ea288
		}
Packit 5ea288
        
Packit 5ea288
		ret = DispatcherStartSweepAllPorts(pm, dispnode);
Packit 5ea288
Packit 5ea288
		if (ret)
Packit 5ea288
			return VSTATUS_OK;
Packit 5ea288
		// fallthrough, no ports with packets inflight
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_GET_DATACOUNTERS:
Packit 5ea288
Packit 5ea288
		if (pmnodep->nodeType == STL_NODE_SW) {
Packit 5ea288
			if (dispnode->info.u.s.needError) {
Packit 5ea288
				dispnode->info.state = PM_DISP_NODE_GET_ERRORCOUNTERS;
Packit 5ea288
				// Initialize activePorts[] for ErrorPortCounters
Packit 5ea288
				if (!dispnode->info.activePorts) {
Packit 5ea288
					IB_LOG_ERROR_FMT(__func__, "PM: No Dispatcher activePorts for Node: %.*s",
Packit 5ea288
						(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString);
Packit 5ea288
					return VSTATUS_NOT_FOUND;
Packit 5ea288
				}
Packit 5ea288
				// Sort activePorts[], ordering by number of VLs and VLSelectMask;
Packit 5ea288
				//  shift non-active ports and ports not needing error counters query to the end
Packit 5ea288
				if (dispnode->info.numPorts > 1) {
Packit 5ea288
					qsort( dispnode->info.activePorts, (size_t)dispnode->info.numPorts,
Packit 5ea288
						   sizeof(PmDispatcherSwitchPort_t), PmDispatcherSwitchPortErrorCompare );
Packit 5ea288
				}
Packit 5ea288
				for (i = 0; i < dispnode->info.numPorts && dispnode->info.activePorts[i].flags.s.NeedsError; i++) {
Packit 5ea288
					dispnode->info.activePorts[i].flags.s.IsDispatched = 0;
Packit 5ea288
				}
Packit 5ea288
				ret = DispatcherStartSweepAllPorts(pm, dispnode);
Packit 5ea288
Packit 5ea288
				if (ret)
Packit 5ea288
					return VSTATUS_OK;
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
		// fallthrough, no ports with packets inflight
Packit 5ea288
		
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORCOUNTERS:
Packit 5ea288
		// Tabulate ports and collect information on needed clears
Packit 5ea288
		dispnode->info.u.s.needClearSome = 0;
Packit 5ea288
		dispnode->info.u.s.canClearAll = 1;
Packit 5ea288
		dispnode->info.clearCounterSelect = clearCounterSelect = 0;
Packit 5ea288
		for (i = 0; i < dispnode->info.numPorts && !dispnode->info.activePorts[i].flags.s.Skip; i++) {
Packit 5ea288
			if (pmnodep->nodeType == STL_NODE_SW) {
Packit 5ea288
				pmportp = pmnodep->up.swPorts[dispnode->info.activePorts[i].portNum];
Packit 5ea288
			} else {
Packit 5ea288
				pmportp = pmnodep->up.caPortp;
Packit 5ea288
			}
Packit 5ea288
			
Packit 5ea288
			if (PmTabulatePort(pm, pmportp, pm->SweepIndex, &clearCounterSelect)) {
Packit 5ea288
				if (dispnode->info.clearCounterSelect && (clearCounterSelect != dispnode->info.clearCounterSelect))
Packit 5ea288
					dispnode->info.u.s.canClearAll = 0;
Packit 5ea288
Packit 5ea288
				dispnode->info.activePorts[i].flags.s.NeedsClear = 1;
Packit 5ea288
				dispnode->info.u.s.needClearSome = 1;
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
Packit 5ea288
		if (dispnode->info.u.s.needClearSome) {
Packit 5ea288
			dispnode->info.state = PM_DISP_NODE_CLR_PORT_STATUS;
Packit 5ea288
			// Initialize activePorts[] for ClearPortCounters
Packit 5ea288
			if (!dispnode->info.activePorts) {
Packit 5ea288
				IB_LOG_ERROR_FMT(__func__, "PM: No Dispatcher activePorts for Node: %.*s",
Packit 5ea288
					(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString);
Packit 5ea288
				return VSTATUS_NOT_FOUND;
Packit 5ea288
			}
Packit 5ea288
			// Sort activePorts[]
Packit 5ea288
			//  shift non-active ports and ports not needing clear to the end
Packit 5ea288
			if (dispnode->info.numPorts > 1) {
Packit 5ea288
				qsort( dispnode->info.activePorts, (size_t)dispnode->info.numPorts,
Packit 5ea288
					   sizeof(PmDispatcherSwitchPort_t), PmDispatcherSwitchPortClearCompare );
Packit 5ea288
			}
Packit 5ea288
			for (i = 0; i < dispnode->info.numPorts && dispnode->info.activePorts[i].flags.s.NeedsClear; i++) {
Packit 5ea288
				dispnode->info.activePorts[i].flags.s.IsDispatched = 0;
Packit 5ea288
			}
Packit 5ea288
			ret = DispatcherStartSweepAllPorts(pm, dispnode);
Packit 5ea288
				
Packit 5ea288
			if (ret)
Packit 5ea288
				return VSTATUS_OK;
Packit 5ea288
		}
Packit 5ea288
		// fallthrough, no ports with packets inflight
Packit 5ea288
	case PM_DISP_NODE_CLR_PORT_STATUS:
Packit 5ea288
		if (dispnode->info.u.s.needErrorInfo) {
Packit 5ea288
			dispnode->info.state = PM_DISP_NODE_GET_ERRORINFO;
Packit 5ea288
			if (!dispnode->info.activePorts) {
Packit 5ea288
				IB_LOG_ERROR_FMT(__func__, "PM: No Dispatcher activePorts for Node: %.*s",
Packit 5ea288
					(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString);
Packit 5ea288
				return VSTATUS_NOT_FOUND;
Packit 5ea288
			}
Packit 5ea288
			// Sort activePorts[]
Packit 5ea288
			//  shift non-active ports and ports not needing clear to the end
Packit 5ea288
			if (dispnode->info.numPorts > 1) {
Packit 5ea288
				qsort( dispnode->info.activePorts, (size_t)dispnode->info.numPorts,
Packit 5ea288
					   sizeof(PmDispatcherSwitchPort_t), PmDispatcherSwitchPortErrorInfoCompare );
Packit 5ea288
			}
Packit 5ea288
			for (i = 0; i < dispnode->info.numPorts && dispnode->info.activePorts[i].flags.s.NeedsErrorInfo; i++) {
Packit 5ea288
				dispnode->info.activePorts[i].flags.s.IsDispatched = 0;
Packit 5ea288
			}
Packit 5ea288
			ret = DispatcherStartSweepAllPorts(pm, dispnode);
Packit 5ea288
Packit 5ea288
			if (ret)
Packit 5ea288
				return VSTATUS_OK;
Packit 5ea288
		}
Packit 5ea288
		// fallthrough, no ports with packets inflight
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORINFO:
Packit 5ea288
		if (dispnode->info.u.s.needClearErrorInfo) {
Packit 5ea288
			dispnode->info.state = PM_DISP_NODE_CLR_ERRORINFO;
Packit 5ea288
			if (!dispnode->info.activePorts) {
Packit 5ea288
				IB_LOG_ERROR_FMT(__func__, "PM: No Dispatcher activePorts for Node: %.*s",
Packit 5ea288
					(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString);
Packit 5ea288
				return VSTATUS_NOT_FOUND;
Packit 5ea288
			}
Packit 5ea288
			// Sort activePorts[]
Packit 5ea288
			//  shift non-active ports and ports not needing clear to the end
Packit 5ea288
			if (dispnode->info.numPorts > 1) {
Packit 5ea288
				qsort( dispnode->info.activePorts, (size_t)dispnode->info.numPorts,
Packit 5ea288
					   sizeof(PmDispatcherSwitchPort_t), PmDispatcherSwitchPortErrorInfoClearCompare );
Packit 5ea288
			}
Packit 5ea288
			for (i = 0; i < dispnode->info.numPorts && dispnode->info.activePorts[i].flags.s.NeedsClearErrorInfo; i++) {
Packit 5ea288
				dispnode->info.activePorts[i].flags.s.IsDispatched = 0;
Packit 5ea288
			}
Packit 5ea288
			ret = DispatcherStartSweepAllPorts(pm, dispnode);
Packit 5ea288
Packit 5ea288
			if (ret)
Packit 5ea288
				return VSTATUS_OK;
Packit 5ea288
		}
Packit 5ea288
		// fallthrough, no ports with packets inflight
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_CLR_ERRORINFO:
Packit 5ea288
		DispatchNodeDone(pm, dispnode);
Packit 5ea288
		return VSTATUS_NOT_FOUND;
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_DONE:
Packit 5ea288
		DEBUG_ASSERT(0);	// unexpected state
Packit 5ea288
		return VSTATUS_NOT_FOUND;	// nothing else to do for this node
Packit 5ea288
Packit 5ea288
	default:
Packit 5ea288
		DEBUG_ASSERT(0);	// unexpected state
Packit 5ea288
		DispatchNodeDone(pm, dispnode);
Packit 5ea288
		return VSTATUS_NOT_FOUND;
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
}	// End of DispatchNodeNextStep()
Packit 5ea288
Packit 5ea288
// returns number of ports with packets in flight
Packit 5ea288
// if 0 then caller need not wait, no packets in flight
Packit 5ea288
static uint8 DispatcherStartSweepAllPorts(Pm_t *pm, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	uint8 slot;
Packit 5ea288
	Status_t status;
Packit 5ea288
#ifndef VIEO_TRACE_DISABLED
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x NodeState %u",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, dispnode->info.state);
Packit 5ea288
#endif
Packit 5ea288
Packit 5ea288
    for (slot = 0; slot < pm_config.PmaBatchSize; ) {
Packit 5ea288
	// reset numVLs back to 0 in case it has changed since the last PM sweep
Packit 5ea288
	dispnode->DispPackets[slot].numVLs = 0;
Packit 5ea288
        status = DispatchNextPacket(pm, dispnode, &dispnode->DispPackets[slot]);
Packit 5ea288
		switch (status) {
Packit 5ea288
		case VSTATUS_OK:
Packit 5ea288
            slot++;
Packit 5ea288
			continue;
Packit 5ea288
		case VSTATUS_NOPORT:
Packit 5ea288
			return slot;
Packit 5ea288
		case VSTATUS_NOT_FOUND:
Packit 5ea288
			break;
Packit 5ea288
		default:
Packit 5ea288
			IB_LOG_ERROR_FMT(__func__, "PM: Unknown Return Status (%u) from DispatchNextPacket() Node:%.*s", status,
Packit 5ea288
				(int)sizeof(dispnode->info.pmnodep->nodeDesc.NodeString), dispnode->info.pmnodep->nodeDesc.NodeString);
Packit 5ea288
		}
Packit 5ea288
    }
Packit 5ea288
Packit 5ea288
	return slot;
Packit 5ea288
Packit 5ea288
}	// End of DispatcherStartSweepAllPorts()
Packit 5ea288
Packit 5ea288
// returns OK if a packet was dispatched, returns NOT_FOUND if none dispatched
Packit 5ea288
static Status_t DispatchNextPacket(Pm_t *pm, PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
    PmPort_t *pmportp;
Packit 5ea288
Packit 5ea288
	if (pm_shutdown || g_pmEngineState != PM_ENGINE_STARTED) {
Packit 5ea288
		IB_LOG_INFO0("PM Engine shut down requested");
Packit 5ea288
		dispnode->info.u.s.needClearSome = FALSE;
Packit 5ea288
		goto abort;
Packit 5ea288
	}
Packit 5ea288
      
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x Node State %u",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, dispnode->info.state);
Packit 5ea288
Packit 5ea288
	dispnode->info.nextPort = dispnode->info.activePorts; //reset pointer to the top to grab and skipped over ports
Packit 5ea288
Packit 5ea288
	while ( dispnode->info.nextPort->flags.s.Skip != 1 ) {
Packit 5ea288
		if (pmnodep->nodeType == STL_NODE_SW)
Packit 5ea288
			pmportp = pmnodep->up.swPorts[dispnode->info.nextPort->portNum];
Packit 5ea288
		else
Packit 5ea288
			pmportp = pmnodep->up.caPortp;
Packit 5ea288
Packit 5ea288
		//FIXME: ACG - Should this be added to parent function like above and removed?
Packit 5ea288
		// Commented out because it will cause Inf loop when true.
Packit 5ea288
		// I am not removing this code, because It may be usefull when multiport queries fail.
Packit 5ea288
		//if (pmportp->Image[pm->SweepIndex].u.s.queryStatus != PM_QUERY_STATUS_OK) 
Packit 5ea288
		//	continue;
Packit 5ea288
        
Packit 5ea288
		switch(MergePortIntoPacket(pm, dispnode, pmportp, disppacket))
Packit 5ea288
        {
Packit 5ea288
		case PM_DISP_SW_MERGE_NOMERGE:
Packit 5ea288
			if (disppacket->numPorts == 0) {
Packit 5ea288
				if (dispnode->info.nextPort != &dispnode->info.activePorts[dispnode->info.numPorts-1]) {
Packit 5ea288
					dispnode->info.nextPort++;
Packit 5ea288
					continue;
Packit 5ea288
				}
Packit 5ea288
				else goto doneNode;
Packit 5ea288
Packit 5ea288
			}
Packit 5ea288
        case PM_DISP_SW_MERGE_CONTINUE:
Packit 5ea288
			if (dispnode->info.nextPort != &dispnode->info.activePorts[dispnode->info.numPorts-1]) {
Packit 5ea288
				dispnode->info.nextPort++;
Packit 5ea288
				continue;
Packit 5ea288
			}
Packit 5ea288
		case PM_DISP_SW_MERGE_DONE:
Packit 5ea288
			if (VSTATUS_OK == DispatchPacketNextStep(pm, dispnode, disppacket))
Packit 5ea288
                return VSTATUS_OK;
Packit 5ea288
            goto abort; 
Packit 5ea288
        case PM_DISP_SW_MERGE_ERROR:
Packit 5ea288
				IB_LOG_ERROR_FMT( __func__,"PM: MergePortIntoPacket() Failure" );
Packit 5ea288
            goto abort;   
Packit 5ea288
        default:
Packit 5ea288
            goto abort;
Packit 5ea288
        }
Packit 5ea288
	} // End of While()
Packit 5ea288
	
Packit 5ea288
	if (disppacket->numPorts) {
Packit 5ea288
		if (VSTATUS_OK == DispatchPacketNextStep(pm, dispnode, disppacket))
Packit 5ea288
                return VSTATUS_OK;
Packit 5ea288
	}
Packit 5ea288
doneNode:
Packit 5ea288
	return VSTATUS_NOPORT;
Packit 5ea288
abort:
Packit 5ea288
	return VSTATUS_NOT_FOUND;
Packit 5ea288
}
Packit 5ea288
int MergePortIntoPacket(Pm_t *pm, PmDispatcherNode_t *dispnode, PmPort_t *pmportp, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
                           // TOTAL - (SM LID-Routed packet header + Mkey) = PM PAYLOAD = 2024
Packit 5ea288
    size_t sizeRemaining = STL_MAX_PAYLOAD_SMP_LR + sizeof(uint64); 
Packit 5ea288
    size_t sizePortInMad;
Packit 5ea288
	Status_t status;
Packit 5ea288
	PmPort_t *pmFirstPort;
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x Node State %u PortSelectMask[3] "FMT_U64" ",
Packit 5ea288
		(int)sizeof(dispnode->info.pmnodep->nodeDesc.NodeString), dispnode->info.pmnodep->nodeDesc.NodeString,
Packit 5ea288
		dispnode->info.pmnodep->NodeGUID, dispnode->info.pmnodep->dlid,
Packit 5ea288
		dispnode->info.state, disppacket->PortSelectMask[3]);
Packit 5ea288
Packit 5ea288
    switch (dispnode->info.state) {
Packit 5ea288
	case PM_DISP_NODE_GET_DATACOUNTERS:
Packit 5ea288
		if (dispnode->info.pmnodep->nodeType == STL_NODE_SW) {
Packit 5ea288
			{
Packit 5ea288
				sizeRemaining -= (sizeof(STL_DATA_PORT_COUNTERS_RSP) - sizeof(struct _port_dpctrs));
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
        break;
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORCOUNTERS:
Packit 5ea288
		{
Packit 5ea288
			sizeRemaining -= (sizeof(STL_ERROR_PORT_COUNTERS_RSP) - sizeof(struct _port_epctrs));
Packit 5ea288
		}
Packit 5ea288
        break;
Packit 5ea288
	case PM_DISP_NODE_CLR_PORT_STATUS:
Packit 5ea288
		sizeRemaining -= sizeof(STL_CLEAR_PORT_STATUS);
Packit 5ea288
        break;
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORINFO:
Packit 5ea288
		sizeRemaining -= (sizeof(STL_ERROR_INFO_RSP) - sizeof(struct _port_error_info));
Packit 5ea288
        break;
Packit 5ea288
	case PM_DISP_NODE_CLR_ERRORINFO:
Packit 5ea288
		sizeRemaining -= sizeof(STL_ERROR_INFO_RSP);
Packit 5ea288
        break;
Packit 5ea288
	default:
Packit 5ea288
        //LOG ERROR 
Packit 5ea288
        return PM_DISP_SW_MERGE_ERROR;
Packit 5ea288
    }
Packit 5ea288
Packit 5ea288
    sizePortInMad = CalculatePortInPacket(dispnode, disppacket);
Packit 5ea288
    if(sizePortInMad == (size_t)(-1)) 
Packit 5ea288
        return PM_DISP_SW_MERGE_ERROR;  
Packit 5ea288
    
Packit 5ea288
	if (disppacket->numPorts == 0) {
Packit 5ea288
		switch (dispnode->info.state) {
Packit 5ea288
		case PM_DISP_NODE_GET_DATACOUNTERS:
Packit 5ea288
			if (dispnode->info.pmnodep->nodeType == STL_NODE_SW) 
Packit 5ea288
				status = vs_pool_alloc(&pm_pool, sizeof(PmDispatcherPort_t) * (sizeRemaining/sizePortInMad), (void *)&disppacket->DispPorts);
Packit 5ea288
			else
Packit 5ea288
				status = vs_pool_alloc(&pm_pool, sizeof(PmDispatcherPort_t), (void *)&disppacket->DispPorts);
Packit 5ea288
			break;
Packit 5ea288
		case PM_DISP_NODE_GET_ERRORCOUNTERS:
Packit 5ea288
			status = vs_pool_alloc(&pm_pool, sizeof(PmDispatcherPort_t) * (sizeRemaining/sizePortInMad), (void *)&disppacket->DispPorts);
Packit 5ea288
			break;
Packit 5ea288
		case PM_DISP_NODE_CLR_PORT_STATUS:
Packit 5ea288
			status = vs_pool_alloc(&pm_pool, sizeof(PmDispatcherPort_t), (void *)&disppacket->DispPorts);
Packit 5ea288
			break;
Packit 5ea288
		case PM_DISP_NODE_GET_ERRORINFO:
Packit 5ea288
			status = vs_pool_alloc(&pm_pool, sizeof(PmDispatcherPort_t) * (sizeRemaining/sizePortInMad), (void *)&disppacket->DispPorts);
Packit 5ea288
			break;
Packit 5ea288
		case PM_DISP_NODE_CLR_ERRORINFO:
Packit 5ea288
			status = vs_pool_alloc(&pm_pool, sizeof(PmDispatcherPort_t), (void *)&disppacket->DispPorts);
Packit 5ea288
			break;
Packit 5ea288
		default:
Packit 5ea288
			return PM_DISP_SW_MERGE_ERROR;
Packit 5ea288
		}
Packit 5ea288
		if (status != VSTATUS_OK) {
Packit 5ea288
			return PM_DISP_SW_MERGE_ERROR;
Packit 5ea288
		}
Packit 5ea288
	}
Packit 5ea288
    sizeRemaining -= sizePortInMad * disppacket->numPorts;
Packit 5ea288
    
Packit 5ea288
    // Check if packet is complete;
Packit 5ea288
    if (sizeRemaining > sizePortInMad) {                                                
Packit 5ea288
        // Check if port was already dispatched
Packit 5ea288
        if (dispnode->info.nextPort->flags.s.IsDispatched)
Packit 5ea288
			goto nomerge;
Packit 5ea288
        //-Check if port is marked as DoNotMerge
Packit 5ea288
        if (dispnode->info.nextPort->flags.s.DoNotMerge) {                          
Packit 5ea288
            //--if Packet is not empty skip this port.  
Packit 5ea288
            disppacket->DispPorts[0].pmportp = pmportp;
Packit 5ea288
            disppacket->DispPorts[0].dispNodeSwPort = dispnode->info.nextPort;
Packit 5ea288
            disppacket->DispPorts[0].dispnode = dispnode;
Packit 5ea288
            disppacket->DispPorts[0].pPortImage = &pmportp->Image[pm->SweepIndex];
Packit 5ea288
			disppacket->DispPorts[0].pPortImagePrev =
Packit 5ea288
				(pm->LastSweepIndex != PM_IMAGE_INDEX_INVALID ? &pmportp->Image[pm->LastSweepIndex] : NULL);
Packit 5ea288
            disppacket->DispPorts[0].dispNodeSwPort->flags.s.IsDispatched = 1;
Packit 5ea288
            disppacket->numPorts = 1;
Packit 5ea288
            setPortSelectMask(disppacket->PortSelectMask, pmportp->portNum, TRUE);
Packit 5ea288
            disppacket->VLSelectMask = dispnode->info.nextPort->VLSelectMask;
Packit 5ea288
            //--if packet is empty copy single packet and mark packet as full
Packit 5ea288
Packit 5ea288
            return PM_DISP_SW_MERGE_DONE;              
Packit 5ea288
        }  
Packit 5ea288
		if (disppacket->numPorts) {
Packit 5ea288
			if (dispnode->info.state == PM_DISP_NODE_CLR_PORT_STATUS) {
Packit 5ea288
				pmFirstPort = disppacket->DispPorts[0].pmportp;
Packit 5ea288
				if (pmportp->Image[pm->SweepIndex].clearSelectMask.AsReg32 ==
Packit 5ea288
						pmFirstPort->Image[pm->SweepIndex].clearSelectMask.AsReg32) {
Packit 5ea288
					disppacket->numPorts++;
Packit 5ea288
					setPortSelectMask(disppacket->PortSelectMask, pmportp->portNum, FALSE);
Packit 5ea288
					dispnode->info.nextPort->flags.s.IsDispatched = 1;
Packit 5ea288
				} else return PM_DISP_SW_MERGE_NOMERGE;
Packit 5ea288
			} else if (dispnode->info.state == PM_DISP_NODE_CLR_ERRORINFO) {
Packit 5ea288
				disppacket->numPorts++;
Packit 5ea288
				setPortSelectMask(disppacket->PortSelectMask, pmportp->portNum, FALSE);
Packit 5ea288
				dispnode->info.nextPort->flags.s.IsDispatched = 1;
Packit 5ea288
			} else if (dispnode->info.state == PM_DISP_NODE_GET_ERRORINFO) {
Packit 5ea288
				disppacket->DispPorts[disppacket->numPorts].pmportp = pmportp;
Packit 5ea288
				disppacket->DispPorts[disppacket->numPorts].dispNodeSwPort = dispnode->info.nextPort;
Packit 5ea288
				disppacket->DispPorts[disppacket->numPorts].dispnode = dispnode;
Packit 5ea288
				disppacket->DispPorts[disppacket->numPorts].pPortImage = &pmportp->Image[pm->SweepIndex];
Packit 5ea288
				disppacket->DispPorts[disppacket->numPorts].pPortImagePrev =
Packit 5ea288
					(pm->LastSweepIndex != PM_IMAGE_INDEX_INVALID ? &pmportp->Image[pm->LastSweepIndex] : NULL);
Packit 5ea288
				disppacket->DispPorts[disppacket->numPorts].dispNodeSwPort->flags.s.IsDispatched = 1;
Packit 5ea288
				disppacket->numPorts++;
Packit 5ea288
				setPortSelectMask(disppacket->PortSelectMask, pmportp->portNum, FALSE);
Packit 5ea288
			} else {
Packit 5ea288
				//check to make sure port can be combined into packet. check for similar VL Mask.
Packit 5ea288
				if ((dispnode->info.nextPort->VLSelectMask | disppacket->VLSelectMask)
Packit 5ea288
					== disppacket->VLSelectMask) {
Packit 5ea288
					disppacket->DispPorts[disppacket->numPorts].pmportp = pmportp;
Packit 5ea288
					disppacket->DispPorts[disppacket->numPorts].dispNodeSwPort = dispnode->info.nextPort;
Packit 5ea288
					disppacket->DispPorts[disppacket->numPorts].dispnode = dispnode;
Packit 5ea288
					disppacket->DispPorts[disppacket->numPorts].pPortImage = &pmportp->Image[pm->SweepIndex];
Packit 5ea288
					disppacket->DispPorts[disppacket->numPorts].pPortImagePrev =
Packit 5ea288
						(pm->LastSweepIndex != PM_IMAGE_INDEX_INVALID ? &pmportp->Image[pm->LastSweepIndex] : NULL);
Packit 5ea288
					disppacket->DispPorts[disppacket->numPorts].dispNodeSwPort->flags.s.IsDispatched = 1;
Packit 5ea288
					disppacket->numPorts++;
Packit 5ea288
					setPortSelectMask(disppacket->PortSelectMask, pmportp->portNum, FALSE);
Packit 5ea288
				} else return PM_DISP_SW_MERGE_NOMERGE;
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
        else {
Packit 5ea288
            disppacket->DispPorts[0].pmportp = pmportp;
Packit 5ea288
            disppacket->DispPorts[0].dispNodeSwPort = dispnode->info.nextPort;
Packit 5ea288
            disppacket->DispPorts[0].dispnode = dispnode;
Packit 5ea288
            disppacket->DispPorts[0].pPortImage = &pmportp->Image[pm->SweepIndex];
Packit 5ea288
			disppacket->DispPorts[0].pPortImagePrev =
Packit 5ea288
				(pm->LastSweepIndex != PM_IMAGE_INDEX_INVALID ? &pmportp->Image[pm->LastSweepIndex] : NULL);
Packit 5ea288
            disppacket->DispPorts[0].dispNodeSwPort->flags.s.IsDispatched = 1;
Packit 5ea288
            disppacket->numPorts = 1;
Packit 5ea288
			setPortSelectMask(disppacket->PortSelectMask, pmportp->portNum, TRUE);
Packit 5ea288
			disppacket->VLSelectMask = dispnode->info.nextPort->VLSelectMask;
Packit 5ea288
        }
Packit 5ea288
        return PM_DISP_SW_MERGE_CONTINUE; 
Packit 5ea288
    }
Packit 5ea288
    else return PM_DISP_SW_MERGE_DONE;
Packit 5ea288
Packit 5ea288
    return PM_DISP_SW_MERGE_ERROR; //-Sanity Check
Packit 5ea288
Packit 5ea288
nomerge:
Packit 5ea288
	if (disppacket->DispPorts && !disppacket->numPorts) {
Packit 5ea288
		vs_pool_free(&pm_pool, disppacket->DispPorts);
Packit 5ea288
		disppacket->DispPorts = NULL;
Packit 5ea288
	}
Packit 5ea288
	return PM_DISP_SW_MERGE_NOMERGE;
Packit 5ea288
Packit 5ea288
}	// End of MergePortIntoPacket()
Packit 5ea288
Packit 5ea288
size_t CalculatePortInPacket(PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	uint8   NumVLs = 0;
Packit 5ea288
Packit 5ea288
	switch (dispnode->info.state) {
Packit 5ea288
	case PM_DISP_NODE_NONE:                      return(-1);
Packit 5ea288
	case PM_DISP_NODE_CLASS_INFO:                return(-1);
Packit 5ea288
	case PM_DISP_NODE_GET_DATACOUNTERS:
Packit 5ea288
		if (dispnode->pm->pmFlags & STL_PM_PROCESS_VL_COUNTERS) {
Packit 5ea288
			if (!disppacket->numPorts)		/* First port should set the numVLs */
Packit 5ea288
				disppacket->numVLs = dispnode->info.nextPort->NumVLs;
Packit 5ea288
			NumVLs = disppacket->numVLs;
Packit 5ea288
		}
Packit 5ea288
		if (dispnode->info.pmnodep->nodeType == STL_NODE_SW) {
Packit 5ea288
			{
Packit 5ea288
				return (sizeof(struct _port_dpctrs) + (NumVLs - 1) * sizeof(struct _vls_dpctrs));
Packit 5ea288
			}
Packit 5ea288
		} else {
Packit 5ea288
			{
Packit 5ea288
				return (sizeof(STL_PORT_STATUS_RSP) + (NumVLs - 1) * sizeof(struct _vls_pctrs));
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORCOUNTERS:
Packit 5ea288
		if (dispnode->pm->pmFlags & STL_PM_PROCESS_VL_COUNTERS) {
Packit 5ea288
			if (!disppacket->numPorts)		/* First port should set the numVLs */
Packit 5ea288
				disppacket->numVLs = dispnode->info.nextPort->NumVLs;
Packit 5ea288
			NumVLs = disppacket->numVLs;
Packit 5ea288
		}
Packit 5ea288
		{
Packit 5ea288
			return (sizeof(struct _port_epctrs) + (NumVLs - 1) * sizeof(struct _vls_epctrs));
Packit 5ea288
		}
Packit 5ea288
	case PM_DISP_NODE_CLR_PORT_STATUS:           return(0);
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORINFO:             return sizeof(struct _port_error_info);
Packit 5ea288
	case PM_DISP_NODE_CLR_ERRORINFO:             return(0);
Packit 5ea288
	case PM_DISP_NODE_DONE:                      return(-1);
Packit 5ea288
	}
Packit 5ea288
	return (-1);
Packit 5ea288
}
Packit 5ea288
static Status_t DispatchPacketNextStep(Pm_t *pm, PmDispatcherNode_t *dispnode, PmDispatcherPacket_t *disppacket)
Packit 5ea288
{
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x Node State %u PortSelectMask[3] "FMT_U64,
Packit 5ea288
		(int)sizeof(dispnode->info.pmnodep->nodeDesc.NodeString), dispnode->info.pmnodep->nodeDesc.NodeString,
Packit 5ea288
		dispnode->info.pmnodep->NodeGUID, dispnode->info.pmnodep->dlid,
Packit 5ea288
		dispnode->info.state, disppacket->PortSelectMask[3]);
Packit 5ea288
                
Packit 5ea288
    DEBUG_ASSERT(dispnode->info.state != PM_DISP_NODE_DONE);
Packit 5ea288
	if (dispnode->info.state == PM_DISP_NODE_DONE)	// safety net
Packit 5ea288
		return VSTATUS_NOT_FOUND;	// nothing else to do for this port        
Packit 5ea288
    dispnode->info.numOutstandingPackets++;    
Packit 5ea288
Packit 5ea288
	if (disppacket->numPorts > 1 && dispnode->info.state != PM_DISP_NODE_CLR_PORT_STATUS
Packit 5ea288
		&& dispnode->info.state != PM_DISP_NODE_CLR_ERRORINFO)
Packit 5ea288
	{
Packit 5ea288
		// Sort DispPorts by Port Number, so that it will match response MAD order
Packit 5ea288
		qsort(disppacket->DispPorts, (size_t)disppacket->numPorts,
Packit 5ea288
			sizeof(PmDispatcherPort_t), PmDispatcherPortNumCompare);
Packit 5ea288
	}
Packit 5ea288
    switch (dispnode->info.state) {
Packit 5ea288
	case PM_DISP_NODE_GET_DATACOUNTERS:
Packit 5ea288
		if ( dispnode->info.pmnodep->nodeType == STL_NODE_FI ) {
Packit 5ea288
			{
Packit 5ea288
				return PmSendGetPortStatus(pm, dispnode, disppacket);
Packit 5ea288
			}
Packit 5ea288
		} else {
Packit 5ea288
			dispnode->info.state = PM_DISP_NODE_GET_DATACOUNTERS;
Packit 5ea288
			{
Packit 5ea288
				return PmSendGetDataPortCounters(pm, dispnode, disppacket);
Packit 5ea288
			}
Packit 5ea288
		}
Packit 5ea288
	
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORCOUNTERS:
Packit 5ea288
		{
Packit 5ea288
			return PmSendGetErrorPortCounters(pm, dispnode, disppacket);
Packit 5ea288
		}
Packit 5ea288
		
Packit 5ea288
	case PM_DISP_NODE_CLR_PORT_STATUS:  
Packit 5ea288
		return PmSendClearPortStatus(pm, dispnode, disppacket);
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_GET_ERRORINFO:
Packit 5ea288
		return PmSendGetErrorInfo(pm, dispnode, disppacket);
Packit 5ea288
Packit 5ea288
	case PM_DISP_NODE_CLR_ERRORINFO:
Packit 5ea288
		return PmSendClearErrorInfo(pm, dispnode, disppacket);
Packit 5ea288
Packit 5ea288
	default:
Packit 5ea288
		DEBUG_ASSERT(0);	// unexpected state
Packit 5ea288
		DispatchPacketDone(pm, disppacket);
Packit 5ea288
		return VSTATUS_NOT_FOUND;
Packit 5ea288
	}
Packit 5ea288
}	// End of DispatchPacketNextStep()
Packit 5ea288
Packit 5ea288
// cs_send_mad callback for all operations against a whole node
Packit 5ea288
// (Get(ClassPortInfo), Clear all Port Counters)
Packit 5ea288
static void DispatchNodeCallback(cntxt_entry_t *entry, Status_t status, void *data, Mai_t *mad)
Packit 5ea288
{
Packit 5ea288
	PmDispatcherNode_t *dispnode = (PmDispatcherNode_t*)data;
Packit 5ea288
	PmNode_t *pmnodep = dispnode->info.pmnodep;
Packit 5ea288
	uint64_t sTime, eTime;
Packit 5ea288
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		(void)vs_time_get(&sTime);
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x Node State %u",
Packit 5ea288
		(int)sizeof(pmnodep->nodeDesc.NodeString), pmnodep->nodeDesc.NodeString,
Packit 5ea288
		pmnodep->NodeGUID, pmnodep->dlid, dispnode->info.state);
Packit 5ea288
Packit 5ea288
	switch (dispnode->info.state) {
Packit 5ea288
	case PM_DISP_NODE_CLASS_INFO:
Packit 5ea288
		if (status != VSTATUS_OK || mad == NULL) {
Packit 5ea288
			PmFailNodeQuery(entry, dispnode, (mad ? mad->base.method : MMTHD_GET),
Packit 5ea288
				(mad ? mad->base.aid : STL_PM_ATTRIB_ID_CLASS_PORTINFO) );
Packit 5ea288
			goto nextnode;	// NodeDone called on Fail
Packit 5ea288
		} else if (mad->base.status != MAD_STATUS_SUCCESS) {
Packit 5ea288
			PmMadFailNodeQuery(entry, mad, dispnode);
Packit 5ea288
			goto nextnode;	// NodeDone called on Fail
Packit 5ea288
		} else if (mad->base.aid != STL_PM_ATTRIB_ID_CLASS_PORTINFO) {
Packit 5ea288
			PmMadAttrWrongNodeQuery(entry, mad, dispnode);
Packit 5ea288
			goto nextnode;	// NodeDone called on Fail
Packit 5ea288
		} else if (FSUCCESS != ProcessPmaClassPortInfo(pmnodep,(STL_CLASS_PORT_INFO*)mad->data) ) {
Packit 5ea288
			PmFailNodeQuery(entry, dispnode, mad->base.method, mad->base.aid);
Packit 5ea288
			goto nextnode;	// NodeDone called on Fail
Packit 5ea288
		}
Packit 5ea288
		break;
Packit 5ea288
	default:
Packit 5ea288
		ASSERT(0);	// or log error
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		PmDispatcherPerfCalcPost(dispnode->pm, mad, entry, pmnodep);
Packit 5ea288
	}
Packit 5ea288
	cs_cntxt_retire_nolock( entry, &dispnode->pm->Dispatcher.cntx  );
Packit 5ea288
Packit 5ea288
	if (VSTATUS_OK == DispatchNodeNextStep(dispnode->pm, pmnodep, dispnode))
Packit 5ea288
		goto done;
Packit 5ea288
	// if NodeNextStep returns ! OK, then Node will be done
Packit 5ea288
Packit 5ea288
nextnode:
Packit 5ea288
	// fails above which goto nextport will also have called done
Packit 5ea288
	DEBUG_ASSERT(dispnode->info.state == PM_DISP_NODE_DONE);
Packit 5ea288
Packit 5ea288
	// loops til finds a node or none left, wake main thread if all done
Packit 5ea288
	(void)DispatchNextNode(dispnode->pm, dispnode);
Packit 5ea288
done:
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		(void)vs_time_get(&eTime);
Packit 5ea288
		dispnode->pm->Dispatcher.perf_stats.callback_calc_time += (eTime - sTime);
Packit 5ea288
	}
Packit 5ea288
}	// End of DispatchNodeCallback()
Packit 5ea288
Packit 5ea288
// given node is completed
Packit 5ea288
static void DispatchNodeDone(Pm_t *pm, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	IB_LOG_DEBUG3_FMT(__func__,"%.*s Guid "FMT_U64" LID 0x%x",
Packit 5ea288
		(int)sizeof(dispnode->info.pmnodep->nodeDesc.NodeString),
Packit 5ea288
		dispnode->info.pmnodep->nodeDesc.NodeString,
Packit 5ea288
		dispnode->info.pmnodep->NodeGUID, dispnode->info.pmnodep->dlid);
Packit 5ea288
Packit 5ea288
	DEBUG_ASSERT(dispnode->info.state != PM_DISP_NODE_DONE);
Packit 5ea288
	// we handle this once when all ports done, hence we will only increment
Packit 5ea288
	// once even if multiple ports fail in the same node
Packit 5ea288
	if (dispnode->info.u.s.failed) {
Packit 5ea288
		pm->Image[pm->SweepIndex].NoRespNodes++;
Packit 5ea288
		INCREMENT_PM_COUNTER(pmCounterPmNoRespNodes);
Packit 5ea288
	}
Packit 5ea288
	dispnode->info.state = PM_DISP_NODE_DONE;
Packit 5ea288
        if(dispnode->info.activePorts) {
Packit 5ea288
            vs_pool_free(&pm_pool, dispnode->info.activePorts);
Packit 5ea288
            dispnode->info.activePorts = NULL;
Packit 5ea288
        }
Packit 5ea288
Packit 5ea288
	pm->Dispatcher.numOutstandingNodes--;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
// PM Sweep Main Loop
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
Packit 5ea288
// returns number of nodes started,
Packit 5ea288
// if 0 then caller need not wait, nothing to do
Packit 5ea288
// caller should check for EngineShutdown before calling
Packit 5ea288
static Status_t DispatcherStartSweepAllNodes(Pm_t *pm)
Packit 5ea288
{
Packit 5ea288
	PmImage_t *pmimagep = &pm->Image[pm->SweepIndex];
Packit 5ea288
	PmDispatcherNode_t *dispnode;
Packit 5ea288
	uint16 slot;
Packit 5ea288
Packit 5ea288
	cs_cntxt_lock(&pm->Dispatcher.cntx);
Packit 5ea288
	// initialize Dispatcher for a new sweep
Packit 5ea288
	pm->Dispatcher.nextLid = 1;
Packit 5ea288
	pm->Dispatcher.numOutstandingNodes = 0;
Packit 5ea288
	pm->Dispatcher.postedEvent = 0;
Packit 5ea288
	for (slot=0; slot < pm_config.MaxParallelNodes; ++slot) {
Packit 5ea288
		pm->Dispatcher.DispNodes[slot].info.pmnodep = NULL;
Packit 5ea288
		pm->Dispatcher.DispNodes[slot].info.state = PM_DISP_NODE_NONE;
Packit 5ea288
	}
Packit 5ea288
	for (slot = 0,dispnode = &pm->Dispatcher.DispNodes[slot];
Packit 5ea288
		slot < pm_config.MaxParallelNodes && pm->Dispatcher.nextLid <=pmimagep->maxLid;
Packit 5ea288
		) {
Packit 5ea288
		if (VSTATUS_OK == DispatchNextNode(pm, dispnode))
Packit 5ea288
			dispnode++,slot++;
Packit 5ea288
	}
Packit 5ea288
	cs_cntxt_unlock(&pm->Dispatcher.cntx);
Packit 5ea288
	return slot;	// number of nodes started
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// returns OK if a node was dispatched, returns NOT_FOUND if none dispatched
Packit 5ea288
static Status_t DispatchNextNode(Pm_t *pm, PmDispatcherNode_t *dispnode)
Packit 5ea288
{
Packit 5ea288
	PmImage_t *pmimagep = &pm->Image[pm->SweepIndex];
Packit 5ea288
Packit 5ea288
	if (pm_shutdown || g_pmEngineState != PM_ENGINE_STARTED) {
Packit 5ea288
		IB_LOG_INFO0("PM Engine shut down requested");
Packit 5ea288
		goto abort;
Packit 5ea288
	}
Packit 5ea288
	while (pm->Dispatcher.nextLid <= pmimagep->maxLid) {
Packit 5ea288
		PmNode_t *pmnodep = pmimagep->LidMap[pm->Dispatcher.nextLid];
Packit 5ea288
		pm->Dispatcher.nextLid++;
Packit 5ea288
		if (! pmnodep)
Packit 5ea288
			continue;
Packit 5ea288
		// we only keep active LIDed ports in LidMap
Packit 5ea288
		DEBUG_ASSERT(pm_node_lided_port(pmnodep)->Image[pm->SweepIndex].u.s.active);
Packit 5ea288
Packit 5ea288
		if (pmnodep->u.s.PmaAvoid) { // ! NodeHasPma(nodep)
Packit 5ea288
			PmSkipNode(pm, pmnodep); // No PMA
Packit 5ea288
			continue;
Packit 5ea288
		}
Packit 5ea288
		if (VSTATUS_OK == DispatchNode(pm, pmnodep, dispnode))
Packit 5ea288
			return VSTATUS_OK;
Packit 5ea288
	}
Packit 5ea288
abort:
Packit 5ea288
	// be sure we only post event once per sweep
Packit 5ea288
	if (! pm->Dispatcher.numOutstandingNodes && ! pm->Dispatcher.postedEvent) {
Packit 5ea288
		pm->Dispatcher.postedEvent = 1;
Packit 5ea288
		vs_event_post(&pm->Dispatcher.sweepDone, VEVENT_WAKE_ONE, (Eventset_t)1);
Packit 5ea288
	}
Packit 5ea288
	return VSTATUS_NOT_FOUND;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
FSTATUS PmSweepAllPortCounters(Pm_t *pm)
Packit 5ea288
{
Packit 5ea288
	PmImage_t *pmimagep = &pm->Image[pm->SweepIndex];
Packit 5ea288
	Eventset_t events;
Packit 5ea288
	Status_t rc;
Packit 5ea288
Packit 5ea288
	IB_LOG_INFO0("START Sweeping All Port Counters...");
Packit 5ea288
	pmimagep->NoRespNodes = pmimagep->NoRespPorts = 0;
Packit 5ea288
	pmimagep->SkippedNodes = pmimagep->SkippedPorts = 0;
Packit 5ea288
	pmimagep->UnexpectedClearPorts = 0;
Packit 5ea288
	pmimagep->DowngradedPorts = 0;
Packit 5ea288
	pmimagep->ErrorInfoPorts = 0;
Packit 5ea288
	(void)PmClearAllNodes(pm);	// clear link based counts
Packit 5ea288
Packit 5ea288
	(void)DispatcherStartSweepAllNodes(pm);
Packit 5ea288
	do {
Packit 5ea288
		rc = vs_event_wait(&pm->Dispatcher.sweepDone, VTIMER_1S, (Eventset_t)1, &events);
Packit 5ea288
	} while (rc == VSTATUS_TIMEOUT);
Packit 5ea288
Packit 5ea288
	IB_LOG_INFO0("DONE Sweeping All Port Counters");
Packit 5ea288
	if (pmimagep->NoRespPorts)
Packit 5ea288
		IB_LOG_WARN_FMT(__func__, "Unable to get %u Ports on %u Nodes", pmimagep->NoRespPorts, pmimagep->NoRespNodes);
Packit 5ea288
	if (pmimagep->UnexpectedClearPorts)
Packit 5ea288
		IB_LOG_WARN_FMT(__func__, "%u Ports were unexpectedly cleared", pmimagep->UnexpectedClearPorts);
Packit 5ea288
	if (pmimagep->DowngradedPorts)
Packit 5ea288
		IB_LOG_INFO_FMT(__func__, "%u Ports were Downgraded", pmimagep->DowngradedPorts);
Packit 5ea288
	if (g_pmDebugPerf) {
Packit 5ea288
		PmDispatcherPerfEnd(pm);
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	if (pm_shutdown || g_pmEngineState != PM_ENGINE_STARTED)
Packit 5ea288
		return FNOT_DONE;
Packit 5ea288
	return FSUCCESS;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
// PM Dispatch Initialization
Packit 5ea288
// -------------------------------------------------------------------------
Packit 5ea288
Packit 5ea288
Status_t PmDispatcherInit(Pm_t *pm)
Packit 5ea288
{
Packit 5ea288
	struct PmDispatcher_s *disp = &pm->Dispatcher;
Packit 5ea288
	PmDispatcherNode_t *dispnode;
Packit 5ea288
	Status_t status;
Packit 5ea288
	uint32 size;
Packit 5ea288
	uint16 slot;
Packit 5ea288
	uint64_t timeout=0;
Packit 5ea288
Packit 5ea288
	memset(disp, 0, sizeof(*disp));
Packit 5ea288
Packit 5ea288
	disp->cntx.hashTableDepth = CNTXT_HASH_TABLE_DEPTH;
Packit 5ea288
	disp->cntx.poolSize = pm_config.MaxParallelNodes * pm_config.PmaBatchSize;
Packit 5ea288
	disp->cntx.maxRetries = pm_config.MaxRetries;
Packit 5ea288
	disp->cntx.ibHandle = hpma;
Packit 5ea288
	disp->cntx.resp_queue = NULL;	// no need for a resp queue
Packit 5ea288
	disp->cntx.totalTimeout = (pm_config.RcvWaitInterval * pm_config.MaxRetries * 1000);
Packit 5ea288
	if (pm_config.MinRcvWaitInterval) {
Packit 5ea288
		timeout = pm_config.MinRcvWaitInterval * 1000;
Packit 5ea288
		disp->cntx.MinRespTimeout = timeout;
Packit 5ea288
	} else {
Packit 5ea288
		timeout = pm_config.RcvWaitInterval * 1000;
Packit 5ea288
		disp->cntx.MinRespTimeout = 0;
Packit 5ea288
	}
Packit 5ea288
	disp->cntx.errorOnSendFail = 1;
Packit 5ea288
#ifdef IB_STACK_OPENIB
Packit 5ea288
	// for openib we let umad do the timeouts.  Hence we add 1 second to
Packit 5ea288
	// the timeout as a safety net just in case umad loses our response.
Packit 5ea288
	disp->cntx.timeoutAdder = VTIMER_1S;
Packit 5ea288
#endif
Packit 5ea288
	status = cs_cntxt_instance_init(&pm_pool, &disp->cntx, timeout);
Packit 5ea288
	if (status != VSTATUS_OK) {
Packit 5ea288
		IB_LOG_ERRORRC("Failed to create Dispatcher Context rc:", status);
Packit 5ea288
		goto fail;
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	status = vs_event_create(&disp->sweepDone, (unsigned char*)"PM Sweep Done",
Packit 5ea288
					(Eventset_t)0);
Packit 5ea288
	if (status != VSTATUS_OK) {
Packit 5ea288
		IB_LOG_ERRORRC("Failed to create Dispatcher Event rc:", status);
Packit 5ea288
		goto freecontext;
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	size = sizeof(PmDispatcherNode_t)*pm_config.MaxParallelNodes;
Packit 5ea288
	status = vs_pool_alloc(&pm_pool, size, (void*)&disp->DispNodes);
Packit 5ea288
	if (status != VSTATUS_OK || !disp->DispNodes) {
Packit 5ea288
		IB_LOG_ERRORRC("Failed to allocate Dispatcher Nodes rc:", status);
Packit 5ea288
		goto freeevent;
Packit 5ea288
	}
Packit 5ea288
	memset(disp->DispNodes, 0, size);
Packit 5ea288
Packit 5ea288
	for (dispnode=&disp->DispNodes[0], slot=0; slot
Packit 5ea288
		uint8 pslot;
Packit 5ea288
		dispnode->pm = pm;
Packit 5ea288
		size = sizeof(PmDispatcherPacket_t)*pm_config.PmaBatchSize;
Packit 5ea288
		status = vs_pool_alloc(&pm_pool, size, (void*)&dispnode->DispPackets);
Packit 5ea288
		if (status != VSTATUS_OK || !dispnode->DispPackets) {
Packit 5ea288
			IB_LOG_ERRORRC("Failed to allocate Dispatcher Packets rc:", status);
Packit 5ea288
			goto freeports;
Packit 5ea288
		}
Packit 5ea288
		dispnode->info.activePorts=NULL;
Packit 5ea288
		memset(dispnode->DispPackets, 0, size);
Packit 5ea288
		for (pslot=0; pslot
Packit 5ea288
			dispnode->DispPackets[pslot].dispnode = dispnode;
Packit 5ea288
	}
Packit 5ea288
Packit 5ea288
	return VSTATUS_OK;
Packit 5ea288
Packit 5ea288
freeports:
Packit 5ea288
	for (dispnode=&disp->DispNodes[0], slot=0; slot
Packit 5ea288
		if (dispnode->DispPackets)
Packit 5ea288
			vs_pool_free(&pm_pool, dispnode->DispPackets);
Packit 5ea288
	}
Packit 5ea288
	vs_pool_free(&pm_pool, disp->DispNodes);
Packit 5ea288
freeevent:
Packit 5ea288
	vs_event_delete(&disp->sweepDone);
Packit 5ea288
freecontext:
Packit 5ea288
	(void)cs_cntxt_instance_free(&pm_pool, &disp->cntx);
Packit 5ea288
fail:
Packit 5ea288
	return VSTATUS_BAD;
Packit 5ea288
}
Packit 5ea288
Packit 5ea288
void PmDispatcherDestroy(Pm_t *pm)
Packit 5ea288
{
Packit 5ea288
	struct PmDispatcher_s *disp = &pm->Dispatcher;
Packit 5ea288
	uint32_t slot;
Packit 5ea288
Packit 5ea288
	for (slot=0; slot
Packit 5ea288
		if (disp->DispNodes[slot].DispPackets)
Packit 5ea288
			vs_pool_free(&pm_pool, disp->DispNodes[slot].DispPackets);
Packit 5ea288
	}
Packit 5ea288
	vs_pool_free(&pm_pool, disp->DispNodes);
Packit 5ea288
	vs_event_delete(&disp->sweepDone);
Packit 5ea288
	(void)cs_cntxt_instance_free(&pm_pool, &disp->cntx);
Packit 5ea288
}