Skip to content

Commit

Permalink
vdpa/virtio: replace doorbell relay with notifier
Browse files Browse the repository at this point in the history
Doorbell relay is used before, but it is time consuming.
Use notifier instead and use DPDK work to do notify because
we can't wait when we process vhost msg, otherwise, deadlock
will happend, so, use work thread to finish the job

Signed-off-by: Kailiang <kailiangz@nvidia.com>
  • Loading branch information
kailiangz1 committed Jan 2, 2024
1 parent c467b1c commit 322c843
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 29 deletions.
101 changes: 75 additions & 26 deletions drivers/vdpa/virtio/virtio_vdpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,20 +337,7 @@ virtio_vdpa_virtq_handler(void *cb_arg)
}

virtio_pci_dev_queue_notify(priv->vpdev, virtq->index);
if (virtq->notifier_state == VIRTIO_VDPA_NOTIFIER_STATE_DISABLED) {
if (rte_vhost_host_notifier_ctrl(priv->vid, virtq->index, true)) {
DRV_LOG(ERR, "%s failed to set notify ctrl virtq %d: %s",
priv->vdev->device->name, virtq->index, strerror(errno));
virtq->notifier_state = VIRTIO_VDPA_NOTIFIER_STATE_ERR;
} else
virtq->notifier_state = VIRTIO_VDPA_NOTIFIER_STATE_ENABLED;
DRV_LOG(INFO, "%s virtq %u notifier state is %s",
priv->vdev->device->name,
virtq->index,
virtq->notifier_state ==
VIRTIO_VDPA_NOTIFIER_STATE_ENABLED ? "enabled" :
"disabled");
}

DRV_LOG(DEBUG, "%s ring virtq %u doorbell i:%d",
priv->vdev->device->name, virtq->index, i);
}
Expand Down Expand Up @@ -382,7 +369,7 @@ virtio_vdpa_virtq_doorbell_relay_disable(struct virtio_vdpa_priv *priv,
}
rte_intr_instance_free(intr_handle);
priv->vrings[vq_idx]->intr_handle = NULL;
priv->vrings[vq_idx]->notifier_state = VIRTIO_VDPA_NOTIFIER_STATE_DISABLED;
priv->vrings[vq_idx]->notifier_state = VIRTIO_VDPA_NOTIFIER_RELAY_DISABLED;
return 0;
}

Expand Down Expand Up @@ -441,6 +428,52 @@ virtio_vdpa_virtq_doorbell_relay_enable(struct virtio_vdpa_priv *priv, int vq_id
return -EINVAL;
}

static int
virtio_vdpa_dev_notifier_work(void *arg)
{
int ret;
struct virtio_vdpa_notifier_work *work = arg;
uint16_t nr_virtqs, i;

DRV_LOG(INFO, "%s vid %d dev notifier work of vq id:%d core:%d start",
work->priv->vdev->device->name, work->priv->vid, work->vq_idx, rte_lcore_id());

ret = rte_vhost_host_notifier_ctrl(work->priv->vid, work->vq_idx, true);
if (ret) {
DRV_LOG(ERR, "%s vid %d dev notifier work failed use relay ret:%d vq id:%d core:%d",
work->priv->vdev->device->name, work->priv->vid, ret, work->vq_idx, rte_lcore_id());

if (work->vq_idx == RTE_VHOST_QUEUE_ALL) {
nr_virtqs = rte_vhost_get_vring_num(work->priv->vid);
i = 0;
} else {
i = work->vq_idx;
nr_virtqs = i + 1;
}
for(; i < nr_virtqs; i++) {
ret = virtio_vdpa_virtq_doorbell_relay_enable(work->priv, i);
if (ret) {
DRV_LOG(ERR, "%s vid %d dev notifier relay of vq id:%d core:%d setup fail",
work->priv->vdev->device->name, work->priv->vid, i, rte_lcore_id());
}
work->priv->vrings[i]->notifier_state = VIRTIO_VDPA_NOTIFIER_RELAY_ENABLED;
}
}
DRV_LOG(INFO, "%s vid %d dev notifier work of vq id:%d core:%d finish",
work->priv->vdev->device->name, work->priv->vid, work->vq_idx, rte_lcore_id());
/* Notify device anyway, in case loss doorbell */
if (work->vq_idx == RTE_VHOST_QUEUE_ALL) {
nr_virtqs = rte_vhost_get_vring_num(work->priv->vid);
i = 0;
for(; i < nr_virtqs; i++)
virtio_pci_dev_queue_notify(work->priv->vpdev, i);
} else
virtio_pci_dev_queue_notify(work->priv->vpdev, work->vq_idx);

rte_free(work);
return ret;
}

static int
virtio_vdpa_virtq_disable(struct virtio_vdpa_priv *priv, int vq_idx)
{
Expand All @@ -457,10 +490,13 @@ virtio_vdpa_virtq_disable(struct virtio_vdpa_priv *priv, int vq_idx)
}
}

ret = virtio_vdpa_virtq_doorbell_relay_disable(priv, vq_idx);
if (ret) {
DRV_LOG(ERR, "%s doorbell relay disable failed ret:%d",
priv->vdev->device->name, ret);
if (priv->vrings[vq_idx]->notifier_state == VIRTIO_VDPA_NOTIFIER_RELAY_ENABLED) {
ret = virtio_vdpa_virtq_doorbell_relay_disable(priv, vq_idx);
if (ret) {
DRV_LOG(ERR, "%s doorbell relay disable failed ret:%d",
priv->vdev->device->name, ret);
}
priv->vrings[vq_idx]->notifier_state = VIRTIO_VDPA_NOTIFIER_RELAY_DISABLED;
}

if (priv->configured) {
Expand Down Expand Up @@ -583,13 +619,6 @@ virtio_vdpa_virtq_enable(struct virtio_vdpa_priv *priv, int vq_idx)
return -EINVAL;
}

ret = virtio_vdpa_virtq_doorbell_relay_enable(priv, vq_idx);
if (ret) {
DRV_LOG(ERR, "%s virtq doorbell relay failed ret:%d",
priv->vdev->device->name, ret);
return ret;
}

priv->vrings[vq_idx]->enable = true;
virtio_pci_dev_queue_notify(priv->vpdev, vq_idx);
return 0;
Expand Down Expand Up @@ -1144,6 +1173,7 @@ virtio_vdpa_dev_config(int vid)
struct virtio_vdpa_priv *priv =
virtio_vdpa_find_priv_resource_by_vdev(vdev);
uint16_t last_avail_idx, last_used_idx, nr_virtqs;
struct virtio_vdpa_notifier_work *notify_work;
uint64_t t_start = rte_rdtsc_precise();
uint64_t t_end;
int ret, i;
Expand Down Expand Up @@ -1235,6 +1265,25 @@ virtio_vdpa_dev_config(int vid)

DRV_LOG(INFO, "%s vid %d move to driver ok", vdev->device->name, vid);

virtio_vdpa_lcore_id = rte_get_next_lcore(virtio_vdpa_lcore_id, 1, 1);
notify_work = rte_zmalloc(NULL, sizeof(*notify_work), 0);
if (!notify_work) {
DRV_LOG(ERR, "%s vfid %d failed to alloc notify work", priv->vdev->device->name, priv->vf_id);
rte_errno = rte_errno ? rte_errno : ENOMEM;
return -rte_errno;
}

notify_work->priv = priv;
notify_work->vq_idx = RTE_VHOST_QUEUE_ALL;
DRV_LOG(INFO, "%s vfid %d launch all vq notifier work lcore:%d",
priv->vdev->device->name, priv->vf_id, virtio_vdpa_lcore_id);
ret = rte_eal_remote_launch(virtio_vdpa_dev_notifier_work, notify_work, virtio_vdpa_lcore_id);
if (ret) {
DRV_LOG(ERR, "%s vfid %d failed launch notifier work ret:%d lcore:%d",
priv->vdev->device->name, priv->vf_id, ret, virtio_vdpa_lcore_id);
rte_free(notify_work);
}

priv->configured = 1;
t_end = rte_rdtsc_precise();
DRV_LOG(INFO, "%s vid %d was configured, took %lu us.", vdev->device->name,
Expand Down
11 changes: 8 additions & 3 deletions drivers/vdpa/virtio/virtio_vdpa.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#define _VIRTIO_VDPA_H_

enum {
VIRTIO_VDPA_NOTIFIER_STATE_DISABLED,
VIRTIO_VDPA_NOTIFIER_STATE_ENABLED,
VIRTIO_VDPA_NOTIFIER_STATE_ERR
VIRTIO_VDPA_NOTIFIER_RELAY_DISABLED,
VIRTIO_VDPA_NOTIFIER_RELAY_ENABLED,
VIRTIO_VDPA_NOTIFIER_RELAY_ERR
};

struct virtio_vdpa_iommu_domain {
Expand Down Expand Up @@ -66,6 +66,11 @@ struct virtio_vdpa_priv {
bool mem_tbl_set;
};

struct virtio_vdpa_notifier_work {
struct virtio_vdpa_priv *priv;
uint16_t vq_idx;
};

#define VIRTIO_VDPA_REMOTE_STATE_DEFAULT_SIZE 8192
#define VIRTIO_VDPA_INTR_RETRIES_USEC 1000
#define VIRTIO_VDPA_INTR_RETRIES 256
Expand Down

0 comments on commit 322c843

Please sign in to comment.