|
|
@@ -28,6 +28,36 @@ static DEFINE_MUTEX(driver_lock);
|
|
|
static const struct vfio_platform_reset_combo reset_lookup_table[] = {
|
|
|
};
|
|
|
|
|
|
+static void vfio_platform_get_reset(struct vfio_platform_device *vdev,
|
|
|
+ struct device *dev)
|
|
|
+{
|
|
|
+ const char *compat;
|
|
|
+ int (*reset)(struct vfio_platform_device *);
|
|
|
+ int ret, i;
|
|
|
+
|
|
|
+ ret = device_property_read_string(dev, "compatible", &compat);
|
|
|
+ if (ret)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (i = 0 ; i < ARRAY_SIZE(reset_lookup_table); i++) {
|
|
|
+ if (!strcmp(reset_lookup_table[i].compat, compat)) {
|
|
|
+ request_module(reset_lookup_table[i].module_name);
|
|
|
+ reset = __symbol_get(
|
|
|
+ reset_lookup_table[i].reset_function_name);
|
|
|
+ if (reset) {
|
|
|
+ vdev->reset = reset;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
|
|
|
+{
|
|
|
+ if (vdev->reset)
|
|
|
+ symbol_put_addr(vdev->reset);
|
|
|
+}
|
|
|
+
|
|
|
static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
|
|
|
{
|
|
|
int cnt = 0, i;
|
|
|
@@ -516,6 +546,8 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ vfio_platform_get_reset(vdev, dev);
|
|
|
+
|
|
|
mutex_init(&vdev->igate);
|
|
|
|
|
|
return 0;
|
|
|
@@ -527,8 +559,11 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
|
|
|
struct vfio_platform_device *vdev;
|
|
|
|
|
|
vdev = vfio_del_group_dev(dev);
|
|
|
- if (vdev)
|
|
|
+
|
|
|
+ if (vdev) {
|
|
|
+ vfio_platform_put_reset(vdev);
|
|
|
iommu_group_put(dev->iommu_group);
|
|
|
+ }
|
|
|
|
|
|
return vdev;
|
|
|
}
|