xref: /freebsd/sys/dev/sfxge/common/efx_tx.c (revision e948693ed767ef8364d5fc71e363ed941432a6e8)
1*e948693eSPhilip Paeps /*-
2*e948693eSPhilip Paeps  * Copyright 2007-2009 Solarflare Communications Inc.  All rights reserved.
3*e948693eSPhilip Paeps  *
4*e948693eSPhilip Paeps  * Redistribution and use in source and binary forms, with or without
5*e948693eSPhilip Paeps  * modification, are permitted provided that the following conditions
6*e948693eSPhilip Paeps  * are met:
7*e948693eSPhilip Paeps  * 1. Redistributions of source code must retain the above copyright
8*e948693eSPhilip Paeps  *    notice, this list of conditions and the following disclaimer.
9*e948693eSPhilip Paeps  * 2. Redistributions in binary form must reproduce the above copyright
10*e948693eSPhilip Paeps  *    notice, this list of conditions and the following disclaimer in the
11*e948693eSPhilip Paeps  *    documentation and/or other materials provided with the distribution.
12*e948693eSPhilip Paeps  *
13*e948693eSPhilip Paeps  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14*e948693eSPhilip Paeps  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*e948693eSPhilip Paeps  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*e948693eSPhilip Paeps  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*e948693eSPhilip Paeps  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*e948693eSPhilip Paeps  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*e948693eSPhilip Paeps  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*e948693eSPhilip Paeps  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*e948693eSPhilip Paeps  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*e948693eSPhilip Paeps  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*e948693eSPhilip Paeps  * SUCH DAMAGE.
24*e948693eSPhilip Paeps  */
25*e948693eSPhilip Paeps 
26*e948693eSPhilip Paeps #include "efsys.h"
27*e948693eSPhilip Paeps #include "efx.h"
28*e948693eSPhilip Paeps #include "efx_types.h"
29*e948693eSPhilip Paeps #include "efx_regs.h"
30*e948693eSPhilip Paeps #include "efx_impl.h"
31*e948693eSPhilip Paeps 
32*e948693eSPhilip Paeps #if EFSYS_OPT_QSTATS
33*e948693eSPhilip Paeps #define	EFX_TX_QSTAT_INCR(_etp, _stat)					\
34*e948693eSPhilip Paeps 	do {								\
35*e948693eSPhilip Paeps 		(_etp)->et_stat[_stat]++;				\
36*e948693eSPhilip Paeps 	_NOTE(CONSTANTCONDITION)					\
37*e948693eSPhilip Paeps 	} while (B_FALSE)
38*e948693eSPhilip Paeps #else
39*e948693eSPhilip Paeps #define	EFX_TX_QSTAT_INCR(_etp, _stat)
40*e948693eSPhilip Paeps #endif
41*e948693eSPhilip Paeps 
42*e948693eSPhilip Paeps 	__checkReturn	int
43*e948693eSPhilip Paeps efx_tx_init(
44*e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
45*e948693eSPhilip Paeps {
46*e948693eSPhilip Paeps 	efx_oword_t oword;
47*e948693eSPhilip Paeps 	int rc;
48*e948693eSPhilip Paeps 
49*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
50*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
51*e948693eSPhilip Paeps 
52*e948693eSPhilip Paeps 	if (!(enp->en_mod_flags & EFX_MOD_EV)) {
53*e948693eSPhilip Paeps 		rc = EINVAL;
54*e948693eSPhilip Paeps 		goto fail1;
55*e948693eSPhilip Paeps 	}
56*e948693eSPhilip Paeps 
57*e948693eSPhilip Paeps 	if (enp->en_mod_flags & EFX_MOD_TX) {
58*e948693eSPhilip Paeps 		rc = EINVAL;
59*e948693eSPhilip Paeps 		goto fail2;
60*e948693eSPhilip Paeps 	}
61*e948693eSPhilip Paeps 
62*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
63*e948693eSPhilip Paeps 
64*e948693eSPhilip Paeps 	/*
65*e948693eSPhilip Paeps 	 * Disable the timer-based TX DMA backoff and allow TX DMA to be
66*e948693eSPhilip Paeps 	 * controlled by the RX FIFO fill level (although always allow a
67*e948693eSPhilip Paeps 	 * minimal trickle).
68*e948693eSPhilip Paeps 	 */
69*e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
70*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
71*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
72*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
73*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
74*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
75*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
76*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
77*e948693eSPhilip Paeps 
78*e948693eSPhilip Paeps 	/*
79*e948693eSPhilip Paeps 	 * Filter all packets less than 14 bytes to avoid parsing
80*e948693eSPhilip Paeps 	 * errors.
81*e948693eSPhilip Paeps 	 */
82*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
83*e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
84*e948693eSPhilip Paeps 
85*e948693eSPhilip Paeps 	/*
86*e948693eSPhilip Paeps 	 * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
87*e948693eSPhilip Paeps 	 * descriptors (which is bad).
88*e948693eSPhilip Paeps 	 */
89*e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
90*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
91*e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
92*e948693eSPhilip Paeps 
93*e948693eSPhilip Paeps 	enp->en_mod_flags |= EFX_MOD_TX;
94*e948693eSPhilip Paeps 	return (0);
95*e948693eSPhilip Paeps 
96*e948693eSPhilip Paeps fail2:
97*e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
98*e948693eSPhilip Paeps fail1:
99*e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
100*e948693eSPhilip Paeps 
101*e948693eSPhilip Paeps 	return (rc);
102*e948693eSPhilip Paeps }
103*e948693eSPhilip Paeps 
104*e948693eSPhilip Paeps #if EFSYS_OPT_FILTER
105*e948693eSPhilip Paeps extern	__checkReturn	int
106*e948693eSPhilip Paeps efx_tx_filter_insert(
107*e948693eSPhilip Paeps 	__in		efx_txq_t *etp,
108*e948693eSPhilip Paeps 	__inout		efx_filter_spec_t *spec)
109*e948693eSPhilip Paeps {
110*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
111*e948693eSPhilip Paeps 	EFSYS_ASSERT3P(spec, !=, NULL);
112*e948693eSPhilip Paeps 
113*e948693eSPhilip Paeps 	spec->efs_dmaq_id = (uint16_t)etp->et_index;
114*e948693eSPhilip Paeps 	return efx_filter_insert_filter(etp->et_enp, spec, B_FALSE);
115*e948693eSPhilip Paeps }
116*e948693eSPhilip Paeps #endif
117*e948693eSPhilip Paeps 
118*e948693eSPhilip Paeps #if EFSYS_OPT_FILTER
119*e948693eSPhilip Paeps extern	__checkReturn	int
120*e948693eSPhilip Paeps efx_tx_filter_remove(
121*e948693eSPhilip Paeps 	__in		efx_txq_t *etp,
122*e948693eSPhilip Paeps 	__inout		efx_filter_spec_t *spec)
123*e948693eSPhilip Paeps {
124*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
125*e948693eSPhilip Paeps 	EFSYS_ASSERT3P(spec, !=, NULL);
126*e948693eSPhilip Paeps 
127*e948693eSPhilip Paeps 	spec->efs_dmaq_id = (uint16_t)etp->et_index;
128*e948693eSPhilip Paeps 	return efx_filter_remove_filter(etp->et_enp, spec);
129*e948693eSPhilip Paeps }
130*e948693eSPhilip Paeps #endif
131*e948693eSPhilip Paeps 
132*e948693eSPhilip Paeps #define	EFX_TX_DESC(_etp, _addr, _size, _eop, _added)			\
133*e948693eSPhilip Paeps 	do {								\
134*e948693eSPhilip Paeps 		unsigned int id;					\
135*e948693eSPhilip Paeps 		size_t offset;						\
136*e948693eSPhilip Paeps 		efx_qword_t qword;					\
137*e948693eSPhilip Paeps 									\
138*e948693eSPhilip Paeps 		id = (_added)++ & (_etp)->et_mask;			\
139*e948693eSPhilip Paeps 		offset = id * sizeof (efx_qword_t);			\
140*e948693eSPhilip Paeps 									\
141*e948693eSPhilip Paeps 		EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index,	\
142*e948693eSPhilip Paeps 		    unsigned int, id, efsys_dma_addr_t, (_addr),	\
143*e948693eSPhilip Paeps 		    size_t, (_size), boolean_t, (_eop));		\
144*e948693eSPhilip Paeps 									\
145*e948693eSPhilip Paeps 		EFX_POPULATE_QWORD_4(qword,				\
146*e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1,			\
147*e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size),	\
148*e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_BUF_ADDR_DW0,				\
149*e948693eSPhilip Paeps 		    (uint32_t)((_addr) & 0xffffffff),			\
150*e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_BUF_ADDR_DW1,				\
151*e948693eSPhilip Paeps 		    (uint32_t)((_addr) >> 32));				\
152*e948693eSPhilip Paeps 		EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword);	\
153*e948693eSPhilip Paeps 									\
154*e948693eSPhilip Paeps 		_NOTE(CONSTANTCONDITION)				\
155*e948693eSPhilip Paeps 	} while (B_FALSE)
156*e948693eSPhilip Paeps 
157*e948693eSPhilip Paeps 	__checkReturn	int
158*e948693eSPhilip Paeps efx_tx_qpost(
159*e948693eSPhilip Paeps 	__in		efx_txq_t *etp,
160*e948693eSPhilip Paeps 	__in_ecount(n)	efx_buffer_t *eb,
161*e948693eSPhilip Paeps 	__in		unsigned int n,
162*e948693eSPhilip Paeps 	__in		unsigned int completed,
163*e948693eSPhilip Paeps 	__inout		unsigned int *addedp)
164*e948693eSPhilip Paeps {
165*e948693eSPhilip Paeps 	unsigned int added = *addedp;
166*e948693eSPhilip Paeps 	unsigned int i;
167*e948693eSPhilip Paeps 	int rc = ENOSPC;
168*e948693eSPhilip Paeps 
169*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
170*e948693eSPhilip Paeps 
171*e948693eSPhilip Paeps 	if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1))
172*e948693eSPhilip Paeps 		goto fail1;
173*e948693eSPhilip Paeps 
174*e948693eSPhilip Paeps 	for (i = 0; i < n; i++) {
175*e948693eSPhilip Paeps 		efx_buffer_t *ebp = &eb[i];
176*e948693eSPhilip Paeps 		efsys_dma_addr_t start = ebp->eb_addr;
177*e948693eSPhilip Paeps 		size_t size = ebp->eb_size;
178*e948693eSPhilip Paeps 		efsys_dma_addr_t end = start + size;
179*e948693eSPhilip Paeps 
180*e948693eSPhilip Paeps 		/* Fragments must not span 4k boundaries. */
181*e948693eSPhilip Paeps 		EFSYS_ASSERT(P2ROUNDUP(start + 1, 4096) >= end);
182*e948693eSPhilip Paeps 
183*e948693eSPhilip Paeps 		EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
184*e948693eSPhilip Paeps 	}
185*e948693eSPhilip Paeps 
186*e948693eSPhilip Paeps 	EFX_TX_QSTAT_INCR(etp, TX_POST);
187*e948693eSPhilip Paeps 
188*e948693eSPhilip Paeps 	*addedp = added;
189*e948693eSPhilip Paeps 	return (0);
190*e948693eSPhilip Paeps 
191*e948693eSPhilip Paeps fail1:
192*e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
193*e948693eSPhilip Paeps 
194*e948693eSPhilip Paeps 	return (rc);
195*e948693eSPhilip Paeps }
196*e948693eSPhilip Paeps 
197*e948693eSPhilip Paeps 		void
198*e948693eSPhilip Paeps efx_tx_qpush(
199*e948693eSPhilip Paeps 	__in	efx_txq_t *etp,
200*e948693eSPhilip Paeps 	__in	unsigned int added)
201*e948693eSPhilip Paeps {
202*e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
203*e948693eSPhilip Paeps 	uint32_t wptr;
204*e948693eSPhilip Paeps 	efx_dword_t dword;
205*e948693eSPhilip Paeps 	efx_oword_t oword;
206*e948693eSPhilip Paeps 
207*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
208*e948693eSPhilip Paeps 
209*e948693eSPhilip Paeps 	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
210*e948693eSPhilip Paeps 	EFSYS_PIO_WRITE_BARRIER();
211*e948693eSPhilip Paeps 
212*e948693eSPhilip Paeps 	/* Push the populated descriptors out */
213*e948693eSPhilip Paeps 	wptr = added & etp->et_mask;
214*e948693eSPhilip Paeps 
215*e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
216*e948693eSPhilip Paeps 
217*e948693eSPhilip Paeps 	/* Only write the third DWORD */
218*e948693eSPhilip Paeps 	EFX_POPULATE_DWORD_1(dword,
219*e948693eSPhilip Paeps 	    EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
220*e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
221*e948693eSPhilip Paeps 			    etp->et_index, &dword, B_FALSE);
222*e948693eSPhilip Paeps }
223*e948693eSPhilip Paeps 
224*e948693eSPhilip Paeps 		void
225*e948693eSPhilip Paeps efx_tx_qflush(
226*e948693eSPhilip Paeps 	__in	efx_txq_t *etp)
227*e948693eSPhilip Paeps {
228*e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
229*e948693eSPhilip Paeps 	efx_oword_t oword;
230*e948693eSPhilip Paeps 	uint32_t label;
231*e948693eSPhilip Paeps 
232*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
233*e948693eSPhilip Paeps 
234*e948693eSPhilip Paeps 	label = etp->et_index;
235*e948693eSPhilip Paeps 
236*e948693eSPhilip Paeps 	/* Flush the queue */
237*e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
238*e948693eSPhilip Paeps 	    FRF_AZ_TX_FLUSH_DESCQ, label);
239*e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
240*e948693eSPhilip Paeps }
241*e948693eSPhilip Paeps 
242*e948693eSPhilip Paeps 		void
243*e948693eSPhilip Paeps efx_tx_qenable(
244*e948693eSPhilip Paeps 	__in	efx_txq_t *etp)
245*e948693eSPhilip Paeps {
246*e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
247*e948693eSPhilip Paeps 	efx_oword_t oword;
248*e948693eSPhilip Paeps 
249*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
250*e948693eSPhilip Paeps 
251*e948693eSPhilip Paeps 	EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
252*e948693eSPhilip Paeps 			    etp->et_index, &oword);
253*e948693eSPhilip Paeps 
254*e948693eSPhilip Paeps 	EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
255*e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
256*e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
257*e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
258*e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
259*e948693eSPhilip Paeps 
260*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
261*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
262*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
263*e948693eSPhilip Paeps 
264*e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
265*e948693eSPhilip Paeps 			    etp->et_index, &oword);
266*e948693eSPhilip Paeps }
267*e948693eSPhilip Paeps 
268*e948693eSPhilip Paeps 	__checkReturn	int
269*e948693eSPhilip Paeps efx_tx_qcreate(
270*e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
271*e948693eSPhilip Paeps 	__in		unsigned int index,
272*e948693eSPhilip Paeps 	__in		unsigned int label,
273*e948693eSPhilip Paeps 	__in		efsys_mem_t *esmp,
274*e948693eSPhilip Paeps 	__in		size_t n,
275*e948693eSPhilip Paeps 	__in		uint32_t id,
276*e948693eSPhilip Paeps 	__in		uint16_t flags,
277*e948693eSPhilip Paeps 	__in		efx_evq_t *eep,
278*e948693eSPhilip Paeps 	__deref_out	efx_txq_t **etpp)
279*e948693eSPhilip Paeps {
280*e948693eSPhilip Paeps 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
281*e948693eSPhilip Paeps 	efx_txq_t *etp;
282*e948693eSPhilip Paeps 	efx_oword_t oword;
283*e948693eSPhilip Paeps 	uint32_t size;
284*e948693eSPhilip Paeps 	int rc;
285*e948693eSPhilip Paeps 
286*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
287*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
288*e948693eSPhilip Paeps 
289*e948693eSPhilip Paeps 	EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS == (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
290*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
291*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit);
292*e948693eSPhilip Paeps 
293*e948693eSPhilip Paeps 	if (!ISP2(n) || !(n & EFX_TXQ_NDESCS_MASK)) {
294*e948693eSPhilip Paeps 		rc = EINVAL;
295*e948693eSPhilip Paeps 		goto fail1;
296*e948693eSPhilip Paeps 	}
297*e948693eSPhilip Paeps 	if (index >= encp->enc_txq_limit) {
298*e948693eSPhilip Paeps 		rc = EINVAL;
299*e948693eSPhilip Paeps 		goto fail2;
300*e948693eSPhilip Paeps 	}
301*e948693eSPhilip Paeps 	for (size = 0; (1 << size) <= (EFX_TXQ_MAXNDESCS / EFX_TXQ_MINNDESCS);
302*e948693eSPhilip Paeps 	    size++)
303*e948693eSPhilip Paeps 		if ((1 << size) == (int)(n / EFX_TXQ_MINNDESCS))
304*e948693eSPhilip Paeps 			break;
305*e948693eSPhilip Paeps 	if (id + (1 << size) >= encp->enc_buftbl_limit) {
306*e948693eSPhilip Paeps 		rc = EINVAL;
307*e948693eSPhilip Paeps 		goto fail3;
308*e948693eSPhilip Paeps 	}
309*e948693eSPhilip Paeps 
310*e948693eSPhilip Paeps 	/* Allocate an TXQ object */
311*e948693eSPhilip Paeps 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
312*e948693eSPhilip Paeps 
313*e948693eSPhilip Paeps 	if (etp == NULL) {
314*e948693eSPhilip Paeps 		rc = ENOMEM;
315*e948693eSPhilip Paeps 		goto fail4;
316*e948693eSPhilip Paeps 	}
317*e948693eSPhilip Paeps 
318*e948693eSPhilip Paeps 	etp->et_magic = EFX_TXQ_MAGIC;
319*e948693eSPhilip Paeps 	etp->et_enp = enp;
320*e948693eSPhilip Paeps 	etp->et_index = index;
321*e948693eSPhilip Paeps 	etp->et_mask = n - 1;
322*e948693eSPhilip Paeps 	etp->et_esmp = esmp;
323*e948693eSPhilip Paeps 
324*e948693eSPhilip Paeps 	/* Set up the new descriptor queue */
325*e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_6(oword,
326*e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
327*e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
328*e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_OWNER_ID, 0,
329*e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_LABEL, label,
330*e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_SIZE, size,
331*e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_TYPE, 0);
332*e948693eSPhilip Paeps 
333*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
334*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
335*e948693eSPhilip Paeps 	    (flags & EFX_CKSUM_IPV4) ? 0 : 1);
336*e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
337*e948693eSPhilip Paeps 	    (flags & EFX_CKSUM_TCPUDP) ? 0 : 1);
338*e948693eSPhilip Paeps 
339*e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
340*e948693eSPhilip Paeps 	    etp->et_index, &oword);
341*e948693eSPhilip Paeps 
342*e948693eSPhilip Paeps 	enp->en_tx_qcount++;
343*e948693eSPhilip Paeps 	*etpp = etp;
344*e948693eSPhilip Paeps 	return (0);
345*e948693eSPhilip Paeps 
346*e948693eSPhilip Paeps fail4:
347*e948693eSPhilip Paeps 	EFSYS_PROBE(fail4);
348*e948693eSPhilip Paeps fail3:
349*e948693eSPhilip Paeps 	EFSYS_PROBE(fail3);
350*e948693eSPhilip Paeps fail2:
351*e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
352*e948693eSPhilip Paeps fail1:
353*e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
354*e948693eSPhilip Paeps 
355*e948693eSPhilip Paeps 	return (rc);
356*e948693eSPhilip Paeps }
357*e948693eSPhilip Paeps 
358*e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
359*e948693eSPhilip Paeps /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 78ca9ab00287fffb */
360*e948693eSPhilip Paeps static const char 	__cs * __cs __efx_tx_qstat_name[] = {
361*e948693eSPhilip Paeps 	"post",
362*e948693eSPhilip Paeps 	"unaligned_split",
363*e948693eSPhilip Paeps };
364*e948693eSPhilip Paeps /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
365*e948693eSPhilip Paeps 
366*e948693eSPhilip Paeps 		const char __cs *
367*e948693eSPhilip Paeps efx_tx_qstat_name(
368*e948693eSPhilip Paeps 	__in	efx_nic_t *enp,
369*e948693eSPhilip Paeps 	__in	unsigned int id)
370*e948693eSPhilip Paeps {
371*e948693eSPhilip Paeps 	_NOTE(ARGUNUSED(enp))
372*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
373*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(id, <, TX_NQSTATS);
374*e948693eSPhilip Paeps 
375*e948693eSPhilip Paeps 	return (__efx_tx_qstat_name[id]);
376*e948693eSPhilip Paeps }
377*e948693eSPhilip Paeps #endif	/* EFSYS_OPT_NAMES */
378*e948693eSPhilip Paeps 
379*e948693eSPhilip Paeps #if EFSYS_OPT_QSTATS
380*e948693eSPhilip Paeps 					void
381*e948693eSPhilip Paeps efx_tx_qstats_update(
382*e948693eSPhilip Paeps 	__in				efx_txq_t *etp,
383*e948693eSPhilip Paeps 	__inout_ecount(TX_NQSTATS)	efsys_stat_t *stat)
384*e948693eSPhilip Paeps {
385*e948693eSPhilip Paeps 	unsigned int id;
386*e948693eSPhilip Paeps 
387*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
388*e948693eSPhilip Paeps 
389*e948693eSPhilip Paeps 	for (id = 0; id < TX_NQSTATS; id++) {
390*e948693eSPhilip Paeps 		efsys_stat_t *essp = &stat[id];
391*e948693eSPhilip Paeps 
392*e948693eSPhilip Paeps 		EFSYS_STAT_INCR(essp, etp->et_stat[id]);
393*e948693eSPhilip Paeps 		etp->et_stat[id] = 0;
394*e948693eSPhilip Paeps 	}
395*e948693eSPhilip Paeps }
396*e948693eSPhilip Paeps #endif	/* EFSYS_OPT_QSTATS */
397*e948693eSPhilip Paeps 
398*e948693eSPhilip Paeps 		void
399*e948693eSPhilip Paeps efx_tx_qdestroy(
400*e948693eSPhilip Paeps 	__in	efx_txq_t *etp)
401*e948693eSPhilip Paeps {
402*e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
403*e948693eSPhilip Paeps 	efx_oword_t oword;
404*e948693eSPhilip Paeps 
405*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
406*e948693eSPhilip Paeps 
407*e948693eSPhilip Paeps 	EFSYS_ASSERT(enp->en_tx_qcount != 0);
408*e948693eSPhilip Paeps 	--enp->en_tx_qcount;
409*e948693eSPhilip Paeps 
410*e948693eSPhilip Paeps 	/* Purge descriptor queue */
411*e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
412*e948693eSPhilip Paeps 
413*e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
414*e948693eSPhilip Paeps 			    etp->et_index, &oword);
415*e948693eSPhilip Paeps 
416*e948693eSPhilip Paeps 	/* Free the TXQ object */
417*e948693eSPhilip Paeps 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
418*e948693eSPhilip Paeps }
419*e948693eSPhilip Paeps 
420*e948693eSPhilip Paeps 		void
421*e948693eSPhilip Paeps efx_tx_fini(
422*e948693eSPhilip Paeps 	__in	efx_nic_t *enp)
423*e948693eSPhilip Paeps {
424*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
425*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
426*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
427*e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
428*e948693eSPhilip Paeps 
429*e948693eSPhilip Paeps 	enp->en_mod_flags &= ~EFX_MOD_TX;
430*e948693eSPhilip Paeps }
431