__IRAM static int32 _swNic_recvLoop(int32 last){ volatile struct rtl_pktHdr * pPkthdr; //don't optimize volatile struct rtl_mBuf * pMbuf; //don't optimize int32 count=0; do{ #ifdef CONFIG_RTL865X_ROMEPERF rtl8651_romeperfEnterPoint(ROMEPERF_INDEX_RECVLOOP); #endif /* Increment counter */ if((RxPkthdrRing[rxPhdrIndex]&DESC_OWNED_BIT)==1){ goto out; } #ifdef SWNIC_EARLYSTOP if(nicRxEarlyStop && ((count & nicRxEarlyStop)==nicRxEarlyStop)){//check global interrupt status uint32 gisrNow = REG32(GISR); if(gisrNow & 0x65000000){ //Bit 30: USB, Bit 29:PCMCIA, Bit 26: PCI, Bit 24:GPIO nicRxAbort=1; goto out; } } #endif #ifdef CONFIG_RTL865X_CACHED_NETWORK_IO #if 0 /*Invalidate D-Cache*/ lx4180_writeCacheCtrl(0); lx4180_writeCacheCtrl(1); lx4180_writeCacheCtrl(0); pPkthdr = (struct rtl_pktHdr *) (RxPkthdrRing[rxPhdrIndex] & ~(DESC_OWNED_BIT | DESC_WRAP)); pMbuf = pPkthdr->ph_mbuf; #else pPkthdr = (struct rtl_pktHdr *) (RxPkthdrRing[rxPhdrIndex] & ~(DESC_OWNED_BIT | DESC_WRAP)); pMbuf = pPkthdr->ph_mbuf; //force update d-cache if hit. src32=(uint32 *)UNCACHE(pPkthdr); dst32=(uint32 *)CACHED(pPkthdr); dst32[0]=src32[0]; dst32[1]=src32[1]; dst32[2]=src32[2]; dst32[3]=src32[3]; src32=(uint32 *)UNCACHE(pMbuf); dst32=(uint32 *)CACHED(pMbuf); dst32[0]=src32[0]; dst32[1]=src32[1]; dst32[2]=src32[2]; dst32[3]=src32[3]; //pkt from ASIC, convert to uncached data pointer for used in //fwd engine pMbuf->m_data=UNCACHE(pMbuf->m_data); pMbuf->m_extbuf=UNCACHE(pMbuf->m_extbuf); #endif #else pPkthdr = (struct rtl_pktHdr *) (RxPkthdrRing[rxPhdrIndex] & ~(DESC_OWNED_BIT | DESC_WRAP)); pMbuf = pPkthdr->ph_mbuf; #endif //CONFIG_RTL865X_CACHED_NETWORK_IO #ifdef CONFIG_RTL865XB_EXP_PERFORMANCE_EVALUATION if(_pernicStart == TRUE){ static uint32 start, end; if(!_pernicPktCount){ startCOP3Counters(_pernicInst); start = jiffies; } else if(_pernicPktCount == _pernicPktLimit){ end = jiffies; stopCOP3Counters(); printk("%d pkts. Total %d bytes, %d ms. %u KBps\n", _pernicPktCount, _pernicByteCount, (uint32)((end-start)*10), (uint32)(_pernicByteCount/((end-start)*10))); _pernicStart = FALSE; } _pernicPktCount++; _pernicByteCount += pPkthdr->ph_len + 4; swNic_isrReclaim(rxPhdrIndex, pPkthdr, pMbuf); /* Increment index */ if ( ++rxPhdrIndex == totalRxPkthdr ) rxPhdrIndex = 0; if ( ++rxMbufIndex == totalRxMbuf ) rxMbufIndex = 0; continue; } #endif assert(pPkthdr->ph_len>0); if((pPkthdr->ph_flags&PKTHDR_DRIVERHOLD)==0){ //exception handling swNic_rxRunoutTxPending((struct rtl_pktHdr *)pPkthdr); goto out; } count++; //SETBITS(pPkthdr->ph_flags, PKT_INCOMING); //packet from physical port pPkthdr->ph_rxdesc=rxPhdrIndex; pPkthdr->ph_flags&=~PKTHDR_DRIVERHOLD; //Transform extension port numbers to continuous number for fwd engine. #ifdef CONFIG_RTL865X_MULTILAYER_BSP //Default run this except L2 BSP. //must call this API after rxPhdrIndex is assigned... if(rtl8651_rxPktPreprocess(pPkthdr)){ rtlglue_printf("Drop rxDesc=%d\n",rxPhdrIndex ); //memDump(pPkthdr->ph_mbuf->m_data, pPkthdr->ph_len,"Loopback Pkt"); swNic_isrReclaim(rxPhdrIndex, pPkthdr, pMbuf); }else #endif { #ifdef CONFIG_RTL865X_ROMEREAL rtl8651_romerealRecord( pPkthdr, 0x00000001 ); #endif/*CONFIG_RTL865X_ROMEREAL*/ /* Invoked installed function pointer to handle packet */ (*installedProcessInputPacket)((struct rtl_pktHdr*)pPkthdr); } #ifdef SWNIC_DEBUG assert(rxPhdrIndex==rxMbufIndex); #endif /* Increment index */ if ( ++rxPhdrIndex == totalRxPkthdr ) rxPhdrIndex = 0; if ( ++rxMbufIndex == totalRxMbuf ) rxMbufIndex = 0; }while(last>=0&&rxPhdrIndex!=last); out: return count; }
__MIPS16 __IRAM_FWD int32 swNic_receive(rtl_nicRx_info *info, int retryCount) { struct rtl_pktHdr * pPkthdr; unsigned char *buf; void *skb; uint32 rxRingIdx; uint32 currRxPktDescIdx; #if defined(CONFIG_RTL_HARDWARE_NAT) uint32 vid; #endif get_next: /* Check OWN bit of descriptors */ #if defined(RTL_MULTIPLE_RX_TX_RING) if (swNic_getRxringIdx(&rxRingIdx,&currRxPktDescIdx,info->priority) == SUCCESS ) #else rxRingIdx = 0; if (__swNic_geRxRingIdx(rxRingIdx,&currRxPktDescIdx)==SUCCESS) #endif { /* Fetch pkthdr */ #ifdef CONFIG_RTL_ENHANCE_RELIABILITY pPkthdr = (struct rtl_pktHdr *) (rxPkthdrRing_base[rxRingIdx] + (sizeof(struct rtl_pktHdr) * currRxPktDescIdx)); #else pPkthdr = (struct rtl_pktHdr *) (rxPkthdrRing[rxRingIdx][currRxPktDescIdx] & ~(DESC_OWNED_BIT | DESC_WRAP)); #endif /* Increment counter */ //rxPktCounter++; #if defined(_PKTHDR_CACHEABLE) _dma_cache_inv((unsigned long)pPkthdr, sizeof(struct rtl_pktHdr)); _dma_cache_inv((unsigned long)(pPkthdr->ph_mbuf), sizeof(struct rtl_mBuf)); #endif _dma_cache_inv((unsigned long)(((struct sk_buff *)pPkthdr->ph_mbuf->skb)->data), pPkthdr->ph_len-4); /* checksum error drop it */ if ((pPkthdr->ph_flags & (CSUM_TCPUDP_OK | CSUM_IP_OK)) != (CSUM_TCPUDP_OK | CSUM_IP_OK)) { RTL_ETH_NIC_DROP_RX_PKT_RESTART; goto get_next; } #if defined(CONFIG_RTL_HARDWARE_NAT) if (rtl8651_rxPktPreprocess(pPkthdr, &vid) != 0) { RTL_ETH_NIC_DROP_RX_PKT_RESTART; goto get_next; } else { #if defined(SKIP_ALLOC_RX_BUFF) buf = NULL; #else buf = alloc_rx_buf(&skb, size_of_cluster); #endif } info->vid = vid; #else /* * vid is assigned in rtl8651_rxPktPreprocess() * do not update it when CONFIG_RTL_HARDWARE_NAT is defined */ info->vid=pPkthdr->ph_vlanId; #if defined(SKIP_ALLOC_RX_BUFF) buf = NULL; #else buf = alloc_rx_buf(&skb, size_of_cluster); #endif #endif #ifdef CONFIG_RTL_VLAN_8021Q //info->srcvid=pPkthdr->ph_svlanId; info->srcvid=pPkthdr->ph_vlanId; #endif #if defined(CONFIG_RTL_8198C) info->pid=(pPkthdr->ph_portlist&0x7); #else info->pid=pPkthdr->ph_portlist; #endif if (buf) { info->input = pPkthdr->ph_mbuf->skb; info->len = pPkthdr->ph_len - 4; /* Increment index */ increase_rx_idx_release_pkthdr(skb, rxRingIdx); REG32(CPUIISR) = (MBUF_DESC_RUNOUT_IP_ALL|PKTHDR_DESC_RUNOUT_IP_ALL); } #if defined(DELAY_REFILL_ETH_RX_BUF) else if (!buffer_reuse(rxRingIdx)) { info->input = pPkthdr->ph_mbuf->skb; info->len = pPkthdr->ph_len - 4; //printk("====CPU is pending====\n"); #if defined(CONFIG_RTL_ETH_PRIV_SKB_DEBUG) mbuf_pending_times ++; #endif /* we do not free this skbuff in swNic_freeRxBuf() */ pPkthdr->ph_mbuf->skb = NULL; /* Increment index */ swNic_increaseRxIdx(rxRingIdx); } #endif else { #if defined(CONFIG_RTL_PROC_DEBUG)||defined(CONFIG_RTL_DEBUG_TOOL) rx_noBuffer_cnt++; #endif #if 0 if (retryCount>RTL_NIC_RX_RETRY_MAX) { /* drop pkt */ increase_rx_idx_release_pkthdr((void*)pPkthdr->ph_mbuf->skb, rxRingIdx); } return RTL_NICRX_REPEAT; #else return RTL_NICRX_NULL; #endif } #if defined(RTL_MULTIPLE_RX_TX_RING) info->priority = rxRingIdx; #endif return RTL_NICRX_OK; } else { return RTL_NICRX_NULL; } }