Esempio n. 1
0
__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;
}
Esempio n. 2
0
__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;
	}
}