summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-22 18:41:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-22 18:41:27 -0700
commitdf7bf834a135e1f5bcbeecbec07605fa5d92f0bd (patch)
treefc3a7e9923f67e51e6c294df9f4321e8f77cbdc3 /drivers
parent429e6c7f90d12a8551b3eaa9faca7cfaefd99b1d (diff)
parent30471982cd667972ba93ce894765d4b8544958e6 (diff)
Merge tag 'vfio-v7.1-rc1-pt2' of https://github.com/awilliam/linux-vfio
Pull more VFIO updates from Alex Williamson: - Fix ordering of dma-buf cleanup versus device disabling in vfio-pci (Matt Evans) - Resolve an inconsistent and incorrect use of spinlock-irq in the virtio vfio-pci variant by conversion to mutex and proceed to modernize and simplify driver with use of guards (Alex Williamson) - Resurrect the removal of the remaining class_create() call in vfio, replacing with const struct class and class_register() (Jori Koolstra, Alex Williamson) - Fix NULL pointer dereference, properly serialize interrupt setup, and cleanup interrupt state tracking in the cdx vfio bus driver (Prasanna Kumar T S M, Alex Williamson) * tag 'vfio-v7.1-rc1-pt2' of https://github.com/awilliam/linux-vfio: vfio/cdx: Consolidate MSI configured state onto cdx_irqs vfio/cdx: Serialize VFIO_DEVICE_SET_IRQS with a per-device mutex vfio/cdx: Fix NULL pointer dereference in interrupt trigger path vfio: replace vfio->device_class with a const struct class vfio/virtio: Use guard() for bar_mutex in legacy I/O vfio/virtio: Use guard() for migf->lock where applicable vfio/virtio: Use guard() for list_lock where applicable vfio/virtio: Convert list_lock from spinlock to mutex vfio/pci: Clean up DMABUFs before disabling function
Diffstat (limited to 'drivers')
-rw-r--r--drivers/vfio/cdx/intr.c38
-rw-r--r--drivers/vfio/cdx/main.c19
-rw-r--r--drivers/vfio/cdx/private.h4
-rw-r--r--drivers/vfio/device_cdev.c8
-rw-r--r--drivers/vfio/pci/vfio_pci_core.c4
-rw-r--r--drivers/vfio/pci/virtio/common.h2
-rw-r--r--drivers/vfio/pci/virtio/legacy_io.c17
-rw-r--r--drivers/vfio/pci/virtio/migrate.c90
-rw-r--r--drivers/vfio/vfio.h4
-rw-r--r--drivers/vfio/vfio_main.c27
10 files changed, 107 insertions, 106 deletions
diff --git a/drivers/vfio/cdx/intr.c b/drivers/vfio/cdx/intr.c
index 8f4402cec9c5..4439481fe633 100644
--- a/drivers/vfio/cdx/intr.c
+++ b/drivers/vfio/cdx/intr.c
@@ -32,26 +32,27 @@ static int vfio_cdx_msi_enable(struct vfio_cdx_device *vdev, int nvec)
return -ENOMEM;
ret = cdx_enable_msi(cdx_dev);
- if (ret) {
- kfree(vdev->cdx_irqs);
- return ret;
- }
+ if (ret)
+ goto err_free;
/* Allocate cdx MSIs */
ret = msi_domain_alloc_irqs(dev, MSI_DEFAULT_DOMAIN, nvec);
- if (ret) {
- cdx_disable_msi(cdx_dev);
- kfree(vdev->cdx_irqs);
- return ret;
- }
+ if (ret)
+ goto err_disable;
for (msi_idx = 0; msi_idx < nvec; msi_idx++)
vdev->cdx_irqs[msi_idx].irq_no = msi_get_virq(dev, msi_idx);
vdev->msi_count = nvec;
- vdev->config_msi = 1;
return 0;
+
+err_disable:
+ cdx_disable_msi(cdx_dev);
+err_free:
+ kfree(vdev->cdx_irqs);
+ vdev->cdx_irqs = NULL;
+ return ret;
}
static int vfio_cdx_msi_set_vector_signal(struct vfio_cdx_device *vdev,
@@ -129,7 +130,7 @@ static void vfio_cdx_msi_disable(struct vfio_cdx_device *vdev)
vfio_cdx_msi_set_block(vdev, 0, vdev->msi_count, NULL);
- if (!vdev->config_msi)
+ if (!vdev->cdx_irqs)
return;
msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
@@ -138,7 +139,6 @@ static void vfio_cdx_msi_disable(struct vfio_cdx_device *vdev)
vdev->cdx_irqs = NULL;
vdev->msi_count = 0;
- vdev->config_msi = 0;
}
static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
@@ -152,6 +152,8 @@ static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
if (start + count > cdx_dev->num_msi)
return -EINVAL;
+ guard(mutex)(&vdev->cdx_irqs_lock);
+
if (!count && (flags & VFIO_IRQ_SET_DATA_NONE)) {
vfio_cdx_msi_disable(vdev);
return 0;
@@ -161,7 +163,7 @@ static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
s32 *fds = data;
int ret;
- if (vdev->config_msi)
+ if (vdev->cdx_irqs)
return vfio_cdx_msi_set_block(vdev, start, count,
fds);
ret = vfio_cdx_msi_enable(vdev, cdx_dev->num_msi);
@@ -175,6 +177,9 @@ static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
return ret;
}
+ if (!vdev->cdx_irqs)
+ return -EINVAL;
+
for (i = start; i < start + count; i++) {
if (!vdev->cdx_irqs[i].trigger)
continue;
@@ -206,12 +211,5 @@ int vfio_cdx_set_irqs_ioctl(struct vfio_cdx_device *vdev,
/* Free All IRQs for the given device */
void vfio_cdx_irqs_cleanup(struct vfio_cdx_device *vdev)
{
- /*
- * Device does not support any interrupt or the interrupts
- * were not configured
- */
- if (!vdev->cdx_irqs)
- return;
-
vfio_cdx_set_msi_trigger(vdev, 0, 0, 0, VFIO_IRQ_SET_DATA_NONE, NULL);
}
diff --git a/drivers/vfio/cdx/main.c b/drivers/vfio/cdx/main.c
index 8ab97405b2bd..b31ed4be7bdc 100644
--- a/drivers/vfio/cdx/main.c
+++ b/drivers/vfio/cdx/main.c
@@ -8,6 +8,23 @@
#include "private.h"
+static int vfio_cdx_init_dev(struct vfio_device *core_vdev)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+
+ mutex_init(&vdev->cdx_irqs_lock);
+ return 0;
+}
+
+static void vfio_cdx_release_dev(struct vfio_device *core_vdev)
+{
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+
+ mutex_destroy(&vdev->cdx_irqs_lock);
+}
+
static int vfio_cdx_open_device(struct vfio_device *core_vdev)
{
struct vfio_cdx_device *vdev =
@@ -273,6 +290,8 @@ static int vfio_cdx_mmap(struct vfio_device *core_vdev,
static const struct vfio_device_ops vfio_cdx_ops = {
.name = "vfio-cdx",
+ .init = vfio_cdx_init_dev,
+ .release = vfio_cdx_release_dev,
.open_device = vfio_cdx_open_device,
.close_device = vfio_cdx_close_device,
.ioctl = vfio_cdx_ioctl,
diff --git a/drivers/vfio/cdx/private.h b/drivers/vfio/cdx/private.h
index 172e48caa3a0..4c00bf633356 100644
--- a/drivers/vfio/cdx/private.h
+++ b/drivers/vfio/cdx/private.h
@@ -6,6 +6,8 @@
#ifndef VFIO_CDX_PRIVATE_H
#define VFIO_CDX_PRIVATE_H
+#include <linux/mutex.h>
+
#define VFIO_CDX_OFFSET_SHIFT 40
static inline u64 vfio_cdx_index_to_offset(u32 index)
@@ -31,11 +33,11 @@ struct vfio_cdx_region {
struct vfio_cdx_device {
struct vfio_device vdev;
struct vfio_cdx_region *regions;
+ struct mutex cdx_irqs_lock;
struct vfio_cdx_irq *cdx_irqs;
u32 flags;
#define BME_SUPPORT BIT(0)
u32 msi_count;
- u8 config_msi;
};
#ifdef CONFIG_GENERIC_MSI_IRQ
diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c
index 8ceca24ac136..54abf312cf04 100644
--- a/drivers/vfio/device_cdev.c
+++ b/drivers/vfio/device_cdev.c
@@ -293,14 +293,8 @@ int vfio_df_ioctl_detach_pt(struct vfio_device_file *df,
return 0;
}
-static char *vfio_device_devnode(const struct device *dev, umode_t *mode)
+int vfio_cdev_init(void)
{
- return kasprintf(GFP_KERNEL, "vfio/devices/%s", dev_name(dev));
-}
-
-int vfio_cdev_init(struct class *device_class)
-{
- device_class->devnode = vfio_device_devnode;
return alloc_chrdev_region(&device_devt, 0,
MINORMASK + 1, "vfio-dev");
}
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index ad52abc46c04..3f8d093aacf8 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -734,10 +734,10 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev)
#if IS_ENABLED(CONFIG_EEH)
eeh_dev_release(vdev->pdev);
#endif
- vfio_pci_core_disable(vdev);
-
vfio_pci_dma_buf_cleanup(vdev);
+ vfio_pci_core_disable(vdev);
+
mutex_lock(&vdev->igate);
vfio_pci_eventfd_replace_locked(vdev, &vdev->err_trigger, NULL);
vfio_pci_eventfd_replace_locked(vdev, &vdev->req_trigger, NULL);
diff --git a/drivers/vfio/pci/virtio/common.h b/drivers/vfio/pci/virtio/common.h
index cb3d5e57d3a3..3ccbd49e6abe 100644
--- a/drivers/vfio/pci/virtio/common.h
+++ b/drivers/vfio/pci/virtio/common.h
@@ -68,7 +68,7 @@ struct virtiovf_migration_file {
enum virtiovf_migf_state state;
enum virtiovf_load_state load_state;
/* synchronize access to the lists */
- spinlock_t list_lock;
+ struct mutex list_lock;
struct list_head buf_list;
struct list_head avail_list;
struct virtiovf_data_buffer *buf;
diff --git a/drivers/vfio/pci/virtio/legacy_io.c b/drivers/vfio/pci/virtio/legacy_io.c
index 1ed349a55629..f022301e60d6 100644
--- a/drivers/vfio/pci/virtio/legacy_io.c
+++ b/drivers/vfio/pci/virtio/legacy_io.c
@@ -34,7 +34,9 @@ virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
common = pos < VIRTIO_PCI_CONFIG_OFF(msix_enabled);
/* offset within the relevant configuration area */
offset = common ? pos : pos - VIRTIO_PCI_CONFIG_OFF(msix_enabled);
- mutex_lock(&virtvdev->bar_mutex);
+
+ guard(mutex)(&virtvdev->bar_mutex);
+
if (read) {
if (common)
ret = virtio_pci_admin_legacy_common_io_read(pdev, offset,
@@ -43,14 +45,12 @@ virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
ret = virtio_pci_admin_legacy_device_io_read(pdev, offset,
count, bar0_buf + pos);
if (ret)
- goto out;
+ return ret;
if (copy_to_user(buf, bar0_buf + pos, count))
- ret = -EFAULT;
+ return -EFAULT;
} else {
- if (copy_from_user(bar0_buf + pos, buf, count)) {
- ret = -EFAULT;
- goto out;
- }
+ if (copy_from_user(bar0_buf + pos, buf, count))
+ return -EFAULT;
if (common)
ret = virtio_pci_admin_legacy_common_io_write(pdev, offset,
@@ -59,8 +59,7 @@ virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
ret = virtio_pci_admin_legacy_device_io_write(pdev, offset,
count, bar0_buf + pos);
}
-out:
- mutex_unlock(&virtvdev->bar_mutex);
+
return ret;
}
diff --git a/drivers/vfio/pci/virtio/migrate.c b/drivers/vfio/pci/virtio/migrate.c
index 7e11834ad512..4b1e5502f0a7 100644
--- a/drivers/vfio/pci/virtio/migrate.c
+++ b/drivers/vfio/pci/virtio/migrate.c
@@ -142,9 +142,8 @@ end:
static void virtiovf_put_data_buffer(struct virtiovf_data_buffer *buf)
{
- spin_lock_irq(&buf->migf->list_lock);
+ guard(mutex)(&buf->migf->list_lock);
list_add_tail(&buf->buf_elm, &buf->migf->avail_list);
- spin_unlock_irq(&buf->migf->list_lock);
}
static int
@@ -170,21 +169,21 @@ virtiovf_get_data_buffer(struct virtiovf_migration_file *migf, size_t length)
INIT_LIST_HEAD(&free_list);
- spin_lock_irq(&migf->list_lock);
+ mutex_lock(&migf->list_lock);
list_for_each_entry_safe(buf, temp_buf, &migf->avail_list, buf_elm) {
list_del_init(&buf->buf_elm);
if (buf->allocated_length >= length) {
- spin_unlock_irq(&migf->list_lock);
+ mutex_unlock(&migf->list_lock);
goto found;
}
/*
* Prevent holding redundant buffers. Put in a free
- * list and call at the end not under the spin lock
+ * list and call at the end not under the mutex
* (&migf->list_lock) to minimize its scope usage.
*/
list_add(&buf->buf_elm, &free_list);
}
- spin_unlock_irq(&migf->list_lock);
+ mutex_unlock(&migf->list_lock);
buf = virtiovf_alloc_data_buffer(migf, length);
found:
@@ -225,10 +224,9 @@ static void virtiovf_clean_migf_resources(struct virtiovf_migration_file *migf)
static void virtiovf_disable_fd(struct virtiovf_migration_file *migf)
{
- mutex_lock(&migf->lock);
+ guard(mutex)(&migf->lock);
migf->state = VIRTIOVF_MIGF_STATE_ERROR;
migf->filp->f_pos = 0;
- mutex_unlock(&migf->lock);
}
static void virtiovf_disable_fds(struct virtiovf_pci_core_device *virtvdev)
@@ -295,6 +293,7 @@ static int virtiovf_release_file(struct inode *inode, struct file *filp)
struct virtiovf_migration_file *migf = filp->private_data;
virtiovf_disable_fd(migf);
+ mutex_destroy(&migf->list_lock);
mutex_destroy(&migf->lock);
kfree(migf);
return 0;
@@ -305,32 +304,27 @@ virtiovf_get_data_buff_from_pos(struct virtiovf_migration_file *migf,
loff_t pos, bool *end_of_data)
{
struct virtiovf_data_buffer *buf;
- bool found = false;
*end_of_data = false;
- spin_lock_irq(&migf->list_lock);
+ guard(mutex)(&migf->list_lock);
+
if (list_empty(&migf->buf_list)) {
*end_of_data = true;
- goto end;
+ return NULL;
}
buf = list_first_entry(&migf->buf_list, struct virtiovf_data_buffer,
buf_elm);
if (pos >= buf->start_pos &&
- pos < buf->start_pos + buf->length) {
- found = true;
- goto end;
- }
+ pos < buf->start_pos + buf->length)
+ return buf;
/*
* As we use a stream based FD we may expect having the data always
* on first chunk
*/
migf->state = VIRTIOVF_MIGF_STATE_ERROR;
-
-end:
- spin_unlock_irq(&migf->list_lock);
- return found ? buf : NULL;
+ return NULL;
}
static ssize_t virtiovf_buf_read(struct virtiovf_data_buffer *vhca_buf,
@@ -369,10 +363,9 @@ static ssize_t virtiovf_buf_read(struct virtiovf_data_buffer *vhca_buf,
}
if (*pos >= vhca_buf->start_pos + vhca_buf->length) {
- spin_lock_irq(&vhca_buf->migf->list_lock);
+ guard(mutex)(&vhca_buf->migf->list_lock);
list_del_init(&vhca_buf->buf_elm);
list_add_tail(&vhca_buf->buf_elm, &vhca_buf->migf->avail_list);
- spin_unlock_irq(&vhca_buf->migf->list_lock);
}
return done;
@@ -391,11 +384,10 @@ static ssize_t virtiovf_save_read(struct file *filp, char __user *buf, size_t le
return -ESPIPE;
pos = &filp->f_pos;
- mutex_lock(&migf->lock);
- if (migf->state == VIRTIOVF_MIGF_STATE_ERROR) {
- done = -ENODEV;
- goto out_unlock;
- }
+ guard(mutex)(&migf->lock);
+
+ if (migf->state == VIRTIOVF_MIGF_STATE_ERROR)
+ return -ENODEV;
while (len) {
ssize_t count;
@@ -404,34 +396,24 @@ static ssize_t virtiovf_save_read(struct file *filp, char __user *buf, size_t le
if (first_loop_call) {
first_loop_call = false;
/* Temporary end of file as part of PRE_COPY */
- if (end_of_data && migf->state == VIRTIOVF_MIGF_STATE_PRECOPY) {
- done = -ENOMSG;
- goto out_unlock;
- }
- if (end_of_data && migf->state != VIRTIOVF_MIGF_STATE_COMPLETE) {
- done = -EINVAL;
- goto out_unlock;
- }
+ if (end_of_data && migf->state == VIRTIOVF_MIGF_STATE_PRECOPY)
+ return -ENOMSG;
+ if (end_of_data && migf->state != VIRTIOVF_MIGF_STATE_COMPLETE)
+ return -EINVAL;
}
if (end_of_data)
- goto out_unlock;
+ return done;
- if (!vhca_buf) {
- done = -EINVAL;
- goto out_unlock;
- }
+ if (!vhca_buf)
+ return -EINVAL;
count = virtiovf_buf_read(vhca_buf, &buf, &len, pos);
- if (count < 0) {
- done = count;
- goto out_unlock;
- }
+ if (count < 0)
+ return count;
done += count;
}
-out_unlock:
- mutex_unlock(&migf->lock);
return done;
}
@@ -549,9 +531,10 @@ virtiovf_add_buf_header(struct virtiovf_data_buffer *header_buf,
header_buf->length = sizeof(header);
header_buf->start_pos = header_buf->migf->max_pos;
migf->max_pos += header_buf->length;
- spin_lock_irq(&migf->list_lock);
- list_add_tail(&header_buf->buf_elm, &migf->buf_list);
- spin_unlock_irq(&migf->list_lock);
+
+ scoped_guard(mutex, &migf->list_lock)
+ list_add_tail(&header_buf->buf_elm, &migf->buf_list);
+
return 0;
}
@@ -616,9 +599,10 @@ virtiovf_read_device_context_chunk(struct virtiovf_migration_file *migf,
buf->start_pos = buf->migf->max_pos;
migf->max_pos += buf->length;
- spin_lock(&migf->list_lock);
- list_add_tail(&buf->buf_elm, &migf->buf_list);
- spin_unlock_irq(&migf->list_lock);
+
+ scoped_guard(mutex, &migf->list_lock)
+ list_add_tail(&buf->buf_elm, &migf->buf_list);
+
return 0;
out_header:
@@ -687,7 +671,7 @@ virtiovf_pci_save_device_data(struct virtiovf_pci_core_device *virtvdev,
mutex_init(&migf->lock);
INIT_LIST_HEAD(&migf->buf_list);
INIT_LIST_HEAD(&migf->avail_list);
- spin_lock_init(&migf->list_lock);
+ mutex_init(&migf->list_lock);
migf->virtvdev = virtvdev;
lockdep_assert_held(&virtvdev->state_mutex);
@@ -1077,7 +1061,7 @@ virtiovf_pci_resume_device_data(struct virtiovf_pci_core_device *virtvdev)
mutex_init(&migf->lock);
INIT_LIST_HEAD(&migf->buf_list);
INIT_LIST_HEAD(&migf->avail_list);
- spin_lock_init(&migf->list_lock);
+ mutex_init(&migf->list_lock);
buf = virtiovf_alloc_data_buffer(migf, VIRTIOVF_TARGET_INITIAL_BUF_SIZE);
if (IS_ERR(buf)) {
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 0854f3fa1a22..e4b72e79b7e3 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -377,7 +377,7 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep);
long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df,
struct vfio_device_bind_iommufd __user *arg);
void vfio_df_unbind_iommufd(struct vfio_device_file *df);
-int vfio_cdev_init(struct class *device_class);
+int vfio_cdev_init(void);
void vfio_cdev_cleanup(void);
#else
static inline void vfio_init_device_cdev(struct vfio_device *device)
@@ -410,7 +410,7 @@ static inline void vfio_df_unbind_iommufd(struct vfio_device_file *df)
{
}
-static inline int vfio_cdev_init(struct class *device_class)
+static inline int vfio_cdev_init(void)
{
return 0;
}
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 8666f35fb3f0..6222376ab6ab 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -49,7 +49,6 @@
#define VFIO_MAGIC 0x5646494f /* "VFIO" */
static struct vfio {
- struct class *device_class;
struct ida device_ida;
struct vfsmount *vfs_mount;
int fs_count;
@@ -64,6 +63,16 @@ MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. Thi
static DEFINE_XARRAY(vfio_device_set_xa);
+static char *vfio_device_devnode(const struct device *dev, umode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "vfio/devices/%s", dev_name(dev));
+}
+
+static const struct class vfio_device_class = {
+ .name = "vfio-dev",
+ .devnode = vfio_device_devnode
+};
+
int vfio_assign_device_set(struct vfio_device *device, void *set_id)
{
unsigned long idx = (unsigned long)set_id;
@@ -299,7 +308,7 @@ static int vfio_init_device(struct vfio_device *device, struct device *dev,
device_initialize(&device->device);
device->device.release = vfio_device_release;
- device->device.class = vfio.device_class;
+ device->device.class = &vfio_device_class;
device->device.parent = device->dev;
return 0;
@@ -1804,13 +1813,11 @@ static int __init vfio_init(void)
goto err_virqfd;
/* /sys/class/vfio-dev/vfioX */
- vfio.device_class = class_create("vfio-dev");
- if (IS_ERR(vfio.device_class)) {
- ret = PTR_ERR(vfio.device_class);
+ ret = class_register(&vfio_device_class);
+ if (ret)
goto err_dev_class;
- }
- ret = vfio_cdev_init(vfio.device_class);
+ ret = vfio_cdev_init();
if (ret)
goto err_alloc_dev_chrdev;
@@ -1819,8 +1826,7 @@ static int __init vfio_init(void)
return 0;
err_alloc_dev_chrdev:
- class_destroy(vfio.device_class);
- vfio.device_class = NULL;
+ class_unregister(&vfio_device_class);
err_dev_class:
vfio_virqfd_exit();
err_virqfd:
@@ -1833,8 +1839,7 @@ static void __exit vfio_cleanup(void)
vfio_debugfs_remove_root();
ida_destroy(&vfio.device_ida);
vfio_cdev_cleanup();
- class_destroy(vfio.device_class);
- vfio.device_class = NULL;
+ class_unregister(&vfio_device_class);
vfio_virqfd_exit();
vfio_group_cleanup();
xa_destroy(&vfio_device_set_xa);