diff --git a/lib/bdev/virtio/bdev_virtio.c b/lib/bdev/virtio/bdev_virtio.c index 530b6c389..e57ce441c 100644 --- a/lib/bdev/virtio/bdev_virtio.c +++ b/lib/bdev/virtio/bdev_virtio.c @@ -632,9 +632,15 @@ bdev_virtio_initialize(void) goto out; } - /* TODO check rc, add virtio_dev_deinit() */ - virtio_init_device(vdev, VIRTIO_SCSI_DEV_SUPPORTED_FEATURES); - virtio_dev_start(vdev); + rc = virtio_dev_init(vdev, VIRTIO_SCSI_DEV_SUPPORTED_FEATURES); + if (rc != 0) { + goto out; + } + + rc = virtio_dev_start(vdev); + if (rc != 0) { + goto out; + } base->vdev = vdev; TAILQ_INIT(&base->found_disks); @@ -648,6 +654,10 @@ bdev_virtio_initialize(void) return 0; out: + if (vdev) { + virtio_dev_free(vdev); + } + spdk_bdev_module_init_done(SPDK_GET_BDEV_MODULE(virtio_scsi)); return rc; } diff --git a/lib/bdev/virtio/rte_virtio/virtio_dev.c b/lib/bdev/virtio/rte_virtio/virtio_dev.c index e31ebdeef..063ae58b8 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_dev.c +++ b/lib/bdev/virtio/rte_virtio/virtio_dev.c @@ -285,7 +285,7 @@ virtio_negotiate_features(struct virtio_dev *dev, uint64_t req_features) /* reset device and renegotiate features if needed */ int -virtio_init_device(struct virtio_dev *dev, uint64_t req_features) +virtio_dev_init(struct virtio_dev *dev, uint64_t req_features) { int ret; @@ -315,6 +315,14 @@ virtio_init_device(struct virtio_dev *dev, uint64_t req_features) return 0; } +void +virtio_dev_free(struct virtio_dev *dev) +{ + virtio_free_queues(dev); + VTPCI_OPS(dev)->free_vdev(dev); + /* FIXME clear VTPCI_OPS(dev) */ +} + int virtio_dev_start(struct virtio_dev *vdev) { diff --git a/lib/bdev/virtio/rte_virtio/virtio_dev.h b/lib/bdev/virtio/rte_virtio/virtio_dev.h index 691443a06..71d1e920a 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_dev.h +++ b/lib/bdev/virtio/rte_virtio/virtio_dev.h @@ -80,7 +80,8 @@ uint16_t virtio_recv_pkts(struct virtqueue *vq, struct virtio_req **reqs, uint16_t virtio_xmit_pkts(struct virtqueue *vq, struct virtio_req *req); -int virtio_init_device(struct virtio_dev *hw, uint64_t req_features); +int virtio_dev_init(struct virtio_dev *hw, uint64_t req_features); +void virtio_dev_free(struct virtio_dev *dev); int virtio_dev_start(struct virtio_dev *hw); struct virtio_dev *get_pci_virtio_hw(void); diff --git a/lib/bdev/virtio/rte_virtio/virtio_pci.c b/lib/bdev/virtio/rte_virtio/virtio_pci.c index 7c31604a0..9a226191b 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_pci.c +++ b/lib/bdev/virtio/rte_virtio/virtio_pci.c @@ -83,6 +83,23 @@ check_vq_phys_addr_ok(struct virtqueue *vq) return 1; } +static void +free_virtio_hw(struct virtio_dev *dev) +{ + struct virtio_hw *hw = virtio_dev_get_hw(dev); + unsigned i; + + for (i = 0; i < 6; ++i) { + if (hw->pci_bar[i].vaddr == NULL) { + continue; + } + + spdk_pci_device_unmap_bar(hw->pci_dev, i, hw->pci_bar[i].vaddr); + } + + free(hw); +} + /* * Since we are in legacy mode: * http://ozlabs.org/~rusty/virtio-spec/virtio-0.9.5.pdf @@ -295,6 +312,7 @@ const struct virtio_pci_ops legacy_ops = { .set_features = legacy_set_features, .get_isr = legacy_get_isr, .set_config_irq = legacy_set_config_irq, + .free_vdev = free_virtio_hw, .set_queue_irq = legacy_set_queue_irq, .get_queue_num = legacy_get_queue_num, .setup_queue = legacy_setup_queue, @@ -503,6 +521,7 @@ const struct virtio_pci_ops modern_ops = { .set_features = modern_set_features, .get_isr = modern_get_isr, .set_config_irq = modern_set_config_irq, + .free_vdev = free_virtio_hw, .set_queue_irq = modern_set_queue_irq, .get_queue_num = modern_get_queue_num, .setup_queue = modern_setup_queue, @@ -692,6 +711,11 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev) unsigned i; hw = calloc(1, sizeof(*hw)); + if (hw == NULL) { + PMD_DRV_LOG(ERR, "calloc failed"); + return -1; + } + vdev = &hw->vdev; vdev->is_hw = 1; hw->pci_dev = pci_dev; @@ -701,8 +725,7 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev) &bar_len); if (rc != 0) { PMD_DRV_LOG(ERR, "failed to memmap PCI BAR %d", i); - free(hw); - return -1; + goto err; } hw->pci_bar[i].vaddr = bar_vaddr; @@ -745,6 +768,10 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev) TAILQ_INSERT_TAIL(&g_virtio_driver.init_ctrlrs, vdev, tailq); return 0; + +err: + free_virtio_hw(vdev); + return -1; } int diff --git a/lib/bdev/virtio/rte_virtio/virtio_pci.h b/lib/bdev/virtio/rte_virtio/virtio_pci.h index bedc4c7bd..395e434ff 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_pci.h +++ b/lib/bdev/virtio/rte_virtio/virtio_pci.h @@ -203,6 +203,8 @@ struct virtio_pci_ops { uint16_t (*set_config_irq)(struct virtio_dev *hw, uint16_t vec); + /** Deinit and free virtio device */ + void (*free_vdev)(struct virtio_dev *vdev); uint16_t (*set_queue_irq)(struct virtio_dev *hw, struct virtqueue *vq, uint16_t vec); diff --git a/lib/bdev/virtio/rte_virtio/virtio_user.c b/lib/bdev/virtio/rte_virtio/virtio_user.c index 81dc81b80..e65722911 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_user.c +++ b/lib/bdev/virtio/rte_virtio/virtio_user.c @@ -201,6 +201,14 @@ virtio_user_notify_queue(struct virtio_dev *vdev, struct virtqueue *vq) strerror(errno)); } +static void +virtio_user_free(struct virtio_dev *vdev) +{ + struct virtio_user_dev *dev = virtio_dev_get_user_dev(vdev); + + virtio_user_dev_uninit(dev); +} + const struct virtio_pci_ops virtio_user_ops = { .read_dev_cfg = virtio_user_read_dev_config, .write_dev_cfg = virtio_user_write_dev_config, @@ -211,6 +219,7 @@ const struct virtio_pci_ops virtio_user_ops = { .set_features = virtio_user_set_features, .get_isr = virtio_user_get_isr, .set_config_irq = virtio_user_set_config_irq, + .free_vdev = virtio_user_free, .set_queue_irq = virtio_user_set_queue_irq, .get_queue_num = virtio_user_get_queue_num, .setup_queue = virtio_user_setup_queue,