xref: /illumos-gate/usr/src/uts/common/io/sfxge/common/efx_ev.c (revision 49ef7e0638c8b771d8a136eae78b1c0f99acc8e0)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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