xref: /dpdk/drivers/common/sfc_efx/base/rhead_ev.c (revision aa6dc1017cd3fa7b722ca877558e871f82eb1f02)
1b97bf1caSAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
2b97bf1caSAndrew Rybchenko  *
3672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
4b97bf1caSAndrew Rybchenko  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5b97bf1caSAndrew Rybchenko  */
6b97bf1caSAndrew Rybchenko 
7b97bf1caSAndrew Rybchenko #include "efx.h"
8b97bf1caSAndrew Rybchenko #include "efx_impl.h"
9b97bf1caSAndrew Rybchenko 
10b97bf1caSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
11b97bf1caSAndrew Rybchenko 
12b97bf1caSAndrew Rybchenko /*
13b97bf1caSAndrew Rybchenko  * Non-interrupting event queue requires interrupting event queue to
14b97bf1caSAndrew Rybchenko  * refer to for wake-up events even if wake ups are never used.
15b97bf1caSAndrew Rybchenko  * It could be even non-allocated event queue.
16b97bf1caSAndrew Rybchenko  */
17b97bf1caSAndrew Rybchenko #define	EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX	(0)
18b97bf1caSAndrew Rybchenko 
19e10a178aSAndy Moreton static			boolean_t
20e10a178aSAndy Moreton rhead_ev_dispatch(
21e10a178aSAndy Moreton 	__in		efx_evq_t *eep,
22e10a178aSAndy Moreton 	__in		efx_qword_t *eventp,
23e10a178aSAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
24e10a178aSAndy Moreton 	__in_opt	void *arg);
25e10a178aSAndy Moreton 
2617580779SAndrew Rybchenko static	__checkReturn	boolean_t
2717580779SAndrew Rybchenko rhead_ev_rx_packets(
2817580779SAndrew Rybchenko 	__in		efx_evq_t *eep,
2917580779SAndrew Rybchenko 	__in		efx_qword_t *eqp,
3017580779SAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
3117580779SAndrew Rybchenko 	__in_opt	void *arg);
3217580779SAndrew Rybchenko 
3396a8519dSAndrew Rybchenko static	__checkReturn	boolean_t
3496a8519dSAndrew Rybchenko rhead_ev_tx_completion(
3596a8519dSAndrew Rybchenko 	__in		efx_evq_t *eep,
3696a8519dSAndrew Rybchenko 	__in		efx_qword_t *eqp,
3796a8519dSAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
3896a8519dSAndrew Rybchenko 	__in_opt	void *arg);
3996a8519dSAndrew Rybchenko 
409edb8ee3SAndrew Rybchenko static	__checkReturn	boolean_t
419edb8ee3SAndrew Rybchenko rhead_ev_mcdi(
429edb8ee3SAndrew Rybchenko 	__in		efx_evq_t *eep,
439edb8ee3SAndrew Rybchenko 	__in		efx_qword_t *eqp,
449edb8ee3SAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
459edb8ee3SAndrew Rybchenko 	__in_opt	void *arg);
469edb8ee3SAndrew Rybchenko 
471a4448beSAndy Moreton #if EFSYS_OPT_EV_EXTENDED_WIDTH
481a4448beSAndy Moreton static			boolean_t
491a4448beSAndy Moreton rhead_ev_ew_dispatch(
501a4448beSAndy Moreton 	__in		efx_evq_t *eep,
511a4448beSAndy Moreton 	__in		efx_xword_t *eventp,
521a4448beSAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
531a4448beSAndy Moreton 	__in_opt	void *arg);
541a4448beSAndy Moreton 
551a4448beSAndy Moreton static			void
561a4448beSAndy Moreton rhead_ev_ew_qpoll(
571a4448beSAndy Moreton 	__in		efx_evq_t *eep,
581a4448beSAndy Moreton 	__inout		unsigned int *countp,
591a4448beSAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
601a4448beSAndy Moreton 	__in_opt	void *arg);
61ea42cae4SAndy Moreton 
62ea42cae4SAndy Moreton #if EFSYS_OPT_DESC_PROXY
63ea42cae4SAndy Moreton static			boolean_t
64ea42cae4SAndy Moreton rhead_ev_ew_txq_desc(
65ea42cae4SAndy Moreton 	__in		efx_evq_t *eep,
66ea42cae4SAndy Moreton 	__in		efx_xword_t *eventp,
67ea42cae4SAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
68ea42cae4SAndy Moreton 	__in_opt	void *arg);
69ea42cae4SAndy Moreton 
70ea42cae4SAndy Moreton static			boolean_t
71ea42cae4SAndy Moreton rhead_ev_ew_virtq_desc(
72ea42cae4SAndy Moreton 	__in		efx_evq_t *eep,
73ea42cae4SAndy Moreton 	__in		efx_xword_t *eventp,
74ea42cae4SAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
75ea42cae4SAndy Moreton 	__in_opt	void *arg);
76ea42cae4SAndy Moreton #endif /* EFSYS_OPT_DESC_PROXY */
771a4448beSAndy Moreton #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
781a4448beSAndy Moreton 
799edb8ee3SAndrew Rybchenko 
80b97bf1caSAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_ev_init(__in efx_nic_t * enp)81b97bf1caSAndrew Rybchenko rhead_ev_init(
82b97bf1caSAndrew Rybchenko 	__in		efx_nic_t *enp)
83b97bf1caSAndrew Rybchenko {
84b97bf1caSAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
85b97bf1caSAndrew Rybchenko 
86b97bf1caSAndrew Rybchenko 	return (0);
87b97bf1caSAndrew Rybchenko }
88b97bf1caSAndrew Rybchenko 
89b97bf1caSAndrew Rybchenko 			void
rhead_ev_fini(__in efx_nic_t * enp)90b97bf1caSAndrew Rybchenko rhead_ev_fini(
91b97bf1caSAndrew Rybchenko 	__in		efx_nic_t *enp)
92b97bf1caSAndrew Rybchenko {
93b97bf1caSAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
94b97bf1caSAndrew Rybchenko }
95b97bf1caSAndrew Rybchenko 
96b97bf1caSAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_ev_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in efsys_mem_t * esmp,__in size_t ndescs,__in uint32_t id,__in uint32_t us,__in uint32_t flags,__in uint32_t irq,__in efx_evq_t * eep)97b97bf1caSAndrew Rybchenko rhead_ev_qcreate(
98b97bf1caSAndrew Rybchenko 	__in		efx_nic_t *enp,
99b97bf1caSAndrew Rybchenko 	__in		unsigned int index,
100b97bf1caSAndrew Rybchenko 	__in		efsys_mem_t *esmp,
101b97bf1caSAndrew Rybchenko 	__in		size_t ndescs,
102b97bf1caSAndrew Rybchenko 	__in		uint32_t id,
103b97bf1caSAndrew Rybchenko 	__in		uint32_t us,
104b97bf1caSAndrew Rybchenko 	__in		uint32_t flags,
105*aa6dc101SAndrew Rybchenko 	__in		uint32_t irq,
106b97bf1caSAndrew Rybchenko 	__in		efx_evq_t *eep)
107b97bf1caSAndrew Rybchenko {
108f8a60f76SAndy Moreton 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
109f8a60f76SAndy Moreton 	size_t desc_size;
1103dee345aSAndrew Rybchenko 	uint32_t target_evq = 0;
111b97bf1caSAndrew Rybchenko 	efx_rc_t rc;
112b97bf1caSAndrew Rybchenko 
113b97bf1caSAndrew Rybchenko 	_NOTE(ARGUNUSED(id))	/* buftbl id managed by MC */
114b97bf1caSAndrew Rybchenko 
115f8a60f76SAndy Moreton 	desc_size = encp->enc_ev_desc_size;
116f8a60f76SAndy Moreton #if EFSYS_OPT_EV_EXTENDED_WIDTH
117f8a60f76SAndy Moreton 	if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH)
118f8a60f76SAndy Moreton 		desc_size = encp->enc_ev_ew_desc_size;
119f8a60f76SAndy Moreton #endif
120f8a60f76SAndy Moreton 	EFSYS_ASSERT(desc_size != 0);
121f8a60f76SAndy Moreton 
122f8a60f76SAndy Moreton 	if (EFSYS_MEM_SIZE(esmp) < (ndescs * desc_size)) {
123f8a60f76SAndy Moreton 		/* Buffer too small for event queue descriptors */
124f8a60f76SAndy Moreton 		rc = EINVAL;
125f8a60f76SAndy Moreton 		goto fail1;
126f8a60f76SAndy Moreton 	}
127f8a60f76SAndy Moreton 
128b97bf1caSAndrew Rybchenko 	/* Set up the handler table */
12917580779SAndrew Rybchenko 	eep->ee_rx	= rhead_ev_rx_packets;
13096a8519dSAndrew Rybchenko 	eep->ee_tx	= rhead_ev_tx_completion;
131b97bf1caSAndrew Rybchenko 	eep->ee_driver	= NULL; /* FIXME */
132b97bf1caSAndrew Rybchenko 	eep->ee_drv_gen	= NULL; /* FIXME */
1339edb8ee3SAndrew Rybchenko 	eep->ee_mcdi	= rhead_ev_mcdi;
134b97bf1caSAndrew Rybchenko 
135ea42cae4SAndy Moreton #if EFSYS_OPT_DESC_PROXY
136ea42cae4SAndy Moreton 	eep->ee_ew_txq_desc	= rhead_ev_ew_txq_desc;
137ea42cae4SAndy Moreton 	eep->ee_ew_virtq_desc	= rhead_ev_ew_virtq_desc;
138ea42cae4SAndy Moreton #endif /* EFSYS_OPT_DESC_PROXY */
139ea42cae4SAndy Moreton 
140b97bf1caSAndrew Rybchenko 	/* Set up the event queue */
141b97bf1caSAndrew Rybchenko 	/* INIT_EVQ expects function-relative vector number */
142b97bf1caSAndrew Rybchenko 	if ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
143b97bf1caSAndrew Rybchenko 	    EFX_EVQ_FLAGS_NOTIFY_INTERRUPT) {
144*aa6dc101SAndrew Rybchenko 		/* IRQ number is specified by caller */
145b97bf1caSAndrew Rybchenko 	} else if (index == EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX) {
1463dee345aSAndrew Rybchenko 		/* Use the first interrupt for always interrupting EvQ */
1473dee345aSAndrew Rybchenko 		irq = 0;
148b97bf1caSAndrew Rybchenko 		flags = (flags & ~EFX_EVQ_FLAGS_NOTIFY_MASK) |
149b97bf1caSAndrew Rybchenko 		    EFX_EVQ_FLAGS_NOTIFY_INTERRUPT;
150b97bf1caSAndrew Rybchenko 	} else {
1513dee345aSAndrew Rybchenko 		target_evq = EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX;
152b97bf1caSAndrew Rybchenko 	}
153b97bf1caSAndrew Rybchenko 
154b97bf1caSAndrew Rybchenko 	/*
155b97bf1caSAndrew Rybchenko 	 * Interrupts may be raised for events immediately after the queue is
156b97bf1caSAndrew Rybchenko 	 * created. See bug58606.
157b97bf1caSAndrew Rybchenko 	 */
1583dee345aSAndrew Rybchenko 	rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, target_evq, us,
1593dee345aSAndrew Rybchenko 	    flags, B_FALSE);
160b97bf1caSAndrew Rybchenko 	if (rc != 0)
161f8a60f76SAndy Moreton 		goto fail2;
162b97bf1caSAndrew Rybchenko 
163b97bf1caSAndrew Rybchenko 	return (0);
164b97bf1caSAndrew Rybchenko 
165f8a60f76SAndy Moreton fail2:
166f8a60f76SAndy Moreton 	EFSYS_PROBE(fail2);
167b97bf1caSAndrew Rybchenko fail1:
168b97bf1caSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
169b97bf1caSAndrew Rybchenko 
170b97bf1caSAndrew Rybchenko 	return (rc);
171b97bf1caSAndrew Rybchenko }
172b97bf1caSAndrew Rybchenko 
173b97bf1caSAndrew Rybchenko 			void
rhead_ev_qdestroy(__in efx_evq_t * eep)174b97bf1caSAndrew Rybchenko rhead_ev_qdestroy(
175b97bf1caSAndrew Rybchenko 	__in		efx_evq_t *eep)
176b97bf1caSAndrew Rybchenko {
177b97bf1caSAndrew Rybchenko 	efx_nic_t *enp = eep->ee_enp;
178b97bf1caSAndrew Rybchenko 
179b97bf1caSAndrew Rybchenko 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_RIVERHEAD);
180b97bf1caSAndrew Rybchenko 
181b97bf1caSAndrew Rybchenko 	(void) efx_mcdi_fini_evq(enp, eep->ee_index);
182b97bf1caSAndrew Rybchenko }
183b97bf1caSAndrew Rybchenko 
184b97bf1caSAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_ev_qprime(__in efx_evq_t * eep,__in unsigned int count)185b97bf1caSAndrew Rybchenko rhead_ev_qprime(
186b97bf1caSAndrew Rybchenko 	__in		efx_evq_t *eep,
187b97bf1caSAndrew Rybchenko 	__in		unsigned int count)
188b97bf1caSAndrew Rybchenko {
189b97bf1caSAndrew Rybchenko 	efx_nic_t *enp = eep->ee_enp;
190b97bf1caSAndrew Rybchenko 	uint32_t rptr;
191b97bf1caSAndrew Rybchenko 	efx_dword_t dword;
192b97bf1caSAndrew Rybchenko 
193b97bf1caSAndrew Rybchenko 	rptr = count & eep->ee_mask;
194b97bf1caSAndrew Rybchenko 
195b97bf1caSAndrew Rybchenko 	EFX_POPULATE_DWORD_2(dword, ERF_GZ_EVQ_ID, eep->ee_index,
196b97bf1caSAndrew Rybchenko 	    ERF_GZ_IDX, rptr);
197b97bf1caSAndrew Rybchenko 	/* EVQ_INT_PRIME lives function control window only on Riverhead */
198341bd4e0SIgor Romanov 	EFX_BAR_FCW_WRITED(enp, ER_GZ_EVQ_INT_PRIME, &dword);
199b97bf1caSAndrew Rybchenko 
200b97bf1caSAndrew Rybchenko 	return (0);
201b97bf1caSAndrew Rybchenko }
202b97bf1caSAndrew Rybchenko 
203b97bf1caSAndrew Rybchenko 			void
rhead_ev_qpost(__in efx_evq_t * eep,__in uint16_t data)204b97bf1caSAndrew Rybchenko rhead_ev_qpost(
205b97bf1caSAndrew Rybchenko 	__in	efx_evq_t *eep,
206b97bf1caSAndrew Rybchenko 	__in	uint16_t data)
207b97bf1caSAndrew Rybchenko {
208b97bf1caSAndrew Rybchenko 	_NOTE(ARGUNUSED(eep, data))
209b97bf1caSAndrew Rybchenko 
210b97bf1caSAndrew Rybchenko 	/* Not implemented yet */
211b97bf1caSAndrew Rybchenko 	EFSYS_ASSERT(B_FALSE);
212b97bf1caSAndrew Rybchenko }
213b97bf1caSAndrew Rybchenko 
214e10a178aSAndy Moreton static	__checkReturn	boolean_t
rhead_ev_dispatch(__in efx_evq_t * eep,__in efx_qword_t * eventp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)215e10a178aSAndy Moreton rhead_ev_dispatch(
216e10a178aSAndy Moreton 	__in		efx_evq_t *eep,
217e10a178aSAndy Moreton 	__in		efx_qword_t *eventp,
218e10a178aSAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
219e10a178aSAndy Moreton 	__in_opt	void *arg)
220e10a178aSAndy Moreton {
221e10a178aSAndy Moreton 	boolean_t should_abort;
222e10a178aSAndy Moreton 	uint32_t code;
223e10a178aSAndy Moreton 
224e10a178aSAndy Moreton 	code = EFX_QWORD_FIELD(*eventp, ESF_GZ_E_TYPE);
225e10a178aSAndy Moreton 	switch (code) {
226e10a178aSAndy Moreton 	case ESE_GZ_EF100_EV_RX_PKTS:
227e10a178aSAndy Moreton 		should_abort = eep->ee_rx(eep, eventp, eecp, arg);
228e10a178aSAndy Moreton 		break;
229e10a178aSAndy Moreton 	case ESE_GZ_EF100_EV_TX_COMPLETION:
230e10a178aSAndy Moreton 		should_abort = eep->ee_tx(eep, eventp, eecp, arg);
231e10a178aSAndy Moreton 		break;
232e10a178aSAndy Moreton 	case ESE_GZ_EF100_EV_MCDI:
233e10a178aSAndy Moreton 		should_abort = eep->ee_mcdi(eep, eventp, eecp, arg);
234e10a178aSAndy Moreton 		break;
235e10a178aSAndy Moreton 	default:
236e10a178aSAndy Moreton 		EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index,
237e10a178aSAndy Moreton 		    uint32_t, EFX_QWORD_FIELD(*eventp, EFX_DWORD_1),
238e10a178aSAndy Moreton 		    uint32_t, EFX_QWORD_FIELD(*eventp, EFX_DWORD_0));
239e10a178aSAndy Moreton 
240e10a178aSAndy Moreton 		EFSYS_ASSERT(eecp->eec_exception != NULL);
241e10a178aSAndy Moreton 		(void) eecp->eec_exception(arg, EFX_EXCEPTION_EV_ERROR, code);
242e10a178aSAndy Moreton 		should_abort = B_TRUE;
243e10a178aSAndy Moreton 		break;
244e10a178aSAndy Moreton 	}
245e10a178aSAndy Moreton 
246e10a178aSAndy Moreton 	return (should_abort);
247e10a178aSAndy Moreton }
248e10a178aSAndy Moreton 
249b97bf1caSAndrew Rybchenko /*
250b97bf1caSAndrew Rybchenko  * Poll event queue in batches. Size of the batch is equal to cache line
251b97bf1caSAndrew Rybchenko  * size divided by event size.
252b97bf1caSAndrew Rybchenko  *
253b97bf1caSAndrew Rybchenko  * Event queue is written by NIC and read by CPU. If CPU starts reading
254b97bf1caSAndrew Rybchenko  * of events on the cache line, read all remaining events in a tight
255b97bf1caSAndrew Rybchenko  * loop while event is present.
256b97bf1caSAndrew Rybchenko  */
257b97bf1caSAndrew Rybchenko #define	EF100_EV_BATCH	8
258b97bf1caSAndrew Rybchenko 
259b97bf1caSAndrew Rybchenko /*
260b97bf1caSAndrew Rybchenko  * Check if event is present.
261b97bf1caSAndrew Rybchenko  *
262b97bf1caSAndrew Rybchenko  * Riverhead EvQs use a phase bit to indicate the presence of valid events,
263b97bf1caSAndrew Rybchenko  * by flipping the phase bit on each wrap of the write index.
264b97bf1caSAndrew Rybchenko  */
265b97bf1caSAndrew Rybchenko #define	EF100_EV_PRESENT(_qword, _phase_bit)				\
266b97bf1caSAndrew Rybchenko 	(EFX_QWORD_FIELD((_qword), ESF_GZ_EV_EVQ_PHASE) == _phase_bit)
267b97bf1caSAndrew Rybchenko 
268b97bf1caSAndrew Rybchenko 			void
rhead_ev_qpoll(__in efx_evq_t * eep,__inout unsigned int * countp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)269b97bf1caSAndrew Rybchenko rhead_ev_qpoll(
270b97bf1caSAndrew Rybchenko 	__in		efx_evq_t *eep,
271b97bf1caSAndrew Rybchenko 	__inout		unsigned int *countp,
272b97bf1caSAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
273b97bf1caSAndrew Rybchenko 	__in_opt	void *arg)
274b97bf1caSAndrew Rybchenko {
275b97bf1caSAndrew Rybchenko 	efx_qword_t ev[EF100_EV_BATCH];
276b97bf1caSAndrew Rybchenko 	unsigned int batch;
277b97bf1caSAndrew Rybchenko 	unsigned int phase_bit;
278b97bf1caSAndrew Rybchenko 	unsigned int total;
279b97bf1caSAndrew Rybchenko 	unsigned int count;
280b97bf1caSAndrew Rybchenko 	unsigned int index;
281b97bf1caSAndrew Rybchenko 	size_t offset;
282b97bf1caSAndrew Rybchenko 
2831a4448beSAndy Moreton #if EFSYS_OPT_EV_EXTENDED_WIDTH
2841a4448beSAndy Moreton 	if (eep->ee_flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) {
2851a4448beSAndy Moreton 		rhead_ev_ew_qpoll(eep, countp, eecp, arg);
2861a4448beSAndy Moreton 		return;
2871a4448beSAndy Moreton 	}
2881a4448beSAndy Moreton #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
2891a4448beSAndy Moreton 
290b97bf1caSAndrew Rybchenko 	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
291b97bf1caSAndrew Rybchenko 	EFSYS_ASSERT(countp != NULL);
292b97bf1caSAndrew Rybchenko 	EFSYS_ASSERT(eecp != NULL);
293b97bf1caSAndrew Rybchenko 
294b97bf1caSAndrew Rybchenko 	count = *countp;
295b97bf1caSAndrew Rybchenko 	do {
296b97bf1caSAndrew Rybchenko 		/* Read up until the end of the batch period */
297b97bf1caSAndrew Rybchenko 		batch = EF100_EV_BATCH - (count & (EF100_EV_BATCH - 1));
298b97bf1caSAndrew Rybchenko 		phase_bit = (count & (eep->ee_mask + 1)) != 0;
299b97bf1caSAndrew Rybchenko 		offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
300b97bf1caSAndrew Rybchenko 		for (total = 0; total < batch; ++total) {
301b97bf1caSAndrew Rybchenko 			EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total]));
302b97bf1caSAndrew Rybchenko 
303b97bf1caSAndrew Rybchenko 			if (!EF100_EV_PRESENT(ev[total], phase_bit))
304b97bf1caSAndrew Rybchenko 				break;
305b97bf1caSAndrew Rybchenko 
306b97bf1caSAndrew Rybchenko 			EFSYS_PROBE3(event, unsigned int, eep->ee_index,
307b97bf1caSAndrew Rybchenko 			    uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1),
308b97bf1caSAndrew Rybchenko 			    uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0));
309b97bf1caSAndrew Rybchenko 
310b97bf1caSAndrew Rybchenko 			offset += sizeof (efx_qword_t);
311b97bf1caSAndrew Rybchenko 		}
312b97bf1caSAndrew Rybchenko 
313b97bf1caSAndrew Rybchenko 		/* Process the batch of events */
314b97bf1caSAndrew Rybchenko 		for (index = 0; index < total; ++index) {
315b97bf1caSAndrew Rybchenko 			boolean_t should_abort;
316b97bf1caSAndrew Rybchenko 
317b97bf1caSAndrew Rybchenko 			EFX_EV_QSTAT_INCR(eep, EV_ALL);
318b97bf1caSAndrew Rybchenko 
319e10a178aSAndy Moreton 			should_abort =
320e10a178aSAndy Moreton 			    rhead_ev_dispatch(eep, &(ev[index]), eecp, arg);
321b97bf1caSAndrew Rybchenko 
322b97bf1caSAndrew Rybchenko 			if (should_abort) {
323b97bf1caSAndrew Rybchenko 				/* Ignore subsequent events */
324b97bf1caSAndrew Rybchenko 				total = index + 1;
325b97bf1caSAndrew Rybchenko 
326b97bf1caSAndrew Rybchenko 				/*
327b97bf1caSAndrew Rybchenko 				 * Poison batch to ensure the outer
328b97bf1caSAndrew Rybchenko 				 * loop is broken out of.
329b97bf1caSAndrew Rybchenko 				 */
330b97bf1caSAndrew Rybchenko 				EFSYS_ASSERT(batch <= EF100_EV_BATCH);
331b97bf1caSAndrew Rybchenko 				batch += (EF100_EV_BATCH << 1);
332b97bf1caSAndrew Rybchenko 				EFSYS_ASSERT(total != batch);
333b97bf1caSAndrew Rybchenko 				break;
334b97bf1caSAndrew Rybchenko 			}
335b97bf1caSAndrew Rybchenko 		}
336b97bf1caSAndrew Rybchenko 
337b97bf1caSAndrew Rybchenko 		/*
338b97bf1caSAndrew Rybchenko 		 * There is no necessity to clear processed events since
339b97bf1caSAndrew Rybchenko 		 * phase bit which is flipping on each write index wrap
340b97bf1caSAndrew Rybchenko 		 * is used for event presence indication.
341b97bf1caSAndrew Rybchenko 		 */
342b97bf1caSAndrew Rybchenko 
343b97bf1caSAndrew Rybchenko 		count += total;
344b97bf1caSAndrew Rybchenko 
345b97bf1caSAndrew Rybchenko 	} while (total == batch);
346b97bf1caSAndrew Rybchenko 
347b97bf1caSAndrew Rybchenko 	*countp = count;
348b97bf1caSAndrew Rybchenko }
349b97bf1caSAndrew Rybchenko 
3501a4448beSAndy Moreton #if EFSYS_OPT_EV_EXTENDED_WIDTH
3511a4448beSAndy Moreton static			boolean_t
rhead_ev_ew_dispatch(__in efx_evq_t * eep,__in efx_xword_t * eventp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)3521a4448beSAndy Moreton rhead_ev_ew_dispatch(
3531a4448beSAndy Moreton 	__in		efx_evq_t *eep,
3541a4448beSAndy Moreton 	__in		efx_xword_t *eventp,
3551a4448beSAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
3561a4448beSAndy Moreton 	__in_opt	void *arg)
3571a4448beSAndy Moreton {
3581a4448beSAndy Moreton 	boolean_t should_abort;
3591a4448beSAndy Moreton 	uint32_t code;
3601a4448beSAndy Moreton 
3611a4448beSAndy Moreton 	EFSYS_ASSERT((eep->ee_flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) != 0);
3621a4448beSAndy Moreton 
3631a4448beSAndy Moreton 	code = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_256_EV32_TYPE);
3641a4448beSAndy Moreton 	switch (code) {
365e10a178aSAndy Moreton 	case ESE_GZ_EF100_EVEW_64BIT:
366e10a178aSAndy Moreton 		/* NOTE: ignore phase bit in encapsulated 64bit event. */
367e10a178aSAndy Moreton 		should_abort =
368e10a178aSAndy Moreton 		    rhead_ev_dispatch(eep, &eventp->ex_qword[0], eecp, arg);
369e10a178aSAndy Moreton 		break;
370e10a178aSAndy Moreton 
371ea42cae4SAndy Moreton #if EFSYS_OPT_DESC_PROXY
372ea42cae4SAndy Moreton 	case ESE_GZ_EF100_EVEW_TXQ_DESC:
373ea42cae4SAndy Moreton 		should_abort = eep->ee_ew_txq_desc(eep, eventp, eecp, arg);
374ea42cae4SAndy Moreton 		break;
375ea42cae4SAndy Moreton 
376ea42cae4SAndy Moreton 	case ESE_GZ_EF100_EVEW_VIRTQ_DESC:
377ea42cae4SAndy Moreton 		should_abort = eep->ee_ew_virtq_desc(eep, eventp, eecp, arg);
378ea42cae4SAndy Moreton 		break;
379ea42cae4SAndy Moreton #endif /* EFSYS_OPT_DESC_PROXY */
380ea42cae4SAndy Moreton 
3811a4448beSAndy Moreton 	default:
3821a4448beSAndy Moreton 		/* Omit currently unused reserved bits from the probe. */
3831a4448beSAndy Moreton 		EFSYS_PROBE7(ew_bad_event, unsigned int, eep->ee_index,
3841a4448beSAndy Moreton 		    uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_7),
3851a4448beSAndy Moreton 		    uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_4),
3861a4448beSAndy Moreton 		    uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_3),
3871a4448beSAndy Moreton 		    uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_2),
3881a4448beSAndy Moreton 		    uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_1),
3891a4448beSAndy Moreton 		    uint32_t, EFX_XWORD_FIELD(*eventp, EFX_DWORD_0));
3901a4448beSAndy Moreton 
3911a4448beSAndy Moreton 		EFSYS_ASSERT(eecp->eec_exception != NULL);
3921a4448beSAndy Moreton 		(void) eecp->eec_exception(arg, EFX_EXCEPTION_EV_ERROR, code);
3931a4448beSAndy Moreton 		should_abort = B_TRUE;
3941a4448beSAndy Moreton 	}
3951a4448beSAndy Moreton 
3961a4448beSAndy Moreton 	return (should_abort);
3971a4448beSAndy Moreton }
3981a4448beSAndy Moreton 
3991a4448beSAndy Moreton /*
4001a4448beSAndy Moreton  * Poll extended width event queue. Size of the batch is equal to cache line
4011a4448beSAndy Moreton  * size divided by event size.
4021a4448beSAndy Moreton  */
4031a4448beSAndy Moreton #define	EF100_EV_EW_BATCH	2
4041a4448beSAndy Moreton 
4051a4448beSAndy Moreton /*
4061a4448beSAndy Moreton  * Check if event is present.
4071a4448beSAndy Moreton  *
4081a4448beSAndy Moreton  * Riverhead EvQs use a phase bit to indicate the presence of valid events,
4091a4448beSAndy Moreton  * by flipping the phase bit on each wrap of the write index.
4101a4448beSAndy Moreton  */
4111a4448beSAndy Moreton #define	EF100_EV_EW_PRESENT(_xword, _phase_bit)				\
4121a4448beSAndy Moreton 	(EFX_XWORD_FIELD((_xword), ESF_GZ_EV_256_EV32_PHASE) == (_phase_bit))
4131a4448beSAndy Moreton 
4141a4448beSAndy Moreton static			void
rhead_ev_ew_qpoll(__in efx_evq_t * eep,__inout unsigned int * countp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)4151a4448beSAndy Moreton rhead_ev_ew_qpoll(
4161a4448beSAndy Moreton 	__in		efx_evq_t *eep,
4171a4448beSAndy Moreton 	__inout		unsigned int *countp,
4181a4448beSAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
4191a4448beSAndy Moreton 	__in_opt	void *arg)
4201a4448beSAndy Moreton {
4211a4448beSAndy Moreton 	efx_xword_t ev[EF100_EV_EW_BATCH];
4221a4448beSAndy Moreton 	unsigned int batch;
4231a4448beSAndy Moreton 	unsigned int phase_bit;
4241a4448beSAndy Moreton 	unsigned int total;
4251a4448beSAndy Moreton 	unsigned int count;
4261a4448beSAndy Moreton 	unsigned int index;
4271a4448beSAndy Moreton 	size_t offset;
4281a4448beSAndy Moreton 
4291a4448beSAndy Moreton 	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
4301a4448beSAndy Moreton 	EFSYS_ASSERT((eep->ee_flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) != 0);
4311a4448beSAndy Moreton 	EFSYS_ASSERT(countp != NULL);
4321a4448beSAndy Moreton 	EFSYS_ASSERT(eecp != NULL);
4331a4448beSAndy Moreton 
4341a4448beSAndy Moreton 	count = *countp;
4351a4448beSAndy Moreton 	do {
4361a4448beSAndy Moreton 		/* Read up until the end of the batch period */
4371a4448beSAndy Moreton 		batch = EF100_EV_EW_BATCH - (count & (EF100_EV_EW_BATCH - 1));
4381a4448beSAndy Moreton 		phase_bit = (count & (eep->ee_mask + 1)) != 0;
4391a4448beSAndy Moreton 		offset = (count & eep->ee_mask) * sizeof (efx_xword_t);
4401a4448beSAndy Moreton 		for (total = 0; total < batch; ++total) {
4411a4448beSAndy Moreton 			EFSYS_MEM_READX(eep->ee_esmp, offset, &(ev[total]));
4421a4448beSAndy Moreton 
4431a4448beSAndy Moreton 			if (!EF100_EV_EW_PRESENT(ev[total], phase_bit))
4441a4448beSAndy Moreton 				break;
4451a4448beSAndy Moreton 
4461a4448beSAndy Moreton 			/* Omit unused reserved bits from the probe. */
4471a4448beSAndy Moreton 			EFSYS_PROBE7(ew_event, unsigned int, eep->ee_index,
4481a4448beSAndy Moreton 			    uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_7),
4491a4448beSAndy Moreton 			    uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_4),
4501a4448beSAndy Moreton 			    uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_3),
4511a4448beSAndy Moreton 			    uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_2),
4521a4448beSAndy Moreton 			    uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_1),
4531a4448beSAndy Moreton 			    uint32_t, EFX_XWORD_FIELD(ev[total], EFX_DWORD_0));
4541a4448beSAndy Moreton 
4551a4448beSAndy Moreton 			offset += sizeof (efx_xword_t);
4561a4448beSAndy Moreton 		}
4571a4448beSAndy Moreton 
4581a4448beSAndy Moreton 		/* Process the batch of events */
4591a4448beSAndy Moreton 		for (index = 0; index < total; ++index) {
4601a4448beSAndy Moreton 			boolean_t should_abort;
4611a4448beSAndy Moreton 
4621a4448beSAndy Moreton 			EFX_EV_QSTAT_INCR(eep, EV_ALL);
4631a4448beSAndy Moreton 
4641a4448beSAndy Moreton 			should_abort =
4651a4448beSAndy Moreton 			    rhead_ev_ew_dispatch(eep, &(ev[index]), eecp, arg);
4661a4448beSAndy Moreton 
4671a4448beSAndy Moreton 			if (should_abort) {
4681a4448beSAndy Moreton 				/* Ignore subsequent events */
4691a4448beSAndy Moreton 				total = index + 1;
4701a4448beSAndy Moreton 
4711a4448beSAndy Moreton 				/*
4721a4448beSAndy Moreton 				 * Poison batch to ensure the outer
4731a4448beSAndy Moreton 				 * loop is broken out of.
4741a4448beSAndy Moreton 				 */
4751a4448beSAndy Moreton 				EFSYS_ASSERT(batch <= EF100_EV_EW_BATCH);
4761a4448beSAndy Moreton 				batch += (EF100_EV_EW_BATCH << 1);
4771a4448beSAndy Moreton 				EFSYS_ASSERT(total != batch);
4781a4448beSAndy Moreton 				break;
4791a4448beSAndy Moreton 			}
4801a4448beSAndy Moreton 		}
4811a4448beSAndy Moreton 
4821a4448beSAndy Moreton 		/*
4831a4448beSAndy Moreton 		 * There is no necessity to clear processed events since
4841a4448beSAndy Moreton 		 * phase bit which is flipping on each write index wrap
4851a4448beSAndy Moreton 		 * is used for event presence indication.
4861a4448beSAndy Moreton 		 */
4871a4448beSAndy Moreton 
4881a4448beSAndy Moreton 		count += total;
4891a4448beSAndy Moreton 
4901a4448beSAndy Moreton 	} while (total == batch);
4911a4448beSAndy Moreton 
4921a4448beSAndy Moreton 	*countp = count;
4931a4448beSAndy Moreton }
4941a4448beSAndy Moreton #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */
4951a4448beSAndy Moreton 
4961a4448beSAndy Moreton 
497b97bf1caSAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_ev_qmoderate(__in efx_evq_t * eep,__in unsigned int us)498b97bf1caSAndrew Rybchenko rhead_ev_qmoderate(
499b97bf1caSAndrew Rybchenko 	__in		efx_evq_t *eep,
500b97bf1caSAndrew Rybchenko 	__in		unsigned int us)
501b97bf1caSAndrew Rybchenko {
502b97bf1caSAndrew Rybchenko 	_NOTE(ARGUNUSED(eep, us))
503b97bf1caSAndrew Rybchenko 
504b97bf1caSAndrew Rybchenko 	return (ENOTSUP);
505b97bf1caSAndrew Rybchenko }
506b97bf1caSAndrew Rybchenko 
507b97bf1caSAndrew Rybchenko 
508b97bf1caSAndrew Rybchenko #if EFSYS_OPT_QSTATS
509b97bf1caSAndrew Rybchenko 			void
rhead_ev_qstats_update(__in efx_evq_t * eep,__inout_ecount (EV_NQSTATS)efsys_stat_t * stat)510b97bf1caSAndrew Rybchenko rhead_ev_qstats_update(
511b97bf1caSAndrew Rybchenko 	__in				efx_evq_t *eep,
512b97bf1caSAndrew Rybchenko 	__inout_ecount(EV_NQSTATS)	efsys_stat_t *stat)
513b97bf1caSAndrew Rybchenko {
514b97bf1caSAndrew Rybchenko 	unsigned int id;
515b97bf1caSAndrew Rybchenko 
516b97bf1caSAndrew Rybchenko 	for (id = 0; id < EV_NQSTATS; id++) {
517b97bf1caSAndrew Rybchenko 		efsys_stat_t *essp = &stat[id];
518b97bf1caSAndrew Rybchenko 
519b97bf1caSAndrew Rybchenko 		EFSYS_STAT_INCR(essp, eep->ee_stat[id]);
520b97bf1caSAndrew Rybchenko 		eep->ee_stat[id] = 0;
521b97bf1caSAndrew Rybchenko 	}
522b97bf1caSAndrew Rybchenko }
523b97bf1caSAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */
524b97bf1caSAndrew Rybchenko 
5259edb8ee3SAndrew Rybchenko static	__checkReturn	boolean_t
rhead_ev_rx_packets(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)52617580779SAndrew Rybchenko rhead_ev_rx_packets(
52717580779SAndrew Rybchenko 	__in		efx_evq_t *eep,
52817580779SAndrew Rybchenko 	__in		efx_qword_t *eqp,
52917580779SAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
53017580779SAndrew Rybchenko 	__in_opt	void *arg)
53117580779SAndrew Rybchenko {
53217580779SAndrew Rybchenko 	efx_nic_t *enp = eep->ee_enp;
53317580779SAndrew Rybchenko 	uint32_t label;
53417580779SAndrew Rybchenko 	uint32_t num_packets;
53517580779SAndrew Rybchenko 	boolean_t should_abort;
53617580779SAndrew Rybchenko 
53717580779SAndrew Rybchenko 	EFX_EV_QSTAT_INCR(eep, EV_RX);
53817580779SAndrew Rybchenko 
53917580779SAndrew Rybchenko 	/* Discard events after RXQ/TXQ errors, or hardware not available */
54017580779SAndrew Rybchenko 	if (enp->en_reset_flags &
54117580779SAndrew Rybchenko 	    (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
54217580779SAndrew Rybchenko 		return (B_FALSE);
54317580779SAndrew Rybchenko 
54417580779SAndrew Rybchenko 	label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_Q_LABEL);
54517580779SAndrew Rybchenko 
54617580779SAndrew Rybchenko 	/*
54717580779SAndrew Rybchenko 	 * On EF100 the EV_RX event reports the number of received
54817580779SAndrew Rybchenko 	 * packets (unlike EF10 which reports a descriptor index).
54917580779SAndrew Rybchenko 	 * The client driver is responsible for maintaining the Rx
55017580779SAndrew Rybchenko 	 * descriptor index, and computing how many descriptors are
55117580779SAndrew Rybchenko 	 * occupied by each received packet (based on the Rx buffer size
55217580779SAndrew Rybchenko 	 * and the packet length from the Rx prefix).
55317580779SAndrew Rybchenko 	 */
55417580779SAndrew Rybchenko 	num_packets = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_NUM_PKT);
55517580779SAndrew Rybchenko 
55617580779SAndrew Rybchenko 	/*
55717580779SAndrew Rybchenko 	 * The receive event may indicate more than one packet, and so
55817580779SAndrew Rybchenko 	 * does not contain the packet length. Read the packet length
55917580779SAndrew Rybchenko 	 * from the prefix when handling each packet.
56017580779SAndrew Rybchenko 	 */
56117580779SAndrew Rybchenko 	EFSYS_ASSERT(eecp->eec_rx_packets != NULL);
56217580779SAndrew Rybchenko 	should_abort = eecp->eec_rx_packets(arg, label, num_packets,
56317580779SAndrew Rybchenko 	    EFX_PKT_PREFIX_LEN);
56417580779SAndrew Rybchenko 
56517580779SAndrew Rybchenko 	return (should_abort);
56617580779SAndrew Rybchenko }
56717580779SAndrew Rybchenko 
56817580779SAndrew Rybchenko static	__checkReturn	boolean_t
rhead_ev_tx_completion(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)56996a8519dSAndrew Rybchenko rhead_ev_tx_completion(
57096a8519dSAndrew Rybchenko 	__in		efx_evq_t *eep,
57196a8519dSAndrew Rybchenko 	__in		efx_qword_t *eqp,
57296a8519dSAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
57396a8519dSAndrew Rybchenko 	__in_opt	void *arg)
57496a8519dSAndrew Rybchenko {
57596a8519dSAndrew Rybchenko 	efx_nic_t *enp = eep->ee_enp;
57696a8519dSAndrew Rybchenko 	uint32_t num_descs;
57796a8519dSAndrew Rybchenko 	uint32_t label;
57896a8519dSAndrew Rybchenko 	boolean_t should_abort;
57996a8519dSAndrew Rybchenko 
58096a8519dSAndrew Rybchenko 	EFX_EV_QSTAT_INCR(eep, EV_TX);
58196a8519dSAndrew Rybchenko 
58296a8519dSAndrew Rybchenko 	/* Discard events after RXQ/TXQ errors, or hardware not available */
58396a8519dSAndrew Rybchenko 	if (enp->en_reset_flags &
58496a8519dSAndrew Rybchenko 	    (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
58596a8519dSAndrew Rybchenko 		return (B_FALSE);
58696a8519dSAndrew Rybchenko 
58796a8519dSAndrew Rybchenko 	label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_TXCMPL_Q_LABEL);
58896a8519dSAndrew Rybchenko 
58996a8519dSAndrew Rybchenko 	/*
59096a8519dSAndrew Rybchenko 	 * On EF100 the EV_TX event reports the number of completed Tx
59196a8519dSAndrew Rybchenko 	 * descriptors (on EF10, the event reports the low bits of the
59296a8519dSAndrew Rybchenko 	 * index of the last completed descriptor).
59396a8519dSAndrew Rybchenko 	 * The client driver completion callback will compute the
59496a8519dSAndrew Rybchenko 	 * descriptor index, so that is not needed here.
59596a8519dSAndrew Rybchenko 	 */
59696a8519dSAndrew Rybchenko 	num_descs = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_TXCMPL_NUM_DESC);
59796a8519dSAndrew Rybchenko 
59896a8519dSAndrew Rybchenko 	EFSYS_PROBE2(tx_ndescs, uint32_t, label, unsigned int, num_descs);
59996a8519dSAndrew Rybchenko 
60096a8519dSAndrew Rybchenko 	EFSYS_ASSERT(eecp->eec_tx_ndescs != NULL);
60196a8519dSAndrew Rybchenko 	should_abort = eecp->eec_tx_ndescs(arg, label, num_descs);
60296a8519dSAndrew Rybchenko 
60396a8519dSAndrew Rybchenko 	return (should_abort);
60496a8519dSAndrew Rybchenko }
60596a8519dSAndrew Rybchenko 
60696a8519dSAndrew Rybchenko static	__checkReturn	boolean_t
rhead_ev_mcdi(__in efx_evq_t * eep,__in efx_qword_t * eqp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)6079edb8ee3SAndrew Rybchenko rhead_ev_mcdi(
6089edb8ee3SAndrew Rybchenko 	__in		efx_evq_t *eep,
6099edb8ee3SAndrew Rybchenko 	__in		efx_qword_t *eqp,
6109edb8ee3SAndrew Rybchenko 	__in		const efx_ev_callbacks_t *eecp,
6119edb8ee3SAndrew Rybchenko 	__in_opt	void *arg)
6129edb8ee3SAndrew Rybchenko {
6139edb8ee3SAndrew Rybchenko 	boolean_t ret;
6149edb8ee3SAndrew Rybchenko 
6159edb8ee3SAndrew Rybchenko 	/*
6169edb8ee3SAndrew Rybchenko 	 * Event format was changed post Riverhead R1 and now
6179edb8ee3SAndrew Rybchenko 	 * MCDI event layout on EF100 is exactly the same as on EF10
6189edb8ee3SAndrew Rybchenko 	 * except added QDMA phase bit which is unused on EF10.
6199edb8ee3SAndrew Rybchenko 	 */
6209edb8ee3SAndrew Rybchenko 	ret = ef10_ev_mcdi(eep, eqp, eecp, arg);
6219edb8ee3SAndrew Rybchenko 
6229edb8ee3SAndrew Rybchenko 	return (ret);
6239edb8ee3SAndrew Rybchenko }
6249edb8ee3SAndrew Rybchenko 
625ea42cae4SAndy Moreton #if EFSYS_OPT_DESC_PROXY
626ea42cae4SAndy Moreton static			boolean_t
rhead_ev_ew_txq_desc(__in efx_evq_t * eep,__in efx_xword_t * eventp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)627ea42cae4SAndy Moreton rhead_ev_ew_txq_desc(
628ea42cae4SAndy Moreton 	__in		efx_evq_t *eep,
629ea42cae4SAndy Moreton 	__in		efx_xword_t *eventp,
630ea42cae4SAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
631ea42cae4SAndy Moreton 	__in_opt	void *arg)
632ea42cae4SAndy Moreton {
633ea42cae4SAndy Moreton 	efx_oword_t txq_desc;
634ea42cae4SAndy Moreton 	uint16_t vi_id;
635ea42cae4SAndy Moreton 	boolean_t should_abort;
636ea42cae4SAndy Moreton 
637ea42cae4SAndy Moreton 	_NOTE(ARGUNUSED(eep))
638ea42cae4SAndy Moreton 
639ea42cae4SAndy Moreton 	vi_id = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_TXQ_DP_VI_ID);
640ea42cae4SAndy Moreton 
641ea42cae4SAndy Moreton 	/*
642ea42cae4SAndy Moreton 	 * NOTE: This is the raw descriptor data, and has not been converted
643ea42cae4SAndy Moreton 	 * to host endian. The handler callback must use the EFX_OWORD macros
644ea42cae4SAndy Moreton 	 * to extract the descriptor fields as host endian values.
645ea42cae4SAndy Moreton 	 */
646ea42cae4SAndy Moreton 	txq_desc = eventp->ex_oword[0];
647ea42cae4SAndy Moreton 
648ea42cae4SAndy Moreton 	EFSYS_ASSERT(eecp->eec_desc_proxy_txq_desc != NULL);
649ea42cae4SAndy Moreton 	should_abort = eecp->eec_desc_proxy_txq_desc(arg, vi_id, txq_desc);
650ea42cae4SAndy Moreton 
651ea42cae4SAndy Moreton 	return (should_abort);
652ea42cae4SAndy Moreton }
653ea42cae4SAndy Moreton #endif /* EFSYS_OPT_DESC_PROXY */
654ea42cae4SAndy Moreton 
655ea42cae4SAndy Moreton 
656ea42cae4SAndy Moreton #if EFSYS_OPT_DESC_PROXY
657ea42cae4SAndy Moreton static			boolean_t
rhead_ev_ew_virtq_desc(__in efx_evq_t * eep,__in efx_xword_t * eventp,__in const efx_ev_callbacks_t * eecp,__in_opt void * arg)658ea42cae4SAndy Moreton rhead_ev_ew_virtq_desc(
659ea42cae4SAndy Moreton 	__in		efx_evq_t *eep,
660ea42cae4SAndy Moreton 	__in		efx_xword_t *eventp,
661ea42cae4SAndy Moreton 	__in		const efx_ev_callbacks_t *eecp,
662ea42cae4SAndy Moreton 	__in_opt	void *arg)
663ea42cae4SAndy Moreton {
664ea42cae4SAndy Moreton 	efx_oword_t virtq_desc;
665ea42cae4SAndy Moreton 	uint16_t vi_id;
666ea42cae4SAndy Moreton 	uint16_t avail;
667ea42cae4SAndy Moreton 	boolean_t should_abort;
668ea42cae4SAndy Moreton 
669ea42cae4SAndy Moreton 	_NOTE(ARGUNUSED(eep))
670ea42cae4SAndy Moreton 
671ea42cae4SAndy Moreton 	vi_id = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_VQ_DP_VI_ID);
672ea42cae4SAndy Moreton 	avail = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_VQ_DP_AVAIL_ENTRY);
673ea42cae4SAndy Moreton 
674ea42cae4SAndy Moreton 	/*
675ea42cae4SAndy Moreton 	 * NOTE: This is the raw descriptor data, and has not been converted
676ea42cae4SAndy Moreton 	 * to host endian. The handler callback must use the EFX_OWORD macros
677ea42cae4SAndy Moreton 	 * to extract the descriptor fields as host endian values.
678ea42cae4SAndy Moreton 	 */
679ea42cae4SAndy Moreton 	virtq_desc = eventp->ex_oword[0];
680ea42cae4SAndy Moreton 
681ea42cae4SAndy Moreton 	EFSYS_ASSERT(eecp->eec_desc_proxy_virtq_desc != NULL);
682ea42cae4SAndy Moreton 	should_abort =
683ea42cae4SAndy Moreton 	    eecp->eec_desc_proxy_virtq_desc(arg, vi_id, avail, virtq_desc);
684ea42cae4SAndy Moreton 
685ea42cae4SAndy Moreton 	return (should_abort);
686ea42cae4SAndy Moreton }
687ea42cae4SAndy Moreton #endif /* EFSYS_OPT_DESC_PROXY */
688ea42cae4SAndy Moreton 
689b97bf1caSAndrew Rybchenko #endif	/* EFSYS_OPT_RIVERHEAD */
690