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 #if EFSYS_OPT_MON_MCDI
34*49ef7e06SGarrett D'Amore #include "mcdi_mon.h"
35*49ef7e06SGarrett D'Amore #endif
36*49ef7e06SGarrett D'Amore
37*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
38*49ef7e06SGarrett D'Amore #define EFX_EV_QSTAT_INCR(_eep, _stat) \
39*49ef7e06SGarrett D'Amore do { \
40*49ef7e06SGarrett D'Amore (_eep)->ee_stat[_stat]++; \
41*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION) \
42*49ef7e06SGarrett D'Amore } while (B_FALSE)
43*49ef7e06SGarrett D'Amore #else
44*49ef7e06SGarrett D'Amore #define EFX_EV_QSTAT_INCR(_eep, _stat)
45*49ef7e06SGarrett D'Amore #endif
46*49ef7e06SGarrett D'Amore
47*49ef7e06SGarrett D'Amore #define EFX_EV_PRESENT(_qword) \
48*49ef7e06SGarrett D'Amore (EFX_QWORD_FIELD((_qword), EFX_DWORD_0) != 0xffffffff && \
49*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD((_qword), EFX_DWORD_1) != 0xffffffff)
50*49ef7e06SGarrett D'Amore
51*49ef7e06SGarrett D'Amore
52*49ef7e06SGarrett D'Amore
53*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
54*49ef7e06SGarrett D'Amore
55*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
56*49ef7e06SGarrett D'Amore siena_ev_init(
57*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
58*49ef7e06SGarrett D'Amore
59*49ef7e06SGarrett D'Amore static void
60*49ef7e06SGarrett D'Amore siena_ev_fini(
61*49ef7e06SGarrett D'Amore __in efx_nic_t *enp);
62*49ef7e06SGarrett D'Amore
63*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
64*49ef7e06SGarrett D'Amore siena_ev_qcreate(
65*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
66*49ef7e06SGarrett D'Amore __in unsigned int index,
67*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp,
68*49ef7e06SGarrett D'Amore __in size_t n,
69*49ef7e06SGarrett D'Amore __in uint32_t id,
70*49ef7e06SGarrett D'Amore __in efx_evq_t *eep);
71*49ef7e06SGarrett D'Amore
72*49ef7e06SGarrett D'Amore static void
73*49ef7e06SGarrett D'Amore siena_ev_qdestroy(
74*49ef7e06SGarrett D'Amore __in efx_evq_t *eep);
75*49ef7e06SGarrett D'Amore
76*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
77*49ef7e06SGarrett D'Amore siena_ev_qprime(
78*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
79*49ef7e06SGarrett D'Amore __in unsigned int count);
80*49ef7e06SGarrett D'Amore
81*49ef7e06SGarrett D'Amore static void
82*49ef7e06SGarrett D'Amore siena_ev_qpoll(
83*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
84*49ef7e06SGarrett D'Amore __inout unsigned int *countp,
85*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
86*49ef7e06SGarrett D'Amore __in_opt void *arg);
87*49ef7e06SGarrett D'Amore
88*49ef7e06SGarrett D'Amore static void
89*49ef7e06SGarrett D'Amore siena_ev_qpost(
90*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
91*49ef7e06SGarrett D'Amore __in uint16_t data);
92*49ef7e06SGarrett D'Amore
93*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
94*49ef7e06SGarrett D'Amore siena_ev_qmoderate(
95*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
96*49ef7e06SGarrett D'Amore __in unsigned int us);
97*49ef7e06SGarrett D'Amore
98*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
99*49ef7e06SGarrett D'Amore static void
100*49ef7e06SGarrett D'Amore siena_ev_qstats_update(
101*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
102*49ef7e06SGarrett D'Amore __inout_ecount(EV_NQSTATS) efsys_stat_t *stat);
103*49ef7e06SGarrett D'Amore
104*49ef7e06SGarrett D'Amore #endif
105*49ef7e06SGarrett D'Amore
106*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
107*49ef7e06SGarrett D'Amore
108*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
109*49ef7e06SGarrett D'Amore static const efx_ev_ops_t __efx_ev_siena_ops = {
110*49ef7e06SGarrett D'Amore siena_ev_init, /* eevo_init */
111*49ef7e06SGarrett D'Amore siena_ev_fini, /* eevo_fini */
112*49ef7e06SGarrett D'Amore siena_ev_qcreate, /* eevo_qcreate */
113*49ef7e06SGarrett D'Amore siena_ev_qdestroy, /* eevo_qdestroy */
114*49ef7e06SGarrett D'Amore siena_ev_qprime, /* eevo_qprime */
115*49ef7e06SGarrett D'Amore siena_ev_qpost, /* eevo_qpost */
116*49ef7e06SGarrett D'Amore siena_ev_qmoderate, /* eevo_qmoderate */
117*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
118*49ef7e06SGarrett D'Amore siena_ev_qstats_update, /* eevo_qstats_update */
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 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
124*49ef7e06SGarrett D'Amore static const efx_ev_ops_t __efx_ev_ef10_ops = {
125*49ef7e06SGarrett D'Amore ef10_ev_init, /* eevo_init */
126*49ef7e06SGarrett D'Amore ef10_ev_fini, /* eevo_fini */
127*49ef7e06SGarrett D'Amore ef10_ev_qcreate, /* eevo_qcreate */
128*49ef7e06SGarrett D'Amore ef10_ev_qdestroy, /* eevo_qdestroy */
129*49ef7e06SGarrett D'Amore ef10_ev_qprime, /* eevo_qprime */
130*49ef7e06SGarrett D'Amore ef10_ev_qpost, /* eevo_qpost */
131*49ef7e06SGarrett D'Amore ef10_ev_qmoderate, /* eevo_qmoderate */
132*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
133*49ef7e06SGarrett D'Amore ef10_ev_qstats_update, /* eevo_qstats_update */
134*49ef7e06SGarrett D'Amore #endif
135*49ef7e06SGarrett D'Amore };
136*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
137*49ef7e06SGarrett D'Amore
138*49ef7e06SGarrett D'Amore
139*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_ev_init(__in efx_nic_t * enp)140*49ef7e06SGarrett D'Amore efx_ev_init(
141*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
142*49ef7e06SGarrett D'Amore {
143*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop;
144*49ef7e06SGarrett D'Amore efx_rc_t rc;
145*49ef7e06SGarrett D'Amore
146*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
148*49ef7e06SGarrett D'Amore
149*49ef7e06SGarrett D'Amore if (enp->en_mod_flags & EFX_MOD_EV) {
150*49ef7e06SGarrett D'Amore rc = EINVAL;
151*49ef7e06SGarrett D'Amore goto fail1;
152*49ef7e06SGarrett D'Amore }
153*49ef7e06SGarrett D'Amore
154*49ef7e06SGarrett D'Amore switch (enp->en_family) {
155*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
156*49ef7e06SGarrett D'Amore case EFX_FAMILY_SIENA:
157*49ef7e06SGarrett D'Amore eevop = &__efx_ev_siena_ops;
158*49ef7e06SGarrett D'Amore break;
159*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
160*49ef7e06SGarrett D'Amore
161*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON
162*49ef7e06SGarrett D'Amore case EFX_FAMILY_HUNTINGTON:
163*49ef7e06SGarrett D'Amore eevop = &__efx_ev_ef10_ops;
164*49ef7e06SGarrett D'Amore break;
165*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON */
166*49ef7e06SGarrett D'Amore
167*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MEDFORD
168*49ef7e06SGarrett D'Amore case EFX_FAMILY_MEDFORD:
169*49ef7e06SGarrett D'Amore eevop = &__efx_ev_ef10_ops;
170*49ef7e06SGarrett D'Amore break;
171*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MEDFORD */
172*49ef7e06SGarrett D'Amore
173*49ef7e06SGarrett D'Amore default:
174*49ef7e06SGarrett D'Amore EFSYS_ASSERT(0);
175*49ef7e06SGarrett D'Amore rc = ENOTSUP;
176*49ef7e06SGarrett D'Amore goto fail1;
177*49ef7e06SGarrett D'Amore }
178*49ef7e06SGarrett D'Amore
179*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0);
180*49ef7e06SGarrett D'Amore
181*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_init(enp)) != 0)
182*49ef7e06SGarrett D'Amore goto fail2;
183*49ef7e06SGarrett D'Amore
184*49ef7e06SGarrett D'Amore enp->en_eevop = eevop;
185*49ef7e06SGarrett D'Amore enp->en_mod_flags |= EFX_MOD_EV;
186*49ef7e06SGarrett D'Amore return (0);
187*49ef7e06SGarrett D'Amore
188*49ef7e06SGarrett D'Amore fail2:
189*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
190*49ef7e06SGarrett D'Amore
191*49ef7e06SGarrett D'Amore fail1:
192*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
193*49ef7e06SGarrett D'Amore
194*49ef7e06SGarrett D'Amore enp->en_eevop = NULL;
195*49ef7e06SGarrett D'Amore enp->en_mod_flags &= ~EFX_MOD_EV;
196*49ef7e06SGarrett D'Amore return (rc);
197*49ef7e06SGarrett D'Amore }
198*49ef7e06SGarrett D'Amore
199*49ef7e06SGarrett D'Amore void
efx_ev_fini(__in efx_nic_t * enp)200*49ef7e06SGarrett D'Amore efx_ev_fini(
201*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
202*49ef7e06SGarrett D'Amore {
203*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
204*49ef7e06SGarrett D'Amore
205*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
206*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
207*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV);
208*49ef7e06SGarrett D'Amore EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
209*49ef7e06SGarrett D'Amore EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
210*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0);
211*49ef7e06SGarrett D'Amore
212*49ef7e06SGarrett D'Amore eevop->eevo_fini(enp);
213*49ef7e06SGarrett D'Amore
214*49ef7e06SGarrett D'Amore enp->en_eevop = NULL;
215*49ef7e06SGarrett D'Amore enp->en_mod_flags &= ~EFX_MOD_EV;
216*49ef7e06SGarrett D'Amore }
217*49ef7e06SGarrett D'Amore
218*49ef7e06SGarrett D'Amore
219*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_ev_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in efsys_mem_t * esmp,__in size_t n,__in uint32_t id,__deref_out efx_evq_t ** eepp)220*49ef7e06SGarrett D'Amore efx_ev_qcreate(
221*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
222*49ef7e06SGarrett D'Amore __in unsigned int index,
223*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp,
224*49ef7e06SGarrett D'Amore __in size_t n,
225*49ef7e06SGarrett D'Amore __in uint32_t id,
226*49ef7e06SGarrett D'Amore __deref_out efx_evq_t **eepp)
227*49ef7e06SGarrett D'Amore {
228*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
229*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
230*49ef7e06SGarrett D'Amore efx_evq_t *eep;
231*49ef7e06SGarrett D'Amore efx_rc_t rc;
232*49ef7e06SGarrett D'Amore
233*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
234*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV);
235*49ef7e06SGarrett D'Amore
236*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, encp->enc_evq_limit);
237*49ef7e06SGarrett D'Amore
238*49ef7e06SGarrett D'Amore /* Allocate an EVQ object */
239*49ef7e06SGarrett D'Amore EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep);
240*49ef7e06SGarrett D'Amore if (eep == NULL) {
241*49ef7e06SGarrett D'Amore rc = ENOMEM;
242*49ef7e06SGarrett D'Amore goto fail1;
243*49ef7e06SGarrett D'Amore }
244*49ef7e06SGarrett D'Amore
245*49ef7e06SGarrett D'Amore eep->ee_magic = EFX_EVQ_MAGIC;
246*49ef7e06SGarrett D'Amore eep->ee_enp = enp;
247*49ef7e06SGarrett D'Amore eep->ee_index = index;
248*49ef7e06SGarrett D'Amore eep->ee_mask = n - 1;
249*49ef7e06SGarrett D'Amore eep->ee_esmp = esmp;
250*49ef7e06SGarrett D'Amore
251*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_qcreate(enp, index, esmp, n, id, eep)) != 0)
252*49ef7e06SGarrett D'Amore goto fail2;
253*49ef7e06SGarrett D'Amore
254*49ef7e06SGarrett D'Amore enp->en_ev_qcount++;
255*49ef7e06SGarrett D'Amore *eepp = eep;
256*49ef7e06SGarrett D'Amore
257*49ef7e06SGarrett D'Amore return (0);
258*49ef7e06SGarrett D'Amore
259*49ef7e06SGarrett D'Amore fail2:
260*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
261*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep);
262*49ef7e06SGarrett D'Amore fail1:
263*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
264*49ef7e06SGarrett D'Amore return (rc);
265*49ef7e06SGarrett D'Amore }
266*49ef7e06SGarrett D'Amore
267*49ef7e06SGarrett D'Amore void
efx_ev_qdestroy(__in efx_evq_t * eep)268*49ef7e06SGarrett D'Amore efx_ev_qdestroy(
269*49ef7e06SGarrett D'Amore __in efx_evq_t *eep)
270*49ef7e06SGarrett D'Amore {
271*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
272*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
273*49ef7e06SGarrett D'Amore
274*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
275*49ef7e06SGarrett D'Amore
276*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_ev_qcount != 0);
277*49ef7e06SGarrett D'Amore --enp->en_ev_qcount;
278*49ef7e06SGarrett D'Amore
279*49ef7e06SGarrett D'Amore eevop->eevo_qdestroy(eep);
280*49ef7e06SGarrett D'Amore
281*49ef7e06SGarrett D'Amore /* Free the EVQ object */
282*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep);
283*49ef7e06SGarrett D'Amore }
284*49ef7e06SGarrett D'Amore
285*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_ev_qprime(__in efx_evq_t * eep,__in unsigned int count)286*49ef7e06SGarrett D'Amore efx_ev_qprime(
287*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
288*49ef7e06SGarrett D'Amore __in unsigned int count)
289*49ef7e06SGarrett D'Amore {
290*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
291*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
292*49ef7e06SGarrett D'Amore efx_rc_t rc;
293*49ef7e06SGarrett D'Amore
294*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
295*49ef7e06SGarrett D'Amore
296*49ef7e06SGarrett D'Amore if (!(enp->en_mod_flags & EFX_MOD_INTR)) {
297*49ef7e06SGarrett D'Amore rc = EINVAL;
298*49ef7e06SGarrett D'Amore goto fail1;
299*49ef7e06SGarrett D'Amore }
300*49ef7e06SGarrett D'Amore
301*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_qprime(eep, count)) != 0)
302*49ef7e06SGarrett D'Amore goto fail2;
303*49ef7e06SGarrett D'Amore
304*49ef7e06SGarrett D'Amore return (0);
305*49ef7e06SGarrett D'Amore
306*49ef7e06SGarrett D'Amore fail2:
307*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
308*49ef7e06SGarrett D'Amore fail1:
309*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
310*49ef7e06SGarrett D'Amore return (rc);
311*49ef7e06SGarrett D'Amore }
312*49ef7e06SGarrett D'Amore
313*49ef7e06SGarrett D'Amore __checkReturn boolean_t
efx_ev_qpending(__in efx_evq_t * eep,__in unsigned int count)314*49ef7e06SGarrett D'Amore efx_ev_qpending(
315*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
316*49ef7e06SGarrett D'Amore __in unsigned int count)
317*49ef7e06SGarrett D'Amore {
318*49ef7e06SGarrett D'Amore size_t offset;
319*49ef7e06SGarrett D'Amore efx_qword_t qword;
320*49ef7e06SGarrett D'Amore
321*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
322*49ef7e06SGarrett D'Amore
323*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
324*49ef7e06SGarrett D'Amore EFSYS_MEM_READQ(eep->ee_esmp, offset, &qword);
325*49ef7e06SGarrett D'Amore
326*49ef7e06SGarrett D'Amore return (EFX_EV_PRESENT(qword));
327*49ef7e06SGarrett D'Amore }
328*49ef7e06SGarrett D'Amore
329*49ef7e06SGarrett D'Amore #if EFSYS_OPT_EV_PREFETCH
330*49ef7e06SGarrett D'Amore
331*49ef7e06SGarrett D'Amore void
efx_ev_qprefetch(__in efx_evq_t * eep,__in unsigned int count)332*49ef7e06SGarrett D'Amore efx_ev_qprefetch(
333*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
334*49ef7e06SGarrett D'Amore __in unsigned int count)
335*49ef7e06SGarrett D'Amore {
336*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
337*49ef7e06SGarrett D'Amore unsigned int offset;
338*49ef7e06SGarrett D'Amore
339*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
340*49ef7e06SGarrett D'Amore
341*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
342*49ef7e06SGarrett D'Amore EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
343*49ef7e06SGarrett D'Amore }
344*49ef7e06SGarrett D'Amore
345*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_EV_PREFETCH */
346*49ef7e06SGarrett D'Amore
347*49ef7e06SGarrett D'Amore void
efx_ev_qpoll(__in efx_evq_t * eep,__inout unsigned int * countp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)348*49ef7e06SGarrett D'Amore efx_ev_qpoll(
349*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
350*49ef7e06SGarrett D'Amore __inout unsigned int *countp,
351*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
352*49ef7e06SGarrett D'Amore __in_opt void *arg)
353*49ef7e06SGarrett D'Amore {
354*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
355*49ef7e06SGarrett D'Amore
356*49ef7e06SGarrett D'Amore /*
357*49ef7e06SGarrett D'Amore * FIXME: Huntington will require support for hardware event batching
358*49ef7e06SGarrett D'Amore * and merging, which will need a different ev_qpoll implementation.
359*49ef7e06SGarrett D'Amore *
360*49ef7e06SGarrett D'Amore * Without those features the Falcon/Siena code can be used unchanged.
361*49ef7e06SGarrett D'Amore */
362*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESF_DZ_EV_CODE_LBN == FSF_AZ_EV_CODE_LBN);
363*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESF_DZ_EV_CODE_WIDTH == FSF_AZ_EV_CODE_WIDTH);
364*49ef7e06SGarrett D'Amore
365*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_RX_EV == FSE_AZ_EV_CODE_RX_EV);
366*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_TX_EV == FSE_AZ_EV_CODE_TX_EV);
367*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_DRIVER_EV == FSE_AZ_EV_CODE_DRIVER_EV);
368*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_DRV_GEN_EV ==
369*49ef7e06SGarrett D'Amore FSE_AZ_EV_CODE_DRV_GEN_EV);
370*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI
371*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_MCDI_EV ==
372*49ef7e06SGarrett D'Amore FSE_AZ_EV_CODE_MCDI_EVRESPONSE);
373*49ef7e06SGarrett D'Amore #endif
374*49ef7e06SGarrett D'Amore siena_ev_qpoll(eep, countp, eecp, arg);
375*49ef7e06SGarrett D'Amore }
376*49ef7e06SGarrett D'Amore
377*49ef7e06SGarrett D'Amore void
efx_ev_qpost(__in efx_evq_t * eep,__in uint16_t data)378*49ef7e06SGarrett D'Amore efx_ev_qpost(
379*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
380*49ef7e06SGarrett D'Amore __in uint16_t data)
381*49ef7e06SGarrett D'Amore {
382*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
383*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
384*49ef7e06SGarrett D'Amore
385*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
386*49ef7e06SGarrett D'Amore
387*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eevop != NULL &&
388*49ef7e06SGarrett D'Amore eevop->eevo_qpost != NULL);
389*49ef7e06SGarrett D'Amore
390*49ef7e06SGarrett D'Amore eevop->eevo_qpost(eep, data);
391*49ef7e06SGarrett D'Amore }
392*49ef7e06SGarrett D'Amore
393*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_ev_qmoderate(__in efx_evq_t * eep,__in unsigned int us)394*49ef7e06SGarrett D'Amore efx_ev_qmoderate(
395*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
396*49ef7e06SGarrett D'Amore __in unsigned int us)
397*49ef7e06SGarrett D'Amore {
398*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
399*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
400*49ef7e06SGarrett D'Amore efx_rc_t rc;
401*49ef7e06SGarrett D'Amore
402*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
403*49ef7e06SGarrett D'Amore
404*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_qmoderate(eep, us)) != 0)
405*49ef7e06SGarrett D'Amore goto fail1;
406*49ef7e06SGarrett D'Amore
407*49ef7e06SGarrett D'Amore return (0);
408*49ef7e06SGarrett D'Amore
409*49ef7e06SGarrett D'Amore fail1:
410*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
411*49ef7e06SGarrett D'Amore return (rc);
412*49ef7e06SGarrett D'Amore }
413*49ef7e06SGarrett D'Amore
414*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
415*49ef7e06SGarrett D'Amore void
efx_ev_qstats_update(__in efx_evq_t * eep,__inout_ecount (EV_NQSTATS)efsys_stat_t * stat)416*49ef7e06SGarrett D'Amore efx_ev_qstats_update(
417*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
418*49ef7e06SGarrett D'Amore __inout_ecount(EV_NQSTATS) efsys_stat_t *stat)
419*49ef7e06SGarrett D'Amore
420*49ef7e06SGarrett D'Amore { efx_nic_t *enp = eep->ee_enp;
421*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop;
422*49ef7e06SGarrett D'Amore
423*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
424*49ef7e06SGarrett D'Amore
425*49ef7e06SGarrett D'Amore eevop->eevo_qstats_update(eep, stat);
426*49ef7e06SGarrett D'Amore }
427*49ef7e06SGarrett D'Amore
428*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_QSTATS */
429*49ef7e06SGarrett D'Amore
430*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
431*49ef7e06SGarrett D'Amore
432*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
siena_ev_init(__in efx_nic_t * enp)433*49ef7e06SGarrett D'Amore siena_ev_init(
434*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
435*49ef7e06SGarrett D'Amore {
436*49ef7e06SGarrett D'Amore efx_oword_t oword;
437*49ef7e06SGarrett D'Amore
438*49ef7e06SGarrett D'Amore /*
439*49ef7e06SGarrett D'Amore * Program the event queue for receive and transmit queue
440*49ef7e06SGarrett D'Amore * flush events.
441*49ef7e06SGarrett D'Amore */
442*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_DP_CTRL_REG, &oword);
443*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_FLS_EVQ_ID, 0);
444*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_DP_CTRL_REG, &oword);
445*49ef7e06SGarrett D'Amore
446*49ef7e06SGarrett D'Amore return (0);
447*49ef7e06SGarrett D'Amore
448*49ef7e06SGarrett D'Amore }
449*49ef7e06SGarrett D'Amore
450*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_rx_not_ok(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in uint32_t label,__in uint32_t id,__inout uint16_t * flagsp)451*49ef7e06SGarrett D'Amore siena_ev_rx_not_ok(
452*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
453*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
454*49ef7e06SGarrett D'Amore __in uint32_t label,
455*49ef7e06SGarrett D'Amore __in uint32_t id,
456*49ef7e06SGarrett D'Amore __inout uint16_t *flagsp)
457*49ef7e06SGarrett D'Amore {
458*49ef7e06SGarrett D'Amore boolean_t ignore = B_FALSE;
459*49ef7e06SGarrett D'Amore
460*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TOBE_DISC) != 0) {
461*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TOBE_DISC);
462*49ef7e06SGarrett D'Amore EFSYS_PROBE(tobe_disc);
463*49ef7e06SGarrett D'Amore /*
464*49ef7e06SGarrett D'Amore * Assume this is a unicast address mismatch, unless below
465*49ef7e06SGarrett D'Amore * we find either FSF_AZ_RX_EV_ETH_CRC_ERR or
466*49ef7e06SGarrett D'Amore * EV_RX_PAUSE_FRM_ERR is set.
467*49ef7e06SGarrett D'Amore */
468*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_ADDR_MISMATCH;
469*49ef7e06SGarrett D'Amore }
470*49ef7e06SGarrett D'Amore
471*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_FRM_TRUNC) != 0) {
472*49ef7e06SGarrett D'Amore EFSYS_PROBE2(frm_trunc, uint32_t, label, uint32_t, id);
473*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC);
474*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD;
475*49ef7e06SGarrett D'Amore
476*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER
477*49ef7e06SGarrett D'Amore /*
478*49ef7e06SGarrett D'Amore * Lookout for payload queue ran dry errors and ignore them.
479*49ef7e06SGarrett D'Amore *
480*49ef7e06SGarrett D'Amore * Sadly for the header/data split cases, the descriptor
481*49ef7e06SGarrett D'Amore * pointer in this event refers to the header queue and
482*49ef7e06SGarrett D'Amore * therefore cannot be easily detected as duplicate.
483*49ef7e06SGarrett D'Amore * So we drop these and rely on the receive processing seeing
484*49ef7e06SGarrett D'Amore * a subsequent packet with FSF_AZ_RX_EV_SOP set to discard
485*49ef7e06SGarrett D'Amore * the partially received packet.
486*49ef7e06SGarrett D'Amore */
487*49ef7e06SGarrett D'Amore if ((EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) == 0) &&
488*49ef7e06SGarrett D'Amore (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) == 0) &&
489*49ef7e06SGarrett D'Amore (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT) == 0))
490*49ef7e06SGarrett D'Amore ignore = B_TRUE;
491*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */
492*49ef7e06SGarrett D'Amore }
493*49ef7e06SGarrett D'Amore
494*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_ETH_CRC_ERR) != 0) {
495*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR);
496*49ef7e06SGarrett D'Amore EFSYS_PROBE(crc_err);
497*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_ADDR_MISMATCH;
498*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD;
499*49ef7e06SGarrett D'Amore }
500*49ef7e06SGarrett D'Amore
501*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PAUSE_FRM_ERR) != 0) {
502*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_PAUSE_FRM_ERR);
503*49ef7e06SGarrett D'Amore EFSYS_PROBE(pause_frm_err);
504*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_ADDR_MISMATCH;
505*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD;
506*49ef7e06SGarrett D'Amore }
507*49ef7e06SGarrett D'Amore
508*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BUF_OWNER_ID_ERR) != 0) {
509*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_BUF_OWNER_ID_ERR);
510*49ef7e06SGarrett D'Amore EFSYS_PROBE(owner_id_err);
511*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD;
512*49ef7e06SGarrett D'Amore }
513*49ef7e06SGarrett D'Amore
514*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR) != 0) {
515*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR);
516*49ef7e06SGarrett D'Amore EFSYS_PROBE(ipv4_err);
517*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_CKSUM_IPV4;
518*49ef7e06SGarrett D'Amore }
519*49ef7e06SGarrett D'Amore
520*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR) != 0) {
521*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR);
522*49ef7e06SGarrett D'Amore EFSYS_PROBE(udp_chk_err);
523*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_CKSUM_TCPUDP;
524*49ef7e06SGarrett D'Amore }
525*49ef7e06SGarrett D'Amore
526*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_FRAG_ERR) != 0) {
527*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_IP_FRAG_ERR);
528*49ef7e06SGarrett D'Amore
529*49ef7e06SGarrett D'Amore /*
530*49ef7e06SGarrett D'Amore * If IP is fragmented FSF_AZ_RX_EV_IP_FRAG_ERR is set. This
531*49ef7e06SGarrett D'Amore * causes FSF_AZ_RX_EV_PKT_OK to be clear. This is not an error
532*49ef7e06SGarrett D'Amore * condition.
533*49ef7e06SGarrett D'Amore */
534*49ef7e06SGarrett D'Amore (*flagsp) &= ~(EFX_PKT_TCP | EFX_PKT_UDP | EFX_CKSUM_TCPUDP);
535*49ef7e06SGarrett D'Amore }
536*49ef7e06SGarrett D'Amore
537*49ef7e06SGarrett D'Amore return (ignore);
538*49ef7e06SGarrett D'Amore }
539*49ef7e06SGarrett D'Amore
540*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_rx(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)541*49ef7e06SGarrett D'Amore siena_ev_rx(
542*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
543*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
544*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
545*49ef7e06SGarrett D'Amore __in_opt void *arg)
546*49ef7e06SGarrett D'Amore {
547*49ef7e06SGarrett D'Amore uint32_t id;
548*49ef7e06SGarrett D'Amore uint32_t size;
549*49ef7e06SGarrett D'Amore uint32_t label;
550*49ef7e06SGarrett D'Amore boolean_t ok;
551*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER
552*49ef7e06SGarrett D'Amore boolean_t sop;
553*49ef7e06SGarrett D'Amore boolean_t jumbo_cont;
554*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */
555*49ef7e06SGarrett D'Amore uint32_t hdr_type;
556*49ef7e06SGarrett D'Amore boolean_t is_v6;
557*49ef7e06SGarrett D'Amore uint16_t flags;
558*49ef7e06SGarrett D'Amore boolean_t ignore;
559*49ef7e06SGarrett D'Amore boolean_t should_abort;
560*49ef7e06SGarrett D'Amore
561*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX);
562*49ef7e06SGarrett D'Amore
563*49ef7e06SGarrett D'Amore /* Basic packet information */
564*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_DESC_PTR);
565*49ef7e06SGarrett D'Amore size = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT);
566*49ef7e06SGarrett D'Amore label = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_Q_LABEL);
567*49ef7e06SGarrett D'Amore ok = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_OK) != 0);
568*49ef7e06SGarrett D'Amore
569*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER
570*49ef7e06SGarrett D'Amore sop = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) != 0);
571*49ef7e06SGarrett D'Amore jumbo_cont = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) != 0);
572*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */
573*49ef7e06SGarrett D'Amore
574*49ef7e06SGarrett D'Amore hdr_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_HDR_TYPE);
575*49ef7e06SGarrett D'Amore
576*49ef7e06SGarrett D'Amore is_v6 = (EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_IPV6_PKT) != 0);
577*49ef7e06SGarrett D'Amore
578*49ef7e06SGarrett D'Amore /*
579*49ef7e06SGarrett D'Amore * If packet is marked as OK and packet type is TCP/IP or
580*49ef7e06SGarrett D'Amore * UDP/IP or other IP, then we can rely on the hardware checksums.
581*49ef7e06SGarrett D'Amore */
582*49ef7e06SGarrett D'Amore switch (hdr_type) {
583*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_TCP:
584*49ef7e06SGarrett D'Amore flags = EFX_PKT_TCP | EFX_CKSUM_TCPUDP;
585*49ef7e06SGarrett D'Amore if (is_v6) {
586*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6);
587*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV6;
588*49ef7e06SGarrett D'Amore } else {
589*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4);
590*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4;
591*49ef7e06SGarrett D'Amore }
592*49ef7e06SGarrett D'Amore break;
593*49ef7e06SGarrett D'Amore
594*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
595*49ef7e06SGarrett D'Amore flags = EFX_PKT_UDP | EFX_CKSUM_TCPUDP;
596*49ef7e06SGarrett D'Amore if (is_v6) {
597*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6);
598*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV6;
599*49ef7e06SGarrett D'Amore } else {
600*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4);
601*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4;
602*49ef7e06SGarrett D'Amore }
603*49ef7e06SGarrett D'Amore break;
604*49ef7e06SGarrett D'Amore
605*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
606*49ef7e06SGarrett D'Amore if (is_v6) {
607*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6);
608*49ef7e06SGarrett D'Amore flags = EFX_PKT_IPV6;
609*49ef7e06SGarrett D'Amore } else {
610*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4);
611*49ef7e06SGarrett D'Amore flags = EFX_PKT_IPV4 | EFX_CKSUM_IPV4;
612*49ef7e06SGarrett D'Amore }
613*49ef7e06SGarrett D'Amore break;
614*49ef7e06SGarrett D'Amore
615*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
616*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP);
617*49ef7e06SGarrett D'Amore flags = 0;
618*49ef7e06SGarrett D'Amore break;
619*49ef7e06SGarrett D'Amore
620*49ef7e06SGarrett D'Amore default:
621*49ef7e06SGarrett D'Amore EFSYS_ASSERT(B_FALSE);
622*49ef7e06SGarrett D'Amore flags = 0;
623*49ef7e06SGarrett D'Amore break;
624*49ef7e06SGarrett D'Amore }
625*49ef7e06SGarrett D'Amore
626*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER
627*49ef7e06SGarrett D'Amore /* Report scatter and header/lookahead split buffer flags */
628*49ef7e06SGarrett D'Amore if (sop)
629*49ef7e06SGarrett D'Amore flags |= EFX_PKT_START;
630*49ef7e06SGarrett D'Amore if (jumbo_cont)
631*49ef7e06SGarrett D'Amore flags |= EFX_PKT_CONT;
632*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */
633*49ef7e06SGarrett D'Amore
634*49ef7e06SGarrett D'Amore /* Detect errors included in the FSF_AZ_RX_EV_PKT_OK indication */
635*49ef7e06SGarrett D'Amore if (!ok) {
636*49ef7e06SGarrett D'Amore ignore = siena_ev_rx_not_ok(eep, eqp, label, id, &flags);
637*49ef7e06SGarrett D'Amore if (ignore) {
638*49ef7e06SGarrett D'Amore EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id,
639*49ef7e06SGarrett D'Amore uint32_t, size, uint16_t, flags);
640*49ef7e06SGarrett D'Amore
641*49ef7e06SGarrett D'Amore return (B_FALSE);
642*49ef7e06SGarrett D'Amore }
643*49ef7e06SGarrett D'Amore }
644*49ef7e06SGarrett D'Amore
645*49ef7e06SGarrett D'Amore /* If we're not discarding the packet then it is ok */
646*49ef7e06SGarrett D'Amore if (~flags & EFX_DISCARD)
647*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_OK);
648*49ef7e06SGarrett D'Amore
649*49ef7e06SGarrett D'Amore /* Detect multicast packets that didn't match the filter */
650*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_PKT) != 0) {
651*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_PKT);
652*49ef7e06SGarrett D'Amore
653*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_HASH_MATCH) != 0) {
654*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_HASH_MATCH);
655*49ef7e06SGarrett D'Amore } else {
656*49ef7e06SGarrett D'Amore EFSYS_PROBE(mcast_mismatch);
657*49ef7e06SGarrett D'Amore flags |= EFX_ADDR_MISMATCH;
658*49ef7e06SGarrett D'Amore }
659*49ef7e06SGarrett D'Amore } else {
660*49ef7e06SGarrett D'Amore flags |= EFX_PKT_UNICAST;
661*49ef7e06SGarrett D'Amore }
662*49ef7e06SGarrett D'Amore
663*49ef7e06SGarrett D'Amore /*
664*49ef7e06SGarrett D'Amore * The packet parser in Siena can abort parsing packets under
665*49ef7e06SGarrett D'Amore * certain error conditions, setting the PKT_NOT_PARSED bit
666*49ef7e06SGarrett D'Amore * (which clears PKT_OK). If this is set, then don't trust
667*49ef7e06SGarrett D'Amore * the PKT_TYPE field.
668*49ef7e06SGarrett D'Amore */
669*49ef7e06SGarrett D'Amore if (!ok) {
670*49ef7e06SGarrett D'Amore uint32_t parse_err;
671*49ef7e06SGarrett D'Amore
672*49ef7e06SGarrett D'Amore parse_err = EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_PKT_NOT_PARSED);
673*49ef7e06SGarrett D'Amore if (parse_err != 0)
674*49ef7e06SGarrett D'Amore flags |= EFX_CHECK_VLAN;
675*49ef7e06SGarrett D'Amore }
676*49ef7e06SGarrett D'Amore
677*49ef7e06SGarrett D'Amore if (~flags & EFX_CHECK_VLAN) {
678*49ef7e06SGarrett D'Amore uint32_t pkt_type;
679*49ef7e06SGarrett D'Amore
680*49ef7e06SGarrett D'Amore pkt_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_TYPE);
681*49ef7e06SGarrett D'Amore if (pkt_type >= FSE_AZ_RX_EV_PKT_TYPE_VLAN)
682*49ef7e06SGarrett D'Amore flags |= EFX_PKT_VLAN_TAGGED;
683*49ef7e06SGarrett D'Amore }
684*49ef7e06SGarrett D'Amore
685*49ef7e06SGarrett D'Amore EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id,
686*49ef7e06SGarrett D'Amore uint32_t, size, uint16_t, flags);
687*49ef7e06SGarrett D'Amore
688*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_rx != NULL);
689*49ef7e06SGarrett D'Amore should_abort = eecp->eec_rx(arg, label, id, size, flags);
690*49ef7e06SGarrett D'Amore
691*49ef7e06SGarrett D'Amore return (should_abort);
692*49ef7e06SGarrett D'Amore }
693*49ef7e06SGarrett D'Amore
694*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_tx(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)695*49ef7e06SGarrett D'Amore siena_ev_tx(
696*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
697*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
698*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
699*49ef7e06SGarrett D'Amore __in_opt void *arg)
700*49ef7e06SGarrett D'Amore {
701*49ef7e06SGarrett D'Amore uint32_t id;
702*49ef7e06SGarrett D'Amore uint32_t label;
703*49ef7e06SGarrett D'Amore boolean_t should_abort;
704*49ef7e06SGarrett D'Amore
705*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX);
706*49ef7e06SGarrett D'Amore
707*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0 &&
708*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) == 0 &&
709*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) == 0 &&
710*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) == 0) {
711*49ef7e06SGarrett D'Amore
712*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_DESC_PTR);
713*49ef7e06SGarrett D'Amore label = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_Q_LABEL);
714*49ef7e06SGarrett D'Amore
715*49ef7e06SGarrett D'Amore EFSYS_PROBE2(tx_complete, uint32_t, label, uint32_t, id);
716*49ef7e06SGarrett D'Amore
717*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_tx != NULL);
718*49ef7e06SGarrett D'Amore should_abort = eecp->eec_tx(arg, label, id);
719*49ef7e06SGarrett D'Amore
720*49ef7e06SGarrett D'Amore return (should_abort);
721*49ef7e06SGarrett D'Amore }
722*49ef7e06SGarrett D'Amore
723*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0)
724*49ef7e06SGarrett D'Amore EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index,
725*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1),
726*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0));
727*49ef7e06SGarrett D'Amore
728*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) != 0)
729*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_ERR);
730*49ef7e06SGarrett D'Amore
731*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) != 0)
732*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_TOO_BIG);
733*49ef7e06SGarrett D'Amore
734*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) != 0)
735*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_WQ_FF_FULL);
736*49ef7e06SGarrett D'Amore
737*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_UNEXPECTED);
738*49ef7e06SGarrett D'Amore return (B_FALSE);
739*49ef7e06SGarrett D'Amore }
740*49ef7e06SGarrett D'Amore
741*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_global(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)742*49ef7e06SGarrett D'Amore siena_ev_global(
743*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
744*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
745*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
746*49ef7e06SGarrett D'Amore __in_opt void *arg)
747*49ef7e06SGarrett D'Amore {
748*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(eqp, eecp, arg))
749*49ef7e06SGarrett D'Amore
750*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_GLOBAL);
751*49ef7e06SGarrett D'Amore
752*49ef7e06SGarrett D'Amore return (B_FALSE);
753*49ef7e06SGarrett D'Amore }
754*49ef7e06SGarrett D'Amore
755*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_driver(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)756*49ef7e06SGarrett D'Amore siena_ev_driver(
757*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
758*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
759*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
760*49ef7e06SGarrett D'Amore __in_opt void *arg)
761*49ef7e06SGarrett D'Amore {
762*49ef7e06SGarrett D'Amore boolean_t should_abort;
763*49ef7e06SGarrett D'Amore
764*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER);
765*49ef7e06SGarrett D'Amore should_abort = B_FALSE;
766*49ef7e06SGarrett D'Amore
767*49ef7e06SGarrett D'Amore switch (EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBCODE)) {
768*49ef7e06SGarrett D'Amore case FSE_AZ_TX_DESCQ_FLS_DONE_EV: {
769*49ef7e06SGarrett D'Amore uint32_t txq_index;
770*49ef7e06SGarrett D'Amore
771*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DESCQ_FLS_DONE);
772*49ef7e06SGarrett D'Amore
773*49ef7e06SGarrett D'Amore txq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
774*49ef7e06SGarrett D'Amore
775*49ef7e06SGarrett D'Amore EFSYS_PROBE1(tx_descq_fls_done, uint32_t, txq_index);
776*49ef7e06SGarrett D'Amore
777*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_txq_flush_done != NULL);
778*49ef7e06SGarrett D'Amore should_abort = eecp->eec_txq_flush_done(arg, txq_index);
779*49ef7e06SGarrett D'Amore
780*49ef7e06SGarrett D'Amore break;
781*49ef7e06SGarrett D'Amore }
782*49ef7e06SGarrett D'Amore case FSE_AZ_RX_DESCQ_FLS_DONE_EV: {
783*49ef7e06SGarrett D'Amore uint32_t rxq_index;
784*49ef7e06SGarrett D'Amore uint32_t failed;
785*49ef7e06SGarrett D'Amore
786*49ef7e06SGarrett D'Amore rxq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
787*49ef7e06SGarrett D'Amore failed = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
788*49ef7e06SGarrett D'Amore
789*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_rxq_flush_done != NULL);
790*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_rxq_flush_failed != NULL);
791*49ef7e06SGarrett D'Amore
792*49ef7e06SGarrett D'Amore if (failed) {
793*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_FAILED);
794*49ef7e06SGarrett D'Amore
795*49ef7e06SGarrett D'Amore EFSYS_PROBE1(rx_descq_fls_failed, uint32_t, rxq_index);
796*49ef7e06SGarrett D'Amore
797*49ef7e06SGarrett D'Amore should_abort = eecp->eec_rxq_flush_failed(arg,
798*49ef7e06SGarrett D'Amore rxq_index);
799*49ef7e06SGarrett D'Amore } else {
800*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_DONE);
801*49ef7e06SGarrett D'Amore
802*49ef7e06SGarrett D'Amore EFSYS_PROBE1(rx_descq_fls_done, uint32_t, rxq_index);
803*49ef7e06SGarrett D'Amore
804*49ef7e06SGarrett D'Amore should_abort = eecp->eec_rxq_flush_done(arg, rxq_index);
805*49ef7e06SGarrett D'Amore }
806*49ef7e06SGarrett D'Amore
807*49ef7e06SGarrett D'Amore break;
808*49ef7e06SGarrett D'Amore }
809*49ef7e06SGarrett D'Amore case FSE_AZ_EVQ_INIT_DONE_EV:
810*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_initialized != NULL);
811*49ef7e06SGarrett D'Amore should_abort = eecp->eec_initialized(arg);
812*49ef7e06SGarrett D'Amore
813*49ef7e06SGarrett D'Amore break;
814*49ef7e06SGarrett D'Amore
815*49ef7e06SGarrett D'Amore case FSE_AZ_EVQ_NOT_EN_EV:
816*49ef7e06SGarrett D'Amore EFSYS_PROBE(evq_not_en);
817*49ef7e06SGarrett D'Amore break;
818*49ef7e06SGarrett D'Amore
819*49ef7e06SGarrett D'Amore case FSE_AZ_SRM_UPD_DONE_EV: {
820*49ef7e06SGarrett D'Amore uint32_t code;
821*49ef7e06SGarrett D'Amore
822*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_SRM_UPD_DONE);
823*49ef7e06SGarrett D'Amore
824*49ef7e06SGarrett D'Amore code = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
825*49ef7e06SGarrett D'Amore
826*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_sram != NULL);
827*49ef7e06SGarrett D'Amore should_abort = eecp->eec_sram(arg, code);
828*49ef7e06SGarrett D'Amore
829*49ef7e06SGarrett D'Amore break;
830*49ef7e06SGarrett D'Amore }
831*49ef7e06SGarrett D'Amore case FSE_AZ_WAKE_UP_EV: {
832*49ef7e06SGarrett D'Amore uint32_t id;
833*49ef7e06SGarrett D'Amore
834*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
835*49ef7e06SGarrett D'Amore
836*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_wake_up != NULL);
837*49ef7e06SGarrett D'Amore should_abort = eecp->eec_wake_up(arg, id);
838*49ef7e06SGarrett D'Amore
839*49ef7e06SGarrett D'Amore break;
840*49ef7e06SGarrett D'Amore }
841*49ef7e06SGarrett D'Amore case FSE_AZ_TX_PKT_NON_TCP_UDP:
842*49ef7e06SGarrett D'Amore EFSYS_PROBE(tx_pkt_non_tcp_udp);
843*49ef7e06SGarrett D'Amore break;
844*49ef7e06SGarrett D'Amore
845*49ef7e06SGarrett D'Amore case FSE_AZ_TIMER_EV: {
846*49ef7e06SGarrett D'Amore uint32_t id;
847*49ef7e06SGarrett D'Amore
848*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
849*49ef7e06SGarrett D'Amore
850*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_timer != NULL);
851*49ef7e06SGarrett D'Amore should_abort = eecp->eec_timer(arg, id);
852*49ef7e06SGarrett D'Amore
853*49ef7e06SGarrett D'Amore break;
854*49ef7e06SGarrett D'Amore }
855*49ef7e06SGarrett D'Amore case FSE_AZ_RX_DSC_ERROR_EV:
856*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DSC_ERROR);
857*49ef7e06SGarrett D'Amore
858*49ef7e06SGarrett D'Amore EFSYS_PROBE(rx_dsc_error);
859*49ef7e06SGarrett D'Amore
860*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL);
861*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg,
862*49ef7e06SGarrett D'Amore EFX_EXCEPTION_RX_DSC_ERROR, 0);
863*49ef7e06SGarrett D'Amore
864*49ef7e06SGarrett D'Amore break;
865*49ef7e06SGarrett D'Amore
866*49ef7e06SGarrett D'Amore case FSE_AZ_TX_DSC_ERROR_EV:
867*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DSC_ERROR);
868*49ef7e06SGarrett D'Amore
869*49ef7e06SGarrett D'Amore EFSYS_PROBE(tx_dsc_error);
870*49ef7e06SGarrett D'Amore
871*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL);
872*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg,
873*49ef7e06SGarrett D'Amore EFX_EXCEPTION_TX_DSC_ERROR, 0);
874*49ef7e06SGarrett D'Amore
875*49ef7e06SGarrett D'Amore break;
876*49ef7e06SGarrett D'Amore
877*49ef7e06SGarrett D'Amore default:
878*49ef7e06SGarrett D'Amore break;
879*49ef7e06SGarrett D'Amore }
880*49ef7e06SGarrett D'Amore
881*49ef7e06SGarrett D'Amore return (should_abort);
882*49ef7e06SGarrett D'Amore }
883*49ef7e06SGarrett D'Amore
884*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_drv_gen(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)885*49ef7e06SGarrett D'Amore siena_ev_drv_gen(
886*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
887*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
888*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
889*49ef7e06SGarrett D'Amore __in_opt void *arg)
890*49ef7e06SGarrett D'Amore {
891*49ef7e06SGarrett D'Amore uint32_t data;
892*49ef7e06SGarrett D'Amore boolean_t should_abort;
893*49ef7e06SGarrett D'Amore
894*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRV_GEN);
895*49ef7e06SGarrett D'Amore
896*49ef7e06SGarrett D'Amore data = EFX_QWORD_FIELD(*eqp, FSF_AZ_EV_DATA_DW0);
897*49ef7e06SGarrett D'Amore if (data >= ((uint32_t)1 << 16)) {
898*49ef7e06SGarrett D'Amore EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index,
899*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1),
900*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0));
901*49ef7e06SGarrett D'Amore return (B_TRUE);
902*49ef7e06SGarrett D'Amore }
903*49ef7e06SGarrett D'Amore
904*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_software != NULL);
905*49ef7e06SGarrett D'Amore should_abort = eecp->eec_software(arg, (uint16_t)data);
906*49ef7e06SGarrett D'Amore
907*49ef7e06SGarrett D'Amore return (should_abort);
908*49ef7e06SGarrett D'Amore }
909*49ef7e06SGarrett D'Amore
910*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI
911*49ef7e06SGarrett D'Amore
912*49ef7e06SGarrett D'Amore static __checkReturn boolean_t
siena_ev_mcdi(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)913*49ef7e06SGarrett D'Amore siena_ev_mcdi(
914*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
915*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp,
916*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
917*49ef7e06SGarrett D'Amore __in_opt void *arg)
918*49ef7e06SGarrett D'Amore {
919*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
920*49ef7e06SGarrett D'Amore unsigned code;
921*49ef7e06SGarrett D'Amore boolean_t should_abort = B_FALSE;
922*49ef7e06SGarrett D'Amore
923*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
924*49ef7e06SGarrett D'Amore
925*49ef7e06SGarrett D'Amore if (enp->en_family != EFX_FAMILY_SIENA)
926*49ef7e06SGarrett D'Amore goto out;
927*49ef7e06SGarrett D'Amore
928*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_link_change != NULL);
929*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL);
930*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
931*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_monitor != NULL);
932*49ef7e06SGarrett D'Amore #endif
933*49ef7e06SGarrett D'Amore
934*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE);
935*49ef7e06SGarrett D'Amore
936*49ef7e06SGarrett D'Amore code = EFX_QWORD_FIELD(*eqp, MCDI_EVENT_CODE);
937*49ef7e06SGarrett D'Amore switch (code) {
938*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_BADSSERT:
939*49ef7e06SGarrett D'Amore efx_mcdi_ev_death(enp, EINTR);
940*49ef7e06SGarrett D'Amore break;
941*49ef7e06SGarrett D'Amore
942*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_CMDDONE:
943*49ef7e06SGarrett D'Amore efx_mcdi_ev_cpl(enp,
944*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, CMDDONE_SEQ),
945*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, CMDDONE_DATALEN),
946*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, CMDDONE_ERRNO));
947*49ef7e06SGarrett D'Amore break;
948*49ef7e06SGarrett D'Amore
949*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_LINKCHANGE: {
950*49ef7e06SGarrett D'Amore efx_link_mode_t link_mode;
951*49ef7e06SGarrett D'Amore
952*49ef7e06SGarrett D'Amore siena_phy_link_ev(enp, eqp, &link_mode);
953*49ef7e06SGarrett D'Amore should_abort = eecp->eec_link_change(arg, link_mode);
954*49ef7e06SGarrett D'Amore break;
955*49ef7e06SGarrett D'Amore }
956*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_SENSOREVT: {
957*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
958*49ef7e06SGarrett D'Amore efx_mon_stat_t id;
959*49ef7e06SGarrett D'Amore efx_mon_stat_value_t value;
960*49ef7e06SGarrett D'Amore efx_rc_t rc;
961*49ef7e06SGarrett D'Amore
962*49ef7e06SGarrett D'Amore if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0)
963*49ef7e06SGarrett D'Amore should_abort = eecp->eec_monitor(arg, id, value);
964*49ef7e06SGarrett D'Amore else if (rc == ENOTSUP) {
965*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg,
966*49ef7e06SGarrett D'Amore EFX_EXCEPTION_UNKNOWN_SENSOREVT,
967*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, DATA));
968*49ef7e06SGarrett D'Amore } else
969*49ef7e06SGarrett D'Amore EFSYS_ASSERT(rc == ENODEV); /* Wrong port */
970*49ef7e06SGarrett D'Amore #else
971*49ef7e06SGarrett D'Amore should_abort = B_FALSE;
972*49ef7e06SGarrett D'Amore #endif
973*49ef7e06SGarrett D'Amore break;
974*49ef7e06SGarrett D'Amore }
975*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_SCHEDERR:
976*49ef7e06SGarrett D'Amore /* Informational only */
977*49ef7e06SGarrett D'Amore break;
978*49ef7e06SGarrett D'Amore
979*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_REBOOT:
980*49ef7e06SGarrett D'Amore efx_mcdi_ev_death(enp, EIO);
981*49ef7e06SGarrett D'Amore break;
982*49ef7e06SGarrett D'Amore
983*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_MAC_STATS_DMA:
984*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MAC_STATS
985*49ef7e06SGarrett D'Amore if (eecp->eec_mac_stats != NULL) {
986*49ef7e06SGarrett D'Amore eecp->eec_mac_stats(arg,
987*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, MAC_STATS_DMA_GENERATION));
988*49ef7e06SGarrett D'Amore }
989*49ef7e06SGarrett D'Amore #endif
990*49ef7e06SGarrett D'Amore break;
991*49ef7e06SGarrett D'Amore
992*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_FWALERT: {
993*49ef7e06SGarrett D'Amore uint32_t reason = MCDI_EV_FIELD(eqp, FWALERT_REASON);
994*49ef7e06SGarrett D'Amore
995*49ef7e06SGarrett D'Amore if (reason == MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS)
996*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg,
997*49ef7e06SGarrett D'Amore EFX_EXCEPTION_FWALERT_SRAM,
998*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, FWALERT_DATA));
999*49ef7e06SGarrett D'Amore else
1000*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg,
1001*49ef7e06SGarrett D'Amore EFX_EXCEPTION_UNKNOWN_FWALERT,
1002*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, DATA));
1003*49ef7e06SGarrett D'Amore break;
1004*49ef7e06SGarrett D'Amore }
1005*49ef7e06SGarrett D'Amore
1006*49ef7e06SGarrett D'Amore default:
1007*49ef7e06SGarrett D'Amore EFSYS_PROBE1(mc_pcol_error, int, code);
1008*49ef7e06SGarrett D'Amore break;
1009*49ef7e06SGarrett D'Amore }
1010*49ef7e06SGarrett D'Amore
1011*49ef7e06SGarrett D'Amore out:
1012*49ef7e06SGarrett D'Amore return (should_abort);
1013*49ef7e06SGarrett D'Amore }
1014*49ef7e06SGarrett D'Amore
1015*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MCDI */
1016*49ef7e06SGarrett D'Amore
1017*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
siena_ev_qprime(__in efx_evq_t * eep,__in unsigned int count)1018*49ef7e06SGarrett D'Amore siena_ev_qprime(
1019*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
1020*49ef7e06SGarrett D'Amore __in unsigned int count)
1021*49ef7e06SGarrett D'Amore {
1022*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
1023*49ef7e06SGarrett D'Amore uint32_t rptr;
1024*49ef7e06SGarrett D'Amore efx_dword_t dword;
1025*49ef7e06SGarrett D'Amore
1026*49ef7e06SGarrett D'Amore rptr = count & eep->ee_mask;
1027*49ef7e06SGarrett D'Amore
1028*49ef7e06SGarrett D'Amore EFX_POPULATE_DWORD_1(dword, FRF_AZ_EVQ_RPTR, rptr);
1029*49ef7e06SGarrett D'Amore
1030*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITED(enp, FR_AZ_EVQ_RPTR_REG, eep->ee_index,
1031*49ef7e06SGarrett D'Amore &dword, B_FALSE);
1032*49ef7e06SGarrett D'Amore
1033*49ef7e06SGarrett D'Amore return (0);
1034*49ef7e06SGarrett D'Amore }
1035*49ef7e06SGarrett D'Amore
1036*49ef7e06SGarrett D'Amore #define EFX_EV_BATCH 8
1037*49ef7e06SGarrett D'Amore
1038*49ef7e06SGarrett D'Amore static void
siena_ev_qpoll(__in efx_evq_t * eep,__inout unsigned int * countp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)1039*49ef7e06SGarrett D'Amore siena_ev_qpoll(
1040*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
1041*49ef7e06SGarrett D'Amore __inout unsigned int *countp,
1042*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp,
1043*49ef7e06SGarrett D'Amore __in_opt void *arg)
1044*49ef7e06SGarrett D'Amore {
1045*49ef7e06SGarrett D'Amore efx_qword_t ev[EFX_EV_BATCH];
1046*49ef7e06SGarrett D'Amore unsigned int batch;
1047*49ef7e06SGarrett D'Amore unsigned int total;
1048*49ef7e06SGarrett D'Amore unsigned int count;
1049*49ef7e06SGarrett D'Amore unsigned int index;
1050*49ef7e06SGarrett D'Amore size_t offset;
1051*49ef7e06SGarrett D'Amore
1052*49ef7e06SGarrett D'Amore EFSYS_ASSERT(countp != NULL);
1053*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp != NULL);
1054*49ef7e06SGarrett D'Amore
1055*49ef7e06SGarrett D'Amore count = *countp;
1056*49ef7e06SGarrett D'Amore do {
1057*49ef7e06SGarrett D'Amore /* Read up until the end of the batch period */
1058*49ef7e06SGarrett D'Amore batch = EFX_EV_BATCH - (count & (EFX_EV_BATCH - 1));
1059*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
1060*49ef7e06SGarrett D'Amore for (total = 0; total < batch; ++total) {
1061*49ef7e06SGarrett D'Amore EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total]));
1062*49ef7e06SGarrett D'Amore
1063*49ef7e06SGarrett D'Amore if (!EFX_EV_PRESENT(ev[total]))
1064*49ef7e06SGarrett D'Amore break;
1065*49ef7e06SGarrett D'Amore
1066*49ef7e06SGarrett D'Amore EFSYS_PROBE3(event, unsigned int, eep->ee_index,
1067*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1),
1068*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0));
1069*49ef7e06SGarrett D'Amore
1070*49ef7e06SGarrett D'Amore offset += sizeof (efx_qword_t);
1071*49ef7e06SGarrett D'Amore }
1072*49ef7e06SGarrett D'Amore
1073*49ef7e06SGarrett D'Amore #if EFSYS_OPT_EV_PREFETCH && (EFSYS_OPT_EV_PREFETCH_PERIOD > 1)
1074*49ef7e06SGarrett D'Amore /*
1075*49ef7e06SGarrett D'Amore * Prefetch the next batch when we get within PREFETCH_PERIOD
1076*49ef7e06SGarrett D'Amore * of a completed batch. If the batch is smaller, then prefetch
1077*49ef7e06SGarrett D'Amore * immediately.
1078*49ef7e06SGarrett D'Amore */
1079*49ef7e06SGarrett D'Amore if (total == batch && total < EFSYS_OPT_EV_PREFETCH_PERIOD)
1080*49ef7e06SGarrett D'Amore EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
1081*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_EV_PREFETCH */
1082*49ef7e06SGarrett D'Amore
1083*49ef7e06SGarrett D'Amore /* Process the batch of events */
1084*49ef7e06SGarrett D'Amore for (index = 0; index < total; ++index) {
1085*49ef7e06SGarrett D'Amore boolean_t should_abort;
1086*49ef7e06SGarrett D'Amore uint32_t code;
1087*49ef7e06SGarrett D'Amore
1088*49ef7e06SGarrett D'Amore #if EFSYS_OPT_EV_PREFETCH
1089*49ef7e06SGarrett D'Amore /* Prefetch if we've now reached the batch period */
1090*49ef7e06SGarrett D'Amore if (total == batch &&
1091*49ef7e06SGarrett D'Amore index + EFSYS_OPT_EV_PREFETCH_PERIOD == total) {
1092*49ef7e06SGarrett D'Amore offset = (count + batch) & eep->ee_mask;
1093*49ef7e06SGarrett D'Amore offset *= sizeof (efx_qword_t);
1094*49ef7e06SGarrett D'Amore
1095*49ef7e06SGarrett D'Amore EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
1096*49ef7e06SGarrett D'Amore }
1097*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_EV_PREFETCH */
1098*49ef7e06SGarrett D'Amore
1099*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_ALL);
1100*49ef7e06SGarrett D'Amore
1101*49ef7e06SGarrett D'Amore code = EFX_QWORD_FIELD(ev[index], FSF_AZ_EV_CODE);
1102*49ef7e06SGarrett D'Amore switch (code) {
1103*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_RX_EV:
1104*49ef7e06SGarrett D'Amore should_abort = eep->ee_rx(eep,
1105*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg);
1106*49ef7e06SGarrett D'Amore break;
1107*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_TX_EV:
1108*49ef7e06SGarrett D'Amore should_abort = eep->ee_tx(eep,
1109*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg);
1110*49ef7e06SGarrett D'Amore break;
1111*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_DRIVER_EV:
1112*49ef7e06SGarrett D'Amore should_abort = eep->ee_driver(eep,
1113*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg);
1114*49ef7e06SGarrett D'Amore break;
1115*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_DRV_GEN_EV:
1116*49ef7e06SGarrett D'Amore should_abort = eep->ee_drv_gen(eep,
1117*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg);
1118*49ef7e06SGarrett D'Amore break;
1119*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI
1120*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_MCDI_EVRESPONSE:
1121*49ef7e06SGarrett D'Amore should_abort = eep->ee_mcdi(eep,
1122*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg);
1123*49ef7e06SGarrett D'Amore break;
1124*49ef7e06SGarrett D'Amore #endif
1125*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_GLOBAL_EV:
1126*49ef7e06SGarrett D'Amore if (eep->ee_global) {
1127*49ef7e06SGarrett D'Amore should_abort = eep->ee_global(eep,
1128*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg);
1129*49ef7e06SGarrett D'Amore break;
1130*49ef7e06SGarrett D'Amore }
1131*49ef7e06SGarrett D'Amore /* else fallthrough */
1132*49ef7e06SGarrett D'Amore default:
1133*49ef7e06SGarrett D'Amore EFSYS_PROBE3(bad_event,
1134*49ef7e06SGarrett D'Amore unsigned int, eep->ee_index,
1135*49ef7e06SGarrett D'Amore uint32_t,
1136*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(ev[index], EFX_DWORD_1),
1137*49ef7e06SGarrett D'Amore uint32_t,
1138*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(ev[index], EFX_DWORD_0));
1139*49ef7e06SGarrett D'Amore
1140*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL);
1141*49ef7e06SGarrett D'Amore (void) eecp->eec_exception(arg,
1142*49ef7e06SGarrett D'Amore EFX_EXCEPTION_EV_ERROR, code);
1143*49ef7e06SGarrett D'Amore should_abort = B_TRUE;
1144*49ef7e06SGarrett D'Amore }
1145*49ef7e06SGarrett D'Amore if (should_abort) {
1146*49ef7e06SGarrett D'Amore /* Ignore subsequent events */
1147*49ef7e06SGarrett D'Amore total = index + 1;
1148*49ef7e06SGarrett D'Amore break;
1149*49ef7e06SGarrett D'Amore }
1150*49ef7e06SGarrett D'Amore }
1151*49ef7e06SGarrett D'Amore
1152*49ef7e06SGarrett D'Amore /*
1153*49ef7e06SGarrett D'Amore * Now that the hardware has most likely moved onto dma'ing
1154*49ef7e06SGarrett D'Amore * into the next cache line, clear the processed events. Take
1155*49ef7e06SGarrett D'Amore * care to only clear out events that we've processed
1156*49ef7e06SGarrett D'Amore */
1157*49ef7e06SGarrett D'Amore EFX_SET_QWORD(ev[0]);
1158*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
1159*49ef7e06SGarrett D'Amore for (index = 0; index < total; ++index) {
1160*49ef7e06SGarrett D'Amore EFSYS_MEM_WRITEQ(eep->ee_esmp, offset, &(ev[0]));
1161*49ef7e06SGarrett D'Amore offset += sizeof (efx_qword_t);
1162*49ef7e06SGarrett D'Amore }
1163*49ef7e06SGarrett D'Amore
1164*49ef7e06SGarrett D'Amore count += total;
1165*49ef7e06SGarrett D'Amore
1166*49ef7e06SGarrett D'Amore } while (total == batch);
1167*49ef7e06SGarrett D'Amore
1168*49ef7e06SGarrett D'Amore *countp = count;
1169*49ef7e06SGarrett D'Amore }
1170*49ef7e06SGarrett D'Amore
1171*49ef7e06SGarrett D'Amore static void
siena_ev_qpost(__in efx_evq_t * eep,__in uint16_t data)1172*49ef7e06SGarrett D'Amore siena_ev_qpost(
1173*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
1174*49ef7e06SGarrett D'Amore __in uint16_t data)
1175*49ef7e06SGarrett D'Amore {
1176*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
1177*49ef7e06SGarrett D'Amore efx_qword_t ev;
1178*49ef7e06SGarrett D'Amore efx_oword_t oword;
1179*49ef7e06SGarrett D'Amore
1180*49ef7e06SGarrett D'Amore EFX_POPULATE_QWORD_2(ev, FSF_AZ_EV_CODE, FSE_AZ_EV_CODE_DRV_GEN_EV,
1181*49ef7e06SGarrett D'Amore FSF_AZ_EV_DATA_DW0, (uint32_t)data);
1182*49ef7e06SGarrett D'Amore
1183*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_3(oword, FRF_AZ_DRV_EV_QID, eep->ee_index,
1184*49ef7e06SGarrett D'Amore EFX_DWORD_0, EFX_QWORD_FIELD(ev, EFX_DWORD_0),
1185*49ef7e06SGarrett D'Amore EFX_DWORD_1, EFX_QWORD_FIELD(ev, EFX_DWORD_1));
1186*49ef7e06SGarrett D'Amore
1187*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_DRV_EV_REG, &oword);
1188*49ef7e06SGarrett D'Amore }
1189*49ef7e06SGarrett D'Amore
1190*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
siena_ev_qmoderate(__in efx_evq_t * eep,__in unsigned int us)1191*49ef7e06SGarrett D'Amore siena_ev_qmoderate(
1192*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
1193*49ef7e06SGarrett D'Amore __in unsigned int us)
1194*49ef7e06SGarrett D'Amore {
1195*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
1196*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1197*49ef7e06SGarrett D'Amore unsigned int locked;
1198*49ef7e06SGarrett D'Amore efx_dword_t dword;
1199*49ef7e06SGarrett D'Amore efx_rc_t rc;
1200*49ef7e06SGarrett D'Amore
1201*49ef7e06SGarrett D'Amore if (us > encp->enc_evq_timer_max_us) {
1202*49ef7e06SGarrett D'Amore rc = EINVAL;
1203*49ef7e06SGarrett D'Amore goto fail1;
1204*49ef7e06SGarrett D'Amore }
1205*49ef7e06SGarrett D'Amore
1206*49ef7e06SGarrett D'Amore /* If the value is zero then disable the timer */
1207*49ef7e06SGarrett D'Amore if (us == 0) {
1208*49ef7e06SGarrett D'Amore EFX_POPULATE_DWORD_2(dword,
1209*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS,
1210*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_VAL, 0);
1211*49ef7e06SGarrett D'Amore } else {
1212*49ef7e06SGarrett D'Amore uint32_t timer_val;
1213*49ef7e06SGarrett D'Amore
1214*49ef7e06SGarrett D'Amore /* Calculate the timer value in quanta */
1215*49ef7e06SGarrett D'Amore timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns;
1216*49ef7e06SGarrett D'Amore
1217*49ef7e06SGarrett D'Amore /* Moderation value is base 0 so we need to deduct 1 */
1218*49ef7e06SGarrett D'Amore if (timer_val > 0)
1219*49ef7e06SGarrett D'Amore timer_val--;
1220*49ef7e06SGarrett D'Amore
1221*49ef7e06SGarrett D'Amore EFX_POPULATE_DWORD_2(dword,
1222*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_INT_HLDOFF,
1223*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_VAL, timer_val);
1224*49ef7e06SGarrett D'Amore }
1225*49ef7e06SGarrett D'Amore
1226*49ef7e06SGarrett D'Amore locked = (eep->ee_index == 0) ? 1 : 0;
1227*49ef7e06SGarrett D'Amore
1228*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0,
1229*49ef7e06SGarrett D'Amore eep->ee_index, &dword, locked);
1230*49ef7e06SGarrett D'Amore
1231*49ef7e06SGarrett D'Amore return (0);
1232*49ef7e06SGarrett D'Amore
1233*49ef7e06SGarrett D'Amore fail1:
1234*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1235*49ef7e06SGarrett D'Amore
1236*49ef7e06SGarrett D'Amore return (rc);
1237*49ef7e06SGarrett D'Amore }
1238*49ef7e06SGarrett D'Amore
1239*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
siena_ev_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in efsys_mem_t * esmp,__in size_t n,__in uint32_t id,__in efx_evq_t * eep)1240*49ef7e06SGarrett D'Amore siena_ev_qcreate(
1241*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
1242*49ef7e06SGarrett D'Amore __in unsigned int index,
1243*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp,
1244*49ef7e06SGarrett D'Amore __in size_t n,
1245*49ef7e06SGarrett D'Amore __in uint32_t id,
1246*49ef7e06SGarrett D'Amore __in efx_evq_t *eep)
1247*49ef7e06SGarrett D'Amore {
1248*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1249*49ef7e06SGarrett D'Amore uint32_t size;
1250*49ef7e06SGarrett D'Amore efx_oword_t oword;
1251*49ef7e06SGarrett D'Amore efx_rc_t rc;
1252*49ef7e06SGarrett D'Amore
1253*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(esmp));
1254*49ef7e06SGarrett D'Amore
1255*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MAXNEVS));
1256*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MINNEVS));
1257*49ef7e06SGarrett D'Amore
1258*49ef7e06SGarrett D'Amore if (!ISP2(n) || (n < EFX_EVQ_MINNEVS) || (n > EFX_EVQ_MAXNEVS)) {
1259*49ef7e06SGarrett D'Amore rc = EINVAL;
1260*49ef7e06SGarrett D'Amore goto fail1;
1261*49ef7e06SGarrett D'Amore }
1262*49ef7e06SGarrett D'Amore if (index >= encp->enc_evq_limit) {
1263*49ef7e06SGarrett D'Amore rc = EINVAL;
1264*49ef7e06SGarrett D'Amore goto fail2;
1265*49ef7e06SGarrett D'Amore }
1266*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCALE
1267*49ef7e06SGarrett D'Amore if (enp->en_intr.ei_type == EFX_INTR_LINE &&
1268*49ef7e06SGarrett D'Amore index >= EFX_MAXRSS_LEGACY) {
1269*49ef7e06SGarrett D'Amore rc = EINVAL;
1270*49ef7e06SGarrett D'Amore goto fail3;
1271*49ef7e06SGarrett D'Amore }
1272*49ef7e06SGarrett D'Amore #endif
1273*49ef7e06SGarrett D'Amore for (size = 0; (1 << size) <= (EFX_EVQ_MAXNEVS / EFX_EVQ_MINNEVS);
1274*49ef7e06SGarrett D'Amore size++)
1275*49ef7e06SGarrett D'Amore if ((1 << size) == (int)(n / EFX_EVQ_MINNEVS))
1276*49ef7e06SGarrett D'Amore break;
1277*49ef7e06SGarrett D'Amore if (id + (1 << size) >= encp->enc_buftbl_limit) {
1278*49ef7e06SGarrett D'Amore rc = EINVAL;
1279*49ef7e06SGarrett D'Amore goto fail4;
1280*49ef7e06SGarrett D'Amore }
1281*49ef7e06SGarrett D'Amore
1282*49ef7e06SGarrett D'Amore /* Set up the handler table */
1283*49ef7e06SGarrett D'Amore eep->ee_rx = siena_ev_rx;
1284*49ef7e06SGarrett D'Amore eep->ee_tx = siena_ev_tx;
1285*49ef7e06SGarrett D'Amore eep->ee_driver = siena_ev_driver;
1286*49ef7e06SGarrett D'Amore eep->ee_global = siena_ev_global;
1287*49ef7e06SGarrett D'Amore eep->ee_drv_gen = siena_ev_drv_gen;
1288*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI
1289*49ef7e06SGarrett D'Amore eep->ee_mcdi = siena_ev_mcdi;
1290*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MCDI */
1291*49ef7e06SGarrett D'Amore
1292*49ef7e06SGarrett D'Amore /* Set up the new event queue */
1293*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_1(oword, FRF_CZ_TIMER_Q_EN, 1);
1294*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, index, &oword, B_TRUE);
1295*49ef7e06SGarrett D'Amore
1296*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_3(oword, FRF_AZ_EVQ_EN, 1, FRF_AZ_EVQ_SIZE, size,
1297*49ef7e06SGarrett D'Amore FRF_AZ_EVQ_BUF_BASE_ID, id);
1298*49ef7e06SGarrett D'Amore
1299*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, index, &oword, B_TRUE);
1300*49ef7e06SGarrett D'Amore
1301*49ef7e06SGarrett D'Amore return (0);
1302*49ef7e06SGarrett D'Amore
1303*49ef7e06SGarrett D'Amore fail4:
1304*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4);
1305*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCALE
1306*49ef7e06SGarrett D'Amore fail3:
1307*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
1308*49ef7e06SGarrett D'Amore #endif
1309*49ef7e06SGarrett D'Amore fail2:
1310*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
1311*49ef7e06SGarrett D'Amore fail1:
1312*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1313*49ef7e06SGarrett D'Amore
1314*49ef7e06SGarrett D'Amore return (rc);
1315*49ef7e06SGarrett D'Amore }
1316*49ef7e06SGarrett D'Amore
1317*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
1318*49ef7e06SGarrett D'Amore
1319*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
1320*49ef7e06SGarrett D'Amore #if EFSYS_OPT_NAMES
1321*49ef7e06SGarrett D'Amore /* START MKCONFIG GENERATED EfxEventQueueStatNamesBlock b693ddf85aee1bfd */
1322*49ef7e06SGarrett D'Amore static const char *__efx_ev_qstat_name[] = {
1323*49ef7e06SGarrett D'Amore "all",
1324*49ef7e06SGarrett D'Amore "rx",
1325*49ef7e06SGarrett D'Amore "rx_ok",
1326*49ef7e06SGarrett D'Amore "rx_frm_trunc",
1327*49ef7e06SGarrett D'Amore "rx_tobe_disc",
1328*49ef7e06SGarrett D'Amore "rx_pause_frm_err",
1329*49ef7e06SGarrett D'Amore "rx_buf_owner_id_err",
1330*49ef7e06SGarrett D'Amore "rx_ipv4_hdr_chksum_err",
1331*49ef7e06SGarrett D'Amore "rx_tcp_udp_chksum_err",
1332*49ef7e06SGarrett D'Amore "rx_eth_crc_err",
1333*49ef7e06SGarrett D'Amore "rx_ip_frag_err",
1334*49ef7e06SGarrett D'Amore "rx_mcast_pkt",
1335*49ef7e06SGarrett D'Amore "rx_mcast_hash_match",
1336*49ef7e06SGarrett D'Amore "rx_tcp_ipv4",
1337*49ef7e06SGarrett D'Amore "rx_tcp_ipv6",
1338*49ef7e06SGarrett D'Amore "rx_udp_ipv4",
1339*49ef7e06SGarrett D'Amore "rx_udp_ipv6",
1340*49ef7e06SGarrett D'Amore "rx_other_ipv4",
1341*49ef7e06SGarrett D'Amore "rx_other_ipv6",
1342*49ef7e06SGarrett D'Amore "rx_non_ip",
1343*49ef7e06SGarrett D'Amore "rx_batch",
1344*49ef7e06SGarrett D'Amore "tx",
1345*49ef7e06SGarrett D'Amore "tx_wq_ff_full",
1346*49ef7e06SGarrett D'Amore "tx_pkt_err",
1347*49ef7e06SGarrett D'Amore "tx_pkt_too_big",
1348*49ef7e06SGarrett D'Amore "tx_unexpected",
1349*49ef7e06SGarrett D'Amore "global",
1350*49ef7e06SGarrett D'Amore "global_mnt",
1351*49ef7e06SGarrett D'Amore "driver",
1352*49ef7e06SGarrett D'Amore "driver_srm_upd_done",
1353*49ef7e06SGarrett D'Amore "driver_tx_descq_fls_done",
1354*49ef7e06SGarrett D'Amore "driver_rx_descq_fls_done",
1355*49ef7e06SGarrett D'Amore "driver_rx_descq_fls_failed",
1356*49ef7e06SGarrett D'Amore "driver_rx_dsc_error",
1357*49ef7e06SGarrett D'Amore "driver_tx_dsc_error",
1358*49ef7e06SGarrett D'Amore "drv_gen",
1359*49ef7e06SGarrett D'Amore "mcdi_response",
1360*49ef7e06SGarrett D'Amore };
1361*49ef7e06SGarrett D'Amore /* END MKCONFIG GENERATED EfxEventQueueStatNamesBlock */
1362*49ef7e06SGarrett D'Amore
1363*49ef7e06SGarrett D'Amore const char *
efx_ev_qstat_name(__in efx_nic_t * enp,__in unsigned int id)1364*49ef7e06SGarrett D'Amore efx_ev_qstat_name(
1365*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
1366*49ef7e06SGarrett D'Amore __in unsigned int id)
1367*49ef7e06SGarrett D'Amore {
1368*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1369*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(id, <, EV_NQSTATS);
1370*49ef7e06SGarrett D'Amore
1371*49ef7e06SGarrett D'Amore return (__efx_ev_qstat_name[id]);
1372*49ef7e06SGarrett D'Amore }
1373*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_NAMES */
1374*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_QSTATS */
1375*49ef7e06SGarrett D'Amore
1376*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
1377*49ef7e06SGarrett D'Amore
1378*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS
1379*49ef7e06SGarrett D'Amore static void
siena_ev_qstats_update(__in efx_evq_t * eep,__inout_ecount (EV_NQSTATS)efsys_stat_t * stat)1380*49ef7e06SGarrett D'Amore siena_ev_qstats_update(
1381*49ef7e06SGarrett D'Amore __in efx_evq_t *eep,
1382*49ef7e06SGarrett D'Amore __inout_ecount(EV_NQSTATS) efsys_stat_t *stat)
1383*49ef7e06SGarrett D'Amore {
1384*49ef7e06SGarrett D'Amore unsigned int id;
1385*49ef7e06SGarrett D'Amore
1386*49ef7e06SGarrett D'Amore for (id = 0; id < EV_NQSTATS; id++) {
1387*49ef7e06SGarrett D'Amore efsys_stat_t *essp = &stat[id];
1388*49ef7e06SGarrett D'Amore
1389*49ef7e06SGarrett D'Amore EFSYS_STAT_INCR(essp, eep->ee_stat[id]);
1390*49ef7e06SGarrett D'Amore eep->ee_stat[id] = 0;
1391*49ef7e06SGarrett D'Amore }
1392*49ef7e06SGarrett D'Amore }
1393*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_QSTATS */
1394*49ef7e06SGarrett D'Amore
1395*49ef7e06SGarrett D'Amore static void
siena_ev_qdestroy(__in efx_evq_t * eep)1396*49ef7e06SGarrett D'Amore siena_ev_qdestroy(
1397*49ef7e06SGarrett D'Amore __in efx_evq_t *eep)
1398*49ef7e06SGarrett D'Amore {
1399*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp;
1400*49ef7e06SGarrett D'Amore efx_oword_t oword;
1401*49ef7e06SGarrett D'Amore
1402*49ef7e06SGarrett D'Amore /* Purge event queue */
1403*49ef7e06SGarrett D'Amore EFX_ZERO_OWORD(oword);
1404*49ef7e06SGarrett D'Amore
1405*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL,
1406*49ef7e06SGarrett D'Amore eep->ee_index, &oword, B_TRUE);
1407*49ef7e06SGarrett D'Amore
1408*49ef7e06SGarrett D'Amore EFX_ZERO_OWORD(oword);
1409*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, eep->ee_index, &oword, B_TRUE);
1410*49ef7e06SGarrett D'Amore }
1411*49ef7e06SGarrett D'Amore
1412*49ef7e06SGarrett D'Amore static void
siena_ev_fini(__in efx_nic_t * enp)1413*49ef7e06SGarrett D'Amore siena_ev_fini(
1414*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1415*49ef7e06SGarrett D'Amore {
1416*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(enp))
1417*49ef7e06SGarrett D'Amore }
1418*49ef7e06SGarrett D'Amore
1419*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */
1420