summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stokes <mjstokes@google.com>2023-04-12 11:33:43 +0200
committerMichael Stokes <mjstokes@google.com>2023-04-12 11:33:43 +0200
commitf374dceb0feb56cde9341bfbc39ed6c632bde8f3 (patch)
treeab0ce1d12daf8f61049abd6645cac20c63fc785e
parentdb2162076e11391d6520058c2ec3e2e1b89bd7af (diff)
downloadgpu-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.c47
-rw-r--r--mali_kbase/backend/gpu/mali_kbase_pm_policy.c7
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 {