diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4673-drm-amdgpu-Dynamically-probe-for-ATIF-handle-v2.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4673-drm-amdgpu-Dynamically-probe-for-ATIF-handle-v2.patch | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4673-drm-amdgpu-Dynamically-probe-for-ATIF-handle-v2.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4673-drm-amdgpu-Dynamically-probe-for-ATIF-handle-v2.patch new file mode 100644 index 00000000..d4d629d8 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4673-drm-amdgpu-Dynamically-probe-for-ATIF-handle-v2.patch @@ -0,0 +1,234 @@ +From d928e306d055f05452f92a6b9cf6987969cee6a6 Mon Sep 17 00:00:00 2001 +From: Lyude Paul <lyude@redhat.com> +Date: Mon, 25 Jun 2018 21:09:07 -0400 +Subject: [PATCH 4673/5725] 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> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 79 +++++++++++++++++++++++--------- + 1 file 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 22c7e8e..0d8c3fc 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 { + }; + + struct amdgpu_atif { ++ acpi_handle handle; ++ + struct amdgpu_atif_notifications notifications; + struct amdgpu_atif_functions functions; + struct amdgpu_atif_notification_cfg notification_cfg; +@@ -83,8 +85,9 @@ struct amdgpu_atif { + * Executes the requested ATIF function (all asics). + * Returns a pointer to the acpi output buffer. + */ +-static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function, +- struct acpi_buffer *params) ++static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif, ++ int function, ++ struct acpi_buffer *params) + { + acpi_status status; + union acpi_object atif_arg_elements[2]; +@@ -107,7 +110,8 @@ static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function, + atif_arg_elements[1].integer.value = 0; + } + +- status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer); ++ status = acpi_evaluate_object(atif->handle, NULL, &atif_arg, ++ &buffer); + + /* Fail only if calling the method fails and ATIF is supported */ + 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 + * (all asics). + * returns 0 on success, error on failure. + */ +-static int amdgpu_atif_verify_interface(acpi_handle handle, +- struct amdgpu_atif *atif) ++static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif) + { + union acpi_object *info; + struct atif_verify_interface output; + size_t size; + int err = 0; + +- info = amdgpu_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); ++ info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); + if (!info) + return -EIO; + +@@ -213,6 +216,35 @@ static int amdgpu_atif_verify_interface(acpi_handle handle, + return err; + } + ++static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle) ++{ ++ acpi_handle handle = NULL; ++ char acpi_method_name[255] = { 0 }; ++ struct acpi_buffer buffer = { sizeof(acpi_method_name), acpi_method_name }; ++ acpi_status status; ++ ++ /* For PX/HG systems, ATIF and ATPX are in the iGPU's namespace, on dGPU only ++ * systems, ATIF is in the dGPU's namespace. ++ */ ++ status = acpi_get_handle(dhandle, "ATIF", &handle); ++ if (ACPI_SUCCESS(status)) ++ goto out; ++ ++ if (amdgpu_has_atpx()) { ++ status = acpi_get_handle(amdgpu_atpx_get_dhandle(), "ATIF", ++ &handle); ++ if (ACPI_SUCCESS(status)) ++ goto out; ++ } ++ ++ DRM_DEBUG_DRIVER("No ATIF handle found\n"); ++ return NULL; ++out: ++ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); ++ DRM_DEBUG_DRIVER("Found ATIF handle %s\n", acpi_method_name); ++ return handle; ++} ++ + /** + * amdgpu_atif_get_notification_params - determine notify configuration + * +@@ -225,15 +257,16 @@ static int amdgpu_atif_verify_interface(acpi_handle handle, + * where n is specified in the result if a notifier is used. + * Returns 0 on success, error on failure. + */ +-static int amdgpu_atif_get_notification_params(acpi_handle handle, +- struct amdgpu_atif_notification_cfg *n) ++static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif) + { + union acpi_object *info; ++ struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg; + struct atif_system_params params; + size_t size; + int err = 0; + +- info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); ++ info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, ++ NULL); + if (!info) { + err = -EIO; + goto out; +@@ -287,14 +320,15 @@ static int amdgpu_atif_get_notification_params(acpi_handle handle, + * (all asics). + * Returns 0 on success, error on failure. + */ +-static int amdgpu_atif_get_sbios_requests(acpi_handle handle, +- struct atif_sbios_requests *req) ++static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif, ++ struct atif_sbios_requests *req) + { + union acpi_object *info; + size_t size; + int count = 0; + +- info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); ++ info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, ++ NULL); + if (!info) + return -EIO; + +@@ -327,11 +361,10 @@ static int amdgpu_atif_get_sbios_requests(acpi_handle handle, + * Returns NOTIFY code + */ + static int amdgpu_atif_handler(struct amdgpu_device *adev, +- struct acpi_bus_event *event) ++ struct acpi_bus_event *event) + { + struct amdgpu_atif *atif = adev->atif; + struct atif_sbios_requests req; +- acpi_handle handle; + int count; + + DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n", +@@ -347,8 +380,7 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev, + return NOTIFY_DONE; + + /* Check pending SBIOS requests */ +- handle = ACPI_HANDLE(&adev->pdev->dev); +- count = amdgpu_atif_get_sbios_requests(handle, &req); ++ count = amdgpu_atif_get_sbios_requests(atif, &req); + + if (count <= 0) + return NOTIFY_DONE; +@@ -679,7 +711,7 @@ static int amdgpu_acpi_event(struct notifier_block *nb, + */ + int amdgpu_acpi_init(struct amdgpu_device *adev) + { +- acpi_handle handle; ++ acpi_handle handle, atif_handle; + struct amdgpu_atif *atif; + struct amdgpu_atcs *atcs = &adev->atcs; + int ret; +@@ -696,14 +728,20 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) + DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); + } + +- /* Call the ATIF method */ ++ /* Probe for ATIF, and initialize it if found */ ++ atif_handle = amdgpu_atif_probe_handle(handle); ++ if (!atif_handle) ++ goto out; ++ + atif = kzalloc(sizeof(*atif), GFP_KERNEL); + if (!atif) { + DRM_WARN("Not enough memory to initialize ATIF\n"); + goto out; + } ++ atif->handle = atif_handle; + +- ret = amdgpu_atif_verify_interface(handle, atif); ++ /* Call the ATIF method */ ++ ret = amdgpu_atif_verify_interface(atif); + if (ret) { + DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); + kfree(atif); +@@ -739,8 +777,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) + } + + if (atif->functions.system_params) { +- ret = amdgpu_atif_get_notification_params(handle, +- &atif->notification_cfg); ++ ret = amdgpu_atif_get_notification_params(atif); + if (ret) { + DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", + ret); +-- +2.7.4 + |