FreeBSD/sys/dev/cxgbe/t4_sge.c
/*
 * Write a txpkts WR for the packets in txp to the hardware descriptors, update
 * the software descriptor, and advance the pidx.  It is guaranteed that enough
 * descriptors are available.
 *
 * The return value is the # of hardware descriptors used.
 */
Write a txpkts WR for the packets in txp to the hardware descriptors, update
the software descriptor, and advance the pidx.  It is guaranteed that enough
descriptors are available.

The return value is the # of hardware descriptors used.
Write a txpkts WR for the packets in txp to the hardware descriptors update the software descriptor and advance the pidx . It is guaranteed that enough descriptors are available . The return value is the # of hardware descriptors used .
static u_int
write_txpkts_wr(struct sge_txq *txq, struct fw_eth_tx_pkts_wr *wr,
    struct mbuf *m0, const struct txpkts *txp, u_int available)
{
	struct sge_eq *eq = &txq->eq;
	struct tx_sdesc *txsd;
	struct cpl_tx_pkt_core *cpl;
	uint32_t ctrl;
	uint64_t ctrl1;
	int ndesc, checkwrap;
	struct mbuf *m;
	void *flitp;
	TXQ_LOCK_ASSERT_OWNED(txq);
	MPASS(txp->npkt > 0);
	MPASS(txp->plen < 65536);
	MPASS(m0 != NULL);
	MPASS(m0->m_nextpkt != NULL);
	MPASS(txp->len16 <= howmany(SGE_MAX_WR_LEN, 16));
	MPASS(available > 0 && available < eq->sidx);
	ndesc = howmany(txp->len16, EQ_ESIZE / 16);
	MPASS(ndesc <= available);
	MPASS(wr == (void *)&eq->desc[eq->pidx]);
	wr->op_pkd = htobe32(V_FW_WR_OP(FW_ETH_TX_PKTS_WR));
	ctrl = V_FW_WR_LEN16(txp->len16);
	wr->equiq_to_len16 = htobe32(ctrl);
	wr->plen = htobe16(txp->plen);
	wr->npkt = txp->npkt;
	wr->r3 = 0;
	wr->type = txp->wr_type;
	flitp = wr + 1;
	checkwrap = eq->sidx - ndesc < eq->pidx;
	for (m = m0; m != NULL; m = m->m_nextpkt) {
		if (txp->wr_type == 0) {
			struct ulp_txpkt *ulpmc;
			struct ulptx_idata *ulpsc;
			ulpmc = flitp;
			ulpmc->cmd_dest = htobe32(V_ULPTX_CMD(ULP_TX_PKT) |
			    V_ULP_TXPKT_DEST(0) | V_ULP_TXPKT_FID(eq->iqid));
			ulpmc->len = htobe32(mbuf_len16(m));
			ulpsc = (void *)(ulpmc + 1);
			ulpsc->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM) |
			    F_ULP_TX_SC_MORE);
			ulpsc->len = htobe32(sizeof(struct cpl_tx_pkt_core));
			cpl = (void *)(ulpsc + 1);
			if (checkwrap &&
			    (uintptr_t)cpl == (uintptr_t)&eq->desc[eq->sidx])
				cpl = (void *)&eq->desc[0];
			txq->txpkts0_pkts += txp->npkt;
			txq->txpkts0_wrs++;
		} else {
			cpl = flitp;
			txq->txpkts1_pkts += txp->npkt;
			txq->txpkts1_wrs++;
		}
		ctrl1 = 0;
		if (needs_l3_csum(m) == 0)
			ctrl1 |= F_TXPKT_IPCSUM_DIS;
		if (needs_l4_csum(m) == 0)
			ctrl1 |= F_TXPKT_L4CSUM_DIS;
		if (m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP |
		    CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO))
			txq->txcsum++;	
		if (needs_vlan_insertion(m)) {
			ctrl1 |= F_TXPKT_VLAN_VLD |
			    V_TXPKT_VLAN(m->m_pkthdr.ether_vtag);
			txq->vlan_insertion++;
		}
		cpl->ctrl0 = txq->cpl_ctrl0;
		cpl->pack = 0;
		cpl->len = htobe16(m->m_pkthdr.len);
		cpl->ctrl1 = htobe64(ctrl1);
		flitp = cpl + 1;
		if (checkwrap &&
		    (uintptr_t)flitp == (uintptr_t)&eq->desc[eq->sidx])
			flitp = (void *)&eq->desc[0];
		write_gl_to_txd(txq, m, (caddr_t *)(&flitp), checkwrap);
	}
	txsd = &txq->sdesc[eq->pidx];
	txsd->m = m0;
	txsd->desc_used = ndesc;
	return (ndesc);
}
static u_int write_txpkts_wr ( struct sge_txq * txq , struct fw_eth_tx_pkts_wr * wr , struct mbuf * m0 , const struct txpkts * txp , u_int available ) { struct sge_eq * eq = & txq -> eq ; struct tx_sdesc * txsd ; struct cpl_tx_pkt_core * cpl ; uint32_t ctrl ; uint64_t ctrl1 ; int ndesc , checkwrap ; struct mbuf * m ; void * flitp ; TXQ_LOCK_ASSERT_OWNED ( txq ) ; MPASS ( txp -> npkt > 0 ) ; MPASS ( txp -> plen < 65536 ) ; MPASS ( m0 != NULL ) ; MPASS ( m0 -> m_nextpkt != NULL ) ; MPASS ( txp -> len16 <= howmany ( SGE_MAX_WR_LEN , 16 ) ) ; MPASS ( available > 0 && available < eq -> sidx ) ; ndesc = howmany ( txp -> len16 , EQ_ESIZE / 16 ) ; MPASS ( ndesc <= available ) ; MPASS ( wr == ( void * ) & eq -> desc [ eq -> pidx ] ) ; wr -> op_pkd = htobe32 ( V_FW_WR_OP ( FW_ETH_TX_PKTS_WR ) ) ; ctrl = V_FW_WR_LEN16 ( txp -> len16 ) ; wr -> equiq_to_len16 = htobe32 ( ctrl ) ; wr -> plen = htobe16 ( txp -> plen ) ; wr -> npkt = txp -> npkt ; wr -> r3 = 0 ; wr -> type = txp -> wr_type ; flitp = wr + 1 ; checkwrap = eq -> sidx - ndesc < eq -> pidx ; for ( m = m0 ; m != NULL ; m = m -> m_nextpkt ) { if ( txp -> wr_type == 0 ) { struct ulp_txpkt * ulpmc ; struct ulptx_idata * ulpsc ; ulpmc = flitp ; ulpmc -> cmd_dest = htobe32 ( V_ULPTX_CMD ( ULP_TX_PKT ) | V_ULP_TXPKT_DEST ( 0 ) | V_ULP_TXPKT_FID ( eq -> iqid ) ) ; ulpmc -> len = htobe32 ( mbuf_len16 ( m ) ) ; ulpsc = ( void * ) ( ulpmc + 1 ) ; ulpsc -> cmd_more = htobe32 ( V_ULPTX_CMD ( ULP_TX_SC_IMM ) | F_ULP_TX_SC_MORE ) ; ulpsc -> len = htobe32 ( sizeof ( struct cpl_tx_pkt_core ) ) ; cpl = ( void * ) ( ulpsc + 1 ) ; if ( checkwrap && ( uintptr_t ) cpl == ( uintptr_t ) & eq -> desc [ eq -> sidx ] ) cpl = ( void * ) & eq -> desc [ 0 ] ; txq -> txpkts0_pkts += txp -> npkt ; txq -> txpkts0_wrs ++ ; } else { cpl = flitp ; txq -> txpkts1_pkts += txp -> npkt ; txq -> txpkts1_wrs ++ ; } ctrl1 = 0 ; if ( needs_l3_csum ( m ) == 0 ) ctrl1 |= F_TXPKT_IPCSUM_DIS ; if ( needs_l4_csum ( m ) == 0 ) ctrl1 |= F_TXPKT_L4CSUM_DIS ; if ( m -> m_pkthdr . csum_flags & ( CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO ) ) txq -> txcsum ++ ; if ( needs_vlan_insertion ( m ) ) { ctrl1 |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN ( m -> m_pkthdr . ether_vtag ) ; txq -> vlan_insertion ++ ; } cpl -> ctrl0 = txq -> cpl_ctrl0 ; cpl -> pack = 0 ; cpl -> len = htobe16 ( m -> m_pkthdr . len ) ; cpl -> ctrl1 = htobe64 ( ctrl1 ) ; flitp = cpl + 1 ; if ( checkwrap && ( uintptr_t ) flitp == ( uintptr_t ) & eq -> desc [ eq -> sidx ] ) flitp = ( void * ) & eq -> desc [ 0 ] ; write_gl_to_txd ( txq , m , ( caddr_t * ) ( & flitp ) , checkwrap ) ; } txsd = & txq -> sdesc [ eq -> pidx ] ; txsd -> m = m0 ; txsd -> desc_used = ndesc ; return ( ndesc ) ; }
Write a txpkts WR for the packets in txp to the hardware descriptors, update
 the software descriptor, and advance the pidx.
Write a txpkts WR for the packets in txp to the hardware descriptors update the software descriptor and advance the pidx .
/*
	 * At this point we are 16B into a hardware descriptor.  If checkwrap is
	 * set then we know the WR is going to wrap around somewhere.  We'll
	 * check for that at appropriate points.
	 */ /* ULP master command */ /* ULP subcommand */ /* Checksum offload */ /* some hardware assistance provided */ /* VLAN tag insertion */ /* CPL header */