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