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