net/virtio-user: support Rx interrupt

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>
This commit is contained in:
Jianfeng Tan 2017-03-31 19:44:56 +00:00 committed by Yuanhan Liu
parent e6e7ad8b30
commit 3d4fb6fd25
4 changed files with 47 additions and 0 deletions

View 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
---------------

View 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 {

View 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];

View 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;