📄 skge.c
字号:
*/ pTxPort->pTxdRingTail = pTxd; netif_wake_queue(pAC->dev[pTxPort->PortIndex]); return; } if (Control & BMU_OWN) { pTxPort->pTxdRingTail = pTxd; if (pTxPort->TxdRingFree > 0) { netif_wake_queue(pAC->dev[pTxPort->PortIndex]); } return; } /* ** release the DMA mapping, because until not unmapped ** this buffer is considered being under control of the ** adapter card! */ PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; PhysAddr |= (SK_U64) pTxd->VDataLow; pci_unmap_page(pAC->PciDev, PhysAddr, pTxd->pMBuf->len, PCI_DMA_TODEVICE); if (Control & BMU_EOF) DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */ pTxPort->TxdRingFree++; pTxd->TBControl &= ~BMU_SW; pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ } /* while(forever) */} /* FreeTxDescriptors *//***************************************************************************** * * FillRxRing - fill the receive ring with valid descriptors * * Description: * This function fills the receive ring descriptors with data * segments and makes them valid for the BMU. * The active ring is filled completely, if possible. * The non-active ring is filled only partial to save memory. * * Description of rx ring structure: * head - points to the descriptor which will be used next by the BMU * tail - points to the next descriptor to give to the BMU * * Returns: N/A */static void FillRxRing(SK_AC *pAC, /* pointer to the adapter context */RX_PORT *pRxPort) /* ptr to port struct for which the ring should be filled */{unsigned long Flags; spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) { if(!FillRxDescriptor(pAC, pRxPort)) break; } spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);} /* FillRxRing *//***************************************************************************** * * FillRxDescriptor - fill one buffer into the receive ring * * Description: * The function allocates a new receive buffer and * puts it into the next descriptor. * * Returns: * SK_TRUE - a buffer was added to the ring * SK_FALSE - a buffer could not be added */static SK_BOOL FillRxDescriptor(SK_AC *pAC, /* pointer to the adapter context struct */RX_PORT *pRxPort) /* ptr to port struct of ring to fill */{struct sk_buff *pMsgBlock; /* pointer to a new message block */RXD *pRxd; /* the rxd to fill */SK_U16 Length; /* data fragment length */SK_U64 PhysAddr; /* physical address of a rx buffer */ pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); if (pMsgBlock == NULL) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("%s: Allocation of rx buffer failed !\n", pAC->dev[pRxPort->PortIndex]->name)); SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex); return(SK_FALSE); } skb_reserve(pMsgBlock, 2); /* to align IP frames */ /* skb allocated ok, so add buffer */ pRxd = pRxPort->pRxdRingTail; pRxPort->pRxdRingTail = pRxd->pNextRxd; pRxPort->RxdRingFree--; Length = pAC->RxBufSize; PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, virt_to_page(pMsgBlock->data), ((unsigned long) pMsgBlock->data & ~PAGE_MASK), pAC->RxBufSize - 2, PCI_DMA_FROMDEVICE); pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pRxd->pMBuf = pMsgBlock; pRxd->RBControl = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | Length; return (SK_TRUE);} /* FillRxDescriptor *//***************************************************************************** * * ReQueueRxBuffer - fill one buffer back into the receive ring * * Description: * Fill a given buffer back into the rx ring. The buffer * has been previously allocated and aligned, and its phys. * address calculated, so this is no more necessary. * * Returns: N/A */static void ReQueueRxBuffer(SK_AC *pAC, /* pointer to the adapter context struct */RX_PORT *pRxPort, /* ptr to port struct of ring to fill */struct sk_buff *pMsg, /* pointer to the buffer */SK_U32 PhysHigh, /* phys address high dword */SK_U32 PhysLow) /* phys address low dword */{RXD *pRxd; /* the rxd to fill */SK_U16 Length; /* data fragment length */ pRxd = pRxPort->pRxdRingTail; pRxPort->pRxdRingTail = pRxd->pNextRxd; pRxPort->RxdRingFree--; Length = pAC->RxBufSize; pRxd->VDataLow = PhysLow; pRxd->VDataHigh = PhysHigh; pRxd->pMBuf = pMsg; pRxd->RBControl = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | Length; return;} /* ReQueueRxBuffer *//***************************************************************************** * * ReceiveIrq - handle a receive IRQ * * Description: * This function is called when a receive IRQ is set. * It walks the receive descriptor ring and sends up all * frames that are complete. * * Returns: N/A */static void ReceiveIrq( SK_AC *pAC, /* pointer to adapter context */ RX_PORT *pRxPort, /* pointer to receive port struct */ SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */{RXD *pRxd; /* pointer to receive descriptors */SK_U32 Control; /* control field of descriptor */struct sk_buff *pMsg; /* pointer to message holding frame */struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */int FrameLength; /* total length of received frame */SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */SK_EVPARA EvPara; /* an event parameter union */ unsigned long Flags; /* for spin lock */int PortIndex = pRxPort->PortIndex;unsigned int Offset;unsigned int NumBytes;unsigned int ForRlmt;SK_BOOL IsBc;SK_BOOL IsMc;SK_BOOL IsBadFrame; /* Bad frame */SK_U32 FrameStat;SK_U64 PhysAddr;rx_start: /* do forever; exit if BMU_OWN found */ for ( pRxd = pRxPort->pRxdRingHead ; pRxPort->RxdRingFree < pAC->RxDescrPerRing ; pRxd = pRxd->pNextRxd, pRxPort->pRxdRingHead = pRxd, pRxPort->RxdRingFree ++) { /* * For a better understanding of this loop * Go through every descriptor beginning at the head * Please note: the ring might be completely received so the OWN bit * set is not a good crirteria to leave that loop. * Therefore the RingFree counter is used. * On entry of this loop pRxd is a pointer to the Rxd that needs * to be checked next. */ Control = pRxd->RBControl; /* check if this descriptor is ready */ if ((Control & BMU_OWN) != 0) { /* this descriptor is not yet ready */ /* This is the usual end of the loop */ /* We don't need to start the ring again */ FillRxRing(pAC, pRxPort); return; } pAC->DynIrqModInfo.NbrProcessedDescr++; /* get length of frame and check it */ FrameLength = Control & BMU_BBC; if (FrameLength > pAC->RxBufSize) { goto rx_failed; } /* check for STF and EOF */ if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) { goto rx_failed; } /* here we have a complete frame in the ring */ pMsg = pRxd->pMBuf; FrameStat = pRxd->FrameStat; /* check for frame length mismatch */#define XMR_FS_LEN_SHIFT 18#define GMR_FS_LEN_SHIFT 16 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("skge: Frame length mismatch (%u/%u).\n", FrameLength, (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); goto rx_failed; } } else { if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("skge: Frame length mismatch (%u/%u).\n", FrameLength, (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); goto rx_failed; } } /* Set Rx Status */ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { IsBc = (FrameStat & XMR_FS_BC) != 0; IsMc = (FrameStat & XMR_FS_MC) != 0; IsBadFrame = (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0; } else { IsBc = (FrameStat & GMR_FS_BC) != 0; IsMc = (FrameStat & GMR_FS_MC) != 0; IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) || ((FrameStat & GMR_FS_RX_OK) == 0)); } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, ("Received frame of length %d on port %d\n", FrameLength, PortIndex)); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, ("Number of free rx descriptors: %d\n", pRxPort->RxdRingFree));/* DumpMsg(pMsg, "Rx"); */ if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {#if 0 (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {#endif /* there is a receive error in this frame */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("skge: Error in received frame, dropped!\n" "Control: %x\nRxStat: %x\n", Control, FrameStat)); ReQueueRxBuffer(pAC, pRxPort, pMsg, pRxd->VDataHigh, pRxd->VDataLow); continue; } /* * if short frame then copy data to reduce memory waste */ if ((FrameLength < SK_COPY_THRESHOLD) && ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) { /* * Short frame detected and allocation successfull */ /* use new skb and copy data */ skb_reserve(pNewMsg, 2); skb_put(pNewMsg, FrameLength); PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; PhysAddr |= (SK_U64) pRxd->VDataLow; pci_dma_sync_single_for_cpu(pAC->PciDev, (dma_addr_t) PhysAddr, FrameLength, PCI_DMA_FROMDEVICE); memcpy(pNewMsg->data, pMsg, FrameLength); pci_dma_sync_single_for_device(pAC->PciDev, (dma_addr_t) PhysAddr, FrameLength, PCI_DMA_FROMDEVICE); ReQueueRxBuffer(pAC, pRxPort, pMsg, pRxd->VDataHigh, pRxd->VDataLow); pMsg = pNewMsg; } else { /* * if large frame, or SKB allocation failed, pass * the SKB directly to the networking */ PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; PhysAddr |= (SK_U64) pRxd->VDataLow; /* release the DMA mapping */ pci_unmap_single(pAC->PciDev, PhysAddr, pAC->RxBufSize - 2, PCI_DMA_FROMDEVICE); /* set length in message */ skb_put(pMsg, FrameLength); } /* frame > SK_COPY_TRESHOLD */#ifdef USE_SK_RX_CHECKSUM pMsg->csum = pRxd->TcpSums & 0xffff; pMsg->ip_summed = CHECKSUM_HW;#else pMsg->ip_summed = CHECKSUM_NONE;#endif SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); ForRlmt = SK_RLMT_RX_PROTOCOL;#if 0 IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;#endif SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength, IsBc, &Offset, &NumBytes); if (NumBytes != 0) {#if 0 IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;#endif SK_RLMT_LOOKAHEAD(pAC, PortIndex, &pMsg->data[Offset], IsBc, IsMc, &ForRlmt); } if (ForRlmt == SK_RLMT_RX_PROTOCOL) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); /* send up only frames from active port */ if ((PortIndex == pAC->ActivePort) || (pAC->RlmtNets == 2)) { /* frame for upper layer */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));#ifdef xDEBUG DumpMsg(pMsg, "Rx");#endif SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, FrameLength, pRxPort->PortIndex); pMsg->dev = pAC->dev[pRxPort->PortIndex]; pMsg->protocol = eth_type_trans(pMsg, pAC->dev[pRxPort->PortIndex]); netif_rx(pMsg); pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; } else { /* drop frame */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("D")); DEV_KFREE_SKB(pMsg); } } /* if not for rlmt */ else { /* packet for rlmt */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("R")); pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, pAC->IoBase, FrameLength); if (pRlmtMbuf != NULL) { pRlmtMbuf->pNext = NULL; pRlmtMbuf->Length = FrameLength; pRlmtMbuf->PortIdx = PortIndex; EvPara.pParaPtr = pRlmtMbuf; memcpy((char*)(pRlmtMbuf->pData), (char*)(pMsg->data), FrameLength); /* SlowPathLock needed? */ if (SlowPathLock == SK_TRUE) { spin_lock_irqsave(&pAC->SlowPathLock, Flags); SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PACKET_RECEIVED, EvPara); pAC->CheckQueue = SK_TRUE; spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); } else { SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PACKET_RECEIVED, EvPara); pAC->CheckQueue = SK_TRUE; } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("Q")); } if ((pAC->dev[pRxPort->PortIndex]->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 || (ForRlmt & SK_RLMT_RX_PROTOCOL) == SK_RLMT_RX_PROTOCOL) { pMsg->dev = pAC->dev[pRxPort->PortIndex]; pMsg->protocol = eth_type_trans(pMsg, pAC->dev[pRxPort->PortIndex]); netif_rx(pMsg); pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; } else { DEV_KFREE_SKB(pMsg); } } /* if packet for rlmt */ } /* for ..
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -