aca_handle_is_valid() returned false if !list_empty(&handle->node) evaluated to true. Because active registered handles have non-empty nodes in the handle list, valid handles evaluated as invalid. Consequently, amdgpu_aca_get_error_data() returned -EOPNOTSUPP whenever aca_handle_is_valid() evaluated to true.
Fix the logic in aca_handle_is_valid() to verify that the handle is non-NULL, contains a valid mask, and is currently registered in the list. Update amdgpu_aca_get_error_data() to check for invalid handles and return 0 instead of -EOPNOTSUPP so non-ACA blocks in global RAS queries pass through safely without breaking error telemetry. Additionally, modify remove_aca_handle() to unlink handle->node under mgr->lock using list_del_init() prior to calling aca_fini_error_cache(). Standard list_del() leaves node pointers poisoned, causing !list_empty() in aca_handle_is_valid() to evaluate to true for removed handles. Unlinking under lock first prevents concurrent list traversals from racing on node pointers and stops background queries from referencing destroyed error cache mutexes during handle teardown. Signed-off-by: Sreeraj S Kurup <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c index c76664af9902..c35f6be2ef77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c @@ -586,10 +586,7 @@ static int __aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *h static bool aca_handle_is_valid(struct aca_handle *handle) { - if (!handle->mask || !list_empty(&handle->node)) - return false; - - return true; + return handle && handle->mask && !list_empty(&handle->node); } int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle, @@ -599,8 +596,8 @@ int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *han if (!handle || !err_data) return -EINVAL; - if (aca_handle_is_valid(handle)) - return -EOPNOTSUPP; + if (!aca_handle_is_valid(handle)) + return 0; if ((type < 0) || (!(BIT(type) & handle->mask))) return 0; @@ -716,9 +713,13 @@ static void remove_aca_handle(struct aca_handle *handle) { struct aca_handle_manager *mgr = handle->mgr; - aca_fini_error_cache(handle); - list_del(&handle->node); + mutex_lock(&mgr->lock); + list_del_init(&handle->node); mgr->nr_handles--; + mutex_unlock(&mgr->lock); + aca_fini_error_cache(handle); + kfree(handle); + } static void remove_aca_sysfs(struct aca_handle *handle) -- 2.54.0
