aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2018-06-25 21:09:07 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-07-05 17:38:58 -0400
commit280cf1a94b822dfa2b505afcd24979dae643d6bf (patch)
treebf12d79706817954085823cc6b3808a49fff87df /drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
parent24aeefcdee255d21cc43bb511d5fdb760062199d (diff)
drm/amdgpu: Dynamically probe for ATIF handle (v2)
The other day I was testing one of the HP laptops at my office with an i915/amdgpu hybrid setup and noticed that hotplugging was non-functional on almost all of the display outputs. I eventually discovered that all of the external outputs were connected to the amdgpu device instead of i915, and that the hotplugs weren't being detected so long as the GPU was in runtime suspend. After some talking with folks at AMD, I learned that amdgpu is actually supposed to support hotplug detection in runtime suspend so long as the OEM has implemented it properly in the firmware. On this HP ZBook 15 G4 (the machine in question), amdgpu wasn't managing to find the ATIF handle at all despite the fact that I could see acpi events being sent in response to any hotplugging. After going through dumps of the firmware, I discovered that this machine did in fact support ATIF, but that it's ATIF method lived in an entirely different namespace than this device's handle (the device handle was \_SB_.PCI0.PEG0.PEGP, but ATIF lives in ATPX's handle at \_SB_.PCI0.GFX0). So, fix this by probing ATPX's ACPI parent's namespace if we can't find ATIF elsewhere, along with storing a pointer to the proper handle to use for ATIF and using that instead of the device's handle. This fixes HPD detection while in runtime suspend for this ZBook! v2: Update the comment to reflect how the namespaces are arranged based on the system configuration. (Alex) Signed-off-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 22c7e8ec0b9a..0d8c3fc6eace 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -65,6 +65,8 @@ struct amdgpu_atif_functions {
65}; 65};
66 66
67struct amdgpu_atif { 67struct amdgpu_atif {
68 acpi_handle handle;
69
68 struct amdgpu_atif_notifications notifications; 70 struct amdgpu_atif_notifications notifications;
69 struct amdgpu_atif_functions functions; 71 struct amdgpu_atif_functions functions;
70 struct amdgpu_atif_notification_cfg notification_cfg; 72 struct amdgpu_atif_notification_cfg notification_cfg;
@@ -83,8 +85,9 @@ struct amdgpu_atif {
83 * Executes the requested ATIF function (all asics). 85 * Executes the requested ATIF function (all asics).
84 * Returns a pointer to the acpi output buffer. 86 * Returns a pointer to the acpi output buffer.
85 */ 87 */
86static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function, 88static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
87 struct acpi_buffer *params) 89 int function,
90 struct acpi_buffer *params)
88{ 91{
89 acpi_status status; 92 acpi_status status;
90 union acpi_object atif_arg_elements[2]; 93 union acpi_object atif_arg_elements[2];
@@ -107,7 +110,8 @@ static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function,
107 atif_arg_elements[1].integer.value = 0; 110 atif_arg_elements[1].integer.value = 0;
108 } 111 }
109 112
110 status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer); 113 status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
114 &buffer);
111 115
112 /* Fail only if calling the method fails and ATIF is supported */ 116 /* Fail only if calling the method fails and ATIF is supported */
113 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 117 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
@@ -178,15 +182,14 @@ static void amdgpu_atif_parse_functions(struct amdgpu_atif_functions *f, u32 mas
178 * (all asics). 182 * (all asics).
179 * returns 0 on success, error on failure. 183 * returns 0 on success, error on failure.
180 */ 184 */
181static int amdgpu_atif_verify_interface(acpi_handle handle, 185static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif)
182 struct amdgpu_atif *atif)
183{ 186{
184 union acpi_object *info; 187 union acpi_object *info;
185 struct atif_verify_interface output; 188 struct atif_verify_interface output;
186 size_t size; 189 size_t size;
187 int err = 0; 190 int err = 0;
188 191
189 info = amdgpu_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); 192 info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
190 if (!info) 193 if (!info)
191 return -EIO; 194 return -EIO;
192 195
@@ -213,6 +216,35 @@ out:
213 return err; 216 return err;
214} 217}
215 218
219static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle)
220{
221 acpi_handle handle = NULL;
222 char acpi_method_name[255] = { 0 };
223 struct acpi_buffer buffer = { sizeof(acpi_method_name), acpi_method_name };
224 acpi_status status;
225
226 /* For PX/HG systems, ATIF and ATPX are in the iGPU's namespace, on dGPU only
227 * systems, ATIF is in the dGPU's namespace.
228 */
229 status = acpi_get_handle(dhandle, "ATIF", &handle);
230 if (ACPI_SUCCESS(status))
231 goto out;
232
233 if (amdgpu_has_atpx()) {
234 status = acpi_get_handle(amdgpu_atpx_get_dhandle(), "ATIF",
235 &handle);
236 if (ACPI_SUCCESS(status))
237 goto out;
238 }
239
240 DRM_DEBUG_DRIVER("No ATIF handle found\n");
241 return NULL;
242out:
243 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
244 DRM_DEBUG_DRIVER("Found ATIF handle %s\n", acpi_method_name);
245 return handle;
246}
247
216/** 248/**
217 * amdgpu_atif_get_notification_params - determine notify configuration 249 * amdgpu_atif_get_notification_params - determine notify configuration
218 * 250 *
@@ -225,15 +257,16 @@ out:
225 * where n is specified in the result if a notifier is used. 257 * where n is specified in the result if a notifier is used.
226 * Returns 0 on success, error on failure. 258 * Returns 0 on success, error on failure.
227 */ 259 */
228static int amdgpu_atif_get_notification_params(acpi_handle handle, 260static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif)
229 struct amdgpu_atif_notification_cfg *n)
230{ 261{
231 union acpi_object *info; 262 union acpi_object *info;
263 struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg;
232 struct atif_system_params params; 264 struct atif_system_params params;
233 size_t size; 265 size_t size;
234 int err = 0; 266 int err = 0;
235 267
236 info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); 268 info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS,
269 NULL);
237 if (!info) { 270 if (!info) {
238 err = -EIO; 271 err = -EIO;
239 goto out; 272 goto out;
@@ -287,14 +320,15 @@ out:
287 * (all asics). 320 * (all asics).
288 * Returns 0 on success, error on failure. 321 * Returns 0 on success, error on failure.
289 */ 322 */
290static int amdgpu_atif_get_sbios_requests(acpi_handle handle, 323static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif,
291 struct atif_sbios_requests *req) 324 struct atif_sbios_requests *req)
292{ 325{
293 union acpi_object *info; 326 union acpi_object *info;
294 size_t size; 327 size_t size;
295 int count = 0; 328 int count = 0;
296 329
297 info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); 330 info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS,
331 NULL);
298 if (!info) 332 if (!info)
299 return -EIO; 333 return -EIO;
300 334
@@ -327,11 +361,10 @@ out:
327 * Returns NOTIFY code 361 * Returns NOTIFY code
328 */ 362 */
329static int amdgpu_atif_handler(struct amdgpu_device *adev, 363static int amdgpu_atif_handler(struct amdgpu_device *adev,
330 struct acpi_bus_event *event) 364 struct acpi_bus_event *event)
331{ 365{
332 struct amdgpu_atif *atif = adev->atif; 366 struct amdgpu_atif *atif = adev->atif;
333 struct atif_sbios_requests req; 367 struct atif_sbios_requests req;
334 acpi_handle handle;
335 int count; 368 int count;
336 369
337 DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n", 370 DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n",
@@ -347,8 +380,7 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
347 return NOTIFY_DONE; 380 return NOTIFY_DONE;
348 381
349 /* Check pending SBIOS requests */ 382 /* Check pending SBIOS requests */
350 handle = ACPI_HANDLE(&adev->pdev->dev); 383 count = amdgpu_atif_get_sbios_requests(atif, &req);
351 count = amdgpu_atif_get_sbios_requests(handle, &req);
352 384
353 if (count <= 0) 385 if (count <= 0)
354 return NOTIFY_DONE; 386 return NOTIFY_DONE;
@@ -679,7 +711,7 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
679 */ 711 */
680int amdgpu_acpi_init(struct amdgpu_device *adev) 712int amdgpu_acpi_init(struct amdgpu_device *adev)
681{ 713{
682 acpi_handle handle; 714 acpi_handle handle, atif_handle;
683 struct amdgpu_atif *atif; 715 struct amdgpu_atif *atif;
684 struct amdgpu_atcs *atcs = &adev->atcs; 716 struct amdgpu_atcs *atcs = &adev->atcs;
685 int ret; 717 int ret;
@@ -696,14 +728,20 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
696 DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); 728 DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
697 } 729 }
698 730
699 /* Call the ATIF method */ 731 /* Probe for ATIF, and initialize it if found */
732 atif_handle = amdgpu_atif_probe_handle(handle);
733 if (!atif_handle)
734 goto out;
735
700 atif = kzalloc(sizeof(*atif), GFP_KERNEL); 736 atif = kzalloc(sizeof(*atif), GFP_KERNEL);
701 if (!atif) { 737 if (!atif) {
702 DRM_WARN("Not enough memory to initialize ATIF\n"); 738 DRM_WARN("Not enough memory to initialize ATIF\n");
703 goto out; 739 goto out;
704 } 740 }
741 atif->handle = atif_handle;
705 742
706 ret = amdgpu_atif_verify_interface(handle, atif); 743 /* Call the ATIF method */
744 ret = amdgpu_atif_verify_interface(atif);
707 if (ret) { 745 if (ret) {
708 DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); 746 DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret);
709 kfree(atif); 747 kfree(atif);
@@ -739,8 +777,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
739 } 777 }
740 778
741 if (atif->functions.system_params) { 779 if (atif->functions.system_params) {
742 ret = amdgpu_atif_get_notification_params(handle, 780 ret = amdgpu_atif_get_notification_params(atif);
743 &atif->notification_cfg);
744 if (ret) { 781 if (ret) {
745 DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", 782 DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
746 ret); 783 ret);