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 <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/381311
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-10-04 13:19:30 +02:00 committed by Jim Harris
parent 5faa855989
commit 6175e0caf1
6 changed files with 80 additions and 15 deletions

View File

@ -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) {

View File

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

View File

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

View File

@ -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;
}

View File

@ -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_ */

View File

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