FreeBSD/sys/dev/e1000/if_lem.c
/**********************************************************************
 *
 *  Examine each tx_buffer in the used queue. If the hardware is done
 *  processing the packet then free associated resources. The
 *  tx_buffer is put back on the free queue.
 *
 **********************************************************************/
Examine each tx_buffer in the used queue. If the hardware is done
processing the packet then free associated resources. The
tx_buffer is put back on the free queue.
Examine each tx_buffer in the used queue . If the hardware is done processing the packet then free associated resources . The tx_buffer is put back on the free queue .
static void
lem_txeof(struct adapter *adapter)
{
        int first, last, done, num_avail;
        struct em_buffer *tx_buffer;
        struct e1000_tx_desc   *tx_desc, *eop_desc;
	if_t ifp = adapter->ifp;
	EM_TX_LOCK_ASSERT(adapter);
#ifdef DEV_NETMAP
	if (netmap_tx_irq(ifp, 0))
		return;
#endif 
        if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
                return;
        num_avail = adapter->num_tx_desc_avail;
        first = adapter->next_tx_to_clean;
        tx_desc = &adapter->tx_desc_base[first];
        tx_buffer = &adapter->tx_buffer_area[first];
	last = tx_buffer->next_eop;
        eop_desc = &adapter->tx_desc_base[last];
	if (++last == adapter->num_tx_desc)
 		last = 0;
	done = last;
        bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
            BUS_DMASYNC_POSTREAD);
        while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) {
		while (first != done) {
                	tx_desc->upper.data = 0;
                	tx_desc->lower.data = 0;
                	tx_desc->buffer_addr = 0;
                	++num_avail;
			if (tx_buffer->m_head) {
				if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
				bus_dmamap_sync(adapter->txtag,
				    tx_buffer->map,
				    BUS_DMASYNC_POSTWRITE);
				bus_dmamap_unload(adapter->txtag,
				    tx_buffer->map);
                        	m_freem(tx_buffer->m_head);
                        	tx_buffer->m_head = NULL;
                	}
			tx_buffer->next_eop = -1;
			adapter->watchdog_time = ticks;
	                if (++first == adapter->num_tx_desc)
				first = 0;
	                tx_buffer = &adapter->tx_buffer_area[first];
			tx_desc = &adapter->tx_desc_base[first];
		}
		last = tx_buffer->next_eop;
		if (last != -1) {
        		eop_desc = &adapter->tx_desc_base[last];
			if (++last == adapter->num_tx_desc) last = 0;
			done = last;
		} else
			break;
        }
        bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        adapter->next_tx_to_clean = first;
        adapter->num_tx_desc_avail = num_avail;
#ifdef NIC_SEND_COMBINING
	if ((adapter->shadow_tdt & MIT_PENDING_TDT) == MIT_PENDING_TDT) {
		E1000_WRITE_REG(&adapter->hw, E1000_TDT(0),
			0xffff & adapter->shadow_tdt);
		adapter->shadow_tdt = MIT_PENDING_INT;
	} else {
		adapter->shadow_tdt = 0; 
	}
#endif 
        if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) {                
                if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
#ifdef NIC_PARAVIRT
		if (adapter->csb) { 
			adapter->csb->guest_need_txkick = 2; 
		}
#endif 
                if (adapter->num_tx_desc_avail == adapter->num_tx_desc) {
			adapter->watchdog_check = FALSE;
			return;
		} 
        }
}
static void lem_txeof ( struct adapter * adapter ) { int first , last , done , num_avail ; struct em_buffer * tx_buffer ; struct e1000_tx_desc * tx_desc , * eop_desc ; if_t ifp = adapter -> ifp ; EM_TX_LOCK_ASSERT ( adapter ) ; #ifdef DEV_NETMAP if ( netmap_tx_irq ( ifp , 0 ) ) return ; #endif if ( adapter -> num_tx_desc_avail == adapter -> num_tx_desc ) return ; num_avail = adapter -> num_tx_desc_avail ; first = adapter -> next_tx_to_clean ; tx_desc = & adapter -> tx_desc_base [ first ] ; tx_buffer = & adapter -> tx_buffer_area [ first ] ; last = tx_buffer -> next_eop ; eop_desc = & adapter -> tx_desc_base [ last ] ; if ( ++ last == adapter -> num_tx_desc ) last = 0 ; done = last ; bus_dmamap_sync ( adapter -> txdma . dma_tag , adapter -> txdma . dma_map , BUS_DMASYNC_POSTREAD ) ; while ( eop_desc -> upper . fields . status & E1000_TXD_STAT_DD ) { while ( first != done ) { tx_desc -> upper . data = 0 ; tx_desc -> lower . data = 0 ; tx_desc -> buffer_addr = 0 ; ++ num_avail ; if ( tx_buffer -> m_head ) { if_inc_counter ( ifp , IFCOUNTER_OPACKETS , 1 ) ; bus_dmamap_sync ( adapter -> txtag , tx_buffer -> map , BUS_DMASYNC_POSTWRITE ) ; bus_dmamap_unload ( adapter -> txtag , tx_buffer -> map ) ; m_freem ( tx_buffer -> m_head ) ; tx_buffer -> m_head = NULL ; } tx_buffer -> next_eop = -1 ; adapter -> watchdog_time = ticks ; if ( ++ first == adapter -> num_tx_desc ) first = 0 ; tx_buffer = & adapter -> tx_buffer_area [ first ] ; tx_desc = & adapter -> tx_desc_base [ first ] ; } last = tx_buffer -> next_eop ; if ( last != -1 ) { eop_desc = & adapter -> tx_desc_base [ last ] ; if ( ++ last == adapter -> num_tx_desc ) last = 0 ; done = last ; } else break ; } bus_dmamap_sync ( adapter -> txdma . dma_tag , adapter -> txdma . dma_map , BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE ) ; adapter -> next_tx_to_clean = first ; adapter -> num_tx_desc_avail = num_avail ; #ifdef NIC_SEND_COMBINING if ( ( adapter -> shadow_tdt & MIT_PENDING_TDT ) == MIT_PENDING_TDT ) { E1000_WRITE_REG ( & adapter -> hw , E1000_TDT ( 0 ) , 0xffff & adapter -> shadow_tdt ) ; adapter -> shadow_tdt = MIT_PENDING_INT ; } else { adapter -> shadow_tdt = 0 ; } #endif if ( adapter -> num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD ) { if_setdrvflagbits ( ifp , 0 , IFF_DRV_OACTIVE ) ; #ifdef NIC_PARAVIRT if ( adapter -> csb ) { adapter -> csb -> guest_need_txkick = 2 ; } #endif if ( adapter -> num_tx_desc_avail == adapter -> num_tx_desc ) { adapter -> watchdog_check = FALSE ; return ; } } }
Examine each tx_buffer in the used queue.
Examine each tx_buffer in the used queue .
/* DEV_NETMAP */ /*
	 * What this does is get the index of the
	 * first descriptor AFTER the EOP of the 
	 * first packet, that way we can do the
	 * simple comparison on the inner while loop.
	 */ /* We clean the range of the packet */ /* See if we can continue to the next packet */ /* Get new done point */ /* a tdt write is pending, do it */ // disable /* NIC_SEND_COMBINING */ /*
         * If we have enough room, clear IFF_DRV_OACTIVE to
         * tell the stack that it is OK to send packets.
         * If there are no pending descriptors, clear the watchdog.
         */ // XXX also csb_on ? /* acked */ // XXX memory barrier /* NIC_PARAVIRT */