All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nic Chautru <nicolas.chautru@intel.com>
To: dev@dpdk.org, thomas@monjalon.net
Cc: maxime.coquelin@redhat.com, trix@redhat.com, mdr@ashroe.eu,
	bruce.richardson@intel.com, hemant.agrawal@nxp.com,
	david.marchand@redhat.com, stephen@networkplumber.org,
	hernan.vargas@intel.com, Nic Chautru <nicolas.chautru@intel.com>
Subject: [PATCH v4 11/14] baseband/acc: support interrupt
Date: Wed, 21 Sep 2022 17:27:37 -0700	[thread overview]
Message-ID: <1663806460-45162-12-git-send-email-nicolas.chautru@intel.com> (raw)
In-Reply-To: <1663806460-45162-1-git-send-email-nicolas.chautru@intel.com>

Adding support for capability and functions for
MSI/MSI-X interrupt and underlying information ring.

Signed-off-by: Nic Chautru <nicolas.chautru@intel.com>
---
 drivers/baseband/acc/rte_acc200_pmd.c | 346 +++++++++++++++++++++++++++++++++-
 1 file changed, 344 insertions(+), 2 deletions(-)

diff --git a/drivers/baseband/acc/rte_acc200_pmd.c b/drivers/baseband/acc/rte_acc200_pmd.c
index fa23b6e..b8b621a 100644
--- a/drivers/baseband/acc/rte_acc200_pmd.c
+++ b/drivers/baseband/acc/rte_acc200_pmd.c
@@ -220,6 +220,193 @@
 			acc_conf->q_fft.aq_depth_log2);
 }
 
+/* Checks PF Info Ring to find the interrupt cause and handles it accordingly */
+static inline void
+acc200_check_ir(struct acc_device *acc200_dev)
+{
+	volatile union acc_info_ring_data *ring_data;
+	uint16_t info_ring_head = acc200_dev->info_ring_head;
+	if (acc200_dev->info_ring == NULL)
+		return;
+
+	ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head &
+			ACC_INFO_RING_MASK);
+
+	while (ring_data->valid) {
+		if ((ring_data->int_nb < ACC200_PF_INT_DMA_DL_DESC_IRQ) || (
+				ring_data->int_nb >
+				ACC200_PF_INT_DMA_DL5G_DESC_IRQ)) {
+			rte_bbdev_log(WARNING, "InfoRing: ITR:%d Info:0x%x",
+				ring_data->int_nb, ring_data->detailed_info);
+			/* Initialize Info Ring entry and move forward */
+			ring_data->val = 0;
+		}
+		info_ring_head++;
+		ring_data = acc200_dev->info_ring +
+				(info_ring_head & ACC_INFO_RING_MASK);
+	}
+}
+
+/* Checks PF Info Ring to find the interrupt cause and handles it accordingly */
+static inline void
+acc200_pf_interrupt_handler(struct rte_bbdev *dev)
+{
+	struct acc_device *acc200_dev = dev->data->dev_private;
+	volatile union acc_info_ring_data *ring_data;
+	struct acc_deq_intr_details deq_intr_det;
+
+	ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head &
+			ACC_INFO_RING_MASK);
+
+	while (ring_data->valid) {
+
+		rte_bbdev_log_debug(
+				"ACC200 PF Interrupt received, Info Ring data: 0x%x -> %d",
+				ring_data->val, ring_data->int_nb);
+
+		switch (ring_data->int_nb) {
+		case ACC200_PF_INT_DMA_DL_DESC_IRQ:
+		case ACC200_PF_INT_DMA_UL_DESC_IRQ:
+		case ACC200_PF_INT_DMA_FFT_DESC_IRQ:
+		case ACC200_PF_INT_DMA_UL5G_DESC_IRQ:
+		case ACC200_PF_INT_DMA_DL5G_DESC_IRQ:
+			deq_intr_det.queue_id = get_queue_id_from_ring_info(
+					dev->data, *ring_data);
+			if (deq_intr_det.queue_id == UINT16_MAX) {
+				rte_bbdev_log(ERR,
+						"Couldn't find queue: aq_id: %u, qg_id: %u, vf_id: %u",
+						ring_data->aq_id,
+						ring_data->qg_id,
+						ring_data->vf_id);
+				return;
+			}
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_DEQUEUE, &deq_intr_det);
+			break;
+		default:
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_ERROR, NULL);
+			break;
+		}
+
+		/* Initialize Info Ring entry and move forward */
+		ring_data->val = 0;
+		++acc200_dev->info_ring_head;
+		ring_data = acc200_dev->info_ring +
+				(acc200_dev->info_ring_head & ACC_INFO_RING_MASK);
+	}
+}
+
+/* Checks VF Info Ring to find the interrupt cause and handles it accordingly */
+static inline void
+acc200_vf_interrupt_handler(struct rte_bbdev *dev)
+{
+	struct acc_device *acc200_dev = dev->data->dev_private;
+	volatile union acc_info_ring_data *ring_data;
+	struct acc_deq_intr_details deq_intr_det;
+
+	ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head & ACC_INFO_RING_MASK);
+
+	while (ring_data->valid) {
+
+		rte_bbdev_log_debug(
+				"ACC200 VF Interrupt received, Info Ring data: 0x%x\n",
+				ring_data->val);
+
+		switch (ring_data->int_nb) {
+		case ACC200_VF_INT_DMA_DL_DESC_IRQ:
+		case ACC200_VF_INT_DMA_UL_DESC_IRQ:
+		case ACC200_VF_INT_DMA_FFT_DESC_IRQ:
+		case ACC200_VF_INT_DMA_UL5G_DESC_IRQ:
+		case ACC200_VF_INT_DMA_DL5G_DESC_IRQ:
+			/* VFs are not aware of their vf_id - it's set to 0 in
+			 * queue structures.
+			 */
+			ring_data->vf_id = 0;
+			deq_intr_det.queue_id = get_queue_id_from_ring_info(
+					dev->data, *ring_data);
+			if (deq_intr_det.queue_id == UINT16_MAX) {
+				rte_bbdev_log(ERR,
+						"Couldn't find queue: aq_id: %u, qg_id: %u",
+						ring_data->aq_id,
+						ring_data->qg_id);
+				return;
+			}
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_DEQUEUE, &deq_intr_det);
+			break;
+		default:
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_ERROR, NULL);
+			break;
+		}
+
+		/* Initialize Info Ring entry and move forward */
+		ring_data->valid = 0;
+		++acc200_dev->info_ring_head;
+		ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head
+				& ACC_INFO_RING_MASK);
+	}
+}
+
+/* Interrupt handler triggered by ACC200 dev for handling specific interrupt */
+static void
+acc200_dev_interrupt_handler(void *cb_arg)
+{
+	struct rte_bbdev *dev = cb_arg;
+	struct acc_device *acc200_dev = dev->data->dev_private;
+
+	/* Read info ring */
+	if (acc200_dev->pf_device)
+		acc200_pf_interrupt_handler(dev);
+	else
+		acc200_vf_interrupt_handler(dev);
+}
+
+/* Allocate and setup inforing */
+static int
+allocate_info_ring(struct rte_bbdev *dev)
+{
+	struct acc_device *d = dev->data->dev_private;
+	const struct acc200_registry_addr *reg_addr;
+	rte_iova_t info_ring_iova;
+	uint32_t phys_low, phys_high;
+
+	if (d->info_ring != NULL)
+		return 0; /* Already configured */
+
+	/* Choose correct registry addresses for the device type */
+	if (d->pf_device)
+		reg_addr = &pf_reg_addr;
+	else
+		reg_addr = &vf_reg_addr;
+	/* Allocate InfoRing */
+	if (d->info_ring == NULL)
+		d->info_ring = rte_zmalloc_socket("Info Ring",
+				ACC_INFO_RING_NUM_ENTRIES *
+				sizeof(*d->info_ring), RTE_CACHE_LINE_SIZE,
+				dev->data->socket_id);
+	if (d->info_ring == NULL) {
+		rte_bbdev_log(ERR,
+				"Failed to allocate Info Ring for %s:%u",
+				dev->device->driver->name,
+				dev->data->dev_id);
+		return -ENOMEM;
+	}
+	info_ring_iova = rte_malloc_virt2iova(d->info_ring);
+
+	/* Setup Info Ring */
+	phys_high = (uint32_t)(info_ring_iova >> 32);
+	phys_low  = (uint32_t)(info_ring_iova);
+	acc_reg_write(d, reg_addr->info_ring_hi, phys_high);
+	acc_reg_write(d, reg_addr->info_ring_lo, phys_low);
+	acc_reg_write(d, reg_addr->info_ring_en, ACC200_REG_IRQ_EN_ALL);
+	d->info_ring_head = (acc_reg_read(d, reg_addr->info_ring_ptr) &
+			0xFFF) / sizeof(union acc_info_ring_data);
+	return 0;
+}
+
+
 /* Allocate 64MB memory used for all software rings */
 static int
 acc200_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
@@ -227,6 +414,7 @@
 	uint32_t phys_low, phys_high, value;
 	struct acc_device *d = dev->data->dev_private;
 	const struct acc200_registry_addr *reg_addr;
+	int ret;
 
 	if (d->pf_device && !d->acc_conf.pf_mode_en) {
 		rte_bbdev_log(NOTICE,
@@ -327,6 +515,14 @@
 	acc_reg_write(d, reg_addr->tail_ptrs_fft_hi, phys_high);
 	acc_reg_write(d, reg_addr->tail_ptrs_fft_lo, phys_low);
 
+	ret = allocate_info_ring(dev);
+	if (ret < 0) {
+		rte_bbdev_log(ERR, "Failed to allocate info_ring for %s:%u",
+				dev->device->driver->name,
+				dev->data->dev_id);
+		/* Continue */
+	}
+
 	if (d->harq_layout == NULL)
 		d->harq_layout = rte_zmalloc_socket("HARQ Layout",
 				ACC_HARQ_LAYOUT * sizeof(*d->harq_layout),
@@ -349,17 +545,121 @@
 	return 0;
 }
 
+static int
+acc200_intr_enable(struct rte_bbdev *dev)
+{
+	int ret;
+	struct acc_device *d = dev->data->dev_private;
+	/*
+	 * MSI/MSI-X are supported
+	 * Option controlled by vfio-intr through EAL parameter
+	 */
+	if (rte_intr_type_get(dev->intr_handle) == RTE_INTR_HANDLE_VFIO_MSI) {
+
+		ret = allocate_info_ring(dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't allocate info ring for device: %s",
+					dev->data->name);
+			return ret;
+		}
+		ret = rte_intr_enable(dev->intr_handle);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't enable interrupts for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+		ret = rte_intr_callback_register(dev->intr_handle,
+				acc200_dev_interrupt_handler, dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't register interrupt callback for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+
+		return 0;
+	} else if (rte_intr_type_get(dev->intr_handle) == RTE_INTR_HANDLE_VFIO_MSIX) {
+
+		ret = allocate_info_ring(dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't allocate info ring for device: %s",
+					dev->data->name);
+			return ret;
+		}
+
+		int i, max_queues;
+		struct acc_device *acc200_dev = dev->data->dev_private;
+
+		if (acc200_dev->pf_device)
+			max_queues = ACC200_MAX_PF_MSIX;
+		else
+			max_queues = ACC200_MAX_VF_MSIX;
+
+		if (rte_intr_efd_enable(dev->intr_handle, max_queues)) {
+			rte_bbdev_log(ERR, "Failed to create fds for %u queues",
+					dev->data->num_queues);
+			return -1;
+		}
+
+		for (i = 0; i < max_queues; ++i) {
+			if (rte_intr_efds_index_set(dev->intr_handle, i,
+					rte_intr_fd_get(dev->intr_handle)))
+				return -rte_errno;
+		}
+
+		if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec",
+				dev->data->num_queues)) {
+			rte_bbdev_log(ERR, "Failed to allocate %u vectors",
+					dev->data->num_queues);
+			return -ENOMEM;
+		}
+
+		ret = rte_intr_enable(dev->intr_handle);
+
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't enable interrupts for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+		ret = rte_intr_callback_register(dev->intr_handle,
+				acc200_dev_interrupt_handler, dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't register interrupt callback for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+
+		return 0;
+	}
+
+	rte_bbdev_log(ERR, "ACC200 (%s) supports only VFIO MSI/MSI-X interrupts\n",
+			dev->data->name);
+	return -ENOTSUP;
+}
+
 /* Free memory used for software rings */
 static int
 acc200_dev_close(struct rte_bbdev *dev)
 {
 	struct acc_device *d = dev->data->dev_private;
+	acc200_check_ir(d);
 	if (d->sw_rings_base != NULL) {
 		rte_free(d->tail_ptrs);
+		rte_free(d->info_ring);
 		rte_free(d->sw_rings_base);
 		rte_free(d->harq_layout);
 		d->sw_rings_base = NULL;
 		d->tail_ptrs = NULL;
+		d->info_ring = NULL;
 		d->harq_layout = NULL;
 	}
 	/* Ensure all in flight HW transactions are completed */
@@ -652,6 +952,7 @@
 					RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH |
 					RTE_BBDEV_TURBO_SOFT_OUTPUT |
 					RTE_BBDEV_TURBO_EARLY_TERMINATION |
+					RTE_BBDEV_TURBO_DEC_INTERRUPTS |
 					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN |
 					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT |
 					RTE_BBDEV_TURBO_MAP_DEC |
@@ -673,6 +974,7 @@
 					RTE_BBDEV_TURBO_CRC_24B_ATTACH |
 					RTE_BBDEV_TURBO_RV_INDEX_BYPASS |
 					RTE_BBDEV_TURBO_RATE_MATCH |
+					RTE_BBDEV_TURBO_ENC_INTERRUPTS |
 					RTE_BBDEV_TURBO_ENC_SCATTER_GATHER,
 				.num_buffers_src =
 						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
@@ -686,7 +988,8 @@
 				.capability_flags =
 					RTE_BBDEV_LDPC_RATE_MATCH |
 					RTE_BBDEV_LDPC_CRC_24B_ATTACH |
-					RTE_BBDEV_LDPC_INTERLEAVER_BYPASS,
+					RTE_BBDEV_LDPC_INTERLEAVER_BYPASS |
+					RTE_BBDEV_LDPC_ENC_INTERRUPTS,
 				.num_buffers_src =
 						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
 				.num_buffers_dst =
@@ -707,7 +1010,8 @@
 				RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS |
 				RTE_BBDEV_LDPC_DEC_SCATTER_GATHER |
 				RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION |
-				RTE_BBDEV_LDPC_LLR_COMPRESSION,
+				RTE_BBDEV_LDPC_LLR_COMPRESSION |
+				RTE_BBDEV_LDPC_DEC_INTERRUPTS,
 			.llr_size = 8,
 			.llr_decimals = 1,
 			.num_buffers_src =
@@ -775,15 +1079,46 @@
 	dev_info->min_alignment = 1;
 	dev_info->capabilities = bbdev_capabilities;
 	dev_info->harq_buffer_size = 0;
+
+	acc200_check_ir(d);
+}
+
+static int
+acc200_queue_intr_enable(struct rte_bbdev *dev, uint16_t queue_id)
+{
+	struct acc_queue *q = dev->data->queues[queue_id].queue_private;
+
+	if (rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSI &&
+			rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSIX)
+		return -ENOTSUP;
+
+	q->irq_enable = 1;
+	return 0;
+}
+
+static int
+acc200_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id)
+{
+	struct acc_queue *q = dev->data->queues[queue_id].queue_private;
+
+	if (rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSI &&
+			rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSIX)
+		return -ENOTSUP;
+
+	q->irq_enable = 0;
+	return 0;
 }
 
 static const struct rte_bbdev_ops acc200_bbdev_ops = {
 	.setup_queues = acc200_setup_queues,
+	.intr_enable = acc200_intr_enable,
 	.close = acc200_dev_close,
 	.info_get = acc200_dev_info_get,
 	.queue_setup = acc200_queue_setup,
 	.queue_release = acc200_queue_release,
 	.queue_stop = acc_queue_stop,
+	.queue_intr_enable = acc200_queue_intr_enable,
+	.queue_intr_disable = acc200_queue_intr_disable
 };
 
 /* ACC200 PCI PF address map */
@@ -2694,6 +3029,7 @@
 	if (op->status != 0) {
 		/* These errors are not expected */
 		q_data->queue_stats.dequeue_err_count++;
+		acc200_check_ir(q->d);
 	}
 
 	/* CRC invalid if error exists */
@@ -2763,6 +3099,9 @@
 
 	op->ldpc_dec.iter_count = (uint8_t) rsp.iter_cnt;
 
+	if (op->status & (1 << RTE_BBDEV_DRV_ERROR))
+		acc200_check_ir(q->d);
+
 	/* Check if this is the last desc in batch (Atomic Queue) */
 	if (desc->req.last_desc_in_batch) {
 		(*aq_dequeued)++;
@@ -3232,6 +3571,9 @@
 	if (op->status != 0)
 		q_data->queue_stats.dequeue_err_count++;
 
+	if (op->status & (1 << RTE_BBDEV_DRV_ERROR))
+		acc200_check_ir(q->d);
+
 	/* Check if this is the last desc in batch (Atomic Queue) */
 	if (desc->req.last_desc_in_batch) {
 		(*aq_dequeued)++;
-- 
1.8.3.1


  parent reply	other threads:[~2022-09-22  0:29 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-22  0:27 From: Nic Chautru <nicolas.chautru@intel.com> Nic Chautru
2022-09-22  0:27 ` [PATCH v4 01/14] baseband/acc100: remove unused registers Nic Chautru
2022-09-22  0:37   ` Chautru, Nicolas
2022-09-22 13:08     ` Maxime Coquelin
2022-09-22 13:09   ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 02/14] baseband/acc100: refactor to segregate common code Nic Chautru
2022-09-22 13:15   ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 03/14] baseband/acc: rename directory from acc100 to acc Nic Chautru
2022-09-22 13:17   ` Maxime Coquelin
2022-09-22 18:06     ` Chautru, Nicolas
2022-09-22  0:27 ` [PATCH v4 04/14] baseband/acc: introduce PMD for ACC200 Nic Chautru
2022-09-22 14:01   ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 05/14] baseband/acc: add HW register definitions " Nic Chautru
2022-09-22 14:04   ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 06/14] baseband/acc: add info get function " Nic Chautru
2022-09-22 14:11   ` Maxime Coquelin
2022-09-22 18:20     ` Chautru, Nicolas
2022-09-22  0:27 ` [PATCH v4 07/14] baseband/acc: add queue configuration " Nic Chautru
2022-09-22 14:30   ` Maxime Coquelin
2022-09-22 18:51     ` Chautru, Nicolas
2022-09-22  0:27 ` [PATCH v4 08/14] baseband/acc: add LDPC processing functions Nic Chautru
2022-09-23  8:29   ` Maxime Coquelin
2022-09-23 21:55     ` Chautru, Nicolas
2022-09-27 13:12       ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 09/14] baseband/acc: add LTE " Nic Chautru
2022-09-23  8:59   ` Maxime Coquelin
2022-09-23 22:21     ` Chautru, Nicolas
2022-09-27 13:33       ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 10/14] baseband/acc: add support for FFT operations Nic Chautru
2022-09-23  9:05   ` Maxime Coquelin
2022-09-23 22:31     ` Chautru, Nicolas
2022-09-22  0:27 ` Nic Chautru [this message]
2022-09-23  9:17   ` [PATCH v4 11/14] baseband/acc: support interrupt Maxime Coquelin
2022-09-23 22:58     ` Chautru, Nicolas
2022-09-22  0:27 ` [PATCH v4 12/14] baseband/acc: add device status and vf2pf comms Nic Chautru
2022-09-23  9:23   ` Maxime Coquelin
2022-09-24  0:04     ` Chautru, Nicolas
2022-09-22  0:27 ` [PATCH v4 13/14] baseband/acc: add PF configure companion function Nic Chautru
2022-09-23  9:26   ` Maxime Coquelin
2022-09-24  0:20     ` Chautru, Nicolas
2022-09-27 13:56       ` Maxime Coquelin
2022-09-22  0:27 ` [PATCH v4 14/14] baseband/acc: simplify meson dependency Nic Chautru
2022-09-23 11:41 ` From: Nic Chautru <nicolas.chautru@intel.com> Maxime Coquelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1663806460-45162-12-git-send-email-nicolas.chautru@intel.com \
    --to=nicolas.chautru@intel.com \
    --cc=bruce.richardson@intel.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=hemant.agrawal@nxp.com \
    --cc=hernan.vargas@intel.com \
    --cc=maxime.coquelin@redhat.com \
    --cc=mdr@ashroe.eu \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    --cc=trix@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.