Skip to content

Commit

Permalink
vdpa/virtio: Set call fd when device config
Browse files Browse the repository at this point in the history
Set device call fd in one time, this can scae ioctl
time

Signed-off-by: Kailiang <kailiangz@nvidia.com>
  • Loading branch information
kailiangz1 committed Apr 30, 2024
1 parent d2f242a commit c54d3b5
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 109 deletions.
1 change: 1 addition & 0 deletions drivers/common/virtio/version.map
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ INTERNAL {
virtio_pci_dev_state_dump;
virtio_pci_dev_state_all_queues_disable;
virtio_pci_dev_interrupt_enable;
virtio_pci_dev_interrupt_fd_set;
virtio_pci_dev_interrupt_disable;
virtio_pci_dev_interrupts_num_get;
virtio_pci_dev_interrupts_alloc;
Expand Down
93 changes: 12 additions & 81 deletions drivers/common/virtio/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ virtio_pci_dev_interrupts_num_get(struct virtio_pci_dev *vpdev)

#define VFIO_FD_INVALID -1
int
virtio_pci_dev_interrupts_alloc(struct virtio_pci_dev *vpdev, int nvec)
virtio_pci_dev_interrupts_alloc(struct virtio_pci_dev *vpdev, int nvec, int fds[])
{
struct vfio_irq_set *irq_set;
int ret, i;
Expand All @@ -677,7 +677,7 @@ virtio_pci_dev_interrupts_alloc(struct virtio_pci_dev *vpdev, int nvec)
irq_set->start = 0;

for (i = 0; i < nvec; i++)
*((int *)&irq_set->data + i) = VFIO_FD_INVALID;
*((int *)&irq_set->data + i) = fds[i];

ret = ioctl(vpdev->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
rte_free(irq_set);
Expand Down Expand Up @@ -726,34 +726,11 @@ virtio_pci_dev_state_interrupt_enable_only(struct virtio_pci_dev *vpdev, int vec
}

int
virtio_pci_dev_state_interrupt_enable(struct virtio_pci_dev *vpdev, int fd, int vec, void *state)
virtio_pci_dev_state_interrupt_enable(struct virtio_pci_dev *vpdev, int vec, void *state)
{
struct virtio_hw *hw = &vpdev->hw;
struct vfio_irq_set *irq_set;
struct virtio_dev_queue_info *q_info;
struct virtio_dev_common_state *state_info;
int ret, *data;

irq_set = rte_zmalloc(NULL, (sizeof(struct vfio_irq_set) + sizeof(int)), 0);
if (irq_set == NULL) {
PMD_INIT_LOG(ERR, "Dev %s malloc fail", VP_DEV_NAME(vpdev));
return -ENOMEM;
}
irq_set->argsz = sizeof(struct vfio_irq_set) + sizeof(int);
irq_set->count = 1;
irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
irq_set->start = vec;
data = (int *)&irq_set->data;
*data = fd;

ret = ioctl(vpdev->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
rte_free(irq_set);
if (ret) {
PMD_INIT_LOG(ERR, "Dev %s enabling MSI-X: %s", VP_DEV_NAME(vpdev), strerror(errno));
return ret;
}

if (vec == 0) {
state_info = state;
Expand All @@ -769,31 +746,8 @@ int
virtio_pci_dev_state_interrupt_disable(struct virtio_pci_dev *vpdev, int vec, void *state)
{
struct virtio_hw *hw = &vpdev->hw;
struct vfio_irq_set *irq_set;
struct virtio_dev_queue_info *q_info;
struct virtio_dev_common_state *state_info;
int ret, *data;

irq_set = rte_zmalloc(NULL, (sizeof(struct vfio_irq_set) + sizeof(int)), 0);
if (irq_set == NULL) {
PMD_INIT_LOG(ERR, "Dev %s malloc fail", VP_DEV_NAME(vpdev));
return -ENOMEM;
}
irq_set->argsz = sizeof(struct vfio_irq_set) + sizeof(int);
irq_set->count = 1;
irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
irq_set->start = vec;
data = (int *)&irq_set->data;
*data = VFIO_FD_INVALID;

ret = ioctl(vpdev->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
rte_free(irq_set);
if (ret) {
PMD_INIT_LOG(ERR, "Dev %s disabling MSI-X: %s", VP_DEV_NAME(vpdev), strerror(errno));
return ret;
}

if (vec == 0) {
state_info = state;
Expand All @@ -807,9 +761,8 @@ virtio_pci_dev_state_interrupt_disable(struct virtio_pci_dev *vpdev, int vec, vo
}

int
virtio_pci_dev_interrupt_enable(struct virtio_pci_dev *vpdev, int fd, int vec)
virtio_pci_dev_interrupt_fd_set(struct virtio_pci_dev *vpdev, int fd, int vec)
{
struct virtio_hw *hw = &vpdev->hw;
struct vfio_irq_set *irq_set;
int ret, *data;

Expand All @@ -830,16 +783,17 @@ virtio_pci_dev_interrupt_enable(struct virtio_pci_dev *vpdev, int fd, int vec)
ret = ioctl(vpdev->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
rte_free(irq_set);
if (ret) {
PMD_INIT_LOG(ERR, "Dev %s enabling MSI-X: %s", VP_DEV_NAME(vpdev), strerror(errno));
PMD_INIT_LOG(ERR, "Dev %s set MSI-X fd: %s", VP_DEV_NAME(vpdev), strerror(errno));
return ret;
}

VIRTIO_OPS(hw)->intr_detect(hw);
if (vpdev->msix_status != VIRTIO_MSIX_ENABLED) {
PMD_INIT_LOG(ERR, "Dev %s MSI-X not enabled,status: %d",
VP_DEV_NAME(vpdev), vpdev->msix_status);
return -EINVAL;
}
return 0;
}

int
virtio_pci_dev_interrupt_enable(struct virtio_pci_dev *vpdev, int vec)
{
struct virtio_hw *hw = &vpdev->hw;

if (vec == 0) {
if (VIRTIO_OPS(hw)->set_config_irq(hw, 0) ==
Expand All @@ -859,29 +813,6 @@ int
virtio_pci_dev_interrupt_disable(struct virtio_pci_dev *vpdev, int vec)
{
struct virtio_hw *hw = &vpdev->hw;
struct vfio_irq_set *irq_set;
int ret, *data;

irq_set = rte_zmalloc(NULL, (sizeof(struct vfio_irq_set) + sizeof(int)), 0);
if (irq_set == NULL) {
PMD_INIT_LOG(ERR, "Dev %s malloc fail", VP_DEV_NAME(vpdev));
return -ENOMEM;
}
irq_set->argsz = sizeof(struct vfio_irq_set) + sizeof(int);
irq_set->count = 1;
irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
irq_set->start = vec;
data = (int *)&irq_set->data;
*data = VFIO_FD_INVALID;

ret = ioctl(vpdev->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
rte_free(irq_set);
if (ret) {
PMD_INIT_LOG(ERR, "Dev %s disabling MSI-X: %s", VP_DEV_NAME(vpdev), strerror(errno));
return ret;
}

if (vec == 0) {
if (VIRTIO_OPS(hw)->set_config_irq(hw, VIRTIO_MSI_NO_VECTOR) !=
Expand Down
8 changes: 5 additions & 3 deletions drivers/common/virtio/virtio_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,21 @@ int virtio_pci_dev_state_queue_set(struct virtio_pci_dev *vpdev, uint16_t qid, c
__rte_internal
void virtio_pci_dev_state_queue_del(struct virtio_pci_dev *vpdev, uint16_t qid, void *state);
__rte_internal
int virtio_pci_dev_state_interrupt_enable(struct virtio_pci_dev *vpdev, int fd, int vec, void *state);
int virtio_pci_dev_state_interrupt_enable(struct virtio_pci_dev *vpdev, int vec, void *state);
__rte_internal
int virtio_pci_dev_state_interrupt_enable_only(struct virtio_pci_dev *vpdev, int vec, void *state);
__rte_internal
int virtio_pci_dev_state_interrupt_disable(struct virtio_pci_dev *vpdev, int vec, void *state);
__rte_internal
int virtio_pci_dev_interrupt_enable(struct virtio_pci_dev *vpdev, int fd, int vec);
int virtio_pci_dev_interrupt_enable(struct virtio_pci_dev *vpdev, int vec);
__rte_internal
int virtio_pci_dev_interrupt_fd_set(struct virtio_pci_dev *vpdev, int fd, int vec);
__rte_internal
int virtio_pci_dev_interrupt_disable(struct virtio_pci_dev *vpdev, int vec);
__rte_internal
int virtio_pci_dev_interrupts_num_get(struct virtio_pci_dev *vpdev);
__rte_internal
int virtio_pci_dev_interrupts_alloc(struct virtio_pci_dev *vpdev, int nvec);
int virtio_pci_dev_interrupts_alloc(struct virtio_pci_dev *vpdev, int nvec, int fds[]);
__rte_internal
int virtio_pci_dev_interrupts_free(struct virtio_pci_dev *vpdev);
__rte_internal
Expand Down
97 changes: 72 additions & 25 deletions drivers/vdpa/virtio/virtio_vdpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <virtio_api.h>
#include <virtio_lm.h>
#include <virtio_util.h>
#include <vhost.h>

#include "rte_vf_rpc.h"
#include "virtio_vdpa.h"
Expand Down Expand Up @@ -499,6 +500,46 @@ virtio_vdpa_virtq_doorbell_relay_enable(struct virtio_vdpa_priv *priv, int vq_id
return -EINVAL;
}

static void
virtio_vdpa_dev_set_call_fd(struct virtio_vdpa_priv *priv)
{
struct rte_vhost_vring vq;
uint16_t nr_virtqs, i;
int ret, *fds;

nr_virtqs = rte_vhost_get_vring_num(priv->vid);

fds = rte_zmalloc(NULL, (nr_virtqs + 1) * sizeof(*fds), 0 );
if (!fds) {
DRV_LOG(ERR, "Failed to alloc memory to set call fd vid:%d", priv->vid);
return;
}

if (priv->dev_ops->reg_dev_intr)
fds[0] = rte_intr_fd_get(priv->pdev->intr_handle);
else
fds[0] = VIRTIO_INVALID_EVENTFD;

for(i = 0; i < nr_virtqs; i++) {
fds[i+1] = VIRTIO_INVALID_EVENTFD;
priv->vrings[i]->callfd = VIRTIO_INVALID_EVENTFD;
ret = rte_vhost_get_vhost_vring(priv->vid, i, &vq);
if (ret) {
DRV_LOG(ERR, "vid %d virtq %d is invalid",priv->vid, i);
continue;
}
if (vq.callfd != VIRTIO_INVALID_EVENTFD) {
priv->vrings[i]->callfd = vq.callfd;
fds[i+1] = vq.callfd;
}
}

ret = virtio_pci_dev_interrupts_alloc(priv->vpdev, nr_virtqs, fds);
if (ret) {
DRV_LOG(ERR, "Failed to set call fd vid:%d", priv->vid);
}
}

static void*
virtio_vdpa_dev_notifier(void *arg)
{
Expand Down Expand Up @@ -638,14 +679,33 @@ virtio_vdpa_virtq_enable(struct virtio_vdpa_priv *priv, int vq_idx)
}

if (priv->configured) {
ret = virtio_pci_dev_interrupt_enable(priv->vpdev, vq.callfd, vq_idx + 1);

if (priv->vrings[vq_idx]->callfd != vq.callfd) {
ret = virtio_pci_dev_interrupt_fd_set(priv->vpdev, VIRTIO_INVALID_EVENTFD, vq_idx + 1);
if (ret) {
DRV_LOG(ERR, "error enabling virtio interrupts fd: %d(%s)",
ret, strerror(errno));
return ret;
}
ret = virtio_pci_dev_interrupt_fd_set(priv->vpdev, vq.callfd, vq_idx + 1);
if (ret) {
DRV_LOG(ERR, "error enabling virtio interrupts fd: %d(%s)",
ret, strerror(errno));
return ret;
}
DRV_LOG(INFO, "vid %d virtq %d pre fd:%d new fd:%d", vid, vq_idx,
priv->vrings[vq_idx]->callfd, vq.callfd);
priv->vrings[vq_idx]->callfd = vq.callfd;
}

ret = virtio_pci_dev_interrupt_enable(priv->vpdev, vq_idx + 1);
if (ret) {
DRV_LOG(ERR, "%s virtq interrupt enable failed ret:%d",
priv->vdev->device->name, ret);
return ret;
}
}
virtio_pci_dev_state_interrupt_enable(priv->vpdev, vq.callfd, vq_idx + 1, priv->state_mz->addr);
virtio_pci_dev_state_interrupt_enable(priv->vpdev, vq_idx + 1, priv->state_mz->addr);
} else {
DRV_LOG(DEBUG, "%s virtq %d call fd is -1, interrupt is disabled",
priv->vdev->device->name, vq_idx);
Expand Down Expand Up @@ -1502,7 +1562,11 @@ virtio_vdpa_dev_close(int vid)
virtio_pci_dev_state_dev_status_set(priv->state_mz->addr, VIRTIO_CONFIG_STATUS_ACK |
VIRTIO_CONFIG_STATUS_DRIVER);


ret = virtio_pci_dev_interrupts_free(priv->vpdev);
if (ret) {
DRV_LOG(ERR, "Error free virtio dev interrupts: %s",
strerror(errno));
}

virtio_vdpa_lcore_id = rte_get_next_lcore(virtio_vdpa_lcore_id, 1, 1);
priv->lcore_id = virtio_vdpa_lcore_id;
Expand Down Expand Up @@ -1561,6 +1625,8 @@ virtio_vdpa_dev_config(int vid)
return -EINVAL;
}

virtio_vdpa_dev_set_call_fd(priv);

nr_virtqs = rte_vhost_get_vring_num(vid);
if (priv->nvec < (nr_virtqs + 1)) {
DRV_LOG(ERR, "%s warning: dev interrupts %d less than queue: %d",
Expand Down Expand Up @@ -2086,6 +2152,7 @@ virtio_vdpa_queues_alloc(struct virtio_vdpa_priv *priv)
priv->vrings[i] = vr;
priv->vrings[i]->index = i;
priv->vrings[i]->priv = priv;
priv->vrings[i]->callfd = VIRTIO_INVALID_EVENTFD;
}
return 0;
}
Expand Down Expand Up @@ -2178,14 +2245,6 @@ virtio_vdpa_dev_do_remove(struct rte_pci_device *pci_dev, struct virtio_vdpa_pri
if (priv->vdev)
rte_vdpa_unregister_device(priv->vdev);

if (priv->vpdev) {
ret = virtio_pci_dev_interrupts_free(priv->vpdev);
if (ret) {
DRV_LOG(ERR, "Error free virtio dev interrupts: %s",
strerror(errno));
}
}

virtio_vdpa_queues_free(priv);

if (priv->vpdev) {
Expand Down Expand Up @@ -2255,7 +2314,7 @@ virtio_vdpa_dev_probe(struct rte_pci_driver *pci_drv __rte_unused,
static bool domain_init = false;
int vdpa = 0;
rte_uuid_t vm_uuid = {0};
int ret, fd, vf_id = 0, state_len, iommu_idx;
int ret, vf_id = 0, state_len, iommu_idx;
struct virtio_vdpa_priv *priv;
struct virtio_vdpa_iommu_domain *iommu_domain;
const struct virtio_vdpa_dma_mem *mem;
Expand Down Expand Up @@ -2561,17 +2620,6 @@ virtio_vdpa_dev_probe(struct rte_pci_driver *pci_drv __rte_unused,
virtio_vdpa_save_state_update_hwidx(priv, 0, false);
}

/* After restart from HA and interrupts alloc might cause traffic stop,
* move to bottom AMAP to save downtime
*/
ret = virtio_pci_dev_interrupts_alloc(priv->vpdev, priv->nvec);
if (ret) {
DRV_LOG(ERR, "%s error alloc virtio dev interrupts ret:%d %s",
devname, ret, strerror(errno));
rte_errno = VFE_VDPA_ERR_ADD_VF_INTERRUPT_ALLOC;
goto error;
}

if (priv->dev_ops->reg_dev_intr) {
ret = priv->dev_ops->reg_dev_intr(priv);
if (ret) {
Expand All @@ -2580,8 +2628,7 @@ virtio_vdpa_dev_probe(struct rte_pci_driver *pci_drv __rte_unused,
goto error;
}

fd = rte_intr_fd_get(priv->pdev->intr_handle);
ret = virtio_pci_dev_interrupt_enable(priv->vpdev, fd, 0);
ret = virtio_pci_dev_interrupt_enable(priv->vpdev, 0);
if (ret) {
DRV_LOG(ERR, "%s error enabling virtio dev interrupts: %d(%s)",
devname, ret, strerror(errno));
Expand Down
1 change: 1 addition & 0 deletions drivers/vdpa/virtio/virtio_vdpa.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct virtio_vdpa_vring_info {
uint64_t used;
uint16_t size;
uint16_t index;
int callfd;
uint8_t notifier_state;
bool enable;
bool conf_enable; /* save queue enable configuration got from vhost */
Expand Down

0 comments on commit c54d3b5

Please sign in to comment.