Skip to content

Commit f9ff685

Browse files
Lyudealexdeucher
authored andcommitted
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 <[email protected]> Signed-off-by: Alex Deucher <[email protected]> Cc: [email protected]
1 parent 4aa5d5e commit f9ff685

File tree

1 file changed

+58
-21
lines changed

1 file changed

+58
-21
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ struct amdgpu_atif_functions {
6565
};
6666

6767
struct amdgpu_atif {
68+
acpi_handle handle;
69+
6870
struct amdgpu_atif_notifications notifications;
6971
struct amdgpu_atif_functions functions;
7072
struct amdgpu_atif_notification_cfg notification_cfg;
@@ -83,8 +85,9 @@ struct amdgpu_atif {
8385
* Executes the requested ATIF function (all asics).
8486
* Returns a pointer to the acpi output buffer.
8587
*/
86-
static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function,
87-
struct acpi_buffer *params)
88+
static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
89+
int function,
90+
struct acpi_buffer *params)
8891
{
8992
acpi_status status;
9093
union acpi_object atif_arg_elements[2];
@@ -107,7 +110,8 @@ static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function,
107110
atif_arg_elements[1].integer.value = 0;
108111
}
109112

110-
status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer);
113+
status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
114+
&buffer);
111115

112116
/* Fail only if calling the method fails and ATIF is supported */
113117
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
178182
* (all asics).
179183
* returns 0 on success, error on failure.
180184
*/
181-
static int amdgpu_atif_verify_interface(acpi_handle handle,
182-
struct amdgpu_atif *atif)
185+
static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif)
183186
{
184187
union acpi_object *info;
185188
struct atif_verify_interface output;
186189
size_t size;
187190
int err = 0;
188191

189-
info = amdgpu_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
192+
info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
190193
if (!info)
191194
return -EIO;
192195

@@ -213,6 +216,35 @@ static int amdgpu_atif_verify_interface(acpi_handle handle,
213216
return err;
214217
}
215218

219+
static 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;
242+
out:
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+
216248
/**
217249
* amdgpu_atif_get_notification_params - determine notify configuration
218250
*
@@ -225,15 +257,16 @@ static int amdgpu_atif_verify_interface(acpi_handle handle,
225257
* where n is specified in the result if a notifier is used.
226258
* Returns 0 on success, error on failure.
227259
*/
228-
static int amdgpu_atif_get_notification_params(acpi_handle handle,
229-
struct amdgpu_atif_notification_cfg *n)
260+
static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif)
230261
{
231262
union acpi_object *info;
263+
struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg;
232264
struct atif_system_params params;
233265
size_t size;
234266
int err = 0;
235267

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);
237270
if (!info) {
238271
err = -EIO;
239272
goto out;
@@ -287,14 +320,15 @@ static int amdgpu_atif_get_notification_params(acpi_handle handle,
287320
* (all asics).
288321
* Returns 0 on success, error on failure.
289322
*/
290-
static int amdgpu_atif_get_sbios_requests(acpi_handle handle,
291-
struct atif_sbios_requests *req)
323+
static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif,
324+
struct atif_sbios_requests *req)
292325
{
293326
union acpi_object *info;
294327
size_t size;
295328
int count = 0;
296329

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);
298332
if (!info)
299333
return -EIO;
300334

@@ -327,11 +361,10 @@ static int amdgpu_atif_get_sbios_requests(acpi_handle handle,
327361
* Returns NOTIFY code
328362
*/
329363
static int amdgpu_atif_handler(struct amdgpu_device *adev,
330-
struct acpi_bus_event *event)
364+
struct acpi_bus_event *event)
331365
{
332366
struct amdgpu_atif *atif = adev->atif;
333367
struct atif_sbios_requests req;
334-
acpi_handle handle;
335368
int count;
336369

337370
DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n",
@@ -347,8 +380,7 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
347380
return NOTIFY_DONE;
348381

349382
/* Check pending SBIOS requests */
350-
handle = ACPI_HANDLE(&adev->pdev->dev);
351-
count = amdgpu_atif_get_sbios_requests(handle, &req);
383+
count = amdgpu_atif_get_sbios_requests(atif, &req);
352384

353385
if (count <= 0)
354386
return NOTIFY_DONE;
@@ -679,7 +711,7 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
679711
*/
680712
int amdgpu_acpi_init(struct amdgpu_device *adev)
681713
{
682-
acpi_handle handle;
714+
acpi_handle handle, atif_handle;
683715
struct amdgpu_atif *atif;
684716
struct amdgpu_atcs *atcs = &adev->atcs;
685717
int ret;
@@ -696,14 +728,20 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
696728
DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
697729
}
698730

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+
700736
atif = kzalloc(sizeof(*atif), GFP_KERNEL);
701737
if (!atif) {
702738
DRM_WARN("Not enough memory to initialize ATIF\n");
703739
goto out;
704740
}
741+
atif->handle = atif_handle;
705742

706-
ret = amdgpu_atif_verify_interface(handle, atif);
743+
/* Call the ATIF method */
744+
ret = amdgpu_atif_verify_interface(atif);
707745
if (ret) {
708746
DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret);
709747
kfree(atif);
@@ -739,8 +777,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
739777
}
740778

741779
if (atif->functions.system_params) {
742-
ret = amdgpu_atif_get_notification_params(handle,
743-
&atif->notification_cfg);
780+
ret = amdgpu_atif_get_notification_params(atif);
744781
if (ret) {
745782
DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
746783
ret);

0 commit comments

Comments
 (0)