📄 sky2.c
字号:
SK_OUT32(IoC, Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG), GET_PUT_IDX(pLETab)); } /* Update put index */ UPDATE_HWPUT_IDX(pLETab); } } SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("<== GiveRxBufferToHw()\n"));} /* GiveRxBufferToHw *//*********************************************************************** * * FillReceiveTableYukon2 - map any waiting RX buffers to HW * * Description: * If the list element table contains more empty elements than * specified this function tries to refill them. * * Notes: * This function can run only once per port in a system at one time. * * Returns: N/A */void FillReceiveTableYukon2(SK_AC *pAC, /* pointer to adapter control context */SK_IOC IoC, /* I/O control context */int Port) /* port index of RX */{ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("==> FillReceiveTableYukon2 (Port %c)\n", 'A' + Port)); if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) > pAC->MaxUnusedRxLeWorking) { /* ** Give alle waiting receive buffers down ** The queue holds all RX packets that ** need a fresh allocation of the sk_buff. */ if (pAC->RxPort[Port].RxQ_waiting.pHead != NULL) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("Waiting queue is not empty -> give it to HW")); GiveRxBufferToHw(pAC, IoC, Port, NULL); } } SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("<== FillReceiveTableYukon2 ()\n"));} /* FillReceiveTableYukon2 *//****************************************************************************** * * * HandleReceives - will pass any ready RX packet to kernel * * Description: * This functions handles a received packet. It checks wether it is * valid, updates the receive list element table and gives the receive * buffer to Linux * * Notes: * This function can run only once per port at one time in the system. * * Returns: N/A */static SK_BOOL HandleReceives(SK_AC *pAC, /* adapter control context */int Port, /* port on which a packet has been received */SK_U16 FrameLength, /* number of bytes which was actually received */SK_U32 FrameStatus, /* MAC frame status word */SK_U16 Tcp1, /* first hw checksum */SK_U16 Tcp2, /* second hw checksum */SK_U32 Tist, /* timestamp */SK_U16 Vlan /* Vlan Id */#ifdef SK_EXTREME, SK_U32 ExtremeCsumResult#endif){ SK_PACKET *pSkPacket; SK_LE_TABLE *pLETab; SK_MBUF *pRlmtMbuf; /* buffer for giving RLMT frame */ struct sk_buff *pMsg; /* ptr to message holding frame */#ifdef __ia64__ struct sk_buff *pNewMsg; /* used when IP aligning */#endif SK_BOOL IsGoodPkt; SK_BOOL IsBc; SK_BOOL IsMc; SK_EVPARA EvPara; /* an event parameter union */ SK_I16 LenToFree; /* must be signed integer */ unsigned long Flags; /* for spin lock */ unsigned int RlmtNotifier; unsigned short Type; int IpFrameLength; int HeaderLength; int NumBytes; int Result; int Offset = 0; SK_U16 HighVal; SK_BOOL CheckBcMc = SK_FALSE;#ifdef Y2_SYNC_CHECK SK_U16 MyTcp;#endif#ifdef USE_ASF_DASH_FW static SK_U8 CntNetWUPP = 0; /* Count Network Stack Wake Up Packet Passes */ SK_U8 ret8;#endif SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("==> HandleReceives (Port %c)\n", 'A' + Port)); if (HW_FEATURE(pAC, HWF_WA_DEV_521)) { HighVal = (SK_U16)(((FrameStatus) & GMR_FS_LEN_MSK) >> GMR_FS_LEN_SHIFT); if ((HighVal > ETH_MAX_LEN) || (FrameStatus == 0x7ffc0001)) { FrameStatus = 0; } else if (HighVal != FrameLength) { SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("521: We take pkt len %x stat: %x\n", FrameLength, FrameStatus)); /* ** Try to recover the status word. The multicast and broadcast bits ** from status word are set when we have a valid packet header. */ FrameStatus = 0; /* Set the ReceiveOK bit. */ FrameStatus |= GMR_FS_RX_OK; /* Set now the length into the status word */ FrameStatus |= (FrameLength << GMR_FS_LEN_SHIFT); /* Insure that bit 31 is reset */ FrameStatus &= ~GMR_FS_LKUP_BIT2; CheckBcMc = SK_TRUE; } } /* ** Check whether we want to receive this packet */ SK_Y2_RXSTAT_CHECK_PKT(FrameLength, FrameStatus, IsGoodPkt); /* ** Take first receive buffer out of working queue */ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket); if (pSkPacket == NULL) { SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, ("Packet not available. NULL pointer.\n")); return(SK_TRUE); } if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { NbrRxBuffersInHW--; } /* ** Verify the received length of the frame! Note that having ** multiple RxBuffers being aware of one single receive packet ** (one packet spread over multiple RxBuffers) is not supported ** by this driver! */ if ((FrameLength > pAC->RxPort[Port].RxBufSize) || (FrameLength > (SK_U16) pSkPacket->PacketLen)) { IsGoodPkt = SK_FALSE; } /* ** Initialize vars for selected port */ pLETab = &pAC->RxPort[Port].RxLET; /* ** Reset own bit in LE's between old and new Done index ** This is not really necessary but makes debugging easier */ CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE); /* ** Free the list elements for new Rx buffers */ SET_DONE_INDEX(pLETab, pSkPacket->NextLE); pMsg = pSkPacket->pMBuf; SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("Received frame of length %d on port %d\n",FrameLength, Port)); if (!IsGoodPkt) { /* ** release the DMA mapping */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) pci_dma_sync_single(pAC->PciDev, (dma_addr_t) pSkPacket->pFrag->pPhys, pSkPacket->pFrag->FragLen, PCI_DMA_FROMDEVICE);#else pci_dma_sync_single_for_cpu(pAC->PciDev, (dma_addr_t) pSkPacket->pFrag->pPhys, pSkPacket->pFrag->FragLen, PCI_DMA_FROMDEVICE);#endif DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, ("<== HandleReceives (Port %c)\n", 'A' + Port)); /* ** Sanity check for RxBuffer overruns... */ LenToFree = FrameLength - (pSkPacket->pFrag->FragLen); while (LenToFree > 0) { POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket); if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { NbrRxBuffersInHW--; } CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE); SET_DONE_INDEX(pLETab, pSkPacket->NextLE);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) pci_dma_sync_single(pAC->PciDev, (dma_addr_t) pSkPacket->pFrag->pPhys, pSkPacket->pFrag->FragLen, PCI_DMA_FROMDEVICE);#else pci_dma_sync_single_for_device(pAC->PciDev, (dma_addr_t) pSkPacket->pFrag->pPhys, pSkPacket->pFrag->FragLen, PCI_DMA_FROMDEVICE); #endif DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); LenToFree = LenToFree - ((SK_I16)(pSkPacket->pFrag->FragLen)); SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, ("<==HandleReceives (Port %c) drop faulty len pkt(2)\n",'A'+Port)); } return(SK_TRUE); } else { /* ** Release the DMA mapping */ pci_unmap_single(pAC->PciDev, pSkPacket->pFrag->pPhys, pAC->RxPort[Port].RxBufSize, PCI_DMA_FROMDEVICE); skb_put(pMsg, FrameLength); /* set message len */ pMsg->ip_summed = CHECKSUM_NONE; /* initial default */#ifdef Y2_SYNC_CHECK pAC->FramesWithoutSyncCheck++; if (pAC->FramesWithoutSyncCheck > Y2_RESYNC_WATERMARK) { if ((Tcp1 != 1) || (Tcp2 != 0)) { pAC->FramesWithoutSyncCheck = 0; MyTcp = (SK_U16) SkCsCalculateChecksum( &pMsg->data[14], FrameLength - 14); if (MyTcp != Tcp1) { /* Queue port reset event */ SkLocalEventQueue(pAC, SKGE_DRV, SK_DRV_RECOVER,Port,-1,SK_FALSE); } } }#endif if (pAC->RxPort[Port].UseRxCsum) {#ifdef SK_EXTREME if (HW_IS_EXT_LE_FORMAT(pAC)) { /* Checksum calculation for Yukon Extreme */ if (CSS_IS_IPV4(ExtremeCsumResult) && CSS_IPV4_CSUM_OK(ExtremeCsumResult)) { pMsg->ip_summed = CHECKSUM_UNNECESSARY; } else { pMsg->ip_summed = CHECKSUM_NONE; } } else {#endif Type = ntohs(*((short*)&pMsg->data[12])); if (Type == 0x800) { *((char *)&(IpFrameLength)) = pMsg->data[16]; *(((char *)&(IpFrameLength))+1) = pMsg->data[17]; IpFrameLength = ntohs(IpFrameLength); HeaderLength = FrameLength - IpFrameLength; if (HeaderLength == 0xe) { Result = SkCsGetReceiveInfo(pAC,&pMsg->data[14],Tcp1,Tcp2, Port, IpFrameLength); if ((Result == SKCS_STATUS_IP_FRAGMENT) || (Result == SKCS_STATUS_IP_CSUM_OK) || (Result == SKCS_STATUS_TCP_CSUM_OK) || (Result == SKCS_STATUS_UDP_CSUM_OK)) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) pMsg->ip_summed = CHECKSUM_COMPLETE; pMsg->csum = Tcp1 & 0xffff;#else pMsg->ip_summed = CHECKSUM_UNNECESSARY;#endif } else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR) || (Result == SKCS_STATUS_UDP_CSUM_ERROR) || (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) || (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) || (Result == SKCS_STATUS_IP_CSUM_ERROR)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, ("skge: CRC error. Frame dropped!\n")); DEV_KFREE_SKB_ANY(pMsg); PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_RX_PROGRESS, ("<==HandleReceives(Port %c)\n",'A'+Port)); return(SK_TRUE); } else { pMsg->ip_summed = CHECKSUM_NONE; } } /* end if (HeaderLength == valid) */ } /* end if (Type == 0x800) -> IP frame */#ifdef SK_EXTREME } /* if (HW_IS_EXT_LE_FORMAT(pAC)) */#endif } /* end if (pRxPort->UseRxCsum) */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,("V")); RlmtNotifier = SK_RLMT_RX_PROTOCOL; if (CheckBcMc == SK_TRUE) { /* Check if this is a broadcast packet */ if (SK_ADDR_EQUAL(pMsg->data, "\xFF\xFF\xFF\xFF\xFF\xFF")) { /* Broadcast packet */ FrameStatus |= GMR_FS_BC; } else if (pMsg->data[0] & 0x01) { /* Multicast packet */ FrameStatus |= GMR_FS_MC; } } IsBc = (FrameStatus & GMR_FS_BC) ? SK_TRUE : SK_FALSE; SK_RLMT_PRE_LOOKAHEAD(pAC,Port,FrameLength, IsBc,&Offset,&NumBytes); if (NumBytes != 0) { IsMc = (FrameStatus & GMR_FS_MC) ? SK_TRUE : SK_FALSE; SK_RLMT_LOOKAHEAD(pAC,Port,&pMsg->data[Offset], IsBc,IsMc,&RlmtNotifier); } if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) { SK_DBG_MSG(NULL,SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,("W")); if ((Port == pAC->ActivePort)||(pAC->RlmtNets == 2)) { /* send up only frames from active port */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,("U"));#ifdef SK_ASF#ifdef USE_ASF_DASH_FW pAC->ReceivedPacket = SK_TRUE; if ( (pAC->SendWolPattern == SK_TRUE) && (pAC->MaxPorts > 0) ) { CntNetWUPP++; if (CntNetWUPP > 5) { printk("sk98lin: Wakeup packet could not be passed to protocol stack (more than 5 retries)\n"); pAC->SendWolPattern = SK_FALSE; CntNetWUPP = 0; } else { /* Read pattern from ASF Fifo and send it up the stack. */ SetRamAddr(pAC, SK_ST_FIFOTYPE, SK_ST_BUFADDR_LOW, SK_ST_BUFADDR_HIGH); ret8 = AccessRamBuf(pAC, SK_ST_BUFSIZE, SK_TRUE); if (ret8 == 0) { pAC->SendWolPattern = SK_FALSE; printk("sk98lin: Wakeup packet passed to protocol stack (%u retries)\n", (CntNetWUPP-1) ); CntNetWUPP = 0; } if (ret8 == 2) { pAC->SendWolPattern = SK_FALSE; printk("sk98lin: No wakeup packet passed to protocol stack (other reason)\n"); CntNetWUPP = 0; } } }#endif#endif#ifdef xDEBUG DumpMsg(pMsg, "Rx");#endif SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, FrameLength, Port);#ifdef __ia64__ pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC); skb_reserve(pNewMsg, 2); /* to align IP */ SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len); pNewMsg->ip_summed = pMsg->ip_summed; skb_put(pNewMsg, pMsg->len); DEV_KFREE_SKB_ANY(pMsg); pMsg = pNewMsg;#endif pMsg->dev = pAC->dev[Port]; pMsg->protocol = eth_type_trans(pMsg, pAC->dev[Port]);#ifdef CONFIG_SK98LIN_NAPI netif_receive_skb(pMsg);#else netif_rx(pMsg);#endif pAC->dev[Port]->last_rx = jiffies; } else { /* drop frame */ SK_DBG_MSG(NULL,SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,("D")); DEV_KFREE_SKB_ANY(pMsg); } } else { /* This is an RLMT-packet! */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -