diff options
author | Eric Auger <eric.auger@linaro.org> | 2015-06-15 05:09:44 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2015-06-22 11:35:30 -0400 |
commit | 3eeb0d510c65e777030156f03c116393095a3248 (patch) | |
tree | 078e388fa2c34850a13668efd4499673ed92d506 /drivers/vfio | |
parent | 813ae66008aeb97a48f20efefeb962179b642dbe (diff) |
VFIO: platform: populate the reset function on probe
The reset function lookup happens on vfio-platform probe. The reset
module load is requested and a reference to the function symbol is
hold. The reference is released on vfio-platform remove.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Acked-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Tested-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r-- | drivers/vfio/platform/vfio_platform_common.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index 63935811cbd9..f3391a93bc0c 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c | |||
@@ -28,6 +28,36 @@ static DEFINE_MUTEX(driver_lock); | |||
28 | static const struct vfio_platform_reset_combo reset_lookup_table[] = { | 28 | static const struct vfio_platform_reset_combo reset_lookup_table[] = { |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static void vfio_platform_get_reset(struct vfio_platform_device *vdev, | ||
32 | struct device *dev) | ||
33 | { | ||
34 | const char *compat; | ||
35 | int (*reset)(struct vfio_platform_device *); | ||
36 | int ret, i; | ||
37 | |||
38 | ret = device_property_read_string(dev, "compatible", &compat); | ||
39 | if (ret) | ||
40 | return; | ||
41 | |||
42 | for (i = 0 ; i < ARRAY_SIZE(reset_lookup_table); i++) { | ||
43 | if (!strcmp(reset_lookup_table[i].compat, compat)) { | ||
44 | request_module(reset_lookup_table[i].module_name); | ||
45 | reset = __symbol_get( | ||
46 | reset_lookup_table[i].reset_function_name); | ||
47 | if (reset) { | ||
48 | vdev->reset = reset; | ||
49 | return; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static void vfio_platform_put_reset(struct vfio_platform_device *vdev) | ||
56 | { | ||
57 | if (vdev->reset) | ||
58 | symbol_put_addr(vdev->reset); | ||
59 | } | ||
60 | |||
31 | static int vfio_platform_regions_init(struct vfio_platform_device *vdev) | 61 | static int vfio_platform_regions_init(struct vfio_platform_device *vdev) |
32 | { | 62 | { |
33 | int cnt = 0, i; | 63 | int cnt = 0, i; |
@@ -516,6 +546,8 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev, | |||
516 | return ret; | 546 | return ret; |
517 | } | 547 | } |
518 | 548 | ||
549 | vfio_platform_get_reset(vdev, dev); | ||
550 | |||
519 | mutex_init(&vdev->igate); | 551 | mutex_init(&vdev->igate); |
520 | 552 | ||
521 | return 0; | 553 | return 0; |
@@ -527,8 +559,11 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev) | |||
527 | struct vfio_platform_device *vdev; | 559 | struct vfio_platform_device *vdev; |
528 | 560 | ||
529 | vdev = vfio_del_group_dev(dev); | 561 | vdev = vfio_del_group_dev(dev); |
530 | if (vdev) | 562 | |
563 | if (vdev) { | ||
564 | vfio_platform_put_reset(vdev); | ||
531 | iommu_group_put(dev->iommu_group); | 565 | iommu_group_put(dev->iommu_group); |
566 | } | ||
532 | 567 | ||
533 | return vdev; | 568 | return vdev; |
534 | } | 569 | } |