diff options
author | Sinan Kaya <okaya@codeaurora.org> | 2016-07-19 09:01:46 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2016-07-19 12:26:44 -0400 |
commit | d30daa33ec1d035acfdfc7662d7a5360592af44c (patch) | |
tree | 1ce71778d5c55adade4c911258d797028359d35b | |
parent | 5afec27474fdc52e9d80b359ce10fab59c85d131 (diff) |
vfio: platform: call _RST method when using ACPI
The device tree code checks for the presence of a reset driver and calls
the of_reset function pointer by looking up the reset driver as a module.
ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device. _RST method is
expected to stop DMA transfers and IRQs.
This patch introduces two functions as vfio_platform_acpi_has_reset and
vfio_platform_acpi_call_reset. The has reset method is used to declare
reset capability via the ioctl flag VFIO_DEVICE_FLAGS_RESET. The call
reset function is used to execute the _RST ACPI method.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r-- | drivers/vfio/platform/vfio_platform_common.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index a9760c2e68ad..a15a69b52080 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>" | 28 | #define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>" |
29 | #define DRIVER_DESC "VFIO platform base module" | 29 | #define DRIVER_DESC "VFIO platform base module" |
30 | 30 | ||
31 | #define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL) | ||
32 | |||
31 | static LIST_HEAD(reset_list); | 33 | static LIST_HEAD(reset_list); |
32 | static DEFINE_MUTEX(driver_lock); | 34 | static DEFINE_MUTEX(driver_lock); |
33 | 35 | ||
@@ -71,13 +73,53 @@ static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, | |||
71 | return WARN_ON(!vdev->acpihid) ? -EINVAL : 0; | 73 | return WARN_ON(!vdev->acpihid) ? -EINVAL : 0; |
72 | } | 74 | } |
73 | 75 | ||
76 | int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev, | ||
77 | const char **extra_dbg) | ||
78 | { | ||
79 | #ifdef CONFIG_ACPI | ||
80 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
81 | struct device *dev = vdev->device; | ||
82 | acpi_handle handle = ACPI_HANDLE(dev); | ||
83 | acpi_status acpi_ret; | ||
84 | |||
85 | acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, &buffer); | ||
86 | if (ACPI_FAILURE(acpi_ret)) { | ||
87 | if (extra_dbg) | ||
88 | *extra_dbg = acpi_format_exception(acpi_ret); | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | #else | ||
94 | return -ENOENT; | ||
95 | #endif | ||
96 | } | ||
97 | |||
98 | bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev) | ||
99 | { | ||
100 | #ifdef CONFIG_ACPI | ||
101 | struct device *dev = vdev->device; | ||
102 | acpi_handle handle = ACPI_HANDLE(dev); | ||
103 | |||
104 | return acpi_has_method(handle, "_RST"); | ||
105 | #else | ||
106 | return false; | ||
107 | #endif | ||
108 | } | ||
109 | |||
74 | static bool vfio_platform_has_reset(struct vfio_platform_device *vdev) | 110 | static bool vfio_platform_has_reset(struct vfio_platform_device *vdev) |
75 | { | 111 | { |
112 | if (VFIO_PLATFORM_IS_ACPI(vdev)) | ||
113 | return vfio_platform_acpi_has_reset(vdev); | ||
114 | |||
76 | return vdev->of_reset ? true : false; | 115 | return vdev->of_reset ? true : false; |
77 | } | 116 | } |
78 | 117 | ||
79 | static void vfio_platform_get_reset(struct vfio_platform_device *vdev) | 118 | static void vfio_platform_get_reset(struct vfio_platform_device *vdev) |
80 | { | 119 | { |
120 | if (VFIO_PLATFORM_IS_ACPI(vdev)) | ||
121 | return; | ||
122 | |||
81 | vdev->of_reset = vfio_platform_lookup_reset(vdev->compat, | 123 | vdev->of_reset = vfio_platform_lookup_reset(vdev->compat, |
82 | &vdev->reset_module); | 124 | &vdev->reset_module); |
83 | if (!vdev->of_reset) { | 125 | if (!vdev->of_reset) { |
@@ -89,6 +131,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev) | |||
89 | 131 | ||
90 | static void vfio_platform_put_reset(struct vfio_platform_device *vdev) | 132 | static void vfio_platform_put_reset(struct vfio_platform_device *vdev) |
91 | { | 133 | { |
134 | if (VFIO_PLATFORM_IS_ACPI(vdev)) | ||
135 | return; | ||
136 | |||
92 | if (vdev->of_reset) | 137 | if (vdev->of_reset) |
93 | module_put(vdev->reset_module); | 138 | module_put(vdev->reset_module); |
94 | } | 139 | } |
@@ -164,7 +209,10 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev) | |||
164 | static int vfio_platform_call_reset(struct vfio_platform_device *vdev, | 209 | static int vfio_platform_call_reset(struct vfio_platform_device *vdev, |
165 | const char **extra_dbg) | 210 | const char **extra_dbg) |
166 | { | 211 | { |
167 | if (vdev->of_reset) { | 212 | if (VFIO_PLATFORM_IS_ACPI(vdev)) { |
213 | dev_info(vdev->device, "reset\n"); | ||
214 | return vfio_platform_acpi_call_reset(vdev, extra_dbg); | ||
215 | } else if (vdev->of_reset) { | ||
168 | dev_info(vdev->device, "reset\n"); | 216 | dev_info(vdev->device, "reset\n"); |
169 | return vdev->of_reset(vdev); | 217 | return vdev->of_reset(vdev); |
170 | } | 218 | } |