net/virtio-user: support Rx interrupt
authorJianfeng Tan <jianfeng.tan@intel.com>
Fri, 31 Mar 2017 19:44:56 +0000 (19:44 +0000)
committerYuanhan Liu <yuanhan.liu@linux.intel.com>
Sat, 1 Apr 2017 08:36:17 +0000 (10:36 +0200)
For rxq interrupt, the device (backend driver) will notify driver
through callfd. Each virtqueue has a callfd. To keep compatible
with the existing framework, we will give these callfds to
interrupt thread for listening for interrupts.

Before that, we need to allocate intr_handle, and fill callfds
into it so that driver can use it to set up rxq interrupt mode.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
doc/guides/rel_notes/release_17_05.rst
drivers/net/virtio/virtio_user/virtio_user_dev.c
drivers/net/virtio/virtio_user/virtio_user_dev.h
drivers/net/virtio/virtio_user_ethdev.c

index ee8eb6b..d7ea0df 100644 (file)
@@ -161,6 +161,14 @@ New Features
   * Enable Vhost PMD's MTU get feature.
   * Get max MTU value from host in Virtio PMD
 
+* **Added interrupt mode support for virtio-user.**
+
+  Implemented Rxq interrupt mode support for virtio-user as a virtual
+  device. Supported cases:
+
+  * Rxq interrupt for virtio-user + vhost-user as the backend.
+  * Rxq interrupt for virtio-user + vhost-kernel as the backend.
+
 
 Resolved Issues
 ---------------
index b0070d5..8471975 100644 (file)
@@ -250,6 +250,30 @@ virtio_user_dev_init_notify(struct virtio_user_dev *dev)
        return 0;
 }
 
+static int
+virtio_user_fill_intr_handle(struct virtio_user_dev *dev)
+{
+       uint32_t i;
+       struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
+
+       if (!eth_dev->intr_handle) {
+               eth_dev->intr_handle = malloc(sizeof(*eth_dev->intr_handle));
+               if (!eth_dev->intr_handle) {
+                       PMD_DRV_LOG(ERR, "fail to allocate intr_handle");
+                       return -1;
+               }
+               memset(eth_dev->intr_handle, 0, sizeof(*eth_dev->intr_handle));
+       }
+
+       for (i = 0; i < dev->max_queue_pairs; ++i)
+               eth_dev->intr_handle->efds[i] = dev->callfds[i];
+       eth_dev->intr_handle->nb_efd = dev->max_queue_pairs;
+       eth_dev->intr_handle->max_intr = dev->max_queue_pairs + 1;
+       eth_dev->intr_handle->type = RTE_INTR_HANDLE_VDEV;
+
+       return 0;
+}
+
 static int
 virtio_user_dev_setup(struct virtio_user_dev *dev)
 {
@@ -262,6 +286,9 @@ virtio_user_dev_setup(struct virtio_user_dev *dev)
        if (virtio_user_dev_init_notify(dev) < 0)
                return -1;
 
+       if (virtio_user_fill_intr_handle(dev) < 0)
+               return -1;
+
        if (is_vhost_user_by_type(dev->path)) {
                dev->ops = &ops_user;
        } else {
index 8abaa68..8361b6b 100644 (file)
@@ -60,6 +60,7 @@ struct virtio_user_dev {
                                   */
        uint64_t        device_features; /* supported features by device */
        uint8_t         status;
+       uint8_t         port_id;
        uint8_t         mac_addr[ETHER_ADDR_LEN];
        char            path[PATH_MAX];
        struct vring    vrings[VIRTIO_MAX_VIRTQUEUES];
index 740d7b1..9dd55fa 100644 (file)
@@ -148,6 +148,15 @@ virtio_user_set_config_irq(struct virtio_hw *hw __rte_unused,
        return VIRTIO_MSI_NO_VECTOR;
 }
 
+static uint16_t
+virtio_user_set_queue_irq(struct virtio_hw *hw __rte_unused,
+                         struct virtqueue *vq __rte_unused,
+                         uint16_t vec)
+{
+       /* pretend we have done that */
+       return vec;
+}
+
 /* This function is to get the queue size, aka, number of descs, of a specified
  * queue. Different with the VHOST_USER_GET_QUEUE_NUM, which is used to get the
  * max supported queues.
@@ -226,6 +235,7 @@ const struct virtio_pci_ops virtio_user_ops = {
        .set_features   = virtio_user_set_features,
        .get_isr        = virtio_user_get_isr,
        .set_config_irq = virtio_user_set_config_irq,
+       .set_queue_irq  = virtio_user_set_queue_irq,
        .get_queue_num  = virtio_user_get_queue_num,
        .setup_queue    = virtio_user_setup_queue,
        .del_queue      = virtio_user_del_queue,
@@ -313,6 +323,7 @@ virtio_user_eth_dev_alloc(const char *name)
        }
 
        hw->port_id = data->port_id;
+       dev->port_id = data->port_id;
        virtio_hw_internal[hw->port_id].vtpci_ops = &virtio_user_ops;
        hw->use_msix = 0;
        hw->modern   = 0;