Commit 77bf762f authored by Alex Deucher's avatar Alex Deucher

drm/amdgpu/acpi: unify ATCS handling (v3)

Treat it like ATIF and check both the dGPU and APU for
the method.  This is required because ATCS may be hung
off of the APU in ACPI on A+A systems.

v2: add back accidently removed ACPI handle check.
v3: Fix incorrect atif check (Colin)
    Fix uninitialized variable (Colin)
Reviewed-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent cd11b58c
...@@ -269,6 +269,7 @@ struct amdgpu_irq_src; ...@@ -269,6 +269,7 @@ struct amdgpu_irq_src;
struct amdgpu_fpriv; struct amdgpu_fpriv;
struct amdgpu_bo_va_mapping; struct amdgpu_bo_va_mapping;
struct amdgpu_atif; struct amdgpu_atif;
struct amdgpu_atcs;
struct kfd_vm_fault_info; struct kfd_vm_fault_info;
struct amdgpu_hive_info; struct amdgpu_hive_info;
struct amdgpu_reset_context; struct amdgpu_reset_context;
...@@ -682,20 +683,6 @@ struct amdgpu_vram_scratch { ...@@ -682,20 +683,6 @@ struct amdgpu_vram_scratch {
u64 gpu_addr; u64 gpu_addr;
}; };
/*
* ACPI
*/
struct amdgpu_atcs_functions {
bool get_ext_state;
bool pcie_perf_req;
bool pcie_dev_rdy;
bool pcie_bus_width;
};
struct amdgpu_atcs {
struct amdgpu_atcs_functions functions;
};
/* /*
* CGS * CGS
*/ */
...@@ -826,7 +813,7 @@ struct amdgpu_device { ...@@ -826,7 +813,7 @@ struct amdgpu_device {
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS]; struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
struct debugfs_blob_wrapper debugfs_vbios_blob; struct debugfs_blob_wrapper debugfs_vbios_blob;
struct amdgpu_atif *atif; struct amdgpu_atif *atif;
struct amdgpu_atcs atcs; struct amdgpu_atcs *atcs;
struct mutex srbm_mutex; struct mutex srbm_mutex;
/* GRBM index mutex. Protects concurrent access to GRBM index */ /* GRBM index mutex. Protects concurrent access to GRBM index */
struct mutex grbm_idx_mutex; struct mutex grbm_idx_mutex;
......
...@@ -71,12 +71,25 @@ struct amdgpu_atif { ...@@ -71,12 +71,25 @@ struct amdgpu_atif {
struct amdgpu_dm_backlight_caps backlight_caps; struct amdgpu_dm_backlight_caps backlight_caps;
}; };
struct amdgpu_atcs_functions {
bool get_ext_state;
bool pcie_perf_req;
bool pcie_dev_rdy;
bool pcie_bus_width;
};
struct amdgpu_atcs {
acpi_handle handle;
struct amdgpu_atcs_functions functions;
};
/* Call the ATIF method /* Call the ATIF method
*/ */
/** /**
* amdgpu_atif_call - call an ATIF method * amdgpu_atif_call - call an ATIF method
* *
* @atif: acpi handle * @atif: atif structure
* @function: the ATIF function to execute * @function: the ATIF function to execute
* @params: ATIF function params * @params: ATIF function params
* *
...@@ -236,6 +249,35 @@ static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle) ...@@ -236,6 +249,35 @@ static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle)
return handle; return handle;
} }
static acpi_handle amdgpu_atcs_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, ATCS and ATPX are in the iGPU's namespace, on dGPU only
* systems, ATIF is in the dGPU's namespace.
*/
status = acpi_get_handle(dhandle, "ATCS", &handle);
if (ACPI_SUCCESS(status))
goto out;
if (amdgpu_has_atpx()) {
status = acpi_get_handle(amdgpu_atpx_get_dhandle(), "ATCS",
&handle);
if (ACPI_SUCCESS(status))
goto out;
}
DRM_DEBUG_DRIVER("No ATCS handle found\n");
return NULL;
out:
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
DRM_DEBUG_DRIVER("Found ATCS handle %s\n", acpi_method_name);
return handle;
}
/** /**
* amdgpu_atif_get_notification_params - determine notify configuration * amdgpu_atif_get_notification_params - determine notify configuration
* *
...@@ -485,14 +527,15 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev, ...@@ -485,14 +527,15 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
/** /**
* amdgpu_atcs_call - call an ATCS method * amdgpu_atcs_call - call an ATCS method
* *
* @handle: acpi handle * @atcs: atcs structure
* @function: the ATCS function to execute * @function: the ATCS function to execute
* @params: ATCS function params * @params: ATCS function params
* *
* Executes the requested ATCS function (all asics). * Executes the requested ATCS function (all asics).
* Returns a pointer to the acpi output buffer. * Returns a pointer to the acpi output buffer.
*/ */
static union acpi_object *amdgpu_atcs_call(acpi_handle handle, int function, static union acpi_object *amdgpu_atcs_call(struct amdgpu_atcs *atcs,
int function,
struct acpi_buffer *params) struct acpi_buffer *params)
{ {
acpi_status status; acpi_status status;
...@@ -516,7 +559,7 @@ static union acpi_object *amdgpu_atcs_call(acpi_handle handle, int function, ...@@ -516,7 +559,7 @@ static union acpi_object *amdgpu_atcs_call(acpi_handle handle, int function,
atcs_arg_elements[1].integer.value = 0; atcs_arg_elements[1].integer.value = 0;
} }
status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer); status = acpi_evaluate_object(atcs->handle, "ATCS", &atcs_arg, &buffer);
/* Fail only if calling the method fails and ATIF is supported */ /* Fail only if calling the method fails and ATIF is supported */
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
...@@ -550,7 +593,6 @@ static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mas ...@@ -550,7 +593,6 @@ static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mas
/** /**
* amdgpu_atcs_verify_interface - verify ATCS * amdgpu_atcs_verify_interface - verify ATCS
* *
* @handle: acpi handle
* @atcs: amdgpu atcs struct * @atcs: amdgpu atcs struct
* *
* Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function
...@@ -558,15 +600,14 @@ static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mas ...@@ -558,15 +600,14 @@ static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mas
* (all asics). * (all asics).
* returns 0 on success, error on failure. * returns 0 on success, error on failure.
*/ */
static int amdgpu_atcs_verify_interface(acpi_handle handle, static int amdgpu_atcs_verify_interface(struct amdgpu_atcs *atcs)
struct amdgpu_atcs *atcs)
{ {
union acpi_object *info; union acpi_object *info;
struct atcs_verify_interface output; struct atcs_verify_interface output;
size_t size; size_t size;
int err = 0; int err = 0;
info = amdgpu_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL); info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_VERIFY_INTERFACE, NULL);
if (!info) if (!info)
return -EIO; return -EIO;
...@@ -603,8 +644,10 @@ static int amdgpu_atcs_verify_interface(acpi_handle handle, ...@@ -603,8 +644,10 @@ static int amdgpu_atcs_verify_interface(acpi_handle handle,
*/ */
bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev) bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev)
{ {
struct amdgpu_atcs *atcs = &adev->atcs; struct amdgpu_atcs *atcs = adev->atcs;
if (!atcs)
return false;
if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy) if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy)
return true; return true;
...@@ -622,19 +665,15 @@ bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *ade ...@@ -622,19 +665,15 @@ bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *ade
*/ */
int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev) int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev)
{ {
acpi_handle handle;
union acpi_object *info; union acpi_object *info;
struct amdgpu_atcs *atcs = &adev->atcs; struct amdgpu_atcs *atcs = adev->atcs;
/* Get the device handle */ if (!atcs)
handle = ACPI_HANDLE(&adev->pdev->dev);
if (!handle)
return -EINVAL; return -EINVAL;
if (!atcs->functions.pcie_dev_rdy) if (!atcs->functions.pcie_dev_rdy)
return -EINVAL; return -EINVAL;
info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL); info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL);
if (!info) if (!info)
return -EIO; return -EIO;
...@@ -657,21 +696,18 @@ int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev) ...@@ -657,21 +696,18 @@ int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev)
int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
u8 perf_req, bool advertise) u8 perf_req, bool advertise)
{ {
acpi_handle handle;
union acpi_object *info; union acpi_object *info;
struct amdgpu_atcs *atcs = &adev->atcs; struct amdgpu_atcs *atcs = adev->atcs;
struct atcs_pref_req_input atcs_input; struct atcs_pref_req_input atcs_input;
struct atcs_pref_req_output atcs_output; struct atcs_pref_req_output atcs_output;
struct acpi_buffer params; struct acpi_buffer params;
size_t size; size_t size;
u32 retry = 3; u32 retry = 3;
if (amdgpu_acpi_pcie_notify_device_ready(adev)) if (!atcs)
return -EINVAL; return -EINVAL;
/* Get the device handle */ if (amdgpu_acpi_pcie_notify_device_ready(adev))
handle = ACPI_HANDLE(&adev->pdev->dev);
if (!handle)
return -EINVAL; return -EINVAL;
if (!atcs->functions.pcie_perf_req) if (!atcs->functions.pcie_perf_req)
...@@ -691,7 +727,7 @@ int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, ...@@ -691,7 +727,7 @@ int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
params.pointer = &atcs_input; params.pointer = &atcs_input;
while (retry--) { while (retry--) {
info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, &params); info = amdgpu_atcs_call(atcs, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, &params);
if (!info) if (!info)
return -EIO; return -EIO;
...@@ -767,32 +803,26 @@ static int amdgpu_acpi_event(struct notifier_block *nb, ...@@ -767,32 +803,26 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
*/ */
int amdgpu_acpi_init(struct amdgpu_device *adev) int amdgpu_acpi_init(struct amdgpu_device *adev)
{ {
acpi_handle handle, atif_handle; acpi_handle handle, atif_handle, atcs_handle;
struct amdgpu_atif *atif; struct amdgpu_atif *atif;
struct amdgpu_atcs *atcs = &adev->atcs; struct amdgpu_atcs *atcs;
int ret; int ret = 0;
/* Get the device handle */ /* Get the device handle */
handle = ACPI_HANDLE(&adev->pdev->dev); handle = ACPI_HANDLE(&adev->pdev->dev);
if (!adev->bios || !handle) if (!adev->bios || !handle)
return 0; return ret;
/* Call the ATCS method */
ret = amdgpu_atcs_verify_interface(handle, atcs);
if (ret) {
DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
}
/* Probe for ATIF, and initialize it if found */ /* Probe for ATIF, and initialize it if found */
atif_handle = amdgpu_atif_probe_handle(handle); atif_handle = amdgpu_atif_probe_handle(handle);
if (!atif_handle) if (!atif_handle)
goto out; goto atcs;
atif = kzalloc(sizeof(*atif), GFP_KERNEL); atif = kzalloc(sizeof(*atif), GFP_KERNEL);
if (!atif) { if (!atif) {
DRM_WARN("Not enough memory to initialize ATIF\n"); DRM_WARN("Not enough memory to initialize ATIF\n");
goto out; goto atcs;
} }
atif->handle = atif_handle; atif->handle = atif_handle;
...@@ -801,7 +831,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) ...@@ -801,7 +831,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
if (ret) { if (ret) {
DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret);
kfree(atif); kfree(atif);
goto out; goto atcs;
} }
adev->atif = atif; adev->atif = atif;
...@@ -810,7 +840,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) ...@@ -810,7 +840,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
if (amdgpu_device_has_dc_support(adev)) { if (amdgpu_device_has_dc_support(adev)) {
#if defined(CONFIG_DRM_AMD_DC) #if defined(CONFIG_DRM_AMD_DC)
struct amdgpu_display_manager *dm = &adev->dm; struct amdgpu_display_manager *dm = &adev->dm;
atif->bd = dm->backlight_dev; if (dm->backlight_dev)
atif->bd = dm->backlight_dev;
#endif #endif
} else { } else {
struct drm_encoder *tmp; struct drm_encoder *tmp;
...@@ -862,6 +893,28 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) ...@@ -862,6 +893,28 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
atif->backlight_caps.caps_valid = false; atif->backlight_caps.caps_valid = false;
} }
atcs:
/* Probe for ATCS, and initialize it if found */
atcs_handle = amdgpu_atcs_probe_handle(handle);
if (!atcs_handle)
goto out;
atcs = kzalloc(sizeof(*atcs), GFP_KERNEL);
if (!atcs) {
DRM_WARN("Not enough memory to initialize ATCS\n");
goto out;
}
atcs->handle = atcs_handle;
/* Call the ATCS method */
ret = amdgpu_atcs_verify_interface(atcs);
if (ret) {
DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
kfree(atcs);
goto out;
}
adev->atcs = atcs;
out: out:
adev->acpi_nb.notifier_call = amdgpu_acpi_event; adev->acpi_nb.notifier_call = amdgpu_acpi_event;
register_acpi_notifier(&adev->acpi_nb); register_acpi_notifier(&adev->acpi_nb);
...@@ -892,6 +945,7 @@ void amdgpu_acpi_fini(struct amdgpu_device *adev) ...@@ -892,6 +945,7 @@ void amdgpu_acpi_fini(struct amdgpu_device *adev)
{ {
unregister_acpi_notifier(&adev->acpi_nb); unregister_acpi_notifier(&adev->acpi_nb);
kfree(adev->atif); kfree(adev->atif);
kfree(adev->atcs);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment