[v3,56/60] common/sfc_efx/base: support creation of extended width EvQ
diff mbox series

Message ID 1600949555-28043-57-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
From: Andy Moreton <amoreton@xilinx.com>

Add a flag to request an extended width event queue, and
check that the supplied buffer is large enough to hold the
event queue descriptors.

Signed-off-by: Andy Moreton <amoreton@xilinx.com>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/common/sfc_efx/base/ef10_ev.c    |  2 +
 drivers/common/sfc_efx/base/ef10_nic.c   | 18 +++++++-
 drivers/common/sfc_efx/base/efx.h        | 12 +++++-
 drivers/common/sfc_efx/base/efx_ev.c     | 53 ++++++++++++++++++++----
 drivers/common/sfc_efx/base/efx_mcdi.c   | 20 +++++++--
 drivers/common/sfc_efx/base/rhead_ev.c   | 19 ++++++++-
 drivers/common/sfc_efx/base/rhead_impl.h |  4 ++
 drivers/common/sfc_efx/base/rhead_nic.c  |  6 +++
 drivers/net/sfc/sfc_ev.c                 |  6 +--
 9 files changed, 120 insertions(+), 20 deletions(-)

Patch
diff mbox series

diff --git a/drivers/common/sfc_efx/base/ef10_ev.c b/drivers/common/sfc_efx/base/ef10_ev.c
index aec1c468a4..8e7cc27d63 100644
--- a/drivers/common/sfc_efx/base/ef10_ev.c
+++ b/drivers/common/sfc_efx/base/ef10_ev.c
@@ -127,6 +127,8 @@  ef10_ev_qcreate(
 
 	_NOTE(ARGUNUSED(id))	/* buftbl id managed by MC */
 
+	EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0);
+
 	/*
 	 * NO_CONT_EV mode is only requested from the firmware when creating
 	 * receive queues, but here it needs to be specified at event queue
diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c
index 7a11930242..81cd436424 100644
--- a/drivers/common/sfc_efx/base/ef10_nic.c
+++ b/drivers/common/sfc_efx/base/ef10_nic.c
@@ -1043,14 +1043,14 @@  ef10_get_datapath_caps(
 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 	efx_mcdi_req_t req;
 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN,
-		MC_CMD_GET_CAPABILITIES_V5_OUT_LEN);
+		MC_CMD_GET_CAPABILITIES_V7_OUT_LEN);
 	efx_rc_t rc;
 
 	req.emr_cmd = MC_CMD_GET_CAPABILITIES;
 	req.emr_in_buf = payload;
 	req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
 	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_GET_CAPABILITIES_V5_OUT_LEN;
+	req.emr_out_length = MC_CMD_GET_CAPABILITIES_V7_OUT_LEN;
 
 	efx_mcdi_execute_quiet(enp, &req);
 
@@ -1073,6 +1073,11 @@  ef10_get_datapath_caps(
 	    (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V2_OUT_FLAGS2) &	\
 	    (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN))))
 
+#define	CAP_FLAGS3(_req, _flag)						\
+	(((_req).emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V7_OUT_LEN) && \
+	    (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V7_OUT_FLAGS3) &	\
+	    (1u << (MC_CMD_GET_CAPABILITIES_V7_OUT_ ## _flag ## _LBN))))
+
 	/* Check if RXDP firmware inserts 14 byte prefix */
 	if (CAP_FLAGS1(req, RX_PREFIX_LEN_14))
 		encp->enc_rx_prefix_size = 14;
@@ -1202,6 +1207,15 @@  ef10_get_datapath_caps(
 	else
 		encp->enc_init_evq_v2_supported = B_FALSE;
 
+	/*
+	 * Check if firmware supports extended width event queues, which have
+	 * a different event descriptor layout.
+	 */
+	if (CAP_FLAGS3(req, EXTENDED_WIDTH_EVQS_SUPPORTED))
+		encp->enc_init_evq_extended_width_supported = B_TRUE;
+	else
+		encp->enc_init_evq_extended_width_supported = B_FALSE;
+
 	/*
 	 * Check if the NO_CONT_EV mode for RX events is supported.
 	 */
diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 7e747e6122..ecd16712ba 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1456,6 +1456,7 @@  typedef struct efx_nic_cfg_s {
 	uint32_t		enc_evq_timer_quantum_ns;
 	uint32_t		enc_evq_timer_max_us;
 	uint32_t		enc_clk_mult;
+	uint32_t		enc_ev_ew_desc_size;
 	uint32_t		enc_ev_desc_size;
 	uint32_t		enc_rx_desc_size;
 	uint32_t		enc_tx_desc_size;
@@ -1557,6 +1558,7 @@  typedef struct efx_nic_cfg_s {
 	boolean_t		enc_allow_set_mac_with_installed_filters;
 	boolean_t		enc_enhanced_set_mac_supported;
 	boolean_t		enc_init_evq_v2_supported;
+	boolean_t		enc_init_evq_extended_width_supported;
 	boolean_t		enc_no_cont_ev_mode_supported;
 	boolean_t		enc_init_rxq_with_buffer_size;
 	boolean_t		enc_rx_packed_stream_supported;
@@ -2264,13 +2266,15 @@  LIBEFX_API
 extern	__checkReturn	size_t
 efx_evq_size(
 	__in	const efx_nic_t *enp,
-	__in	unsigned int ndescs);
+	__in	unsigned int ndescs,
+	__in	uint32_t flags);
 
 LIBEFX_API
 extern	__checkReturn	unsigned int
 efx_evq_nbufs(
 	__in	const efx_nic_t *enp,
-	__in	unsigned int ndescs);
+	__in	unsigned int ndescs,
+	__in	uint32_t flags);
 
 #define	EFX_EVQ_FLAGS_TYPE_MASK		(0x3)
 #define	EFX_EVQ_FLAGS_TYPE_AUTO		(0x0)
@@ -2291,6 +2295,10 @@  efx_evq_nbufs(
  */
 #define	EFX_EVQ_FLAGS_NO_CONT_EV	(0x10)
 
+/* Configure EVQ for extended width events (EF100 only) */
+#define	EFX_EVQ_FLAGS_EXTENDED_WIDTH	(0x20)
+
+
 LIBEFX_API
 extern	__checkReturn	efx_rc_t
 efx_ev_qcreate(
diff --git a/drivers/common/sfc_efx/base/efx_ev.c b/drivers/common/sfc_efx/base/efx_ev.c
index 99a7743edb..32e7fff3af 100644
--- a/drivers/common/sfc_efx/base/efx_ev.c
+++ b/drivers/common/sfc_efx/base/efx_ev.c
@@ -201,19 +201,35 @@  efx_ev_init(
 	__checkReturn	size_t
 efx_evq_size(
 	__in	const efx_nic_t *enp,
-	__in	unsigned int ndescs)
+	__in	unsigned int ndescs,
+	__in	uint32_t flags)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	size_t desc_size;
 
-	return (ndescs * encp->enc_ev_desc_size);
+	desc_size = encp->enc_ev_desc_size;
+
+#if EFSYS_OPT_EV_EXTENDED_WIDTH
+	if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH)
+		desc_size = encp->enc_ev_ew_desc_size;
+#else
+	EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0);
+#endif
+
+	return (ndescs * desc_size);
 }
 
 	__checkReturn	unsigned int
 efx_evq_nbufs(
 	__in	const efx_nic_t *enp,
-	__in	unsigned int ndescs)
+	__in	unsigned int ndescs,
+	__in	uint32_t flags)
 {
-	return (EFX_DIV_ROUND_UP(efx_evq_size(enp, ndescs), EFX_BUF_SIZE));
+	size_t size;
+
+	size = efx_evq_size(enp, ndescs, flags);
+
+	return (EFX_DIV_ROUND_UP(size, EFX_BUF_SIZE));
 }
 
 		void
@@ -282,6 +298,13 @@  efx_ev_qcreate(
 		goto fail4;
 	}
 
+	if ((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) &&
+	    (encp->enc_ev_ew_desc_size == 0)) {
+		/* Extended width event descriptors are not supported. */
+		rc = EINVAL;
+		goto fail5;
+	}
+
 	EFSYS_ASSERT(ISP2(encp->enc_evq_max_nevs));
 	EFSYS_ASSERT(ISP2(encp->enc_evq_min_nevs));
 
@@ -289,14 +312,20 @@  efx_ev_qcreate(
 	    ndescs < encp->enc_evq_min_nevs ||
 	    ndescs > encp->enc_evq_max_nevs) {
 		rc = EINVAL;
-		goto fail5;
+		goto fail6;
+	}
+
+	if (EFSYS_MEM_SIZE(esmp) < (ndescs * encp->enc_ev_desc_size)) {
+		/* Buffer too small for event queue descriptors. */
+		rc = EINVAL;
+		goto fail7;
 	}
 
 	/* Allocate an EVQ object */
 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep);
 	if (eep == NULL) {
 		rc = ENOMEM;
-		goto fail6;
+		goto fail8;
 	}
 
 	eep->ee_magic = EFX_EVQ_MAGIC;
@@ -319,16 +348,20 @@  efx_ev_qcreate(
 
 	if ((rc = eevop->eevo_qcreate(enp, index, esmp, ndescs, id, us, flags,
 	    eep)) != 0)
-		goto fail7;
+		goto fail9;
 
 	return (0);
 
-fail7:
-	EFSYS_PROBE(fail7);
+fail9:
+	EFSYS_PROBE(fail9);
 
 	*eepp = NULL;
 	enp->en_ev_qcount--;
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
 fail6:
 	EFSYS_PROBE(fail6);
 fail5:
@@ -1255,6 +1288,8 @@  siena_ev_qcreate(
 
 	_NOTE(ARGUNUSED(esmp))
 
+	EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0);
+
 #if EFSYS_OPT_RX_SCALE
 	if (enp->en_intr.ei_type == EFX_INTR_LINE &&
 	    index >= EFX_MAXRSS_LEGACY) {
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.c b/drivers/common/sfc_efx/base/efx_mcdi.c
index b8e45b458d..ede052a26a 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.c
+++ b/drivers/common/sfc_efx/base/efx_mcdi.c
@@ -2475,6 +2475,7 @@  efx_mcdi_init_evq(
 		MC_CMD_INIT_EVQ_V2_IN_LEN(INIT_EVQ_MAXNBUFS),
 		MC_CMD_INIT_EVQ_V2_OUT_LEN);
 	boolean_t interrupting;
+	int ev_extended_width;
 	int ev_cut_through;
 	int ev_merge;
 	unsigned int evq_type;
@@ -2484,7 +2485,7 @@  efx_mcdi_init_evq(
 	int i;
 	efx_rc_t rc;
 
-	npages = efx_evq_nbufs(enp, nevs);
+	npages = efx_evq_nbufs(enp, nevs, flags);
 	if (npages > INIT_EVQ_MAXNBUFS) {
 		rc = EINVAL;
 		goto fail1;
@@ -2558,14 +2559,27 @@  efx_mcdi_init_evq(
 		}
 	}
 
-	MCDI_IN_POPULATE_DWORD_7(req, INIT_EVQ_V2_IN_FLAGS,
+	/*
+	 * On EF100, extended width event queues have a different event
+	 * descriptor layout and are used to support descriptor proxy queues.
+	 */
+	ev_extended_width = 0;
+#if EFSYS_OPT_EV_EXTENDED_WIDTH
+	if (encp->enc_init_evq_extended_width_supported) {
+		if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH)
+			ev_extended_width = 1;
+	}
+#endif
+
+	MCDI_IN_POPULATE_DWORD_8(req, INIT_EVQ_V2_IN_FLAGS,
 	    INIT_EVQ_V2_IN_FLAG_INTERRUPTING, interrupting,
 	    INIT_EVQ_V2_IN_FLAG_RPTR_DOS, 0,
 	    INIT_EVQ_V2_IN_FLAG_INT_ARMD, 0,
 	    INIT_EVQ_V2_IN_FLAG_CUT_THRU, ev_cut_through,
 	    INIT_EVQ_V2_IN_FLAG_RX_MERGE, ev_merge,
 	    INIT_EVQ_V2_IN_FLAG_TX_MERGE, ev_merge,
-	    INIT_EVQ_V2_IN_FLAG_TYPE, evq_type);
+	    INIT_EVQ_V2_IN_FLAG_TYPE, evq_type,
+	    INIT_EVQ_V2_IN_FLAG_EXT_WIDTH, ev_extended_width);
 
 	/* If the value is zero then disable the timer */
 	if (us == 0) {
diff --git a/drivers/common/sfc_efx/base/rhead_ev.c b/drivers/common/sfc_efx/base/rhead_ev.c
index 8392a2be5b..a83c6150d8 100644
--- a/drivers/common/sfc_efx/base/rhead_ev.c
+++ b/drivers/common/sfc_efx/base/rhead_ev.c
@@ -66,11 +66,26 @@  rhead_ev_qcreate(
 	__in		uint32_t flags,
 	__in		efx_evq_t *eep)
 {
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	size_t desc_size;
 	uint32_t irq;
 	efx_rc_t rc;
 
 	_NOTE(ARGUNUSED(id))	/* buftbl id managed by MC */
 
+	desc_size = encp->enc_ev_desc_size;
+#if EFSYS_OPT_EV_EXTENDED_WIDTH
+	if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH)
+		desc_size = encp->enc_ev_ew_desc_size;
+#endif
+	EFSYS_ASSERT(desc_size != 0);
+
+	if (EFSYS_MEM_SIZE(esmp) < (ndescs * desc_size)) {
+		/* Buffer too small for event queue descriptors */
+		rc = EINVAL;
+		goto fail1;
+	}
+
 	/* Set up the handler table */
 	eep->ee_rx	= rhead_ev_rx_packets;
 	eep->ee_tx	= rhead_ev_tx_completion;
@@ -98,10 +113,12 @@  rhead_ev_qcreate(
 	rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, us, flags,
 	    B_FALSE);
 	if (rc != 0)
-		goto fail1;
+		goto fail2;
 
 	return (0);
 
+fail2:
+	EFSYS_PROBE(fail2);
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 
diff --git a/drivers/common/sfc_efx/base/rhead_impl.h b/drivers/common/sfc_efx/base/rhead_impl.h
index 3383c47ec6..09a991f566 100644
--- a/drivers/common/sfc_efx/base/rhead_impl.h
+++ b/drivers/common/sfc_efx/base/rhead_impl.h
@@ -32,6 +32,10 @@  extern "C" {
 #define	RHEAD_RXQ_DESC_SIZE	(sizeof (efx_qword_t))
 #define	RHEAD_TXQ_DESC_SIZE	(sizeof (efx_oword_t))
 
+#if EFSYS_OPT_EV_EXTENDED_WIDTH
+#define	RHEAD_EVQ_EW_DESC_SIZE	(sizeof (efx_xword_t))
+#endif
+
 
 /* NIC */
 
diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c
index 9b8f09d12c..66db68b384 100644
--- a/drivers/common/sfc_efx/base/rhead_nic.c
+++ b/drivers/common/sfc_efx/base/rhead_nic.c
@@ -129,6 +129,12 @@  rhead_board_cfg(
 	encp->enc_evq_timer_quantum_ns = 0;
 	encp->enc_evq_timer_max_us = 0;
 
+#if EFSYS_OPT_EV_EXTENDED_WIDTH
+	encp->enc_ev_ew_desc_size = RHEAD_EVQ_EW_DESC_SIZE;
+#else
+	encp->enc_ev_ew_desc_size = 0;
+#endif
+
 	encp->enc_ev_desc_size = RHEAD_EVQ_DESC_SIZE;
 	encp->enc_rx_desc_size = RHEAD_RXQ_DESC_SIZE;
 	encp->enc_tx_desc_size = RHEAD_TXQ_DESC_SIZE;
diff --git a/drivers/net/sfc/sfc_ev.c b/drivers/net/sfc/sfc_ev.c
index 7e5676fa45..cc7d5d1179 100644
--- a/drivers/net/sfc/sfc_ev.c
+++ b/drivers/net/sfc/sfc_ev.c
@@ -600,7 +600,7 @@  sfc_ev_qstart(struct sfc_evq *evq, unsigned int hw_index)
 
 	/* Clear all events */
 	(void)memset((void *)esmp->esm_base, 0xff,
-		     efx_evq_size(sa->nic, evq->entries));
+		     efx_evq_size(sa->nic, evq->entries, evq_flags));
 
 	if ((sa->intr.lsc_intr && hw_index == sa->mgmt_evq_index) ||
 	    (sa->intr.rxq_intr && evq->dp_rxq != NULL))
@@ -833,8 +833,8 @@  sfc_ev_qinit(struct sfc_adapter *sa,
 
 	/* Allocate DMA space */
 	rc = sfc_dma_alloc(sa, sfc_evq_type2str(type), type_index,
-			   efx_evq_size(sa->nic, evq->entries), socket_id,
-			   &evq->mem);
+			   efx_evq_size(sa->nic, evq->entries, sa->evq_flags),
+			   socket_id, &evq->mem);
 	if (rc != 0)
 		goto fail_dma_alloc;