FreeBSD/sys/dev/e1000/if_em.c
/*********************************************************************
 *
 *  This routine executes in interrupt context. It replenishes
 *  the mbufs in the descriptor and sends data which has been
 *  dma'ed into host memory to upper layer.
 *
 *  We loop at most count times if count is > 0, or until done if
 *  count < 0.
 *  
 *  For polling we also now return the number of cleaned packets
 *********************************************************************/
This routine executes in interrupt context. It replenishes
the mbufs in the descriptor and sends data which has been
dma'ed into host memory to upper layer.

We loop at most count times if count is > 0, or until done if
count < 0.

For polling we also now return the number of cleaned packets
This routine executes in interrupt context . It replenishes the mbufs in the descriptor and sends data which has been dma ' ed into host memory to upper layer . We loop at most count times if count is > 0 or until done if count < 0 . For polling we also now return the number of cleaned packets
static bool
em_rxeof(struct rx_ring *rxr, int count, int *done)
{
	struct adapter		*adapter = rxr->adapter;
	if_t ifp = adapter->ifp;
	struct mbuf		*mp, *sendmp;
	u32			status = 0;
	u16 			len;
	int			i, processed, rxdone = 0;
	bool			eop;
	union e1000_rx_desc_extended	*cur;
	EM_RX_LOCK(rxr);
	bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
#ifdef DEV_NETMAP
	if (netmap_rx_irq(ifp, rxr->me, &processed)) {
		EM_RX_UNLOCK(rxr);
		return (FALSE);
	}
#endif 
	for (i = rxr->next_to_check, processed = 0; count != 0;) {
		if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
			break;
		cur = &rxr->rx_base[i];
		status = le32toh(cur->wb.upper.status_error);
		mp = sendmp = NULL;
		if ((status & E1000_RXD_STAT_DD) == 0)
			break;
		len = le16toh(cur->wb.upper.length);
		eop = (status & E1000_RXD_STAT_EOP) != 0;
		if ((status & E1000_RXDEXT_ERR_FRAME_ERR_MASK) ||
		    (rxr->discard == TRUE)) {
			adapter->dropped_pkts++;
			++rxr->rx_discarded;
			if (!eop) 
				rxr->discard = TRUE;
			else
				rxr->discard = FALSE;
			em_rx_discard(rxr, i);
			goto next_desc;
		}
		bus_dmamap_unload(rxr->rxtag, rxr->rx_buffers[i].map);
		mp = rxr->rx_buffers[i].m_head;
		mp->m_len = len;
		rxr->rx_buffers[i].m_head = NULL;
		if (rxr->fmp == NULL) {
			mp->m_pkthdr.len = len;
			rxr->fmp = rxr->lmp = mp;
		} else {
			mp->m_flags &= ~M_PKTHDR;
			rxr->lmp->m_next = mp;
			rxr->lmp = mp;
			rxr->fmp->m_pkthdr.len += len;
		}
		if (eop) {
			--count;
			sendmp = rxr->fmp;
			if_setrcvif(sendmp, ifp);
			if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
			em_receive_checksum(status, sendmp);
#ifndef __NO_STRICT_ALIGNMENT
			if (adapter->hw.mac.max_frame_size >
			    (MCLBYTES - ETHER_ALIGN) &&
			    em_fixup_rx(rxr) != 0)
				goto skip;
#endif
			if (status & E1000_RXD_STAT_VP) {
				if_setvtag(sendmp, 
				    le16toh(cur->wb.upper.vlan));
				sendmp->m_flags |= M_VLANTAG;
			}
#ifndef __NO_STRICT_ALIGNMENT
skip:
#endif
			rxr->fmp = rxr->lmp = NULL;
		}
next_desc:
		bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
	    		BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
		cur->wb.upper.status_error &= htole32(~0xFF);
		++rxdone;	
		++processed;
		if (++i == adapter->num_rx_desc)
			i = 0;
		if (sendmp != NULL) {
			rxr->next_to_check = i;
			EM_RX_UNLOCK(rxr);
			if_input(ifp, sendmp);
			EM_RX_LOCK(rxr);
			i = rxr->next_to_check;
		}
		if (processed == 8) {
			em_refresh_mbufs(rxr, i);
			processed = 0;
		}
	}
	if (e1000_rx_unrefreshed(rxr))
		em_refresh_mbufs(rxr, i);
	rxr->next_to_check = i;
	if (done != NULL)
		*done = rxdone;
	EM_RX_UNLOCK(rxr);
	return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE);
}
static bool em_rxeof ( struct rx_ring * rxr , int count , int * done ) { struct adapter * adapter = rxr -> adapter ; if_t ifp = adapter -> ifp ; struct mbuf * mp , * sendmp ; u32 status = 0 ; u16 len ; int i , processed , rxdone = 0 ; bool eop ; union e1000_rx_desc_extended * cur ; EM_RX_LOCK ( rxr ) ; bus_dmamap_sync ( rxr -> rxdma . dma_tag , rxr -> rxdma . dma_map , BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE ) ; #ifdef DEV_NETMAP if ( netmap_rx_irq ( ifp , rxr -> me , & processed ) ) { EM_RX_UNLOCK ( rxr ) ; return ( FALSE ) ; } #endif for ( i = rxr -> next_to_check , processed = 0 ; count != 0 ; ) { if ( ( if_getdrvflags ( ifp ) & IFF_DRV_RUNNING ) == 0 ) break ; cur = & rxr -> rx_base [ i ] ; status = le32toh ( cur -> wb . upper . status_error ) ; mp = sendmp = NULL ; if ( ( status & E1000_RXD_STAT_DD ) == 0 ) break ; len = le16toh ( cur -> wb . upper . length ) ; eop = ( status & E1000_RXD_STAT_EOP ) != 0 ; if ( ( status & E1000_RXDEXT_ERR_FRAME_ERR_MASK ) || ( rxr -> discard == TRUE ) ) { adapter -> dropped_pkts ++ ; ++ rxr -> rx_discarded ; if ( ! eop ) rxr -> discard = TRUE ; else rxr -> discard = FALSE ; em_rx_discard ( rxr , i ) ; goto next_desc ; } bus_dmamap_unload ( rxr -> rxtag , rxr -> rx_buffers [ i ] . map ) ; mp = rxr -> rx_buffers [ i ] . m_head ; mp -> m_len = len ; rxr -> rx_buffers [ i ] . m_head = NULL ; if ( rxr -> fmp == NULL ) { mp -> m_pkthdr . len = len ; rxr -> fmp = rxr -> lmp = mp ; } else { mp -> m_flags &= ~ M_PKTHDR ; rxr -> lmp -> m_next = mp ; rxr -> lmp = mp ; rxr -> fmp -> m_pkthdr . len += len ; } if ( eop ) { -- count ; sendmp = rxr -> fmp ; if_setrcvif ( sendmp , ifp ) ; if_inc_counter ( ifp , IFCOUNTER_IPACKETS , 1 ) ; em_receive_checksum ( status , sendmp ) ; #ifndef __NO_STRICT_ALIGNMENT if ( adapter -> hw . mac . max_frame_size > ( MCLBYTES - ETHER_ALIGN ) && em_fixup_rx ( rxr ) != 0 ) goto skip ; #endif if ( status & E1000_RXD_STAT_VP ) { if_setvtag ( sendmp , le16toh ( cur -> wb . upper . vlan ) ) ; sendmp -> m_flags |= M_VLANTAG ; } #ifndef __NO_STRICT_ALIGNMENT skip : #endif rxr -> fmp = rxr -> lmp = NULL ; } next_desc : bus_dmamap_sync ( rxr -> rxdma . dma_tag , rxr -> rxdma . dma_map , BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE ) ; cur -> wb . upper . status_error &= htole32 ( ~ 0xFF ) ; ++ rxdone ; ++ processed ; if ( ++ i == adapter -> num_rx_desc ) i = 0 ; if ( sendmp != NULL ) { rxr -> next_to_check = i ; EM_RX_UNLOCK ( rxr ) ; if_input ( ifp , sendmp ) ; EM_RX_LOCK ( rxr ) ; i = rxr -> next_to_check ; } if ( processed == 8 ) { em_refresh_mbufs ( rxr , i ) ; processed = 0 ; } } if ( e1000_rx_unrefreshed ( rxr ) ) em_refresh_mbufs ( rxr , i ) ; rxr -> next_to_check = i ; if ( done != NULL ) * done = rxdone ; EM_RX_UNLOCK ( rxr ) ; return ( ( status & E1000_RXD_STAT_DD ) ? TRUE : FALSE ) ; }
This routine executes in interrupt context.
This routine executes in interrupt context .
/* Sync the ring */ /* DEV_NETMAP */ /* Catch subsequent segs */ /* Assign correct length to the current fragment */ /* Trigger for refresh */ /* First segment? */ /* Chain mbuf's together */ /* Sync the ring */ /* Zero out the receive descriptors status. */ /* cumulative for POLL */ /* Advance our pointers to the next descriptor. */ /* Send to the stack */ /* Only refresh mbufs every 8 descriptors */ /* Catch any remaining refresh work */