|
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 |
}
|