From 6175e0caf117607380065048c1e1f0fd586196cc Mon Sep 17 00:00:00 2001 From: Dariusz Stojaczyk Date: Wed, 4 Oct 2017 13:19:30 +0200 Subject: [PATCH] rte_virtio: rework vtpci ops Added vtpci_init/deinit() that set up vtpci_internal for given virtio device. This patch allows having multiple devices with different vtpci_ops. Change-Id: I249999cc24073b3de032db194730f496badd0f38 Signed-off-by: Dariusz Stojaczyk Reviewed-on: https://review.gerrithub.io/381311 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Daniel Verkamp --- lib/bdev/virtio/bdev_virtio.c | 2 +- lib/bdev/virtio/rte_virtio/virtio_dev.c | 8 +-- lib/bdev/virtio/rte_virtio/virtio_dev.h | 3 +- lib/bdev/virtio/rte_virtio/virtio_pci.c | 54 +++++++++++++++++-- lib/bdev/virtio/rte_virtio/virtio_pci.h | 23 ++++++-- .../rte_virtio/virtio_user/virtio_user_dev.c | 5 +- 6 files changed, 80 insertions(+), 15 deletions(-) diff --git a/lib/bdev/virtio/bdev_virtio.c b/lib/bdev/virtio/bdev_virtio.c index e57ce441c..193406f20 100644 --- a/lib/bdev/virtio/bdev_virtio.c +++ b/lib/bdev/virtio/bdev_virtio.c @@ -621,7 +621,7 @@ bdev_virtio_initialize(void) } if (scan_pci) { - vtpci_init(); + vtpci_enumerate_pci(); } TAILQ_FOREACH(vdev, &g_virtio_driver.init_ctrlrs, tailq) { diff --git a/lib/bdev/virtio/rte_virtio/virtio_dev.c b/lib/bdev/virtio/rte_virtio/virtio_dev.c index c3790e6d7..0ee1732ce 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_dev.c +++ b/lib/bdev/virtio/rte_virtio/virtio_dev.c @@ -120,8 +120,8 @@ virtio_init_queue(struct virtio_dev *dev, uint16_t vtpci_queue_idx) return -EINVAL; } - snprintf(vq_name, sizeof(vq_name), "port%d_vq%d", - dev->port_id, vtpci_queue_idx); + snprintf(vq_name, sizeof(vq_name), "dev%d_vq%d", + dev->id, vtpci_queue_idx); size = RTE_ALIGN_CEIL(sizeof(*vq) + vq_size * sizeof(struct vq_desc_extra), @@ -318,9 +318,11 @@ virtio_dev_init(struct virtio_dev *dev, uint64_t req_features) void virtio_dev_free(struct virtio_dev *dev) { + uint32_t vdev_id = dev->id; + virtio_free_queues(dev); vtpci_ops(dev)->free_vdev(dev); - /* FIXME clear VTPCI_OPS(dev) */ + vtpci_deinit(vdev_id); } int diff --git a/lib/bdev/virtio/rte_virtio/virtio_dev.h b/lib/bdev/virtio/rte_virtio/virtio_dev.h index b5ce9bf34..bff71dc8a 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_dev.h +++ b/lib/bdev/virtio/rte_virtio/virtio_dev.h @@ -45,7 +45,8 @@ struct virtio_dev { /** Max number of queues the host supports. */ uint16_t max_queues; - uint8_t port_id; + /* Device index. */ + uint32_t id; uint64_t req_guest_features; uint64_t guest_features; int is_hw; diff --git a/lib/bdev/virtio/rte_virtio/virtio_pci.c b/lib/bdev/virtio/rte_virtio/virtio_pci.c index ad84e766e..f54510ae2 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_pci.c +++ b/lib/bdev/virtio/rte_virtio/virtio_pci.c @@ -83,6 +83,12 @@ check_vq_phys_addr_ok(struct virtqueue *vq) return 1; } +static struct rte_pci_ioport * +vtpci_io(struct virtio_dev *vdev) +{ + return &g_virtio_driver.internal[vdev->id].io; +} + static void free_virtio_hw(struct virtio_dev *dev) { @@ -724,7 +730,10 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev) */ if (virtio_read_caps(hw) == 0) { PMD_INIT_LOG(INFO, "modern virtio pci detected."); - vtpci_ops(vdev) = &modern_ops; + rc = vtpci_init(vdev, &modern_ops); + if (rc != 0) { + goto err; + } vdev->modern = 1; TAILQ_INSERT_TAIL(&g_virtio_driver.init_ctrlrs, vdev, tailq); return 0; @@ -745,8 +754,11 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev) } #endif - vtpci_ops(vdev) = &legacy_ops; - vdev->modern = 0; + rc = vtpci_init(vdev, &legacy_ops); + if (rc != 0) { + goto err; + } + vdev->modern = 0; vtpci_read_dev_config(vdev, offsetof(struct virtio_scsi_config, num_queues), &vdev->max_queues, sizeof(vdev->max_queues)); @@ -760,7 +772,29 @@ err: } int -vtpci_init(void) +vtpci_init(struct virtio_dev *vdev, const struct virtio_pci_ops *ops) +{ + unsigned vdev_num; + + for (vdev_num = 0; vdev_num < VIRTIO_MAX_DEVICES; vdev_num++) { + if (g_virtio_driver.internal[vdev_num].vtpci_ops == NULL) { + break; + } + } + + if (vdev_num == VIRTIO_MAX_DEVICES) { + PMD_INIT_LOG(ERR, "Max vhost device limit reached (%d).", VIRTIO_MAX_DEVICES); + return -ENOSPC; + } + + vdev->id = vdev_num; + g_virtio_driver.internal[vdev_num].vtpci_ops = ops; + + return 0; +} + +int +vtpci_enumerate_pci(void) { if (!spdk_process_is_primary()) { PMD_INIT_LOG(INFO, "virtio_pci secondary process support is not implemented yet."); @@ -769,3 +803,15 @@ vtpci_init(void) return spdk_pci_virtio_enumerate(pci_enum_virtio_probe_cb, NULL); } + +const struct virtio_pci_ops * +vtpci_ops(struct virtio_dev *dev) +{ + return g_virtio_driver.internal[dev->id].vtpci_ops; +} + +void +vtpci_deinit(uint32_t id) +{ + g_virtio_driver.internal[id].vtpci_ops = NULL; +} diff --git a/lib/bdev/virtio/rte_virtio/virtio_pci.h b/lib/bdev/virtio/rte_virtio/virtio_pci.h index a7655c7a2..e59c1fd52 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_pci.h +++ b/lib/bdev/virtio/rte_virtio/virtio_pci.h @@ -43,6 +43,8 @@ struct virtqueue; +#define VIRTIO_MAX_DEVICES 128 + /* VirtIO PCI vendor/device ID. */ #define VIRTIO_PCI_VENDORID 0x1AF4 #define VIRTIO_PCI_DEVICEID_SCSI_MODERN 0x1004 @@ -242,11 +244,8 @@ struct vtpci_internal { struct rte_pci_ioport io; }; -#define vtpci_ops(dev) (g_virtio_driver.internal[(dev)->port_id].vtpci_ops) -#define vtpci_io(dev) (&g_virtio_driver.internal[(dev)->port_id].io) - struct virtio_driver { - struct vtpci_internal internal[128]; + struct vtpci_internal internal[VIRTIO_MAX_DEVICES]; TAILQ_HEAD(, virtio_dev) init_ctrlrs; TAILQ_HEAD(, virtio_dev) attached_ctrlrs; }; @@ -268,7 +267,17 @@ vtpci_with_feature(struct virtio_dev *dev, uint64_t bit) return (dev->guest_features & (1ULL << bit)) != 0; } -int vtpci_init(void); +/** + * Init all compatible Virtio PCI devices. + */ +int vtpci_enumerate_pci(void); + +/** + * Init virtual PCI layer for given device. This + * will set vdev->id field. + */ +int vtpci_init(struct virtio_dev *vdev, const struct virtio_pci_ops *ops); + void vtpci_reset(struct virtio_dev *); void vtpci_reinit_complete(struct virtio_dev *); @@ -284,6 +293,10 @@ void vtpci_read_dev_config(struct virtio_dev *, size_t, void *, int); uint8_t vtpci_isr(struct virtio_dev *); +const struct virtio_pci_ops *vtpci_ops(struct virtio_dev *dev); + +void vtpci_deinit(uint32_t id); + extern const struct virtio_pci_ops virtio_user_ops; #endif /* _VIRTIO_PCI_H_ */ diff --git a/lib/bdev/virtio/rte_virtio/virtio_user/virtio_user_dev.c b/lib/bdev/virtio/rte_virtio/virtio_user/virtio_user_dev.c index 055ed9789..a3b376ce9 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_user/virtio_user_dev.c +++ b/lib/bdev/virtio/rte_virtio/virtio_user/virtio_user_dev.c @@ -199,7 +199,10 @@ virtio_user_dev_init(char *path, int queue_size) vdev = &dev->vdev; vdev->is_hw = 0; - vtpci_ops(vdev) = &virtio_user_ops; + if (vtpci_init(vdev, &virtio_user_ops) != 0) { + PMD_INIT_LOG(ERR, "Failed to init device: %s", path); + goto err; + } snprintf(dev->path, PATH_MAX, "%s", path); dev->queue_size = queue_size;