diff options
author | Michael Stokes <mjstokes@google.com> | 2023-04-12 11:33:43 +0200 |
---|---|---|
committer | Michael Stokes <mjstokes@google.com> | 2023-04-12 11:33:43 +0200 |
commit | f374dceb0feb56cde9341bfbc39ed6c632bde8f3 (patch) | |
tree | ab0ce1d12daf8f61049abd6645cac20c63fc785e | |
parent | db2162076e11391d6520058c2ec3e2e1b89bd7af (diff) | |
download | gpu-f374dceb0feb56cde9341bfbc39ed6c632bde8f3.tar.gz |
mali_kbase: Add missing wake_up(poweroff_wait) when cancelling poweroff.
kbase_pm_update_active() may cancel an ongoing poweroff before the
poweroff has completed and enqueued a gpu_poweroff_wait_work item,
which when executed would have unblocked any waiters in
kbase_pm_wait_for_poweroff_work_complete().
kbase_pm_update_active() must therefore also call wake_up(poweroff_wait)
after resetting poweroff_wait_in_progress to false, to prevent
kbase_pm_wait_for_poweroff_work_complete() from waiting indefinitely.
This change also modifies the diagnostic patch in
kbase_pm_wait_for_poweroff_work_complete() to avoid triggering a
subsystem coredump if a gpu_poweroff_wait_work item is actually pending.
Bug: 274137481
Test: Stability soak testing
Change-Id: I9009a6eed7aa305ae04179263e308ba4259afc6a
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_pm_backend.c | 47 | ||||
-rw-r--r-- | mali_kbase/backend/gpu/mali_kbase_pm_policy.c | 7 |
2 files changed, 30 insertions, 24 deletions
diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c index 047b83e..f496ed5 100644 --- a/mali_kbase/backend/gpu/mali_kbase_pm_backend.c +++ b/mali_kbase/backend/gpu/mali_kbase_pm_backend.c @@ -693,36 +693,39 @@ static bool is_poweroff_in_progress(struct kbase_device *kbdev) void kbase_pm_wait_for_poweroff_work_complete(struct kbase_device *kbdev) { -#define POWEROFF_TIMEOUT_MSEC 200 +#define POWEROFF_TIMEOUT_MSEC 500 long remaining = msecs_to_jiffies(POWEROFF_TIMEOUT_MSEC); remaining = wait_event_killable_timeout(kbdev->pm.backend.poweroff_wait, is_poweroff_in_progress(kbdev), remaining); if (!remaining) { - unsigned long flags; - kbasep_platform_event_core_dump(kbdev, "poweroff work timeout"); - dev_err(kbdev->dev, "failed to wait for poweroff worker after %ims", - POWEROFF_TIMEOUT_MSEC); - kbase_gpu_timeout_debug_message(kbdev); - dev_err(kbdev->dev, "gpu_poweroff_wait_work pending %d", - work_pending(&kbdev->pm.backend.gpu_poweroff_wait_work)); + /* If work is now pending, kbase_pm_gpu_poweroff_wait_wq() will + * definitely be called, so it's safe to continue waiting for it. + */ + if (!work_pending(&kbdev->pm.backend.gpu_poweroff_wait_work)) { + unsigned long flags; + kbasep_platform_event_core_dump(kbdev, "poweroff work timeout"); + dev_err(kbdev->dev, "failed to wait for poweroff worker after %ims", + POWEROFF_TIMEOUT_MSEC); + kbase_gpu_timeout_debug_message(kbdev); #if MALI_USE_CSF - //csf.scheduler.state should be accessed with scheduler lock! - //callchains go through this function though holding that lock - //so just print without locking. - dev_err(kbdev->dev, "scheduler.state %d", kbdev->csf.scheduler.state); - dev_err(kbdev->dev, "Firmware ping %d", kbase_csf_firmware_ping_wait(kbdev)); + //csf.scheduler.state should be accessed with scheduler lock! + //callchains go through this function though holding that lock + //so just print without locking. + dev_err(kbdev->dev, "scheduler.state %d", kbdev->csf.scheduler.state); + dev_err(kbdev->dev, "Firmware ping %d", kbase_csf_firmware_ping_wait(kbdev)); #endif - //Attempt another state machine transition prompt. - dev_err(kbdev->dev, "Attempt to prompt state machine"); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_pm_update_state(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + //Attempt another state machine transition prompt. + dev_err(kbdev->dev, "Attempt to prompt state machine"); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_pm_update_state(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - dev_err(kbdev->dev, "GPU state after re-prompt of state machine"); - kbase_gpu_timeout_debug_message(kbdev); + dev_err(kbdev->dev, "GPU state after re-prompt of state machine"); + kbase_gpu_timeout_debug_message(kbdev); - dev_err(kbdev->dev, "retrying wait, this is likely to still hang. %d", - is_poweroff_in_progress(kbdev)); + dev_err(kbdev->dev, "retrying wait, this is likely to still hang. %d", + is_poweroff_in_progress(kbdev)); + } wait_event_killable(kbdev->pm.backend.poweroff_wait, is_poweroff_in_progress(kbdev)); } diff --git a/mali_kbase/backend/gpu/mali_kbase_pm_policy.c b/mali_kbase/backend/gpu/mali_kbase_pm_policy.c index deeb1b5..898d70f 100644 --- a/mali_kbase/backend/gpu/mali_kbase_pm_policy.c +++ b/mali_kbase/backend/gpu/mali_kbase_pm_policy.c @@ -117,10 +117,12 @@ void kbase_pm_update_active(struct kbase_device *kbdev) } else { /* Cancel the invocation of * kbase_pm_gpu_poweroff_wait_wq() from the L2 state - * machine. This is safe - it + * machine. This is safe - if * invoke_poweroff_wait_wq_when_l2_off is true, then * the poweroff work hasn't even been queued yet, - * meaning we can go straight to powering on. + * meaning we can go straight to powering on. We must + * however wake_up(poweroff_wait) in case someone was + * waiting for poweroff_wait_in_progress to become false. */ pm->backend.invoke_poweroff_wait_wq_when_l2_off = false; pm->backend.poweroff_wait_in_progress = false; @@ -130,6 +132,7 @@ void kbase_pm_update_active(struct kbase_device *kbdev) #endif spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + wake_up(&kbdev->pm.backend.poweroff_wait); kbase_pm_do_poweron(kbdev, false); } } else { |