[v3,35/60] common/sfc_efx/base: handle Rx events for Riverhead
diff mbox series

Message ID 1600949555-28043-36-git-send-email-arybchenko@solarflare.com
State Accepted
Delegated to: Ferruh Yigit
Headers show
Series
  • common/sfc_efx: support Riverhead NIC family
Related show

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Andrew Rybchenko Sept. 24, 2020, 12:12 p.m. UTC
Rx event on Riverhead provides a number of received packets and
no classification/offloads information is available Rx event.

Introduce a new event callback to be implemented by drivers.
The callback provides information about the number of completed
packets. libefx-based drivers should implement the new callback
for Riverhead and keep the old one for Siena and EF10 NICs.
The new callback may be used for Medford2 NO_CONT_EV Rx mode
support.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  8 ++++
 drivers/common/sfc_efx/base/rhead_ev.c | 56 +++++++++++++++++++++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 2c49280a43..983b723145 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -2277,6 +2277,13 @@  typedef	__checkReturn	boolean_t
 	__in		uint32_t size,
 	__in		uint16_t flags);
 
+typedef	__checkReturn	boolean_t
+(*efx_rx_packets_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label,
+	__in		unsigned int num_packets,
+	__in		uint32_t flags);
+
 #if EFSYS_OPT_RX_PACKED_STREAM || EFSYS_OPT_RX_ES_SUPER_BUFFER
 
 /*
@@ -2394,6 +2401,7 @@  typedef __checkReturn	boolean_t
 typedef struct efx_ev_callbacks_s {
 	efx_initialized_ev_t		eec_initialized;
 	efx_rx_ev_t			eec_rx;
+	efx_rx_packets_ev_t		eec_rx_packets;
 #if EFSYS_OPT_RX_PACKED_STREAM || EFSYS_OPT_RX_ES_SUPER_BUFFER
 	efx_rx_ps_ev_t			eec_rx_ps;
 #endif
diff --git a/drivers/common/sfc_efx/base/rhead_ev.c b/drivers/common/sfc_efx/base/rhead_ev.c
index 6113cc9cf3..44a79e2e5d 100644
--- a/drivers/common/sfc_efx/base/rhead_ev.c
+++ b/drivers/common/sfc_efx/base/rhead_ev.c
@@ -16,6 +16,13 @@ 
  */
 #define	EFX_RHEAD_ALWAYS_INTERRUPTING_EVQ_INDEX	(0)
 
+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);
+
 
 static	__checkReturn	boolean_t
 rhead_ev_mcdi(
@@ -58,7 +65,7 @@  rhead_ev_qcreate(
 	_NOTE(ARGUNUSED(id))	/* buftbl id managed by MC */
 
 	/* Set up the handler table */
-	eep->ee_rx	= NULL; /* FIXME */
+	eep->ee_rx	= rhead_ev_rx_packets;
 	eep->ee_tx	= NULL; /* FIXME */
 	eep->ee_driver	= NULL; /* FIXME */
 	eep->ee_drv_gen	= NULL; /* FIXME */
@@ -201,6 +208,10 @@  rhead_ev_qpoll(
 
 			code = EFX_QWORD_FIELD(ev[index], ESF_GZ_E_TYPE);
 			switch (code) {
+			case ESE_GZ_EF100_EV_RX_PKTS:
+				should_abort = eep->ee_rx(eep,
+				    &(ev[index]), eecp, arg);
+				break;
 			case ESE_GZ_EF100_EV_MCDI:
 				should_abort = eep->ee_mcdi(eep,
 				    &(ev[index]), eecp, arg);
@@ -274,6 +285,49 @@  rhead_ev_qstats_update(
 }
 #endif /* EFSYS_OPT_QSTATS */
 
+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)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	uint32_t label;
+	uint32_t num_packets;
+	boolean_t should_abort;
+
+	EFX_EV_QSTAT_INCR(eep, EV_RX);
+
+	/* Discard events after RXQ/TXQ errors, or hardware not available */
+	if (enp->en_reset_flags &
+	    (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR | EFX_RESET_HW_UNAVAIL))
+		return (B_FALSE);
+
+	label = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_Q_LABEL);
+
+	/*
+	 * On EF100 the EV_RX event reports the number of received
+	 * packets (unlike EF10 which reports a descriptor index).
+	 * The client driver is responsible for maintaining the Rx
+	 * descriptor index, and computing how many descriptors are
+	 * occupied by each received packet (based on the Rx buffer size
+	 * and the packet length from the Rx prefix).
+	 */
+	num_packets = EFX_QWORD_FIELD(*eqp, ESF_GZ_EV_RXPKTS_NUM_PKT);
+
+	/*
+	 * The receive event may indicate more than one packet, and so
+	 * does not contain the packet length. Read the packet length
+	 * from the prefix when handling each packet.
+	 */
+	EFSYS_ASSERT(eecp->eec_rx_packets != NULL);
+	should_abort = eecp->eec_rx_packets(arg, label, num_packets,
+	    EFX_PKT_PREFIX_LEN);
+
+	return (should_abort);
+}
+
 static	__checkReturn	boolean_t
 rhead_ev_mcdi(
 	__in		efx_evq_t *eep,