In virtio, each rx queue has one exclusive interrupt (corresponding
to irqfd in the qemu/kvm) to get notified when packets are available
in that queue. That is to say, queues cannot share interrupt. So we
have 1:1 mapping between queues and interrupts.

This patch creates eventfds for each Rx queue and configures the info
into kernel.

Signed-off-by: Jianfeng Tan <jianfeng....@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 42 +++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c 
b/drivers/net/virtio/virtio_ethdev.c
index 681a86b..886524c 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1474,6 +1474,9 @@ virtio_dev_start(struct rte_eth_dev *dev)
        struct virtnet_rx *rxvq;
        struct virtnet_tx *txvq __rte_unused;
        struct virtio_hw *hw = dev->data->dev_private;
+       struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+
+       rte_intr_disable(intr_handle);
 
        /* check if lsc interrupt feature is enabled */
        if (dev->data->dev_conf.intr_conf.lsc) {
@@ -1482,9 +1485,37 @@ virtio_dev_start(struct rte_eth_dev *dev)
                        return -ENOTSUP;
                }
 
-               if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) {
-                       PMD_DRV_LOG(ERR, "interrupt enable failed");
-                       return -EIO;
+       }
+
+       if (dev->data->dev_conf.intr_conf.rxq) {
+               /*
+                * 1. uio, igb_uio, vfio (type1): lsc and rxq interrupt share
+                * one interrupt.
+                * 2. vfio (noiommu): .
+                */
+               uint32_t intr_vector;
+
+               if (!rte_intr_cap_multiple(intr_handle)) {
+                       PMD_INIT_LOG(ERR, "Multiple intr vector not supported");
+                       return -1;
+               }
+
+               intr_vector = dev->data->nb_rx_queues;
+               if (rte_intr_efd_enable(intr_handle, intr_vector)) {
+                       PMD_INIT_LOG(ERR, "Fail to create eventfd");
+                       return -1;
+               }
+       }
+
+       if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+               intr_handle->intr_vec =
+                       rte_zmalloc("intr_vec",
+                                   dev->data->nb_rx_queues * sizeof(int),
+                                   0);
+               if (!intr_handle->intr_vec) {
+                       PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
+                                    " intr_vec\n", dev->data->nb_rx_queues);
+                       return -ENOMEM;
                }
        }
 
@@ -1520,6 +1551,11 @@ virtio_dev_start(struct rte_eth_dev *dev)
                VIRTQUEUE_DUMP(txvq->vq);
        }
 
+       if (rte_intr_enable(intr_handle) < 0) {
+               PMD_DRV_LOG(ERR, "interrupt enable failed");
+               return -EIO;
+       }
+
        return 0;
 }
 
-- 
2.7.4

Reply via email to