📄 nsmdiag.c
字号:
case NSM_STATS:
if (copy_from_user(&statCmd, useraddr,
sizeof(statCmd)))
{
ret = NS_STATUS_FAILURE;
}
else
{
getDiagStats(adapter, &statCmd);
if (copy_to_user(useraddr, &statCmd,
sizeof(statCmd)))
{
ret = NS_STATUS_FAILURE;
}
}
break;
default :
ret = NS_STATUS_NOT_SUPPORTED;
}
}
NO(NsmDiagIoctl);
return ret;
}
//*****************************************************************************
// NsmDiagTransmitDone
// Transmit Done Notification (Diag Mode)
//
// Parameters
// pClientDevHndl
// NSM device handle registered with MPL (during MplInitialize)
// packetCnt
// Count of packets whose completion is being reported.
// pTxDone
// MPL allocated MPL_TRANSMIT_DONE structure array in which the
// NSM packet handles and statuses are returned.
//
// Return Value
// None
//*****************************************************************************
NS_VOID
NsmDiagTransmitDone(
NS_VOID *pClientDevHndl,
NS_UINT packetCnt,
MPL_TRANSMIT_DONE *pTxDone
)
{
NSM_CONTEXT *adapter = pClientDevHndl;
NS_UINT i, pktSize, fragCnt;
DIAG_PKT *dPkt;
MPL_LIST_NODE *node;
MPL_PKT_FRAG *pFrag, *pHeadFrag, *pTailFrag;
NI(NsmDiagTransmitDone);
// Unmap and Free done skbs
for(i = 0x0; i < packetCnt; i++)
{
// Get the head frag which was noted as NSM private
pHeadFrag = pTxDone[i].pNsmPrivate;
// Unmap Buffers
pFrag = pHeadFrag; pTailFrag = NULL;
pktSize = 0x0; fragCnt = 0x0;
while (pFrag)
{
pci_unmap_single(adapter->pdev, pFrag->physAddr, pFrag->fragSize,
PCI_DMA_TODEVICE);
pktSize += pFrag->fragSize;
fragCnt++;
// Get next frag
pTailFrag = pFrag;
pFrag = pFrag->pNextFrag;
}
// Update stats
if (pTxDone[i].packetStatus == NS_STATUS_SUCCESS)
{
// Update counters
adapter->diagStats.txPackets++;
adapter->diagStats.txBytes += pktSize;
}
else
{
// Update counters
adapter->diagStats.txErrors++;
// Detailed Error analysis
if (pTxDone[i].cmdSts & CS_ERR_TXA)
{
adapter->diagStats.txAbortedErrors++;
}
if (pTxDone[i].cmdSts & CS_ERR_TX_EC)
{
adapter->diagStats.txCollErrors++;
}
if (pTxDone[i].cmdSts & CS_ERR_TFU)
{
adapter->diagStats.txFifoErrors++;
}
if (pTxDone[i].cmdSts & CS_ERR_TX_CRS)
{
adapter->diagStats.txCarrierErrors++;
}
if (pTxDone[i].cmdSts & CS_ERR_TX_OWC)
{
adapter->diagStats.txWindowErrors++;
}
}
if (pTxDone[i].packetStatus != NS_STATUS_ABORTED)
{
// If we are are out of free pkt nodes to note this completion
// then force a stale one out of the completed list
if (MPL_LIST_GET_SIZE(&adapter->diagFreeList) == 0x0)
{
// Ask ProcessDone function to do a basic validation before freeing
NsmDiagProcessDoneList(adapter, 0x1, NS_TRUE,
&adapter->diagTxDoneList, &adapter->txFragsTail);
adapter->diagStats.txDropped++;
}
// Get a free diag pkt node from the head of the free list
node = MPL_LIST_GET_HEAD(&adapter->diagFreeList);
// Get the Diag Pkt linked to the curr node
dPkt = MPL_LIST_GET_ENTRY(node, DIAG_PKT, link);
// Note pkt details
dPkt->pktStatus = pTxDone[i].packetStatus;
dPkt->cmdSts = pTxDone[i].cmdSts;
dPkt->pktSize = pktSize;
dPkt->appPktHandle = (NS_UINT)pHeadFrag->pPacketHndl;
dPkt->numDesc = fragCnt;
// NSM Diag related
dPkt->pFrag = pHeadFrag;
// Move this packet from the free list to the done list
MplListDel(&adapter->diagFreeList, &dPkt->link);
MplListAddTail(&adapter->diagTxDoneList, &dPkt->link);
}
else
{
// Add the frags back to the free list
adapter->txFragsTail->pNextFrag = pHeadFrag;
adapter->txFragsTail = pTailFrag;
}
}
NO(NsmDiagTransmitDone);
return;
}
//*****************************************************************************
// NsmDiagReceive
// Diag mode Receive Done Notification
//
// Parameters
// pClientDevHndl
// NSM device handle registered with MPL (during MplInitialize)
// packetCnt
// Count of packets whose reception is being reported.
// pPkt
// MPL allocated MPL_PKT structure array in which
// a list of the newly received packets are reported
//
// Return Value
// None
//*****************************************************************************
NS_VOID
NsmDiagReceive(
NS_VOID *pClientDevHndl,
NS_UINT packetCnt,
MPL_PKT *pPkt
)
{
NSM_CONTEXT *adapter = pClientDevHndl;
MPL_PKT_FRAG *pTailFrag, *pHeadFrag;
DIAG_PKT *dPkt;
MPL_LIST_NODE *node;
NS_UINT i, j;
NI(NsmDiagReceive);
// Process the receive list
for(i = 0x0; i < packetCnt; i++)
{
// Get the head frag ptr
pHeadFrag = pPkt[i].pFragHead;
if (pPkt[i].packetStatus == NS_STATUS_SUCCESS)
{
// Update counters
adapter->diagStats.rxPackets++;
adapter->diagStats.rxBytes += pPkt[i].packetSize;
}
else
{
// Update counters
adapter->diagStats.rxErrors++;
// Detailed Error analysis
if (pPkt[i].rxOOB.cmdSts & (CS_RXA | CS_ERR_RXO))
{
adapter->diagStats.rxOverErrors++;
}
if (pPkt[i].rxOOB.cmdSts & CS_ERR_RX_CRCE)
{
adapter->diagStats.rxCrcErrors++;
}
if (pPkt[i].rxOOB.cmdSts & (CS_ERR_RX_LONG | CS_ERR_RX_RUNT))
{
adapter->diagStats.rxLengthErrors++;
}
if (pPkt[i].rxOOB.cmdSts & (CS_ERR_RX_ISE | CS_ERR_RX_FAE))
{
adapter->diagStats.rxFrameErrors++;
}
}
if (pPkt[i].packetStatus != NS_STATUS_ABORTED)
{
// If we are are out of free pkt nodes to note this completion
// then force a stale one out of the completed list
if (MPL_LIST_GET_SIZE(&adapter->diagFreeList) == 0x0)
{
// Ask ProcessDone function to do a basic validation before freeing
NsmDiagProcessDoneList(adapter, 0x1, NS_TRUE,
&adapter->diagRxDoneList, &adapter->rxFragsTail);
adapter->diagStats.rxDropped++;
}
// Get a free diag pkt node from the head of the free list
node = MPL_LIST_GET_HEAD(&adapter->diagFreeList);
// Get the Diag Pkt linked to the curr node
dPkt = MPL_LIST_GET_ENTRY(node, DIAG_PKT, link);
// Note pkt details
dPkt->pktStatus = pPkt[i].packetStatus;
dPkt->cmdSts = pPkt[i].rxOOB.cmdSts;
dPkt->pktSize = pPkt[i].packetSize;
dPkt->appPktHandle = 0x0; // Reference handle for Rx pkts
dPkt->numDesc = pPkt[i].fragCount;
// NSM Diag related
dPkt->pFrag = pHeadFrag;
// Move this packet from the free list to the done list
MplListDel(&adapter->diagFreeList, &dPkt->link);
MplListAddTail(&adapter->diagRxDoneList, &dPkt->link);
}
else
{
pTailFrag = pHeadFrag;
for (j = 0x0; j < (pPkt[i].fragCount - 1); j++)
{
pTailFrag = pTailFrag->pNextFrag;
}
// Add the frags back to the free list
adapter->rxFragsTail->pNextFrag = pHeadFrag;
pTailFrag->pNextFrag = NULL;
adapter->rxFragsTail = pTailFrag;
}
}
NO(NsmDiagReceive);
return;
}
//*****************************************************************************
// NsmDiagProcessDoneList
// Process one or more packets in the Tx/Rx Done queue
//
// Parameters
// adapter
// NSM Context
// pktCnt
// Number of packets to process.
// Set this to 0x0 to process all packets in the completion queue
// validate
// NS_TRUE : Do a basic validation on the packet before releasing it
// NS_FALSE : Just release it
// pList
// Done List (Tx/Rx) to process
// ppTailFrag
// Pointer to a frag pointer at which to append the freed frags
// Return Value
// None
//*****************************************************************************
NS_VOID
NsmDiagProcessDoneList(
NSM_CONTEXT *adapter,
NS_UINT pktCnt,
NS_BOOLEAN validate,
MPL_LIST *pList,
MPL_PKT_FRAG **ppTailFrag)
{
DIAG_PKT *dPkt;
MPL_LIST_NODE *node;
NS_UINT i;
MPL_PKT_FRAG *pTail;
NI(NsmDiagProcessDoneList);
// Check if we need to process all pkts
if (pktCnt == 0x0)
{
pktCnt = MPL_LIST_GET_SIZE(pList);
}
// Process done list
node = MPL_LIST_GET_HEAD(pList);
for (i = 0x0; i < pktCnt; i++)
{
if (MPL_LIST_GET_SIZE(pList) == 0x0)
{
break; //premature?
}
// Get the Diag Pkt linked to the curr node
dPkt = MPL_LIST_GET_ENTRY(node, DIAG_PKT, link);
// Get the next node
node = MPL_LIST_GET_NEXT(node);
if (dPkt->pFrag)
{
// Check if we need to validate this packet before removing
if (validate == NS_TRUE)
{
pktValidate(adapter, dPkt->pFrag);
}
// Put the frags back on the free frag list
pTail = dPkt->pFrag;
while (pTail->pNextFrag)
{
pTail = pTail->pNextFrag;
}
// Add the frags back to the free list
(*ppTailFrag)->pNextFrag = dPkt->pFrag;
*ppTailFrag = pTail;
}
// Move the diag pkt from done list to free list
MplListDel(pList, &dPkt->link);
MplListAddTail(&adapter->diagFreeList, &dPkt->link);
}
NO(NsmDiagProcessDoneList);
return;
}
// Local functions
//*****************************************************************************
// setupTxFrags
// Setup the MPL frags for Tx
//
// Parameters
// adapter
// NSM Context
// Return Value
// NS_TRUE : Setup was successful
// NS_FALSE : Setup failed
//*****************************************************************************
static NS_BOOLEAN
setupTxFrags(
NSM_CONTEXT *adapter)
{
NS_UINT allocSize, i, nodes;
MPL_PKT_FRAG *pFrag = NULL, *prevFrag;
NS_VOID *allocMem;
NS_BOOLEAN ret = NS_FALSE;
struct sk_buff *skb;
NI(setupTxFrags);
// Allocate memory for the frags = total ring size + sts queue size
nodes = adapter->txdCnt + adapter->diagStsQueueSize;
allocSize = sizeof(MPL_PKT_FRAG) * nodes;
allocMem = kmalloc(allocSize, GFP_KERNEL);
if (allocMem == NULL)
{
NSM_DBG(DBG_ERR,("Failed to Alloc mem to tx frags \n"));
NO(setupTxFrags);
return ret;
}
else
{
// Zero up the memory
memset((void *)(allocMem), 0x0, allocSize);
pFrag = (MPL_PKT_FRAG *) allocMem;
prevFrag = NULL;
// Create linked list and attach a buffer
for (i = 0x0; i < nodes; i++)
{
// Allocate buffer
skb = dev_alloc_skb(adapter->txBufferLen);
if (skb == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -