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