[dpdk-dev] [PATCH 19/60] common/sfc_efx/base: move EvQ init/fini wrappers to generic

Andrew Rybchenko arybchenko at solarflare.com
Tue Sep 22 10:49:13 CEST 2020


EvQ init/fini MCDI is similar on Riverhead and these
functions should be reused to implement EvQ creation and
destruction on Riverhead.

Signed-off-by: Andrew Rybchenko <arybchenko at solarflare.com>
Reviewed-by: Andy Moreton <amoreton at xilinx.com>
Reviewed-by: Vijay Kumar Srivastava <vsrivast at xilinx.com>
---
 drivers/common/sfc_efx/base/ef10_ev.c  | 304 ------------------------
 drivers/common/sfc_efx/base/efx_impl.h |  33 +++
 drivers/common/sfc_efx/base/efx_mcdi.c | 306 +++++++++++++++++++++++++
 3 files changed, 339 insertions(+), 304 deletions(-)

diff --git a/drivers/common/sfc_efx/base/ef10_ev.c b/drivers/common/sfc_efx/base/ef10_ev.c
index f0a135ed57..08729cf71e 100644
--- a/drivers/common/sfc_efx/base/ef10_ev.c
+++ b/drivers/common/sfc_efx/base/ef10_ev.c
@@ -100,310 +100,6 @@ efx_mcdi_set_evq_tmr(
 	return (rc);
 }
 
-static	__checkReturn	efx_rc_t
-efx_mcdi_init_evq(
-	__in		efx_nic_t *enp,
-	__in		unsigned int instance,
-	__in		efsys_mem_t *esmp,
-	__in		size_t nevs,
-	__in		uint32_t irq,
-	__in		uint32_t us,
-	__in		uint32_t flags,
-	__in		boolean_t low_latency)
-{
-	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload,
-		MC_CMD_INIT_EVQ_IN_LEN(EF10_EVQ_MAXNBUFS),
-		MC_CMD_INIT_EVQ_OUT_LEN);
-	efx_qword_t *dma_addr;
-	uint64_t addr;
-	int npages;
-	int i;
-	boolean_t interrupting;
-	int ev_cut_through;
-	efx_rc_t rc;
-
-	npages = efx_evq_nbufs(enp, nevs);
-	if (npages > EF10_EVQ_MAXNBUFS) {
-		rc = EINVAL;
-		goto fail1;
-	}
-
-	req.emr_cmd = MC_CMD_INIT_EVQ;
-	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_INIT_EVQ_IN_LEN(npages);
-	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_INIT_EVQ_OUT_LEN;
-
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_SIZE, nevs);
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_INSTANCE, instance);
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_IRQ_NUM, irq);
-
-	interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
-	    EFX_EVQ_FLAGS_NOTIFY_INTERRUPT);
-
-	/*
-	 * On Huntington RX and TX event batching can only be requested together
-	 * (even if the datapath firmware doesn't actually support RX
-	 * batching). If event cut through is enabled no RX batching will occur.
-	 *
-	 * So always enable RX and TX event batching, and enable event cut
-	 * through if we want low latency operation.
-	 */
-	switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) {
-	case EFX_EVQ_FLAGS_TYPE_AUTO:
-		ev_cut_through = low_latency ? 1 : 0;
-		break;
-	case EFX_EVQ_FLAGS_TYPE_THROUGHPUT:
-		ev_cut_through = 0;
-		break;
-	case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY:
-		ev_cut_through = 1;
-		break;
-	default:
-		rc = EINVAL;
-		goto fail2;
-	}
-	MCDI_IN_POPULATE_DWORD_6(req, INIT_EVQ_IN_FLAGS,
-	    INIT_EVQ_IN_FLAG_INTERRUPTING, interrupting,
-	    INIT_EVQ_IN_FLAG_RPTR_DOS, 0,
-	    INIT_EVQ_IN_FLAG_INT_ARMD, 0,
-	    INIT_EVQ_IN_FLAG_CUT_THRU, ev_cut_through,
-	    INIT_EVQ_IN_FLAG_RX_MERGE, 1,
-	    INIT_EVQ_IN_FLAG_TX_MERGE, 1);
-
-	/* If the value is zero then disable the timer */
-	if (us == 0) {
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
-		    MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0);
-	} else {
-		unsigned int ticks;
-
-		if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
-			goto fail3;
-
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
-		    MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, ticks);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, ticks);
-	}
-
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_MODE,
-	    MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS);
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_THRSHLD, 0);
-
-	dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_IN_DMA_ADDR);
-	addr = EFSYS_MEM_ADDR(esmp);
-
-	for (i = 0; i < npages; i++) {
-		EFX_POPULATE_QWORD_2(*dma_addr,
-		    EFX_DWORD_1, (uint32_t)(addr >> 32),
-		    EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
-
-		dma_addr++;
-		addr += EFX_BUF_SIZE;
-	}
-
-	efx_mcdi_execute(enp, &req);
-
-	if (req.emr_rc != 0) {
-		rc = req.emr_rc;
-		goto fail4;
-	}
-
-	if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN) {
-		rc = EMSGSIZE;
-		goto fail5;
-	}
-
-	/* NOTE: ignore the returned IRQ param as firmware does not set it. */
-
-	return (0);
-
-fail5:
-	EFSYS_PROBE(fail5);
-fail4:
-	EFSYS_PROBE(fail4);
-fail3:
-	EFSYS_PROBE(fail3);
-fail2:
-	EFSYS_PROBE(fail2);
-fail1:
-	EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
-	return (rc);
-}
-
-
-static	__checkReturn	efx_rc_t
-efx_mcdi_init_evq_v2(
-	__in		efx_nic_t *enp,
-	__in		unsigned int instance,
-	__in		efsys_mem_t *esmp,
-	__in		size_t nevs,
-	__in		uint32_t irq,
-	__in		uint32_t us,
-	__in		uint32_t flags)
-{
-	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload,
-		MC_CMD_INIT_EVQ_V2_IN_LEN(EF10_EVQ_MAXNBUFS),
-		MC_CMD_INIT_EVQ_V2_OUT_LEN);
-	boolean_t interrupting;
-	unsigned int evq_type;
-	efx_qword_t *dma_addr;
-	uint64_t addr;
-	int npages;
-	int i;
-	efx_rc_t rc;
-
-	npages = efx_evq_nbufs(enp, nevs);
-	if (npages > EF10_EVQ_MAXNBUFS) {
-		rc = EINVAL;
-		goto fail1;
-	}
-
-	req.emr_cmd = MC_CMD_INIT_EVQ;
-	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_INIT_EVQ_V2_IN_LEN(npages);
-	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_INIT_EVQ_V2_OUT_LEN;
-
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_SIZE, nevs);
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_INSTANCE, instance);
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_IRQ_NUM, irq);
-
-	interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
-	    EFX_EVQ_FLAGS_NOTIFY_INTERRUPT);
-
-	switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) {
-	case EFX_EVQ_FLAGS_TYPE_AUTO:
-		evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO;
-		break;
-	case EFX_EVQ_FLAGS_TYPE_THROUGHPUT:
-		evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_THROUGHPUT;
-		break;
-	case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY:
-		evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LOW_LATENCY;
-		break;
-	default:
-		rc = EINVAL;
-		goto fail2;
-	}
-	MCDI_IN_POPULATE_DWORD_4(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_TYPE, evq_type);
-
-	/* If the value is zero then disable the timer */
-	if (us == 0) {
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE,
-		    MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, 0);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, 0);
-	} else {
-		unsigned int ticks;
-
-		if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
-			goto fail3;
-
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE,
-		    MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, ticks);
-		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, ticks);
-	}
-
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_MODE,
-	    MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS);
-	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_THRSHLD, 0);
-
-	dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_V2_IN_DMA_ADDR);
-	addr = EFSYS_MEM_ADDR(esmp);
-
-	for (i = 0; i < npages; i++) {
-		EFX_POPULATE_QWORD_2(*dma_addr,
-		    EFX_DWORD_1, (uint32_t)(addr >> 32),
-		    EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
-
-		dma_addr++;
-		addr += EFX_BUF_SIZE;
-	}
-
-	efx_mcdi_execute(enp, &req);
-
-	if (req.emr_rc != 0) {
-		rc = req.emr_rc;
-		goto fail4;
-	}
-
-	if (req.emr_out_length_used < MC_CMD_INIT_EVQ_V2_OUT_LEN) {
-		rc = EMSGSIZE;
-		goto fail5;
-	}
-
-	/* NOTE: ignore the returned IRQ param as firmware does not set it. */
-
-	EFSYS_PROBE1(mcdi_evq_flags, uint32_t,
-		    MCDI_OUT_DWORD(req, INIT_EVQ_V2_OUT_FLAGS));
-
-	return (0);
-
-fail5:
-	EFSYS_PROBE(fail5);
-fail4:
-	EFSYS_PROBE(fail4);
-fail3:
-	EFSYS_PROBE(fail3);
-fail2:
-	EFSYS_PROBE(fail2);
-fail1:
-	EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
-	return (rc);
-}
-
-static	__checkReturn	efx_rc_t
-efx_mcdi_fini_evq(
-	__in		efx_nic_t *enp,
-	__in		uint32_t instance)
-{
-	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_EVQ_IN_LEN,
-		MC_CMD_FINI_EVQ_OUT_LEN);
-	efx_rc_t rc;
-
-	req.emr_cmd = MC_CMD_FINI_EVQ;
-	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_FINI_EVQ_IN_LEN;
-	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_FINI_EVQ_OUT_LEN;
-
-	MCDI_IN_SET_DWORD(req, FINI_EVQ_IN_INSTANCE, instance);
-
-	efx_mcdi_execute_quiet(enp, &req);
-
-	if (req.emr_rc != 0) {
-		rc = req.emr_rc;
-		goto fail1;
-	}
-
-	return (0);
-
-fail1:
-	/*
-	 * EALREADY is not an error, but indicates that the MC has rebooted and
-	 * that the EVQ has already been destroyed.
-	 */
-	if (rc != EALREADY)
-		EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
-	return (rc);
-}
-
-
 
 	__checkReturn	efx_rc_t
 ef10_ev_init(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index f2ea08bbf6..bf1cfc49ca 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1408,6 +1408,39 @@ efx_mcdi_get_workarounds(
 	__out_opt		uint32_t *implementedp,
 	__out_opt		uint32_t *enabledp);
 
+#if EFX_OPTS_EF10()
+
+LIBEFX_INTERNAL
+extern	__checkReturn	efx_rc_t
+efx_mcdi_init_evq(
+	__in		efx_nic_t *enp,
+	__in		unsigned int instance,
+	__in		efsys_mem_t *esmp,
+	__in		size_t nevs,
+	__in		uint32_t irq,
+	__in		uint32_t us,
+	__in		uint32_t flags,
+	__in		boolean_t low_latency);
+
+LIBEFX_INTERNAL
+extern	__checkReturn	efx_rc_t
+efx_mcdi_init_evq_v2(
+	__in		efx_nic_t *enp,
+	__in		unsigned int instance,
+	__in		efsys_mem_t *esmp,
+	__in		size_t nevs,
+	__in		uint32_t irq,
+	__in		uint32_t us,
+	__in		uint32_t flags);
+
+LIBEFX_INTERNAL
+extern	__checkReturn	efx_rc_t
+efx_mcdi_fini_evq(
+	__in		efx_nic_t *enp,
+	__in		uint32_t instance);
+
+#endif	/* EFX_OPTS_EF10() */
+
 #endif /* EFSYS_OPT_MCDI */
 
 #if EFSYS_OPT_MAC_STATS
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.c b/drivers/common/sfc_efx/base/efx_mcdi.c
index ade7f7fed4..5b733bb88c 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.c
+++ b/drivers/common/sfc_efx/base/efx_mcdi.c
@@ -2443,4 +2443,310 @@ efx_mcdi_phy_module_get_info(
 	return (rc);
 }
 
+#if EFX_OPTS_EF10()
+
+	__checkReturn	efx_rc_t
+efx_mcdi_init_evq(
+	__in		efx_nic_t *enp,
+	__in		unsigned int instance,
+	__in		efsys_mem_t *esmp,
+	__in		size_t nevs,
+	__in		uint32_t irq,
+	__in		uint32_t us,
+	__in		uint32_t flags,
+	__in		boolean_t low_latency)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+		MC_CMD_INIT_EVQ_IN_LEN(EF10_EVQ_MAXNBUFS),
+		MC_CMD_INIT_EVQ_OUT_LEN);
+	efx_qword_t *dma_addr;
+	uint64_t addr;
+	int npages;
+	int i;
+	boolean_t interrupting;
+	int ev_cut_through;
+	efx_rc_t rc;
+
+	npages = efx_evq_nbufs(enp, nevs);
+	if (npages > EF10_EVQ_MAXNBUFS) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_INIT_EVQ;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_INIT_EVQ_IN_LEN(npages);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_INIT_EVQ_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_SIZE, nevs);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_INSTANCE, instance);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_IRQ_NUM, irq);
+
+	interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
+	    EFX_EVQ_FLAGS_NOTIFY_INTERRUPT);
+
+	/*
+	 * On Huntington RX and TX event batching can only be requested together
+	 * (even if the datapath firmware doesn't actually support RX
+	 * batching). If event cut through is enabled no RX batching will occur.
+	 *
+	 * So always enable RX and TX event batching, and enable event cut
+	 * through if we want low latency operation.
+	 */
+	switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) {
+	case EFX_EVQ_FLAGS_TYPE_AUTO:
+		ev_cut_through = low_latency ? 1 : 0;
+		break;
+	case EFX_EVQ_FLAGS_TYPE_THROUGHPUT:
+		ev_cut_through = 0;
+		break;
+	case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY:
+		ev_cut_through = 1;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail2;
+	}
+	MCDI_IN_POPULATE_DWORD_6(req, INIT_EVQ_IN_FLAGS,
+	    INIT_EVQ_IN_FLAG_INTERRUPTING, interrupting,
+	    INIT_EVQ_IN_FLAG_RPTR_DOS, 0,
+	    INIT_EVQ_IN_FLAG_INT_ARMD, 0,
+	    INIT_EVQ_IN_FLAG_CUT_THRU, ev_cut_through,
+	    INIT_EVQ_IN_FLAG_RX_MERGE, 1,
+	    INIT_EVQ_IN_FLAG_TX_MERGE, 1);
+
+	/* If the value is zero then disable the timer */
+	if (us == 0) {
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
+		    MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0);
+	} else {
+		unsigned int ticks;
+
+		if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
+			goto fail3;
+
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE,
+		    MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, ticks);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, ticks);
+	}
+
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_MODE,
+	    MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_THRSHLD, 0);
+
+	dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_IN_DMA_ADDR);
+	addr = EFSYS_MEM_ADDR(esmp);
+
+	for (i = 0; i < npages; i++) {
+		EFX_POPULATE_QWORD_2(*dma_addr,
+		    EFX_DWORD_1, (uint32_t)(addr >> 32),
+		    EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
+
+		dma_addr++;
+		addr += EFX_BUF_SIZE;
+	}
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	/* NOTE: ignore the returned IRQ param as firmware does not set it. */
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+	__checkReturn	efx_rc_t
+efx_mcdi_init_evq_v2(
+	__in		efx_nic_t *enp,
+	__in		unsigned int instance,
+	__in		efsys_mem_t *esmp,
+	__in		size_t nevs,
+	__in		uint32_t irq,
+	__in		uint32_t us,
+	__in		uint32_t flags)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+		MC_CMD_INIT_EVQ_V2_IN_LEN(EF10_EVQ_MAXNBUFS),
+		MC_CMD_INIT_EVQ_V2_OUT_LEN);
+	boolean_t interrupting;
+	unsigned int evq_type;
+	efx_qword_t *dma_addr;
+	uint64_t addr;
+	int npages;
+	int i;
+	efx_rc_t rc;
+
+	npages = efx_evq_nbufs(enp, nevs);
+	if (npages > EF10_EVQ_MAXNBUFS) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_INIT_EVQ;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_INIT_EVQ_V2_IN_LEN(npages);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_INIT_EVQ_V2_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_SIZE, nevs);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_INSTANCE, instance);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_IRQ_NUM, irq);
+
+	interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) ==
+	    EFX_EVQ_FLAGS_NOTIFY_INTERRUPT);
+
+	switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) {
+	case EFX_EVQ_FLAGS_TYPE_AUTO:
+		evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO;
+		break;
+	case EFX_EVQ_FLAGS_TYPE_THROUGHPUT:
+		evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_THROUGHPUT;
+		break;
+	case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY:
+		evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LOW_LATENCY;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail2;
+	}
+	MCDI_IN_POPULATE_DWORD_4(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_TYPE, evq_type);
+
+	/* If the value is zero then disable the timer */
+	if (us == 0) {
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE,
+		    MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, 0);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, 0);
+	} else {
+		unsigned int ticks;
+
+		if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
+			goto fail3;
+
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE,
+		    MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, ticks);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, ticks);
+	}
+
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_MODE,
+	    MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_THRSHLD, 0);
+
+	dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_V2_IN_DMA_ADDR);
+	addr = EFSYS_MEM_ADDR(esmp);
+
+	for (i = 0; i < npages; i++) {
+		EFX_POPULATE_QWORD_2(*dma_addr,
+		    EFX_DWORD_1, (uint32_t)(addr >> 32),
+		    EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
+
+		dma_addr++;
+		addr += EFX_BUF_SIZE;
+	}
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_INIT_EVQ_V2_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	/* NOTE: ignore the returned IRQ param as firmware does not set it. */
+
+	EFSYS_PROBE1(mcdi_evq_flags, uint32_t,
+		    MCDI_OUT_DWORD(req, INIT_EVQ_V2_OUT_FLAGS));
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+	__checkReturn	efx_rc_t
+efx_mcdi_fini_evq(
+	__in		efx_nic_t *enp,
+	__in		uint32_t instance)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_EVQ_IN_LEN,
+		MC_CMD_FINI_EVQ_OUT_LEN);
+	efx_rc_t rc;
+
+	req.emr_cmd = MC_CMD_FINI_EVQ;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_FINI_EVQ_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_FINI_EVQ_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, FINI_EVQ_IN_INSTANCE, instance);
+
+	efx_mcdi_execute_quiet(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	/*
+	 * EALREADY is not an error, but indicates that the MC has rebooted and
+	 * that the EVQ has already been destroyed.
+	 */
+	if (rc != EALREADY)
+		EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+#endif	/* EFX_OPTS_EF10() */
+
 #endif	/* EFSYS_OPT_MCDI */
-- 
2.17.1



More information about the dev mailing list