mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 05:31:37 -04:00
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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,9 +142,8 @@ virtiovf_alloc_data_buffer(struct virtiovf_migration_file *migf, size_t length)
|
||||
|
||||
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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user