FreeBSD/sys/dev/e1000/if_em.c
/*
** The 3 following flush routines are used as a workaround in the
** I219 client parts and only for them.
**
** em_flush_tx_ring - remove all descriptors from the tx_ring
**
** We want to clear all pending descriptors from the TX ring.
** zeroing happens when the HW reads the regs. We  assign the ring itself as
** the data of the next descriptor. We don't care about the data we are about
** to reset the HW.
*/
The 3 following flush routines are used as a workaround in the
I219 client parts and only for them.

remove all descriptors from the tx_ring

We want to clear all pending descriptors from the TX ring.
zeroing happens when the HW reads the regs. We  assign the ring itself as
the data of the next descriptor. We don't care about the data we are about
to reset the HW.
The 3 following flush routines are used as a workaround in the I219 client parts and only for them . remove all descriptors from the tx_ring We want to clear all pending descriptors from the TX ring . zeroing happens when the HW reads the regs . We assign the ring itself as the data of the next descriptor . We don ' t care about the data we are about to reset the HW .
static void
em_flush_tx_ring(struct adapter *adapter)
{
	struct e1000_hw		*hw = &adapter->hw;
	struct tx_ring		*txr = adapter->tx_rings;
	struct e1000_tx_desc	*txd;
	u32			tctl, txd_lower = E1000_TXD_CMD_IFCS;
	u16			size = 512;
	tctl = E1000_READ_REG(hw, E1000_TCTL);
	E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN);
	txd = &txr->tx_base[txr->next_avail_desc++];
	if (txr->next_avail_desc == adapter->num_tx_desc)
		txr->next_avail_desc = 0;
	txd->buffer_addr = txr->txdma.dma_paddr;
	txd->lower.data = htole32(txd_lower | size);
	txd->upper.data = 0;
	wmb();
	E1000_WRITE_REG(hw, E1000_TDT(0), txr->next_avail_desc);
	mb();
	usec_delay(250);
}
static void em_flush_tx_ring ( struct adapter * adapter ) { struct e1000_hw * hw = & adapter -> hw ; struct tx_ring * txr = adapter -> tx_rings ; struct e1000_tx_desc * txd ; u32 tctl , txd_lower = E1000_TXD_CMD_IFCS ; u16 size = 512 ; tctl = E1000_READ_REG ( hw , E1000_TCTL ) ; E1000_WRITE_REG ( hw , E1000_TCTL , tctl | E1000_TCTL_EN ) ; txd = & txr -> tx_base [ txr -> next_avail_desc ++ ] ; if ( txr -> next_avail_desc == adapter -> num_tx_desc ) txr -> next_avail_desc = 0 ; txd -> buffer_addr = txr -> txdma . dma_paddr ; txd -> lower . data = htole32 ( txd_lower | size ) ; txd -> upper . data = 0 ; wmb ( ) ; E1000_WRITE_REG ( hw , E1000_TDT ( 0 ) , txr -> next_avail_desc ) ; mb ( ) ; usec_delay ( 250 ) ; }
The 3 following flush routines are used as a workaround in the
I219 client parts and only for them.
The 3 following flush routines are used as a workaround in the I219 client parts and only for them .
/* Just use the ring as a dummy buffer addr */ /* flush descriptors to memory before notifying the HW */