[PATCH v2 5/5] dma/imx_edma5: add statistics and dump

Gagandeep Singh <[email protected]>
Newsgroups org.dpdk.dev
Message-ID <[email protected]>
Add per-vchan statistics, virtual channel status reporting and a device
dump callback to the eDMA5 dmadev.

stats_get and stats_reset expose the submitted, completed and error
counters maintained by the data path, supporting both a single vchan and
the RTE_DMA_ALL_VCHAN aggregate. vchan_status reports whether a channel is
idle, active or halted on an unreaped error by inspecting the outstanding
jobs in the software ring. dev_dump prints the device and per-vchan
software state to aid debugging.

Signed-off-by: Gagandeep Singh <[email protected]>
Signed-off-by: Prashant Gupta <[email protected]>
---
 drivers/dma/imx_edma5/imx_edma5_dmadev.c | 126 +++++++++++++++++++++++
 1 file changed, 126 insertions(+)

diff --git a/drivers/dma/imx_edma5/imx_edma5_dmadev.c b/drivers/dma/imx_edma5/imx_edma5_dmadev.c
index e7f3bec528..e9210a6793 100644
--- a/drivers/dma/imx_edma5/imx_edma5_dmadev.c
+++ b/drivers/dma/imx_edma5/imx_edma5_dmadev.c
@@ -901,6 +901,126 @@ imx_edma5_burst_capacity(const void *dev_private, uint16_t vchan)
 	return vc->nb_desc - 1 - vc->nb_enqueued;
 }
 
+static int
+imx_edma5_vchan_status(const struct rte_dma_dev *dev, uint16_t vchan,
+		       enum rte_dma_vchan_status *status)
+{
+	const struct imx_edma5_dev *ed = dev->data->dev_private;
+	const struct imx_edma5_vchan *vc = &ed->vchans[vchan];
+	uint16_t idx;
+
+	/*
+	 * HALTED_ERROR if an errored job is still unreaped, ACTIVE while any job
+	 * is outstanding (not done, or enqueued but not submitted), else IDLE.
+	 */
+	*status = RTE_DMA_VCHAN_IDLE;
+
+	for (idx = vc->tail; idx != vc->head; idx = (idx + 1) & vc->desc_mask) {
+		const struct imx_edma5_job *job = &vc->jobs[idx];
+
+		if (job->submitted && job->done && job->error) {
+			*status = RTE_DMA_VCHAN_HALTED_ERROR;
+			break;
+		}
+
+		if (!job->submitted || !job->done) {
+			*status = RTE_DMA_VCHAN_ACTIVE;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+imx_edma5_stats_get(const struct rte_dma_dev *dev, uint16_t vchan,
+		    struct rte_dma_stats *stats, uint32_t stats_sz)
+{
+	const struct imx_edma5_dev *ed = dev->data->dev_private;
+
+	RTE_SET_USED(stats_sz);
+
+	stats->submitted = 0;
+	stats->completed = 0;
+	stats->errors = 0;
+
+	/* RTE_DMA_ALL_VCHAN requests the aggregate across every vchan. */
+	if (vchan == RTE_DMA_ALL_VCHAN) {
+		uint16_t i;
+
+		for (i = 0; i < ed->nb_vchans; i++) {
+			const struct imx_edma5_vchan *vc = &ed->vchans[i];
+
+			stats->submitted += vc->submitted_count;
+			stats->completed += vc->completed_count;
+			stats->errors += vc->errors_count;
+		}
+	} else if (vchan < ed->nb_vchans) {
+		const struct imx_edma5_vchan *vc = &ed->vchans[vchan];
+
+		stats->submitted = vc->submitted_count;
+		stats->completed = vc->completed_count;
+		stats->errors = vc->errors_count;
+	}
+
+	return 0;
+}
+
+static int
+imx_edma5_stats_reset(struct rte_dma_dev *dev, uint16_t vchan)
+{
+	struct imx_edma5_dev *ed = dev->data->dev_private;
+
+	/* RTE_DMA_ALL_VCHAN requests a reset of every vchan. */
+	if (vchan == RTE_DMA_ALL_VCHAN) {
+		uint16_t i;
+
+		for (i = 0; i < ed->nb_vchans; i++) {
+			struct imx_edma5_vchan *vc = &ed->vchans[i];
+
+			vc->submitted_count = 0;
+			vc->completed_count = 0;
+			vc->errors_count = 0;
+		}
+	} else if (vchan < ed->nb_vchans) {
+		struct imx_edma5_vchan *vc = &ed->vchans[vchan];
+
+		vc->submitted_count = 0;
+		vc->completed_count = 0;
+		vc->errors_count = 0;
+	}
+
+	return 0;
+}
+
+static int
+imx_edma5_dump(const struct rte_dma_dev *dev, FILE *f)
+{
+	const struct imx_edma5_dev *ed = dev->data->dev_private;
+	uint16_t i;
+
+	(void)fprintf(f, "  imx_edma5 nb_channels=%u nb_vchans=%u\n",
+		      ed->nb_channels, ed->nb_vchans);
+	for (i = 0; i < ed->nb_vchans; i++) {
+		const struct imx_edma5_vchan *vc = &ed->vchans[i];
+
+		(void)fprintf(f,
+			"    vchan %u: hw_chan=%u nb_desc=%u enqueued=%u "
+			"submitted=%" PRIu64 " completed=%" PRIu64
+			" errors=%" PRIu64 "\n",
+			i, vc->hw_chan, vc->nb_desc, vc->nb_enqueued,
+			vc->submitted_count, vc->completed_count,
+			vc->errors_count);
+		/* Hardware register snapshot for debug (CH_CSR, CH_ES). */
+		(void)fprintf(f,
+			"      hw: CH_CSR=0x%08x CH_ES=0x%08x\n",
+			imx_edma5_read32(vc->ch_regs, IMX_EDMA5_CH_CSR),
+			imx_edma5_read32(vc->ch_regs, IMX_EDMA5_CH_ES));
+	}
+
+	return 0;
+}
+
 static const struct rte_dma_dev_ops imx_edma5_ops = {
 	.dev_info_get	= imx_edma5_info_get,
 	.dev_configure	= imx_edma5_configure,
@@ -909,6 +1029,12 @@ static const struct rte_dma_dev_ops imx_edma5_ops = {
 	.dev_close	= imx_edma5_close,
 
 	.vchan_setup	= imx_edma5_vchan_setup,
+	.vchan_status	= imx_edma5_vchan_status,
+
+	.stats_get	= imx_edma5_stats_get,
+	.stats_reset	= imx_edma5_stats_reset,
+
+	.dev_dump	= imx_edma5_dump,
 };
 
 static int
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.