xref: /freebsd/sys/dev/sfxge/common/efx_tx.c (revision 3c838a9f51e4d2a7753500d167ba7dbbb9827c82)
1e948693eSPhilip Paeps /*-
2*3c838a9fSAndrew Rybchenko  * Copyright (c) 2007-2015 Solarflare Communications Inc.
3*3c838a9fSAndrew Rybchenko  * All rights reserved.
4e948693eSPhilip Paeps  *
5e948693eSPhilip Paeps  * Redistribution and use in source and binary forms, with or without
6*3c838a9fSAndrew Rybchenko  * modification, are permitted provided that the following conditions are met:
7e948693eSPhilip Paeps  *
8*3c838a9fSAndrew Rybchenko  * 1. Redistributions of source code must retain the above copyright notice,
9*3c838a9fSAndrew Rybchenko  *    this list of conditions and the following disclaimer.
10*3c838a9fSAndrew Rybchenko  * 2. Redistributions in binary form must reproduce the above copyright notice,
11*3c838a9fSAndrew Rybchenko  *    this list of conditions and the following disclaimer in the documentation
12*3c838a9fSAndrew Rybchenko  *    and/or other materials provided with the distribution.
13*3c838a9fSAndrew Rybchenko  *
14*3c838a9fSAndrew Rybchenko  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*3c838a9fSAndrew Rybchenko  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*3c838a9fSAndrew Rybchenko  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*3c838a9fSAndrew Rybchenko  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*3c838a9fSAndrew Rybchenko  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*3c838a9fSAndrew Rybchenko  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*3c838a9fSAndrew Rybchenko  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*3c838a9fSAndrew Rybchenko  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*3c838a9fSAndrew Rybchenko  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*3c838a9fSAndrew Rybchenko  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*3c838a9fSAndrew Rybchenko  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*3c838a9fSAndrew Rybchenko  *
26*3c838a9fSAndrew Rybchenko  * The views and conclusions contained in the software and documentation are
27*3c838a9fSAndrew Rybchenko  * those of the authors and should not be interpreted as representing official
28*3c838a9fSAndrew Rybchenko  * policies, either expressed or implied, of the FreeBSD Project.
29e948693eSPhilip Paeps  */
30e948693eSPhilip Paeps 
315dee87d7SPhilip Paeps #include <sys/cdefs.h>
325dee87d7SPhilip Paeps __FBSDID("$FreeBSD$");
335dee87d7SPhilip Paeps 
34e948693eSPhilip Paeps #include "efsys.h"
35e948693eSPhilip Paeps #include "efx.h"
36e948693eSPhilip Paeps #include "efx_types.h"
37e948693eSPhilip Paeps #include "efx_regs.h"
38e948693eSPhilip Paeps #include "efx_impl.h"
39e948693eSPhilip Paeps 
40e948693eSPhilip Paeps #if EFSYS_OPT_QSTATS
41e948693eSPhilip Paeps #define	EFX_TX_QSTAT_INCR(_etp, _stat)					\
42e948693eSPhilip Paeps 	do {								\
43e948693eSPhilip Paeps 		(_etp)->et_stat[_stat]++;				\
44e948693eSPhilip Paeps 	_NOTE(CONSTANTCONDITION)					\
45e948693eSPhilip Paeps 	} while (B_FALSE)
46e948693eSPhilip Paeps #else
47e948693eSPhilip Paeps #define	EFX_TX_QSTAT_INCR(_etp, _stat)
48e948693eSPhilip Paeps #endif
49e948693eSPhilip Paeps 
50*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
51*3c838a9fSAndrew Rybchenko 
52*3c838a9fSAndrew Rybchenko static	__checkReturn	int
53*3c838a9fSAndrew Rybchenko falconsiena_tx_init(
54*3c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
55*3c838a9fSAndrew Rybchenko 
56*3c838a9fSAndrew Rybchenko static			void
57*3c838a9fSAndrew Rybchenko falconsiena_tx_fini(
58*3c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
59*3c838a9fSAndrew Rybchenko 
60*3c838a9fSAndrew Rybchenko static	__checkReturn	int
61*3c838a9fSAndrew Rybchenko falconsiena_tx_qcreate(
62*3c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
63*3c838a9fSAndrew Rybchenko 	__in		unsigned int index,
64*3c838a9fSAndrew Rybchenko 	__in		unsigned int label,
65*3c838a9fSAndrew Rybchenko 	__in		efsys_mem_t *esmp,
66*3c838a9fSAndrew Rybchenko 	__in		size_t n,
67*3c838a9fSAndrew Rybchenko 	__in		uint32_t id,
68*3c838a9fSAndrew Rybchenko 	__in		uint16_t flags,
69*3c838a9fSAndrew Rybchenko 	__in		efx_evq_t *eep,
70*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
71*3c838a9fSAndrew Rybchenko 	__out		unsigned int *addedp);
72*3c838a9fSAndrew Rybchenko 
73*3c838a9fSAndrew Rybchenko static		void
74*3c838a9fSAndrew Rybchenko falconsiena_tx_qdestroy(
75*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp);
76*3c838a9fSAndrew Rybchenko 
77*3c838a9fSAndrew Rybchenko static	__checkReturn	int
78*3c838a9fSAndrew Rybchenko falconsiena_tx_qpost(
79*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
80*3c838a9fSAndrew Rybchenko 	__in_ecount(n)	efx_buffer_t *eb,
81*3c838a9fSAndrew Rybchenko 	__in		unsigned int n,
82*3c838a9fSAndrew Rybchenko 	__in		unsigned int completed,
83*3c838a9fSAndrew Rybchenko 	__inout		unsigned int *addedp);
84*3c838a9fSAndrew Rybchenko 
85*3c838a9fSAndrew Rybchenko static			void
86*3c838a9fSAndrew Rybchenko falconsiena_tx_qpush(
87*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
88*3c838a9fSAndrew Rybchenko 	__in	unsigned int added,
89*3c838a9fSAndrew Rybchenko 	__in	unsigned int pushed);
90*3c838a9fSAndrew Rybchenko 
91*3c838a9fSAndrew Rybchenko static	__checkReturn	int
92*3c838a9fSAndrew Rybchenko falconsiena_tx_qpace(
93*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
94*3c838a9fSAndrew Rybchenko 	__in		unsigned int ns);
95*3c838a9fSAndrew Rybchenko 
96*3c838a9fSAndrew Rybchenko static	__checkReturn	int
97*3c838a9fSAndrew Rybchenko falconsiena_tx_qflush(
98*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp);
99*3c838a9fSAndrew Rybchenko 
100*3c838a9fSAndrew Rybchenko static			void
101*3c838a9fSAndrew Rybchenko falconsiena_tx_qenable(
102*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp);
103*3c838a9fSAndrew Rybchenko 
104*3c838a9fSAndrew Rybchenko 	__checkReturn	int
105*3c838a9fSAndrew Rybchenko falconsiena_tx_qdesc_post(
106*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
107*3c838a9fSAndrew Rybchenko 	__in_ecount(n)	efx_desc_t *ed,
108*3c838a9fSAndrew Rybchenko 	__in		unsigned int n,
109*3c838a9fSAndrew Rybchenko 	__in		unsigned int completed,
110*3c838a9fSAndrew Rybchenko 	__inout		unsigned int *addedp);
111*3c838a9fSAndrew Rybchenko 
112*3c838a9fSAndrew Rybchenko 	void
113*3c838a9fSAndrew Rybchenko falconsiena_tx_qdesc_dma_create(
114*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
115*3c838a9fSAndrew Rybchenko 	__in	efsys_dma_addr_t addr,
116*3c838a9fSAndrew Rybchenko 	__in	size_t size,
117*3c838a9fSAndrew Rybchenko 	__in	boolean_t eop,
118*3c838a9fSAndrew Rybchenko 	__out	efx_desc_t *edp);
119*3c838a9fSAndrew Rybchenko 
120*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
121*3c838a9fSAndrew Rybchenko static			void
122*3c838a9fSAndrew Rybchenko falconsiena_tx_qstats_update(
123*3c838a9fSAndrew Rybchenko 	__in				efx_txq_t *etp,
124*3c838a9fSAndrew Rybchenko 	__inout_ecount(TX_NQSTATS)	efsys_stat_t *stat);
125*3c838a9fSAndrew Rybchenko #endif
126*3c838a9fSAndrew Rybchenko 
127*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
128*3c838a9fSAndrew Rybchenko 
129*3c838a9fSAndrew Rybchenko 
130*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_FALCON
131*3c838a9fSAndrew Rybchenko static efx_tx_ops_t	__efx_tx_falcon_ops = {
132*3c838a9fSAndrew Rybchenko 	falconsiena_tx_init,			/* etxo_init */
133*3c838a9fSAndrew Rybchenko 	falconsiena_tx_fini,			/* etxo_fini */
134*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qcreate,			/* etxo_qcreate */
135*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qdestroy,		/* etxo_qdestroy */
136*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qpost,			/* etxo_qpost */
137*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qpush,			/* etxo_qpush */
138*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qpace,			/* etxo_qpace */
139*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qflush,			/* etxo_qflush */
140*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qenable,			/* etxo_qenable */
141*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_enable */
142*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_disable */
143*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_write */
144*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_post */
145*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qdesc_post,		/* etxo_qdesc_post */
146*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qdesc_dma_create,	/* etxo_qdesc_dma_create */
147*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qdesc_tso_create */
148*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qdesc_vlantci_create */
149*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
150*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qstats_update,		/* etxo_qstats_update */
151*3c838a9fSAndrew Rybchenko #endif
152*3c838a9fSAndrew Rybchenko };
153*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_FALCON */
154*3c838a9fSAndrew Rybchenko 
155*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
156*3c838a9fSAndrew Rybchenko static efx_tx_ops_t	__efx_tx_siena_ops = {
157*3c838a9fSAndrew Rybchenko 	falconsiena_tx_init,			/* etxo_init */
158*3c838a9fSAndrew Rybchenko 	falconsiena_tx_fini,			/* etxo_fini */
159*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qcreate,			/* etxo_qcreate */
160*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qdestroy,		/* etxo_qdestroy */
161*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qpost,			/* etxo_qpost */
162*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qpush,			/* etxo_qpush */
163*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qpace,			/* etxo_qpace */
164*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qflush,			/* etxo_qflush */
165*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qenable,			/* etxo_qenable */
166*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_enable */
167*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_disable */
168*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_write */
169*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qpio_post */
170*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qdesc_post,		/* etxo_qdesc_post */
171*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qdesc_dma_create,	/* etxo_qdesc_dma_create */
172*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qdesc_tso_create */
173*3c838a9fSAndrew Rybchenko 	NULL,					/* etxo_qdesc_vlantci_create */
174*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
175*3c838a9fSAndrew Rybchenko 	falconsiena_tx_qstats_update,		/* etxo_qstats_update */
176*3c838a9fSAndrew Rybchenko #endif
177*3c838a9fSAndrew Rybchenko };
178*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
179*3c838a9fSAndrew Rybchenko 
180*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
181*3c838a9fSAndrew Rybchenko static efx_tx_ops_t	__efx_tx_hunt_ops = {
182*3c838a9fSAndrew Rybchenko 	hunt_tx_init,				/* etxo_init */
183*3c838a9fSAndrew Rybchenko 	hunt_tx_fini,				/* etxo_fini */
184*3c838a9fSAndrew Rybchenko 	hunt_tx_qcreate,			/* etxo_qcreate */
185*3c838a9fSAndrew Rybchenko 	hunt_tx_qdestroy,			/* etxo_qdestroy */
186*3c838a9fSAndrew Rybchenko 	hunt_tx_qpost,				/* etxo_qpost */
187*3c838a9fSAndrew Rybchenko 	hunt_tx_qpush,				/* etxo_qpush */
188*3c838a9fSAndrew Rybchenko 	hunt_tx_qpace,				/* etxo_qpace */
189*3c838a9fSAndrew Rybchenko 	hunt_tx_qflush,				/* etxo_qflush */
190*3c838a9fSAndrew Rybchenko 	hunt_tx_qenable,			/* etxo_qenable */
191*3c838a9fSAndrew Rybchenko 	hunt_tx_qpio_enable,			/* etxo_qpio_enable */
192*3c838a9fSAndrew Rybchenko 	hunt_tx_qpio_disable,			/* etxo_qpio_disable */
193*3c838a9fSAndrew Rybchenko 	hunt_tx_qpio_write,			/* etxo_qpio_write */
194*3c838a9fSAndrew Rybchenko 	hunt_tx_qpio_post,			/* etxo_qpio_post */
195*3c838a9fSAndrew Rybchenko 	hunt_tx_qdesc_post,			/* etxo_qdesc_post */
196*3c838a9fSAndrew Rybchenko 	hunt_tx_qdesc_dma_create,		/* etxo_qdesc_dma_create */
197*3c838a9fSAndrew Rybchenko 	hunt_tx_qdesc_tso_create,		/* etxo_qdesc_tso_create */
198*3c838a9fSAndrew Rybchenko 	hunt_tx_qdesc_vlantci_create,		/* etxo_qdesc_vlantci_create */
199*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
200*3c838a9fSAndrew Rybchenko 	hunt_tx_qstats_update,			/* etxo_qstats_update */
201*3c838a9fSAndrew Rybchenko #endif
202*3c838a9fSAndrew Rybchenko };
203*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
204*3c838a9fSAndrew Rybchenko 
205e948693eSPhilip Paeps 	__checkReturn	int
206e948693eSPhilip Paeps efx_tx_init(
207e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
208e948693eSPhilip Paeps {
209*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop;
210e948693eSPhilip Paeps 	int rc;
211e948693eSPhilip Paeps 
212e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
213e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
214e948693eSPhilip Paeps 
215e948693eSPhilip Paeps 	if (!(enp->en_mod_flags & EFX_MOD_EV)) {
216e948693eSPhilip Paeps 		rc = EINVAL;
217e948693eSPhilip Paeps 		goto fail1;
218e948693eSPhilip Paeps 	}
219e948693eSPhilip Paeps 
220e948693eSPhilip Paeps 	if (enp->en_mod_flags & EFX_MOD_TX) {
221e948693eSPhilip Paeps 		rc = EINVAL;
222e948693eSPhilip Paeps 		goto fail2;
223e948693eSPhilip Paeps 	}
224e948693eSPhilip Paeps 
225*3c838a9fSAndrew Rybchenko 	switch (enp->en_family) {
226*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_FALCON
227*3c838a9fSAndrew Rybchenko 	case EFX_FAMILY_FALCON:
228*3c838a9fSAndrew Rybchenko 		etxop = (efx_tx_ops_t *)&__efx_tx_falcon_ops;
229*3c838a9fSAndrew Rybchenko 		break;
230*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_FALCON */
231*3c838a9fSAndrew Rybchenko 
232*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
233*3c838a9fSAndrew Rybchenko 	case EFX_FAMILY_SIENA:
234*3c838a9fSAndrew Rybchenko 		etxop = (efx_tx_ops_t *)&__efx_tx_siena_ops;
235*3c838a9fSAndrew Rybchenko 		break;
236*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
237*3c838a9fSAndrew Rybchenko 
238*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
239*3c838a9fSAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
240*3c838a9fSAndrew Rybchenko 		etxop = (efx_tx_ops_t *)&__efx_tx_hunt_ops;
241*3c838a9fSAndrew Rybchenko 		break;
242*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
243*3c838a9fSAndrew Rybchenko 
244*3c838a9fSAndrew Rybchenko 	default:
245*3c838a9fSAndrew Rybchenko 		EFSYS_ASSERT(0);
246*3c838a9fSAndrew Rybchenko 		rc = ENOTSUP;
247*3c838a9fSAndrew Rybchenko 		goto fail3;
248*3c838a9fSAndrew Rybchenko 	}
249*3c838a9fSAndrew Rybchenko 
250e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
251e948693eSPhilip Paeps 
252*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_init(enp)) != 0)
253*3c838a9fSAndrew Rybchenko 		goto fail4;
254*3c838a9fSAndrew Rybchenko 
255*3c838a9fSAndrew Rybchenko 	enp->en_etxop = etxop;
256*3c838a9fSAndrew Rybchenko 	enp->en_mod_flags |= EFX_MOD_TX;
257*3c838a9fSAndrew Rybchenko 	return (0);
258*3c838a9fSAndrew Rybchenko 
259*3c838a9fSAndrew Rybchenko fail4:
260*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail4);
261*3c838a9fSAndrew Rybchenko fail3:
262*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail3);
263*3c838a9fSAndrew Rybchenko fail2:
264*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
265*3c838a9fSAndrew Rybchenko fail1:
266*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
267*3c838a9fSAndrew Rybchenko 
268*3c838a9fSAndrew Rybchenko 	enp->en_etxop = NULL;
269*3c838a9fSAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_TX;
270*3c838a9fSAndrew Rybchenko 	return (rc);
271*3c838a9fSAndrew Rybchenko }
272*3c838a9fSAndrew Rybchenko 
273*3c838a9fSAndrew Rybchenko 			void
274*3c838a9fSAndrew Rybchenko efx_tx_fini(
275*3c838a9fSAndrew Rybchenko 	__in	efx_nic_t *enp)
276*3c838a9fSAndrew Rybchenko {
277*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
278*3c838a9fSAndrew Rybchenko 
279*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
280*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
281*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
282*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
283*3c838a9fSAndrew Rybchenko 
284*3c838a9fSAndrew Rybchenko 	etxop->etxo_fini(enp);
285*3c838a9fSAndrew Rybchenko 
286*3c838a9fSAndrew Rybchenko 	enp->en_etxop = NULL;
287*3c838a9fSAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_TX;
288*3c838a9fSAndrew Rybchenko }
289*3c838a9fSAndrew Rybchenko 
290*3c838a9fSAndrew Rybchenko 	__checkReturn	int
291*3c838a9fSAndrew Rybchenko efx_tx_qcreate(
292*3c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
293*3c838a9fSAndrew Rybchenko 	__in		unsigned int index,
294*3c838a9fSAndrew Rybchenko 	__in		unsigned int label,
295*3c838a9fSAndrew Rybchenko 	__in		efsys_mem_t *esmp,
296*3c838a9fSAndrew Rybchenko 	__in		size_t n,
297*3c838a9fSAndrew Rybchenko 	__in		uint32_t id,
298*3c838a9fSAndrew Rybchenko 	__in		uint16_t flags,
299*3c838a9fSAndrew Rybchenko 	__in		efx_evq_t *eep,
300*3c838a9fSAndrew Rybchenko 	__deref_out	efx_txq_t **etpp,
301*3c838a9fSAndrew Rybchenko 	__out		unsigned int *addedp)
302*3c838a9fSAndrew Rybchenko {
303*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
304*3c838a9fSAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
305*3c838a9fSAndrew Rybchenko 	efx_txq_t *etp;
306*3c838a9fSAndrew Rybchenko 	int rc;
307*3c838a9fSAndrew Rybchenko 
308*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
309*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
310*3c838a9fSAndrew Rybchenko 
311*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit);
312*3c838a9fSAndrew Rybchenko 
313*3c838a9fSAndrew Rybchenko 	/* Allocate an TXQ object */
314*3c838a9fSAndrew Rybchenko 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
315*3c838a9fSAndrew Rybchenko 
316*3c838a9fSAndrew Rybchenko 	if (etp == NULL) {
317*3c838a9fSAndrew Rybchenko 		rc = ENOMEM;
318*3c838a9fSAndrew Rybchenko 		goto fail1;
319*3c838a9fSAndrew Rybchenko 	}
320*3c838a9fSAndrew Rybchenko 
321*3c838a9fSAndrew Rybchenko 	etp->et_magic = EFX_TXQ_MAGIC;
322*3c838a9fSAndrew Rybchenko 	etp->et_enp = enp;
323*3c838a9fSAndrew Rybchenko 	etp->et_index = index;
324*3c838a9fSAndrew Rybchenko 	etp->et_mask = n - 1;
325*3c838a9fSAndrew Rybchenko 	etp->et_esmp = esmp;
326*3c838a9fSAndrew Rybchenko 
327*3c838a9fSAndrew Rybchenko 	/* Initial descriptor index may be modified by etxo_qcreate */
328*3c838a9fSAndrew Rybchenko 	*addedp = 0;
329*3c838a9fSAndrew Rybchenko 
330*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_qcreate(enp, index, label, esmp,
331*3c838a9fSAndrew Rybchenko 	    n, id, flags, eep, etp, addedp)) != 0)
332*3c838a9fSAndrew Rybchenko 			goto fail2;
333*3c838a9fSAndrew Rybchenko 
334*3c838a9fSAndrew Rybchenko 	enp->en_tx_qcount++;
335*3c838a9fSAndrew Rybchenko 	*etpp = etp;
336*3c838a9fSAndrew Rybchenko 
337*3c838a9fSAndrew Rybchenko 	return (0);
338*3c838a9fSAndrew Rybchenko 
339*3c838a9fSAndrew Rybchenko fail2:
340*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
341*3c838a9fSAndrew Rybchenko 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
342*3c838a9fSAndrew Rybchenko fail1:
343*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
344*3c838a9fSAndrew Rybchenko 	return (rc);
345*3c838a9fSAndrew Rybchenko }
346*3c838a9fSAndrew Rybchenko 
347*3c838a9fSAndrew Rybchenko 		void
348*3c838a9fSAndrew Rybchenko efx_tx_qdestroy(
349*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp)
350*3c838a9fSAndrew Rybchenko {
351*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
352*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
353*3c838a9fSAndrew Rybchenko 
354*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
355*3c838a9fSAndrew Rybchenko 
356*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT(enp->en_tx_qcount != 0);
357*3c838a9fSAndrew Rybchenko 	--enp->en_tx_qcount;
358*3c838a9fSAndrew Rybchenko 
359*3c838a9fSAndrew Rybchenko 	etxop->etxo_qdestroy(etp);
360*3c838a9fSAndrew Rybchenko 
361*3c838a9fSAndrew Rybchenko 	/* Free the TXQ object */
362*3c838a9fSAndrew Rybchenko 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
363*3c838a9fSAndrew Rybchenko }
364*3c838a9fSAndrew Rybchenko 
365*3c838a9fSAndrew Rybchenko 	__checkReturn	int
366*3c838a9fSAndrew Rybchenko efx_tx_qpost(
367*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
368*3c838a9fSAndrew Rybchenko 	__in_ecount(n)	efx_buffer_t *eb,
369*3c838a9fSAndrew Rybchenko 	__in		unsigned int n,
370*3c838a9fSAndrew Rybchenko 	__in		unsigned int completed,
371*3c838a9fSAndrew Rybchenko 	__inout		unsigned int *addedp)
372*3c838a9fSAndrew Rybchenko {
373*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
374*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
375*3c838a9fSAndrew Rybchenko 	int rc;
376*3c838a9fSAndrew Rybchenko 
377*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
378*3c838a9fSAndrew Rybchenko 
379*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_qpost(etp, eb,
380*3c838a9fSAndrew Rybchenko 	    n, completed, addedp)) != 0)
381*3c838a9fSAndrew Rybchenko 		goto fail1;
382*3c838a9fSAndrew Rybchenko 
383*3c838a9fSAndrew Rybchenko 	return (0);
384*3c838a9fSAndrew Rybchenko 
385*3c838a9fSAndrew Rybchenko fail1:
386*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
387*3c838a9fSAndrew Rybchenko 	return (rc);
388*3c838a9fSAndrew Rybchenko }
389*3c838a9fSAndrew Rybchenko 
390*3c838a9fSAndrew Rybchenko 			void
391*3c838a9fSAndrew Rybchenko efx_tx_qpush(
392*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
393*3c838a9fSAndrew Rybchenko 	__in	unsigned int added,
394*3c838a9fSAndrew Rybchenko 	__in	unsigned int pushed)
395*3c838a9fSAndrew Rybchenko {
396*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
397*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
398*3c838a9fSAndrew Rybchenko 
399*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
400*3c838a9fSAndrew Rybchenko 
401*3c838a9fSAndrew Rybchenko 	etxop->etxo_qpush(etp, added, pushed);
402*3c838a9fSAndrew Rybchenko }
403*3c838a9fSAndrew Rybchenko 
404*3c838a9fSAndrew Rybchenko 	__checkReturn	int
405*3c838a9fSAndrew Rybchenko efx_tx_qpace(
406*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
407*3c838a9fSAndrew Rybchenko 	__in		unsigned int ns)
408*3c838a9fSAndrew Rybchenko {
409*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
410*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
411*3c838a9fSAndrew Rybchenko 	int rc;
412*3c838a9fSAndrew Rybchenko 
413*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
414*3c838a9fSAndrew Rybchenko 
415*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_qpace(etp, ns)) != 0)
416*3c838a9fSAndrew Rybchenko 		goto fail1;
417*3c838a9fSAndrew Rybchenko 
418*3c838a9fSAndrew Rybchenko 	return (0);
419*3c838a9fSAndrew Rybchenko 
420*3c838a9fSAndrew Rybchenko fail1:
421*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
422*3c838a9fSAndrew Rybchenko 	return (rc);
423*3c838a9fSAndrew Rybchenko }
424*3c838a9fSAndrew Rybchenko 
425*3c838a9fSAndrew Rybchenko 	__checkReturn	int
426*3c838a9fSAndrew Rybchenko efx_tx_qflush(
427*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp)
428*3c838a9fSAndrew Rybchenko {
429*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
430*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
431*3c838a9fSAndrew Rybchenko 	int rc;
432*3c838a9fSAndrew Rybchenko 
433*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
434*3c838a9fSAndrew Rybchenko 
435*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_qflush(etp)) != 0)
436*3c838a9fSAndrew Rybchenko 		goto fail1;
437*3c838a9fSAndrew Rybchenko 
438*3c838a9fSAndrew Rybchenko 	return (0);
439*3c838a9fSAndrew Rybchenko 
440*3c838a9fSAndrew Rybchenko fail1:
441*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
442*3c838a9fSAndrew Rybchenko 	return (rc);
443*3c838a9fSAndrew Rybchenko }
444*3c838a9fSAndrew Rybchenko 
445*3c838a9fSAndrew Rybchenko 			void
446*3c838a9fSAndrew Rybchenko efx_tx_qenable(
447*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp)
448*3c838a9fSAndrew Rybchenko {
449*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
450*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
451*3c838a9fSAndrew Rybchenko 
452*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
453*3c838a9fSAndrew Rybchenko 
454*3c838a9fSAndrew Rybchenko 	etxop->etxo_qenable(etp);
455*3c838a9fSAndrew Rybchenko }
456*3c838a9fSAndrew Rybchenko 
457*3c838a9fSAndrew Rybchenko 	__checkReturn	int
458*3c838a9fSAndrew Rybchenko efx_tx_qpio_enable(
459*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp)
460*3c838a9fSAndrew Rybchenko {
461*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
462*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
463*3c838a9fSAndrew Rybchenko 	int rc;
464*3c838a9fSAndrew Rybchenko 
465*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
466*3c838a9fSAndrew Rybchenko 
467*3c838a9fSAndrew Rybchenko 	if (~enp->en_features & EFX_FEATURE_PIO_BUFFERS) {
468*3c838a9fSAndrew Rybchenko 		rc = ENOTSUP;
469*3c838a9fSAndrew Rybchenko 		goto fail1;
470*3c838a9fSAndrew Rybchenko 	}
471*3c838a9fSAndrew Rybchenko 	if (etxop->etxo_qpio_enable == NULL) {
472*3c838a9fSAndrew Rybchenko 		rc = ENOTSUP;
473*3c838a9fSAndrew Rybchenko 		goto fail2;
474*3c838a9fSAndrew Rybchenko 	}
475*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_qpio_enable(etp)) != 0)
476*3c838a9fSAndrew Rybchenko 		goto fail3;
477*3c838a9fSAndrew Rybchenko 
478*3c838a9fSAndrew Rybchenko 	return (0);
479*3c838a9fSAndrew Rybchenko 
480*3c838a9fSAndrew Rybchenko fail3:
481*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail3);
482*3c838a9fSAndrew Rybchenko fail2:
483*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
484*3c838a9fSAndrew Rybchenko fail1:
485*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
486*3c838a9fSAndrew Rybchenko 	return (rc);
487*3c838a9fSAndrew Rybchenko }
488*3c838a9fSAndrew Rybchenko 
489*3c838a9fSAndrew Rybchenko 		void
490*3c838a9fSAndrew Rybchenko efx_tx_qpio_disable(
491*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp)
492*3c838a9fSAndrew Rybchenko {
493*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
494*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
495*3c838a9fSAndrew Rybchenko 
496*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
497*3c838a9fSAndrew Rybchenko 
498*3c838a9fSAndrew Rybchenko 	if (etxop->etxo_qpio_disable != NULL)
499*3c838a9fSAndrew Rybchenko 		etxop->etxo_qpio_disable(etp);
500*3c838a9fSAndrew Rybchenko }
501*3c838a9fSAndrew Rybchenko 
502*3c838a9fSAndrew Rybchenko 	__checkReturn	int
503*3c838a9fSAndrew Rybchenko efx_tx_qpio_write(
504*3c838a9fSAndrew Rybchenko 	__in			efx_txq_t *etp,
505*3c838a9fSAndrew Rybchenko 	__in_ecount(buf_length)	uint8_t *buffer,
506*3c838a9fSAndrew Rybchenko 	__in			size_t buf_length,
507*3c838a9fSAndrew Rybchenko 	__in			size_t pio_buf_offset)
508*3c838a9fSAndrew Rybchenko {
509*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
510*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
511*3c838a9fSAndrew Rybchenko 	int rc;
512*3c838a9fSAndrew Rybchenko 
513*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
514*3c838a9fSAndrew Rybchenko 
515*3c838a9fSAndrew Rybchenko 	if (etxop->etxo_qpio_write != NULL) {
516*3c838a9fSAndrew Rybchenko 		if ((rc = etxop->etxo_qpio_write(etp, buffer, buf_length,
517*3c838a9fSAndrew Rybchenko 						pio_buf_offset)) != 0)
518*3c838a9fSAndrew Rybchenko 			goto fail1;
519*3c838a9fSAndrew Rybchenko 		return (0);
520*3c838a9fSAndrew Rybchenko 	}
521*3c838a9fSAndrew Rybchenko 
522*3c838a9fSAndrew Rybchenko 	return (ENOTSUP);
523*3c838a9fSAndrew Rybchenko 
524*3c838a9fSAndrew Rybchenko fail1:
525*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
526*3c838a9fSAndrew Rybchenko 	return (rc);
527*3c838a9fSAndrew Rybchenko }
528*3c838a9fSAndrew Rybchenko 
529*3c838a9fSAndrew Rybchenko 	__checkReturn	int
530*3c838a9fSAndrew Rybchenko efx_tx_qpio_post(
531*3c838a9fSAndrew Rybchenko 	__in			efx_txq_t *etp,
532*3c838a9fSAndrew Rybchenko 	__in			size_t pkt_length,
533*3c838a9fSAndrew Rybchenko 	__in			unsigned int completed,
534*3c838a9fSAndrew Rybchenko 	__inout			unsigned int *addedp)
535*3c838a9fSAndrew Rybchenko {
536*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
537*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
538*3c838a9fSAndrew Rybchenko 	int rc;
539*3c838a9fSAndrew Rybchenko 
540*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
541*3c838a9fSAndrew Rybchenko 
542*3c838a9fSAndrew Rybchenko 	if (etxop->etxo_qpio_post != NULL) {
543*3c838a9fSAndrew Rybchenko 		if ((rc = etxop->etxo_qpio_post(etp, pkt_length, completed,
544*3c838a9fSAndrew Rybchenko 						addedp)) != 0)
545*3c838a9fSAndrew Rybchenko 			goto fail1;
546*3c838a9fSAndrew Rybchenko 		return (0);
547*3c838a9fSAndrew Rybchenko 	}
548*3c838a9fSAndrew Rybchenko 
549*3c838a9fSAndrew Rybchenko 	return (ENOTSUP);
550*3c838a9fSAndrew Rybchenko 
551*3c838a9fSAndrew Rybchenko fail1:
552*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
553*3c838a9fSAndrew Rybchenko 	return (rc);
554*3c838a9fSAndrew Rybchenko }
555*3c838a9fSAndrew Rybchenko 
556*3c838a9fSAndrew Rybchenko 	__checkReturn	int
557*3c838a9fSAndrew Rybchenko efx_tx_qdesc_post(
558*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
559*3c838a9fSAndrew Rybchenko 	__in_ecount(n)	efx_desc_t *ed,
560*3c838a9fSAndrew Rybchenko 	__in		unsigned int n,
561*3c838a9fSAndrew Rybchenko 	__in		unsigned int completed,
562*3c838a9fSAndrew Rybchenko 	__inout		unsigned int *addedp)
563*3c838a9fSAndrew Rybchenko {
564*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
565*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
566*3c838a9fSAndrew Rybchenko 	int rc;
567*3c838a9fSAndrew Rybchenko 
568*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
569*3c838a9fSAndrew Rybchenko 
570*3c838a9fSAndrew Rybchenko 	if ((rc = etxop->etxo_qdesc_post(etp, ed,
571*3c838a9fSAndrew Rybchenko 	    n, completed, addedp)) != 0)
572*3c838a9fSAndrew Rybchenko 		goto fail1;
573*3c838a9fSAndrew Rybchenko 
574*3c838a9fSAndrew Rybchenko 	return (0);
575*3c838a9fSAndrew Rybchenko 
576*3c838a9fSAndrew Rybchenko fail1:
577*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
578*3c838a9fSAndrew Rybchenko 	return (rc);
579*3c838a9fSAndrew Rybchenko }
580*3c838a9fSAndrew Rybchenko 
581*3c838a9fSAndrew Rybchenko 	void
582*3c838a9fSAndrew Rybchenko efx_tx_qdesc_dma_create(
583*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
584*3c838a9fSAndrew Rybchenko 	__in	efsys_dma_addr_t addr,
585*3c838a9fSAndrew Rybchenko 	__in	size_t size,
586*3c838a9fSAndrew Rybchenko 	__in	boolean_t eop,
587*3c838a9fSAndrew Rybchenko 	__out	efx_desc_t *edp)
588*3c838a9fSAndrew Rybchenko {
589*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
590*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
591*3c838a9fSAndrew Rybchenko 
592*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
593*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT(etxop->etxo_qdesc_dma_create != NULL);
594*3c838a9fSAndrew Rybchenko 
595*3c838a9fSAndrew Rybchenko 	etxop->etxo_qdesc_dma_create(etp, addr, size, eop, edp);
596*3c838a9fSAndrew Rybchenko }
597*3c838a9fSAndrew Rybchenko 
598*3c838a9fSAndrew Rybchenko 	void
599*3c838a9fSAndrew Rybchenko efx_tx_qdesc_tso_create(
600*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
601*3c838a9fSAndrew Rybchenko 	__in	uint16_t ipv4_id,
602*3c838a9fSAndrew Rybchenko 	__in	uint32_t tcp_seq,
603*3c838a9fSAndrew Rybchenko 	__in	uint8_t  tcp_flags,
604*3c838a9fSAndrew Rybchenko 	__out	efx_desc_t *edp)
605*3c838a9fSAndrew Rybchenko {
606*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
607*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
608*3c838a9fSAndrew Rybchenko 
609*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
610*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT(etxop->etxo_qdesc_tso_create != NULL);
611*3c838a9fSAndrew Rybchenko 
612*3c838a9fSAndrew Rybchenko 	etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp);
613*3c838a9fSAndrew Rybchenko }
614*3c838a9fSAndrew Rybchenko 
615*3c838a9fSAndrew Rybchenko 	void
616*3c838a9fSAndrew Rybchenko efx_tx_qdesc_vlantci_create(
617*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
618*3c838a9fSAndrew Rybchenko 	__in	uint16_t tci,
619*3c838a9fSAndrew Rybchenko 	__out	efx_desc_t *edp)
620*3c838a9fSAndrew Rybchenko {
621*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
622*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
623*3c838a9fSAndrew Rybchenko 
624*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
625*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT(etxop->etxo_qdesc_vlantci_create != NULL);
626*3c838a9fSAndrew Rybchenko 
627*3c838a9fSAndrew Rybchenko 	etxop->etxo_qdesc_vlantci_create(etp, tci, edp);
628*3c838a9fSAndrew Rybchenko }
629*3c838a9fSAndrew Rybchenko 
630*3c838a9fSAndrew Rybchenko 
631*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
632*3c838a9fSAndrew Rybchenko 			void
633*3c838a9fSAndrew Rybchenko efx_tx_qstats_update(
634*3c838a9fSAndrew Rybchenko 	__in				efx_txq_t *etp,
635*3c838a9fSAndrew Rybchenko 	__inout_ecount(TX_NQSTATS)	efsys_stat_t *stat)
636*3c838a9fSAndrew Rybchenko {
637*3c838a9fSAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
638*3c838a9fSAndrew Rybchenko 	efx_tx_ops_t *etxop = enp->en_etxop;
639*3c838a9fSAndrew Rybchenko 
640*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
641*3c838a9fSAndrew Rybchenko 
642*3c838a9fSAndrew Rybchenko 	etxop->etxo_qstats_update(etp, stat);
643*3c838a9fSAndrew Rybchenko }
644*3c838a9fSAndrew Rybchenko #endif
645*3c838a9fSAndrew Rybchenko 
646*3c838a9fSAndrew Rybchenko 
647*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
648*3c838a9fSAndrew Rybchenko 
649*3c838a9fSAndrew Rybchenko static	__checkReturn	int
650*3c838a9fSAndrew Rybchenko falconsiena_tx_init(
651*3c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp)
652*3c838a9fSAndrew Rybchenko {
653*3c838a9fSAndrew Rybchenko 	efx_oword_t oword;
654*3c838a9fSAndrew Rybchenko 
655e948693eSPhilip Paeps 	/*
656e948693eSPhilip Paeps 	 * Disable the timer-based TX DMA backoff and allow TX DMA to be
657e948693eSPhilip Paeps 	 * controlled by the RX FIFO fill level (although always allow a
658e948693eSPhilip Paeps 	 * minimal trickle).
659e948693eSPhilip Paeps 	 */
660e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
661e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
662e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
663e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
664e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
665e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
666e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
667e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
668e948693eSPhilip Paeps 
669e948693eSPhilip Paeps 	/*
670e948693eSPhilip Paeps 	 * Filter all packets less than 14 bytes to avoid parsing
671e948693eSPhilip Paeps 	 * errors.
672e948693eSPhilip Paeps 	 */
673e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
674e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
675e948693eSPhilip Paeps 
676e948693eSPhilip Paeps 	/*
677e948693eSPhilip Paeps 	 * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
678e948693eSPhilip Paeps 	 * descriptors (which is bad).
679e948693eSPhilip Paeps 	 */
680e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
681e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
682e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
683e948693eSPhilip Paeps 
684e948693eSPhilip Paeps 	return (0);
685e948693eSPhilip Paeps }
686e948693eSPhilip Paeps 
687e948693eSPhilip Paeps #define	EFX_TX_DESC(_etp, _addr, _size, _eop, _added)			\
688e948693eSPhilip Paeps 	do {								\
689e948693eSPhilip Paeps 		unsigned int id;					\
690e948693eSPhilip Paeps 		size_t offset;						\
691e948693eSPhilip Paeps 		efx_qword_t qword;					\
692e948693eSPhilip Paeps 									\
693e948693eSPhilip Paeps 		id = (_added)++ & (_etp)->et_mask;			\
694e948693eSPhilip Paeps 		offset = id * sizeof (efx_qword_t);			\
695e948693eSPhilip Paeps 									\
696e948693eSPhilip Paeps 		EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index,	\
697e948693eSPhilip Paeps 		    unsigned int, id, efsys_dma_addr_t, (_addr),	\
698e948693eSPhilip Paeps 		    size_t, (_size), boolean_t, (_eop));		\
699e948693eSPhilip Paeps 									\
700e948693eSPhilip Paeps 		EFX_POPULATE_QWORD_4(qword,				\
701e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1,			\
702e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size),	\
703e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_BUF_ADDR_DW0,				\
704e948693eSPhilip Paeps 		    (uint32_t)((_addr) & 0xffffffff),			\
705e948693eSPhilip Paeps 		    FSF_AZ_TX_KER_BUF_ADDR_DW1,				\
706e948693eSPhilip Paeps 		    (uint32_t)((_addr) >> 32));				\
707e948693eSPhilip Paeps 		EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword);	\
708e948693eSPhilip Paeps 									\
709e948693eSPhilip Paeps 		_NOTE(CONSTANTCONDITION)				\
710e948693eSPhilip Paeps 	} while (B_FALSE)
711e948693eSPhilip Paeps 
712*3c838a9fSAndrew Rybchenko static	__checkReturn	int
713*3c838a9fSAndrew Rybchenko falconsiena_tx_qpost(
714e948693eSPhilip Paeps 	__in		efx_txq_t *etp,
715e948693eSPhilip Paeps 	__in_ecount(n)	efx_buffer_t *eb,
716e948693eSPhilip Paeps 	__in		unsigned int n,
717e948693eSPhilip Paeps 	__in		unsigned int completed,
718e948693eSPhilip Paeps 	__inout		unsigned int *addedp)
719e948693eSPhilip Paeps {
720e948693eSPhilip Paeps 	unsigned int added = *addedp;
721e948693eSPhilip Paeps 	unsigned int i;
722e948693eSPhilip Paeps 	int rc = ENOSPC;
723e948693eSPhilip Paeps 
724e948693eSPhilip Paeps 	if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1))
725e948693eSPhilip Paeps 		goto fail1;
726e948693eSPhilip Paeps 
727e948693eSPhilip Paeps 	for (i = 0; i < n; i++) {
728e948693eSPhilip Paeps 		efx_buffer_t *ebp = &eb[i];
729e948693eSPhilip Paeps 		efsys_dma_addr_t start = ebp->eb_addr;
730e948693eSPhilip Paeps 		size_t size = ebp->eb_size;
731e948693eSPhilip Paeps 		efsys_dma_addr_t end = start + size;
732e948693eSPhilip Paeps 
733e948693eSPhilip Paeps 		/* Fragments must not span 4k boundaries. */
734e948693eSPhilip Paeps 		EFSYS_ASSERT(P2ROUNDUP(start + 1, 4096) >= end);
735e948693eSPhilip Paeps 
736e948693eSPhilip Paeps 		EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
737e948693eSPhilip Paeps 	}
738e948693eSPhilip Paeps 
739e948693eSPhilip Paeps 	EFX_TX_QSTAT_INCR(etp, TX_POST);
740e948693eSPhilip Paeps 
741e948693eSPhilip Paeps 	*addedp = added;
742e948693eSPhilip Paeps 	return (0);
743e948693eSPhilip Paeps 
744e948693eSPhilip Paeps fail1:
745e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
746e948693eSPhilip Paeps 
747e948693eSPhilip Paeps 	return (rc);
748e948693eSPhilip Paeps }
749e948693eSPhilip Paeps 
750*3c838a9fSAndrew Rybchenko static		void
751*3c838a9fSAndrew Rybchenko falconsiena_tx_qpush(
752e948693eSPhilip Paeps 	__in	efx_txq_t *etp,
753*3c838a9fSAndrew Rybchenko 	__in	unsigned int added,
754*3c838a9fSAndrew Rybchenko 	__in	unsigned int pushed)
755e948693eSPhilip Paeps {
756e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
757e948693eSPhilip Paeps 	uint32_t wptr;
758e948693eSPhilip Paeps 	efx_dword_t dword;
759e948693eSPhilip Paeps 	efx_oword_t oword;
760e948693eSPhilip Paeps 
761e948693eSPhilip Paeps 	/* Push the populated descriptors out */
762e948693eSPhilip Paeps 	wptr = added & etp->et_mask;
763e948693eSPhilip Paeps 
764e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
765e948693eSPhilip Paeps 
766e948693eSPhilip Paeps 	/* Only write the third DWORD */
767e948693eSPhilip Paeps 	EFX_POPULATE_DWORD_1(dword,
768e948693eSPhilip Paeps 	    EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
769*3c838a9fSAndrew Rybchenko 
770*3c838a9fSAndrew Rybchenko 	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
771*3c838a9fSAndrew Rybchenko 	EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
772*3c838a9fSAndrew Rybchenko 	    wptr, pushed & etp->et_mask);
773*3c838a9fSAndrew Rybchenko 	EFSYS_PIO_WRITE_BARRIER();
774e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
775e948693eSPhilip Paeps 			    etp->et_index, &dword, B_FALSE);
776e948693eSPhilip Paeps }
777e948693eSPhilip Paeps 
7782fc13da6SAndrew Rybchenko #define	EFX_MAX_PACE_VALUE 20
7792fc13da6SAndrew Rybchenko #define	EFX_TX_PACE_CLOCK_BASE	104
7802fc13da6SAndrew Rybchenko 
781*3c838a9fSAndrew Rybchenko static	__checkReturn	int
782*3c838a9fSAndrew Rybchenko falconsiena_tx_qpace(
7832fc13da6SAndrew Rybchenko 	__in		efx_txq_t *etp,
7842fc13da6SAndrew Rybchenko 	__in		unsigned int ns)
7852fc13da6SAndrew Rybchenko {
7862fc13da6SAndrew Rybchenko 	efx_nic_t *enp = etp->et_enp;
7872fc13da6SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
7882fc13da6SAndrew Rybchenko 	efx_oword_t oword;
7892fc13da6SAndrew Rybchenko 	unsigned int pace_val;
7902fc13da6SAndrew Rybchenko 	unsigned int timer_period;
7912fc13da6SAndrew Rybchenko 	int rc;
7922fc13da6SAndrew Rybchenko 
7932fc13da6SAndrew Rybchenko 	if (ns == 0) {
7942fc13da6SAndrew Rybchenko 		pace_val = 0;
7952fc13da6SAndrew Rybchenko 	} else {
7962fc13da6SAndrew Rybchenko 		/*
7972fc13da6SAndrew Rybchenko 		 * The pace_val to write into the table is s.t
7982fc13da6SAndrew Rybchenko 		 * ns <= timer_period * (2 ^ pace_val)
7992fc13da6SAndrew Rybchenko 		 */
8002fc13da6SAndrew Rybchenko 		timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult;
8012fc13da6SAndrew Rybchenko 		for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
8022fc13da6SAndrew Rybchenko 			if ((timer_period << pace_val) >= ns)
8032fc13da6SAndrew Rybchenko 				break;
8042fc13da6SAndrew Rybchenko 		}
8052fc13da6SAndrew Rybchenko 	}
8062fc13da6SAndrew Rybchenko 	if (pace_val > EFX_MAX_PACE_VALUE) {
8072fc13da6SAndrew Rybchenko 		rc = EINVAL;
8082fc13da6SAndrew Rybchenko 		goto fail1;
8092fc13da6SAndrew Rybchenko 	}
8102fc13da6SAndrew Rybchenko 
8112fc13da6SAndrew Rybchenko 	/* Update the pacing table */
8122fc13da6SAndrew Rybchenko 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
813*3c838a9fSAndrew Rybchenko 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index,
814*3c838a9fSAndrew Rybchenko 	    &oword, B_TRUE);
8152fc13da6SAndrew Rybchenko 
8162fc13da6SAndrew Rybchenko 	return (0);
8172fc13da6SAndrew Rybchenko 
8182fc13da6SAndrew Rybchenko fail1:
8192fc13da6SAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
8202fc13da6SAndrew Rybchenko 
8212fc13da6SAndrew Rybchenko 	return (rc);
8222fc13da6SAndrew Rybchenko }
8232fc13da6SAndrew Rybchenko 
824*3c838a9fSAndrew Rybchenko static	__checkReturn	int
825*3c838a9fSAndrew Rybchenko falconsiena_tx_qflush(
826e948693eSPhilip Paeps 	__in		efx_txq_t *etp)
827e948693eSPhilip Paeps {
828e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
829e948693eSPhilip Paeps 	efx_oword_t oword;
830e948693eSPhilip Paeps 	uint32_t label;
831e948693eSPhilip Paeps 
8322fc13da6SAndrew Rybchenko 	efx_tx_qpace(etp, 0);
8332fc13da6SAndrew Rybchenko 
834e948693eSPhilip Paeps 	label = etp->et_index;
835e948693eSPhilip Paeps 
836e948693eSPhilip Paeps 	/* Flush the queue */
837e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
838e948693eSPhilip Paeps 	    FRF_AZ_TX_FLUSH_DESCQ, label);
839e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
840*3c838a9fSAndrew Rybchenko 
841*3c838a9fSAndrew Rybchenko 	return (0);
842e948693eSPhilip Paeps }
843e948693eSPhilip Paeps 
844*3c838a9fSAndrew Rybchenko static		void
845*3c838a9fSAndrew Rybchenko falconsiena_tx_qenable(
846e948693eSPhilip Paeps 	__in	efx_txq_t *etp)
847e948693eSPhilip Paeps {
848e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
849e948693eSPhilip Paeps 	efx_oword_t oword;
850e948693eSPhilip Paeps 
851e948693eSPhilip Paeps 	EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
852*3c838a9fSAndrew Rybchenko 			    etp->et_index, &oword, B_TRUE);
853e948693eSPhilip Paeps 
854e948693eSPhilip Paeps 	EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
855e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
856e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
857e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
858e948693eSPhilip Paeps 	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
859e948693eSPhilip Paeps 
860e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
861e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
862e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
863e948693eSPhilip Paeps 
864e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
865*3c838a9fSAndrew Rybchenko 			    etp->et_index, &oword, B_TRUE);
866e948693eSPhilip Paeps }
867e948693eSPhilip Paeps 
868*3c838a9fSAndrew Rybchenko static	__checkReturn	int
869*3c838a9fSAndrew Rybchenko falconsiena_tx_qcreate(
870e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
871e948693eSPhilip Paeps 	__in		unsigned int index,
872e948693eSPhilip Paeps 	__in		unsigned int label,
873e948693eSPhilip Paeps 	__in		efsys_mem_t *esmp,
874e948693eSPhilip Paeps 	__in		size_t n,
875e948693eSPhilip Paeps 	__in		uint32_t id,
876e948693eSPhilip Paeps 	__in		uint16_t flags,
877e948693eSPhilip Paeps 	__in		efx_evq_t *eep,
878*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
879*3c838a9fSAndrew Rybchenko 	__out		unsigned int *addedp)
880e948693eSPhilip Paeps {
881e948693eSPhilip Paeps 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
882e948693eSPhilip Paeps 	efx_oword_t oword;
883e948693eSPhilip Paeps 	uint32_t size;
884e948693eSPhilip Paeps 	int rc;
885e948693eSPhilip Paeps 
886c071447aSAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS ==
887c071447aSAndrew Rybchenko 	    (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
888c071447aSAndrew Rybchenko 	EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
889e948693eSPhilip Paeps 
890*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT(ISP2(EFX_TXQ_MAXNDESCS(encp)));
891*3c838a9fSAndrew Rybchenko 	EFX_STATIC_ASSERT(ISP2(EFX_TXQ_MINNDESCS));
892*3c838a9fSAndrew Rybchenko 
893*3c838a9fSAndrew Rybchenko 	if (!ISP2(n) || (n < EFX_TXQ_MINNDESCS) || (n > EFX_EVQ_MAXNEVS)) {
894e948693eSPhilip Paeps 		rc = EINVAL;
895e948693eSPhilip Paeps 		goto fail1;
896e948693eSPhilip Paeps 	}
897e948693eSPhilip Paeps 	if (index >= encp->enc_txq_limit) {
898e948693eSPhilip Paeps 		rc = EINVAL;
899e948693eSPhilip Paeps 		goto fail2;
900e948693eSPhilip Paeps 	}
901*3c838a9fSAndrew Rybchenko 	for (size = 0;
902*3c838a9fSAndrew Rybchenko 	    (1 << size) <= (EFX_TXQ_MAXNDESCS(encp) / EFX_TXQ_MINNDESCS);
903e948693eSPhilip Paeps 	    size++)
904e948693eSPhilip Paeps 		if ((1 << size) == (int)(n / EFX_TXQ_MINNDESCS))
905e948693eSPhilip Paeps 			break;
906e948693eSPhilip Paeps 	if (id + (1 << size) >= encp->enc_buftbl_limit) {
907e948693eSPhilip Paeps 		rc = EINVAL;
908e948693eSPhilip Paeps 		goto fail3;
909e948693eSPhilip Paeps 	}
910e948693eSPhilip Paeps 
911e948693eSPhilip Paeps 	/* Set up the new descriptor queue */
912e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_6(oword,
913e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
914e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
915e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_OWNER_ID, 0,
916e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_LABEL, label,
917e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_SIZE, size,
918e948693eSPhilip Paeps 	    FRF_AZ_TX_DESCQ_TYPE, 0);
919e948693eSPhilip Paeps 
920e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
921e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
922e948693eSPhilip Paeps 	    (flags & EFX_CKSUM_IPV4) ? 0 : 1);
923e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
924e948693eSPhilip Paeps 	    (flags & EFX_CKSUM_TCPUDP) ? 0 : 1);
925e948693eSPhilip Paeps 
926e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
927*3c838a9fSAndrew Rybchenko 	    etp->et_index, &oword, B_TRUE);
928e948693eSPhilip Paeps 
929e948693eSPhilip Paeps 	return (0);
930e948693eSPhilip Paeps 
931e948693eSPhilip Paeps fail3:
932e948693eSPhilip Paeps 	EFSYS_PROBE(fail3);
933e948693eSPhilip Paeps fail2:
934e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
935e948693eSPhilip Paeps fail1:
936e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
937e948693eSPhilip Paeps 
938e948693eSPhilip Paeps 	return (rc);
939e948693eSPhilip Paeps }
940e948693eSPhilip Paeps 
941*3c838a9fSAndrew Rybchenko 	__checkReturn	int
942*3c838a9fSAndrew Rybchenko falconsiena_tx_qdesc_post(
943*3c838a9fSAndrew Rybchenko 	__in		efx_txq_t *etp,
944*3c838a9fSAndrew Rybchenko 	__in_ecount(n)	efx_desc_t *ed,
945*3c838a9fSAndrew Rybchenko 	__in		unsigned int n,
946*3c838a9fSAndrew Rybchenko 	__in		unsigned int completed,
947*3c838a9fSAndrew Rybchenko 	__inout		unsigned int *addedp)
948*3c838a9fSAndrew Rybchenko {
949*3c838a9fSAndrew Rybchenko 	unsigned int added = *addedp;
950*3c838a9fSAndrew Rybchenko 	unsigned int i;
951*3c838a9fSAndrew Rybchenko 	int rc;
952*3c838a9fSAndrew Rybchenko 
953*3c838a9fSAndrew Rybchenko 	if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
954*3c838a9fSAndrew Rybchenko 		rc = ENOSPC;
955*3c838a9fSAndrew Rybchenko 		goto fail1;
956*3c838a9fSAndrew Rybchenko 	}
957*3c838a9fSAndrew Rybchenko 
958*3c838a9fSAndrew Rybchenko 	for (i = 0; i < n; i++) {
959*3c838a9fSAndrew Rybchenko 		efx_desc_t *edp = &ed[i];
960*3c838a9fSAndrew Rybchenko 		unsigned int id;
961*3c838a9fSAndrew Rybchenko 		size_t offset;
962*3c838a9fSAndrew Rybchenko 
963*3c838a9fSAndrew Rybchenko 		id = added++ & etp->et_mask;
964*3c838a9fSAndrew Rybchenko 		offset = id * sizeof (efx_desc_t);
965*3c838a9fSAndrew Rybchenko 
966*3c838a9fSAndrew Rybchenko 		EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
967*3c838a9fSAndrew Rybchenko 	}
968*3c838a9fSAndrew Rybchenko 
969*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
970*3c838a9fSAndrew Rybchenko 		    unsigned int, added, unsigned int, n);
971*3c838a9fSAndrew Rybchenko 
972*3c838a9fSAndrew Rybchenko 	EFX_TX_QSTAT_INCR(etp, TX_POST);
973*3c838a9fSAndrew Rybchenko 
974*3c838a9fSAndrew Rybchenko 	*addedp = added;
975*3c838a9fSAndrew Rybchenko 	return (0);
976*3c838a9fSAndrew Rybchenko 
977*3c838a9fSAndrew Rybchenko fail1:
978*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE1(fail1, int, rc);
979*3c838a9fSAndrew Rybchenko 	return (rc);
980*3c838a9fSAndrew Rybchenko }
981*3c838a9fSAndrew Rybchenko 
982*3c838a9fSAndrew Rybchenko 	void
983*3c838a9fSAndrew Rybchenko falconsiena_tx_qdesc_dma_create(
984*3c838a9fSAndrew Rybchenko 	__in	efx_txq_t *etp,
985*3c838a9fSAndrew Rybchenko 	__in	efsys_dma_addr_t addr,
986*3c838a9fSAndrew Rybchenko 	__in	size_t size,
987*3c838a9fSAndrew Rybchenko 	__in	boolean_t eop,
988*3c838a9fSAndrew Rybchenko 	__out	efx_desc_t *edp)
989*3c838a9fSAndrew Rybchenko {
990*3c838a9fSAndrew Rybchenko 	/* Fragments must not span 4k boundaries. */
991*3c838a9fSAndrew Rybchenko 	EFSYS_ASSERT(P2ROUNDUP(addr + 1, 4096) >= addr + size);
992*3c838a9fSAndrew Rybchenko 
993*3c838a9fSAndrew Rybchenko 	EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
994*3c838a9fSAndrew Rybchenko 		    efsys_dma_addr_t, addr,
995*3c838a9fSAndrew Rybchenko 		    size_t, size, boolean_t, eop);
996*3c838a9fSAndrew Rybchenko 
997*3c838a9fSAndrew Rybchenko 	EFX_POPULATE_QWORD_4(edp->ed_eq,
998*3c838a9fSAndrew Rybchenko 			    FSF_AZ_TX_KER_CONT, eop ? 0 : 1,
999*3c838a9fSAndrew Rybchenko 			    FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)size,
1000*3c838a9fSAndrew Rybchenko 			    FSF_AZ_TX_KER_BUF_ADDR_DW0,
1001*3c838a9fSAndrew Rybchenko 			    (uint32_t)(addr & 0xffffffff),
1002*3c838a9fSAndrew Rybchenko 			    FSF_AZ_TX_KER_BUF_ADDR_DW1,
1003*3c838a9fSAndrew Rybchenko 			    (uint32_t)(addr >> 32));
1004*3c838a9fSAndrew Rybchenko }
1005*3c838a9fSAndrew Rybchenko 
1006*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
1007*3c838a9fSAndrew Rybchenko 
1008fe900081SAndrew Rybchenko #if EFSYS_OPT_QSTATS
1009e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
1010*3c838a9fSAndrew Rybchenko /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 9d8d26a0a5e2c453 */
1011*3c838a9fSAndrew Rybchenko static const char 	*__efx_tx_qstat_name[] = {
1012e948693eSPhilip Paeps 	"post",
1013*3c838a9fSAndrew Rybchenko 	"post_pio",
1014e948693eSPhilip Paeps };
1015e948693eSPhilip Paeps /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
1016e948693eSPhilip Paeps 
1017*3c838a9fSAndrew Rybchenko 		const char *
1018e948693eSPhilip Paeps efx_tx_qstat_name(
1019e948693eSPhilip Paeps 	__in	efx_nic_t *enp,
1020e948693eSPhilip Paeps 	__in	unsigned int id)
1021e948693eSPhilip Paeps {
1022e948693eSPhilip Paeps 	_NOTE(ARGUNUSED(enp))
1023e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1024e948693eSPhilip Paeps 	EFSYS_ASSERT3U(id, <, TX_NQSTATS);
1025e948693eSPhilip Paeps 
1026e948693eSPhilip Paeps 	return (__efx_tx_qstat_name[id]);
1027e948693eSPhilip Paeps }
1028e948693eSPhilip Paeps #endif	/* EFSYS_OPT_NAMES */
1029fe900081SAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */
1030e948693eSPhilip Paeps 
1031*3c838a9fSAndrew Rybchenko #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
1032*3c838a9fSAndrew Rybchenko 
1033e948693eSPhilip Paeps #if EFSYS_OPT_QSTATS
1034*3c838a9fSAndrew Rybchenko static					void
1035*3c838a9fSAndrew Rybchenko falconsiena_tx_qstats_update(
1036e948693eSPhilip Paeps 	__in				efx_txq_t *etp,
1037e948693eSPhilip Paeps 	__inout_ecount(TX_NQSTATS)	efsys_stat_t *stat)
1038e948693eSPhilip Paeps {
1039e948693eSPhilip Paeps 	unsigned int id;
1040e948693eSPhilip Paeps 
1041e948693eSPhilip Paeps 	for (id = 0; id < TX_NQSTATS; id++) {
1042e948693eSPhilip Paeps 		efsys_stat_t *essp = &stat[id];
1043e948693eSPhilip Paeps 
1044e948693eSPhilip Paeps 		EFSYS_STAT_INCR(essp, etp->et_stat[id]);
1045e948693eSPhilip Paeps 		etp->et_stat[id] = 0;
1046e948693eSPhilip Paeps 	}
1047e948693eSPhilip Paeps }
1048e948693eSPhilip Paeps #endif	/* EFSYS_OPT_QSTATS */
1049e948693eSPhilip Paeps 
1050*3c838a9fSAndrew Rybchenko static		void
1051*3c838a9fSAndrew Rybchenko falconsiena_tx_qdestroy(
1052e948693eSPhilip Paeps 	__in	efx_txq_t *etp)
1053e948693eSPhilip Paeps {
1054e948693eSPhilip Paeps 	efx_nic_t *enp = etp->et_enp;
1055e948693eSPhilip Paeps 	efx_oword_t oword;
1056e948693eSPhilip Paeps 
1057e948693eSPhilip Paeps 	/* Purge descriptor queue */
1058e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
1059e948693eSPhilip Paeps 
1060e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
1061*3c838a9fSAndrew Rybchenko 			    etp->et_index, &oword, B_TRUE);
1062e948693eSPhilip Paeps }
1063e948693eSPhilip Paeps 
1064*3c838a9fSAndrew Rybchenko static		void
1065*3c838a9fSAndrew Rybchenko falconsiena_tx_fini(
1066e948693eSPhilip Paeps 	__in	efx_nic_t *enp)
1067e948693eSPhilip Paeps {
1068*3c838a9fSAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
1069e948693eSPhilip Paeps }
1070*3c838a9fSAndrew Rybchenko 
1071*3c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
1072