FreeBSD/sys/dev/ixl/ixl_txrx.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 .
bool
ixl_txeof(struct ixl_queue *que)
{
	struct tx_ring		*txr = &que->txr;
	u32			first, last, head, done, processed;
	struct ixl_tx_buf	*buf;
	struct i40e_tx_desc	*tx_desc, *eop_desc;
	mtx_assert(&txr->mtx, MA_OWNED);
#ifdef DEV_NETMAP
	if (netmap_tx_irq(que->vsi->ifp, que->me))
		return FALSE;
#endif 
	if (txr->avail == que->num_desc) {
		que->busy = 0;
		return FALSE;
	}
	processed = 0;
	first = txr->next_to_clean;
	buf = &txr->buffers[first];
	tx_desc = (struct i40e_tx_desc *)&txr->base[first];
	last = buf->eop_index;
	if (last == -1)
		return FALSE;
	eop_desc = (struct i40e_tx_desc *)&txr->base[last];
	head = ixl_get_tx_head(que);
	if (++last == que->num_desc) last = 0;
	done = last;
        bus_dmamap_sync(txr->dma.tag, txr->dma.map,
            BUS_DMASYNC_POSTREAD);
	while (first != head) {
		while (first != done) {
			++txr->avail;
			++processed;
			if (buf->m_head) {
				txr->bytes += 
				    buf->m_head->m_pkthdr.len;
				txr->tx_bytes += 
				    buf->m_head->m_pkthdr.len;
				bus_dmamap_sync(buf->tag,
				    buf->map,
				    BUS_DMASYNC_POSTWRITE);
				bus_dmamap_unload(buf->tag,
				    buf->map);
				m_freem(buf->m_head);
				buf->m_head = NULL;
				buf->map = NULL;
			}
			buf->eop_index = -1;
			if (++first == que->num_desc)
				first = 0;
			buf = &txr->buffers[first];
			tx_desc = &txr->base[first];
		}
		++txr->packets;
		last = buf->eop_index;
		if (last != -1) {
			eop_desc = &txr->base[last];
			if (++last == que->num_desc) last = 0;
			done = last;
		} else
			break;
	}
	bus_dmamap_sync(txr->dma.tag, txr->dma.map,
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
	txr->next_to_clean = first;
	if ((processed == 0) && (que->busy != IXL_QUEUE_HUNG))
		++que->busy;
	if (processed)
		que->busy = 1; 
	if (txr->avail == que->num_desc) {
		que->busy = 0;
		return FALSE;
	}
	return TRUE;
}
bool ixl_txeof ( struct ixl_queue * que ) { struct tx_ring * txr = & que -> txr ; u32 first , last , head , done , processed ; struct ixl_tx_buf * buf ; struct i40e_tx_desc * tx_desc , * eop_desc ; mtx_assert ( & txr -> mtx , MA_OWNED ) ; #ifdef DEV_NETMAP if ( netmap_tx_irq ( que -> vsi -> ifp , que -> me ) ) return FALSE ; #endif if ( txr -> avail == que -> num_desc ) { que -> busy = 0 ; return FALSE ; } processed = 0 ; first = txr -> next_to_clean ; buf = & txr -> buffers [ first ] ; tx_desc = ( struct i40e_tx_desc * ) & txr -> base [ first ] ; last = buf -> eop_index ; if ( last == -1 ) return FALSE ; eop_desc = ( struct i40e_tx_desc * ) & txr -> base [ last ] ; head = ixl_get_tx_head ( que ) ; if ( ++ last == que -> num_desc ) last = 0 ; done = last ; bus_dmamap_sync ( txr -> dma . tag , txr -> dma . map , BUS_DMASYNC_POSTREAD ) ; while ( first != head ) { while ( first != done ) { ++ txr -> avail ; ++ processed ; if ( buf -> m_head ) { txr -> bytes += buf -> m_head -> m_pkthdr . len ; txr -> tx_bytes += buf -> m_head -> m_pkthdr . len ; bus_dmamap_sync ( buf -> tag , buf -> map , BUS_DMASYNC_POSTWRITE ) ; bus_dmamap_unload ( buf -> tag , buf -> map ) ; m_freem ( buf -> m_head ) ; buf -> m_head = NULL ; buf -> map = NULL ; } buf -> eop_index = -1 ; if ( ++ first == que -> num_desc ) first = 0 ; buf = & txr -> buffers [ first ] ; tx_desc = & txr -> base [ first ] ; } ++ txr -> packets ; last = buf -> eop_index ; if ( last != -1 ) { eop_desc = & txr -> base [ last ] ; if ( ++ last == que -> num_desc ) last = 0 ; done = last ; } else break ; } bus_dmamap_sync ( txr -> dma . tag , txr -> dma . map , BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE ) ; txr -> next_to_clean = first ; if ( ( processed == 0 ) && ( que -> busy != IXL_QUEUE_HUNG ) ) ++ que -> busy ; if ( processed ) que -> busy = 1 ; if ( txr -> avail == que -> num_desc ) { que -> busy = 0 ; return FALSE ; } return TRUE ; }
Examine each tx_buffer in the used queue.
Examine each tx_buffer in the used queue .
// XXX todo: implement moderation /* DEF_NETMAP */ /* These are not the descriptors you seek, move along :) */ /* Get the Head WB value */ /*
	** Get the index of the first descriptor
	** BEYOND the EOP and call that 'done'.
	** I do this so the comparison in the
	** inner while loop below can be simple
	*/ /*
	** The HEAD index of the ring is written in a 
	** defined location, this rather than a done bit
	** is what is used to keep track of what must be
	** 'cleaned'.
	*/ /* We clean the range of the packet */ /* for ITR adjustment */ /* for TX stats */ /* See if there is more work now */ /* Get next done point */ /*
	** Hang detection, we know there's
	** work outstanding or the first return
	** would have been taken, so indicate an
	** unsuccessful pass, in local_timer if
	** the value is too great the queue will
	** be considered hung. If anything has been
	** cleaned then reset the state.
	*/ /* Note this turns off HUNG */ /*
	 * If there are no pending descriptors, clear the timeout.
	 */