FreeBSD/sys/dev/e1000/if_igb.c
/*********************************************************************
 *
 *  This routine maps the mbufs to Advanced TX descriptors.
 *  
 **********************************************************************/
This routine maps the mbufs to Advanced TX descriptors.
This routine maps the mbufs to Advanced TX descriptors .
static int
igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
{
	struct adapter  *adapter = txr->adapter;
	u32		olinfo_status = 0, cmd_type_len;
	int             i, j, error, nsegs;
	int		first;
	bool		remap = TRUE;
	struct mbuf	*m_head;
	bus_dma_segment_t segs[IGB_MAX_SCATTER];
	bus_dmamap_t	map;
	struct igb_tx_buf *txbuf;
	union e1000_adv_tx_desc *txd = NULL;
	m_head = *m_headp;
        cmd_type_len = (E1000_ADVTXD_DTYP_DATA |
	    E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT);
	if (m_head->m_flags & M_VLANTAG)
        	cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
        first = txr->next_avail_desc;
	txbuf = &txr->tx_buffers[first];
	map = txbuf->map;
retry:
	error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
	    *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
	if (__predict_false(error)) {
		struct mbuf *m;
		switch (error) {
		case EFBIG:
			if (remap == TRUE) {
				remap = FALSE;
				m = m_collapse(*m_headp, M_NOWAIT,
				    IGB_MAX_SCATTER);
				if (m == NULL) {
					adapter->mbuf_defrag_failed++;
					m_freem(*m_headp);
					*m_headp = NULL;
					return (ENOBUFS);
				}
				*m_headp = m;
				goto retry;
			} else
				return (error);
		default:
			txr->no_tx_dma_setup++;
			m_freem(*m_headp);
			*m_headp = NULL;
			return (error);
		}
	}
	if (txr->tx_avail < (nsegs + 2)) {
		txr->no_desc_avail++;
		bus_dmamap_unload(txr->txtag, map);
		return (ENOBUFS);
	}
	m_head = *m_headp;
	error = igb_tx_ctx_setup(txr, m_head, &cmd_type_len, &olinfo_status);
	if (__predict_false(error)) {
		m_freem(*m_headp);
		*m_headp = NULL;
		return (error);
	}
	if (adapter->hw.mac.type == e1000_82575)
		olinfo_status |= txr->me << 4;
	i = txr->next_avail_desc;
	for (j = 0; j < nsegs; j++) {
		bus_size_t seglen;
		bus_addr_t segaddr;
		txbuf = &txr->tx_buffers[i];
		txd = &txr->tx_base[i];
		seglen = segs[j].ds_len;
		segaddr = htole64(segs[j].ds_addr);
		txd->read.buffer_addr = segaddr;
		txd->read.cmd_type_len = htole32(E1000_TXD_CMD_IFCS |
		    cmd_type_len | seglen);
		txd->read.olinfo_status = htole32(olinfo_status);
		if (++i == txr->num_desc)
			i = 0;
	}
	txd->read.cmd_type_len |=
	    htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS);
	txr->tx_avail -= nsegs;
	txr->next_avail_desc = i;
	txbuf->m_head = m_head;
	txr->tx_buffers[first].map = txbuf->map;
	txbuf->map = map;
	bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
        txbuf = &txr->tx_buffers[first];
	txbuf->eop = txd;
        bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
	++txr->total_packets;
	E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), i);
	return (0);
}
static int igb_xmit ( struct tx_ring * txr , struct mbuf * * m_headp ) { struct adapter * adapter = txr -> adapter ; u32 olinfo_status = 0 , cmd_type_len ; int i , j , error , nsegs ; int first ; bool remap = TRUE ; struct mbuf * m_head ; bus_dma_segment_t segs [ IGB_MAX_SCATTER ] ; bus_dmamap_t map ; struct igb_tx_buf * txbuf ; union e1000_adv_tx_desc * txd = NULL ; m_head = * m_headp ; cmd_type_len = ( E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT ) ; if ( m_head -> m_flags & M_VLANTAG ) cmd_type_len |= E1000_ADVTXD_DCMD_VLE ; first = txr -> next_avail_desc ; txbuf = & txr -> tx_buffers [ first ] ; map = txbuf -> map ; retry : error = bus_dmamap_load_mbuf_sg ( txr -> txtag , map , * m_headp , segs , & nsegs , BUS_DMA_NOWAIT ) ; if ( __predict_false ( error ) ) { struct mbuf * m ; switch ( error ) { case EFBIG : if ( remap == TRUE ) { remap = FALSE ; m = m_collapse ( * m_headp , M_NOWAIT , IGB_MAX_SCATTER ) ; if ( m == NULL ) { adapter -> mbuf_defrag_failed ++ ; m_freem ( * m_headp ) ; * m_headp = NULL ; return ( ENOBUFS ) ; } * m_headp = m ; goto retry ; } else return ( error ) ; default : txr -> no_tx_dma_setup ++ ; m_freem ( * m_headp ) ; * m_headp = NULL ; return ( error ) ; } } if ( txr -> tx_avail < ( nsegs + 2 ) ) { txr -> no_desc_avail ++ ; bus_dmamap_unload ( txr -> txtag , map ) ; return ( ENOBUFS ) ; } m_head = * m_headp ; error = igb_tx_ctx_setup ( txr , m_head , & cmd_type_len , & olinfo_status ) ; if ( __predict_false ( error ) ) { m_freem ( * m_headp ) ; * m_headp = NULL ; return ( error ) ; } if ( adapter -> hw . mac . type == e1000_82575 ) olinfo_status |= txr -> me << 4 ; i = txr -> next_avail_desc ; for ( j = 0 ; j < nsegs ; j ++ ) { bus_size_t seglen ; bus_addr_t segaddr ; txbuf = & txr -> tx_buffers [ i ] ; txd = & txr -> tx_base [ i ] ; seglen = segs [ j ] . ds_len ; segaddr = htole64 ( segs [ j ] . ds_addr ) ; txd -> read . buffer_addr = segaddr ; txd -> read . cmd_type_len = htole32 ( E1000_TXD_CMD_IFCS | cmd_type_len | seglen ) ; txd -> read . olinfo_status = htole32 ( olinfo_status ) ; if ( ++ i == txr -> num_desc ) i = 0 ; } txd -> read . cmd_type_len |= htole32 ( E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS ) ; txr -> tx_avail -= nsegs ; txr -> next_avail_desc = i ; txbuf -> m_head = m_head ; txr -> tx_buffers [ first ] . map = txbuf -> map ; txbuf -> map = map ; bus_dmamap_sync ( txr -> txtag , map , BUS_DMASYNC_PREWRITE ) ; txbuf = & txr -> tx_buffers [ first ] ; txbuf -> eop = txd ; bus_dmamap_sync ( txr -> txdma . dma_tag , txr -> txdma . dma_map , BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE ) ; ++ txr -> total_packets ; E1000_WRITE_REG ( & adapter -> hw , E1000_TDT ( txr -> me ) , i ) ; return ( 0 ) ; }
This routine maps the mbufs to Advanced TX descriptors.
This routine maps the mbufs to Advanced TX descriptors .
/* Basic descriptor defines */ /*
         * Important to capture the first descriptor
         * used because it will contain the index of
         * the one we tell the hardware to report back
         */ /*
	 * Map the packet for DMA.
	 */ /* Try it again? - one try */ /* Make certain there are enough descriptors */ /*
	** Set up the appropriate offload context
	** this will consume the first descriptor
	*/ /* 82575 needs the queue index added */ /*
	** Here we swap the map so the last descriptor,
	** which gets the completion interrupt has the
	** real map, and the first descriptor gets the
	** unused map from this descriptor.
	*/ /* Set the EOP descriptor that will be marked done */ /*
	 * Advance the Transmit Descriptor Tail (Tdt), this tells the
	 * hardware that this frame is available to transmit.
	 */