aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/platform/vfio_platform_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/platform/vfio_platform_common.c')
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c183
1 files changed, 64 insertions, 119 deletions
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index c0771a9567fb..55dc4f43c31e 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -218,86 +218,70 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
return -EINVAL;
}
-static void vfio_platform_release(void *device_data)
+void vfio_platform_close_device(struct vfio_device *core_vdev)
{
- struct vfio_platform_device *vdev = device_data;
-
- mutex_lock(&driver_lock);
-
- if (!(--vdev->refcnt)) {
- const char *extra_dbg = NULL;
- int ret;
+ struct vfio_platform_device *vdev =
+ container_of(core_vdev, struct vfio_platform_device, vdev);
+ const char *extra_dbg = NULL;
+ int ret;
- ret = vfio_platform_call_reset(vdev, &extra_dbg);
- if (ret && vdev->reset_required) {
- dev_warn(vdev->device, "reset driver is required and reset call failed in release (%d) %s\n",
- ret, extra_dbg ? extra_dbg : "");
- WARN_ON(1);
- }
- pm_runtime_put(vdev->device);
- vfio_platform_regions_cleanup(vdev);
- vfio_platform_irq_cleanup(vdev);
+ ret = vfio_platform_call_reset(vdev, &extra_dbg);
+ if (WARN_ON(ret && vdev->reset_required)) {
+ dev_warn(
+ vdev->device,
+ "reset driver is required and reset call failed in release (%d) %s\n",
+ ret, extra_dbg ? extra_dbg : "");
}
-
- mutex_unlock(&driver_lock);
-
- module_put(vdev->parent_module);
+ pm_runtime_put(vdev->device);
+ vfio_platform_regions_cleanup(vdev);
+ vfio_platform_irq_cleanup(vdev);
}
+EXPORT_SYMBOL_GPL(vfio_platform_close_device);
-static int vfio_platform_open(void *device_data)
+int vfio_platform_open_device(struct vfio_device *core_vdev)
{
- struct vfio_platform_device *vdev = device_data;
+ struct vfio_platform_device *vdev =
+ container_of(core_vdev, struct vfio_platform_device, vdev);
+ const char *extra_dbg = NULL;
int ret;
- if (!try_module_get(vdev->parent_module))
- return -ENODEV;
-
- mutex_lock(&driver_lock);
-
- if (!vdev->refcnt) {
- const char *extra_dbg = NULL;
-
- ret = vfio_platform_regions_init(vdev);
- if (ret)
- goto err_reg;
+ ret = vfio_platform_regions_init(vdev);
+ if (ret)
+ return ret;
- ret = vfio_platform_irq_init(vdev);
- if (ret)
- goto err_irq;
+ ret = vfio_platform_irq_init(vdev);
+ if (ret)
+ goto err_irq;
- ret = pm_runtime_get_sync(vdev->device);
- if (ret < 0)
- goto err_pm;
+ ret = pm_runtime_get_sync(vdev->device);
+ if (ret < 0)
+ goto err_rst;
- ret = vfio_platform_call_reset(vdev, &extra_dbg);
- if (ret && vdev->reset_required) {
- dev_warn(vdev->device, "reset driver is required and reset call failed in open (%d) %s\n",
- ret, extra_dbg ? extra_dbg : "");
- goto err_rst;
- }
+ ret = vfio_platform_call_reset(vdev, &extra_dbg);
+ if (ret && vdev->reset_required) {
+ dev_warn(
+ vdev->device,
+ "reset driver is required and reset call failed in open (%d) %s\n",
+ ret, extra_dbg ? extra_dbg : "");
+ goto err_rst;
}
-
- vdev->refcnt++;
-
- mutex_unlock(&driver_lock);
return 0;
err_rst:
pm_runtime_put(vdev->device);
-err_pm:
vfio_platform_irq_cleanup(vdev);
err_irq:
vfio_platform_regions_cleanup(vdev);
-err_reg:
- mutex_unlock(&driver_lock);
- module_put(THIS_MODULE);
return ret;
}
+EXPORT_SYMBOL_GPL(vfio_platform_open_device);
-static long vfio_platform_ioctl(void *device_data,
- unsigned int cmd, unsigned long arg)
+long vfio_platform_ioctl(struct vfio_device *core_vdev,
+ unsigned int cmd, unsigned long arg)
{
- struct vfio_platform_device *vdev = device_data;
+ struct vfio_platform_device *vdev =
+ container_of(core_vdev, struct vfio_platform_device, vdev);
+
unsigned long minsz;
if (cmd == VFIO_DEVICE_GET_INFO) {
@@ -400,6 +384,7 @@ static long vfio_platform_ioctl(void *device_data,
return -ENOTTY;
}
+EXPORT_SYMBOL_GPL(vfio_platform_ioctl);
static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg,
char __user *buf, size_t count,
@@ -456,10 +441,11 @@ err:
return -EFAULT;
}
-static ssize_t vfio_platform_read(void *device_data, char __user *buf,
- size_t count, loff_t *ppos)
+ssize_t vfio_platform_read(struct vfio_device *core_vdev,
+ char __user *buf, size_t count, loff_t *ppos)
{
- struct vfio_platform_device *vdev = device_data;
+ struct vfio_platform_device *vdev =
+ container_of(core_vdev, struct vfio_platform_device, vdev);
unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
@@ -477,6 +463,7 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(vfio_platform_read);
static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg,
const char __user *buf, size_t count,
@@ -532,10 +519,11 @@ err:
return -EFAULT;
}
-static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
- size_t count, loff_t *ppos)
+ssize_t vfio_platform_write(struct vfio_device *core_vdev, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- struct vfio_platform_device *vdev = device_data;
+ struct vfio_platform_device *vdev =
+ container_of(core_vdev, struct vfio_platform_device, vdev);
unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
@@ -553,6 +541,7 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(vfio_platform_write);
static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
struct vm_area_struct *vma)
@@ -574,9 +563,10 @@ static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
req_len, vma->vm_page_prot);
}
-static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+int vfio_platform_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma)
{
- struct vfio_platform_device *vdev = device_data;
+ struct vfio_platform_device *vdev =
+ container_of(core_vdev, struct vfio_platform_device, vdev);
unsigned int index;
index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
@@ -613,16 +603,7 @@ static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
return -EINVAL;
}
-
-static const struct vfio_device_ops vfio_platform_ops = {
- .name = "vfio-platform",
- .open = vfio_platform_open,
- .release = vfio_platform_release,
- .ioctl = vfio_platform_ioctl,
- .read = vfio_platform_read,
- .write = vfio_platform_write,
- .mmap = vfio_platform_mmap,
-};
+EXPORT_SYMBOL_GPL(vfio_platform_mmap);
static int vfio_platform_of_probe(struct vfio_platform_device *vdev,
struct device *dev)
@@ -654,14 +635,10 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev,
* If the firmware is ACPI type, then acpi_disabled is 0. All other checks are
* valid checks. We cannot claim that this system is DT.
*/
-int vfio_platform_probe_common(struct vfio_platform_device *vdev,
- struct device *dev)
+int vfio_platform_init_common(struct vfio_platform_device *vdev)
{
- struct iommu_group *group;
int ret;
-
- if (!vdev)
- return -EINVAL;
+ struct device *dev = vdev->vdev.dev;
ret = vfio_platform_acpi_probe(vdev, dev);
if (ret)
@@ -671,53 +648,21 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
return ret;
vdev->device = dev;
+ mutex_init(&vdev->igate);
ret = vfio_platform_get_reset(vdev);
- if (ret && vdev->reset_required) {
+ if (ret && vdev->reset_required)
dev_err(dev, "No reset function found for device %s\n",
vdev->name);
- return ret;
- }
-
- group = vfio_iommu_group_get(dev);
- if (!group) {
- dev_err(dev, "No IOMMU group for device %s\n", vdev->name);
- ret = -EINVAL;
- goto put_reset;
- }
-
- ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
- if (ret)
- goto put_iommu;
-
- mutex_init(&vdev->igate);
-
- pm_runtime_enable(vdev->device);
- return 0;
-
-put_iommu:
- vfio_iommu_group_put(group, dev);
-put_reset:
- vfio_platform_put_reset(vdev);
return ret;
}
-EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
+EXPORT_SYMBOL_GPL(vfio_platform_init_common);
-struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
+void vfio_platform_release_common(struct vfio_platform_device *vdev)
{
- struct vfio_platform_device *vdev;
-
- vdev = vfio_del_group_dev(dev);
-
- if (vdev) {
- pm_runtime_disable(vdev->device);
- vfio_platform_put_reset(vdev);
- vfio_iommu_group_put(dev->iommu_group, dev);
- }
-
- return vdev;
+ vfio_platform_put_reset(vdev);
}
-EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
+EXPORT_SYMBOL_GPL(vfio_platform_release_common);
void __vfio_platform_register_reset(struct vfio_platform_reset_node *node)
{