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