Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[test purpose] vdpa/virtio: Set call fd when device config #83

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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