📄 receive.c
字号:
NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
DBGPRINT(DBG_COMP_RXIOC, DBG_LEVEL_ERR,
("RxIOC CurRxRQIdx(%x), PrevRxRQIdx(%x)\n",
CurrentRxReportQIdx, pRecvDmaQ->PrevRxReportQIndex));
for (i = pRecvDmaQ->PrevRxReportQIndex;
i != CurrentRxReportQIdx;
i = (i == pHwInfo->MaxIdxOfRxReportQ)? 0 : ++i)
{
//
// Get the VC from report queue.
//
pEntryOfRxReportQ = &RxReportQueue[i];
Vci = (ULONG) pEntryOfRxReportQ->RxReportQDWord1.VC;
//
// Get the physical address of reported buffer to search
// the buffer from CompletingXXXBufQ accordingly.
//
Dest = pEntryOfRxReportQ->RxReportQDWord0.Index;
tmpBufferType = (pEntryOfRxReportQ->RxReportQDWord0.rqSlotType == 1)?
RECV_BIG_BUFFER :
RECV_SMALL_BUFFER;
//
// Search reported buffer queue first.
// if not find the buffer then search another buffer queue.
//
if (RECV_BIG_BUFFER == tmpBufferType)
{
#if DBG
pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedBigRxSlots;
#endif // end of DBG
tbAtm155SearchRecvBufferFromQueue(
&pRecvDmaQ->CompletingBigBufQ,
Dest,
&pRecvBufHead);
if (NULL == pRecvBufHead)
{
tmpBufferType = RECV_SMALL_BUFFER;
#if DBG
pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedSmallRxSlots;
#endif // end of DBG
//
// Try from "Small" buffer pool.
//
tbAtm155SearchRecvBufferFromQueue(
&pRecvDmaQ->CompletingSmallBufQ,
Dest,
&pRecvBufHead);
}
}
else
{
#if DBG
pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedSmallRxSlots;
#endif // end of DBG
tbAtm155SearchRecvBufferFromQueue(
&pRecvDmaQ->CompletingSmallBufQ,
Dest,
&pRecvBufHead);
if (NULL == pRecvBufHead)
{
tmpBufferType = RECV_BIG_BUFFER;
#if DBG
pdbgTotalUsedRxSlots = &pRecvDmaQ->dbgTotalUsedBigRxSlots;
#endif // end of DBG
//
// Try from "Big" buffer pool.
//
tbAtm155SearchRecvBufferFromQueue(
&pRecvDmaQ->CompletingBigBufQ,
Dest,
&pRecvBufHead);
}
}
if (NULL == pRecvBufHead)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Can NOT find from either pool.(Dest=%lx)\n", Dest));
DBGPRINT(DBG_COMP_NRXBUFFOUND, DBG_LEVEL_ERR,
("RxIOC CurRxRQIdx(%x), PrevRxRQIdx(%x)\n",
CurrentRxReportQIdx, pRecvDmaQ->PrevRxReportQIndex));
DBGPRINT(DBG_COMP_NRXBUFFOUND, DBG_LEVEL_ERR,
("RxIOC RxReportEntryW0(%lx), RxReportEntryW1(%lx)\n",
pEntryOfRxReportQ->RxReportQueueDword0,
pEntryOfRxReportQ->RxReportQueueDword1));
continue;
}
if (RECV_BIG_BUFFER == tmpBufferType)
{
//
// Make sure return to the corresponding queue.
//
pFreeBufQ = &pSar->FreeBigBufferQ;
pTmpFreeSlots = &pRecvDmaQ->RemainingReceiveBigSlots;
fRxSlotsLowOrNone = pSar->fBigllSlotsLowOrNone;
}
else
{
//
// Make sure return to the corresponding queue.
//
pFreeBufQ = &pSar->FreeSmallBufferQ;
pTmpFreeSlots = &pRecvDmaQ->RemainingReceiveSmallSlots;
fRxSlotsLowOrNone = pSar->fSmallSlotsLowOrNone;
}
//
// Update the remaining free slot count for the buffer queue.
//
(*pTmpFreeSlots)++;
//
// flush the cache.
//
NdisFlushBuffer(pRecvBufHead->FlushBuffer, FALSE);
NdisMUpdateSharedMemory(
pAdapter->MiniportAdapterHandle,
pRecvBufHead->Alloc[RECV_BUFFER_ALIGNED].Size,
pRecvBufHead->Alloc[RECV_BUFFER_ALIGNED].VirtualAddress,
pRecvBufHead->Alloc[RECV_BUFFER_ALIGNED].PhysicalAddress);
#if DBG
(*pdbgTotalUsedRxSlots)++;
#endif // end of DBG
//
// Check if the Vc is valid.
//
NdisDprReleaseSpinLock(&pRecvDmaQ->lock);
pVc = tbAtm155UnHashVc(pAdapter, Vci);
NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
if (NULL == pVc)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("There is not a valid VC for %u\n", Vci));
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvInvalidVpiVci);
//
// Return the receive buffer to the free pool.
//
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
continue;
}
//
// BUGFIX 158842
//
if (!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_RECEIVE)))
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("We don't have a valid VC_BLOCK: 0x%x for VCI: %u\n", pVc, Vci));
//
// Return the receive buffer to the free pool.
//
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
continue;
}
pRecvSegInfo = pVc->RecvSegInfo;
if (pVc->RecvBufType != tmpBufferType)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Buffer types are not matched with the VC's.\n"));
//
//
// The buffer type is not matched with the type reported
// from Rx report queue, return the receive buffer to the
// free pool, then go to handle the next report entry.
//
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
continue;
}
//
// Point to the list which queues the receive buffers until
// a whole packet is in (indicates by EOP flag in Rx report queue.)
//
pSegCompleting = &pRecvSegInfo->SegCompleting;
//
// Let's check if the data in the receive buffer is healthy.
//
if (pEntryOfRxReportQ->RxReportQDWord1.Bad)
{
//
// Data in the buffer is bad.
//
// 1. Release any chained buffers in the VC.
// 2. Return the current receive buffer back to the buffer pool.
//
if (NULL != pSegCompleting->BufListHead)
{
NdisDprReleaseSpinLock(&pRecvDmaQ->lock);
//
// It is possible that receive congestion happened.
// Abort the receive buffers, which contain the packet,
// into the list.
//
tbAtm155ProcessReturnPacket(
pAdapter,
pSegCompleting->BufListHead->Packet,
pSegCompleting->BufListHead,
FALSE);
NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
//
// Check if the buffer has been freed in tbAtm155ProcessReturnPacket()
//
if (NULL != pRecvSegInfo)
{
pSegCompleting->BufListHead = NULL;
pSegCompleting->BufListTail = NULL;
pSegCompleting->BufferCount = 0;
}
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR, ("Recved a bad packet.\n"));
}
//
// Return the receive buffer to the free pool.
//
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
//
// There are for
// 1. Adapters in ADAPTER_BLOCK
// 2. VC in VC_BLOCK
//
switch (pEntryOfRxReportQ->RxReportQDWord1.Status)
{
case Crc32ErrDiscard:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("CRC32 Error detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvCrcError);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvCrcError);
break;
case LengthErrDiscard:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Packet Length Error detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusError);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusError);
break;
case AbortedPktDiscard:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Aborted Packet detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusError);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusError);
break;
case SlotCongDiscard:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Slot Congestion detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvCellsDropped);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvCellsDropped);
break;
case OtherCellErrDiscard:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Other Cell Error detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusNoBuffer);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusNoBuffer);
break;
case ReassemblyTimeout:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Reassembly Timeout detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvReassemblyErr);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvReassemblyErr);
break;
case PktTooLongErr:
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Packet Too Long detected, discard packet.\n"));
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvPdusError);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvPdusError);
break;
}
continue;
}
//
// Save Vc info to this receive buffer.
//
pRecvBufHead->pVc = pVc;
if ((pEntryOfRxReportQ->RxReportQDWord1.Sop == 0) &&
(NULL == pSegCompleting->BufListHead))
{
//
// The SOP of the packet is lost.
// Return this receive buffer to the free pool.
//
DBGPRINT(DBG_COMP_SPECIAL, DBG_LEVEL_ERR,
("Lost the SOP of the packet, discard packet.\n"));
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
continue;
}
if (pEntryOfRxReportQ->RxReportQDWord1.Sop)
{
if ((pEntryOfRxReportQ->RxReportQDWord1.Eop) &&
(1 == pEntryOfRxReportQ->RxReportQDWord1.Status))
{
//
// AAL5 Reassembly Timeout.
// Return this receive buffer to the free pool.
//
DBGPRINT(DBG_COMP_SPECIAL, DBG_LEVEL_ERR,
("Experienced reassembly timeout. discard packet.\n"));
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
continue;
}
NdisDprReleaseSpinLock(&pRecvDmaQ->lock);
NdisDprAcquireSpinLock(&pVc->lock);
//
// Verify if the VC is still active again for just in case.
//
if (!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_RECEIVE)))
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("We don't have a valid VC_BLOCK now: 0x%x for VCI: %u\n", pVc, Vci));
NdisDprReleaseSpinLock(&pVc->lock);
NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
//
// Return the receive buffer to the free pool.
//
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvBufHead, TRUE);
continue;
}
//
// Reference the VC
//
tbAtm155ReferenceVc(pVc);
NdisDprReleaseSpinLock(&pVc->lock);
NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
//
// This flag indicates if the slot being reported contains
// the first byte of an AAL5 packet.
// Also, it may be used by the driver to detect error conditions
// which may not have been reported due to lack of slots
// (receive congestion).
//
if (NULL != pSegCompleting->BufListHead)
{
NdisDprReleaseSpinLock(&pRecvDmaQ->lock);
//
// It is possible that receive congestion happened.
// Abort the receive buffers in the list.
//
tbAtm155ProcessReturnPacket(
pAdapter,
pSegCompleting->BufListHead->Packet,
pSegCompleting->BufListHead,
FALSE);
NdisDprAcquireSpinLock(&pRecvDmaQ->lock);
//
// Check if the buffer has been freed in tbAtm155ProcessReturnPacket()
//
if (NULL != pRecvSegInfo)
{
pSegCompleting->BufListHead = NULL;
pSegCompleting->BufListTail = NULL;
pSegCompleting->BufferCount = 0;
}
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.RecvCellsDropped);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.RecvCellsDropped);
}
//
// Grab a packet for the receive.
//
Packet = pRecvBufHead->Packet;
//
// Save the first receive buffer to be used with the packet.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -