summaryrefslogtreecommitdiff
path: root/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mali_kbase/csf/mali_kbase_csf_reset_gpu.c')
-rw-r--r--mali_kbase/csf/mali_kbase_csf_reset_gpu.c157
1 files changed, 71 insertions, 86 deletions
diff --git a/mali_kbase/csf/mali_kbase_csf_reset_gpu.c b/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
index b8ad3a4..53f05fb 100644
--- a/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
+++ b/mali_kbase/csf/mali_kbase_csf_reset_gpu.c
@@ -41,21 +41,18 @@ enum kbasep_soft_reset_status {
MCU_REINIT_FAILED
};
-static inline bool
-kbase_csf_reset_state_is_silent(enum kbase_csf_reset_gpu_state state)
+static inline bool kbase_csf_reset_state_is_silent(enum kbase_csf_reset_gpu_state state)
{
return (state == KBASE_CSF_RESET_GPU_COMMITTED_SILENT);
}
-static inline bool
-kbase_csf_reset_state_is_committed(enum kbase_csf_reset_gpu_state state)
+static inline bool kbase_csf_reset_state_is_committed(enum kbase_csf_reset_gpu_state state)
{
return (state == KBASE_CSF_RESET_GPU_COMMITTED ||
state == KBASE_CSF_RESET_GPU_COMMITTED_SILENT);
}
-static inline bool
-kbase_csf_reset_state_is_active(enum kbase_csf_reset_gpu_state state)
+static inline bool kbase_csf_reset_state_is_active(enum kbase_csf_reset_gpu_state state)
{
return (state == KBASE_CSF_RESET_GPU_HAPPENING);
}
@@ -103,8 +100,7 @@ int kbase_reset_gpu_prevent_and_wait(struct kbase_device *kbdev)
{
down_read(&kbdev->csf.reset.sem);
- if (atomic_read(&kbdev->csf.reset.state) ==
- KBASE_CSF_RESET_GPU_FAILED) {
+ if (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_FAILED) {
up_read(&kbdev->csf.reset.sem);
return -ENOMEM;
}
@@ -123,8 +119,7 @@ int kbase_reset_gpu_try_prevent(struct kbase_device *kbdev)
if (!down_read_trylock(&kbdev->csf.reset.sem))
return -EAGAIN;
- if (atomic_read(&kbdev->csf.reset.state) ==
- KBASE_CSF_RESET_GPU_FAILED) {
+ if (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_FAILED) {
up_read(&kbdev->csf.reset.sem);
return -ENOMEM;
}
@@ -174,9 +169,8 @@ bool kbase_reset_gpu_failed(struct kbase_device *kbdev)
/* Mark the reset as now happening, and synchronize with other threads that
* might be trying to access the GPU
*/
-static void kbase_csf_reset_begin_hw_access_sync(
- struct kbase_device *kbdev,
- enum kbase_csf_reset_gpu_state initial_reset_state)
+static void kbase_csf_reset_begin_hw_access_sync(struct kbase_device *kbdev,
+ enum kbase_csf_reset_gpu_state initial_reset_state)
{
unsigned long hwaccess_lock_flags;
unsigned long scheduler_spin_lock_flags;
@@ -204,15 +198,13 @@ static void kbase_csf_reset_begin_hw_access_sync(
/* Mark the reset as finished and allow others threads to once more access the
* GPU
*/
-static void kbase_csf_reset_end_hw_access(struct kbase_device *kbdev,
- int err_during_reset,
+static void kbase_csf_reset_end_hw_access(struct kbase_device *kbdev, int err_during_reset,
bool firmware_inited)
{
unsigned long hwaccess_lock_flags;
unsigned long scheduler_spin_lock_flags;
- WARN_ON(!kbase_csf_reset_state_is_active(
- atomic_read(&kbdev->csf.reset.state)));
+ WARN_ON(!kbase_csf_reset_state_is_active(atomic_read(&kbdev->csf.reset.state)));
/* Once again, we synchronize with atomic context threads accessing the
* HW, as otherwise any actions they defer could get lost
@@ -221,8 +213,7 @@ static void kbase_csf_reset_end_hw_access(struct kbase_device *kbdev,
kbase_csf_scheduler_spin_lock(kbdev, &scheduler_spin_lock_flags);
if (!err_during_reset) {
- atomic_set(&kbdev->csf.reset.state,
- KBASE_CSF_RESET_GPU_NOT_PENDING);
+ atomic_set(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_NOT_PENDING);
} else {
dev_err(kbdev->dev, "Reset failed to complete");
atomic_set(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_FAILED);
@@ -250,35 +241,41 @@ void kbase_csf_debug_dump_registers(struct kbase_device *kbdev)
#define DOORBELL_CFG_BASE 0x20000
#define MCUC_DB_VALUE_0 0x80
struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
- kbase_io_history_dump(kbdev);
+ kbase_io_history_dump(kbdev);
dev_err(kbdev->dev, "MCU state:");
- dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x MCU_STATUS=0x%08x",
- kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)),
- kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_STATUS)),
- kbase_reg_read(kbdev, GPU_CONTROL_REG(MCU_STATUS)));
+ dev_err(kbdev->dev, "Register state:");
+ dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x MCU_STATUS=0x%08x",
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_RAWSTAT)),
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_STATUS)),
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(MCU_STATUS)));
dev_err(kbdev->dev,
- " JOB_IRQ_RAWSTAT=0x%08x MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x",
- kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_RAWSTAT)),
- kbase_reg_read(kbdev, MMU_CONTROL_REG(MMU_IRQ_RAWSTAT)),
- kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_FAULTSTATUS)));
- dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x",
- kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK)),
- kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_MASK)),
- kbase_reg_read(kbdev, MMU_CONTROL_REG(MMU_IRQ_MASK)));
- dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x",
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE0)),
- kbase_reg_read(kbdev, GPU_CONTROL_REG(PWR_OVERRIDE1)));
- dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x TILER_CONFIG=0x%08x",
- kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_CONFIG)),
- kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_MMU_CONFIG)),
- kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG)));
- dev_err(kbdev->dev, " MCU DB0: %x", kbase_reg_read(kbdev, DOORBELL_CFG_BASE + MCUC_DB_VALUE_0));
+ " JOB_IRQ_RAWSTAT=0x%08x MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x",
+ kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_RAWSTAT)),
+ kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_RAWSTAT)),
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_FAULTSTATUS)));
+ dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x",
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)),
+ kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK)),
+ kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK)));
+ if (kbdev->gpu_props.gpu_id.arch_id < GPU_ID_ARCH_MAKE(14, 10, 0)) {
+ dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x",
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(PWR_OVERRIDE0)),
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(PWR_OVERRIDE1)));
+ dev_err(kbdev->dev,
+ " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x TILER_CONFIG=0x%08x",
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(SHADER_CONFIG)),
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(L2_MMU_CONFIG)),
+ kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(TILER_CONFIG)));
+ }
+
+ dev_err(kbdev->dev, " MCU DB0: %x", kbase_reg_read32(kbdev, DOORBELL_CFG_BASE + MCUC_DB_VALUE_0));
dev_err(kbdev->dev, " MCU GLB_REQ %x GLB_ACK %x",
kbase_csf_firmware_global_input_read(global_iface, GLB_REQ),
kbase_csf_firmware_global_output(global_iface, GLB_ACK));
#undef MCUC_DB_VALUE_0
#undef DOORBELL_CFG_BASE
+
}
/**
@@ -317,8 +314,7 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic
spin_lock(&kbdev->mmu_mask_change);
kbase_pm_reset_start_locked(kbdev);
- dev_dbg(kbdev->dev,
- "We're about to flush out the IRQs and their bottom halves\n");
+ dev_dbg(kbdev->dev, "We're about to flush out the IRQs and their bottom halves\n");
kbdev->irq_reset_flush = true;
/* Disable IRQ to avoid IRQ handlers to kick in after releasing the
@@ -336,13 +332,11 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic
dev_dbg(kbdev->dev, "Flush out any in-flight work items\n");
kbase_flush_mmu_wqs(kbdev);
- dev_dbg(kbdev->dev,
- "The flush has completed so reset the active indicator\n");
+ dev_dbg(kbdev->dev, "The flush has completed so reset the active indicator\n");
kbdev->irq_reset_flush = false;
if (!silent)
- dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)",
- RESET_TIMEOUT);
+ dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)", RESET_TIMEOUT);
/* Output the state of some interesting registers to help in the
* debugging of GPU resets, and dump the firmware trace buffer
@@ -353,9 +347,11 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic
kbase_csf_firmware_log_dump_buffer(kbdev);
}
- spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
- kbase_ipa_control_handle_gpu_reset_pre(kbdev);
- spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+ {
+ spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
+ kbase_ipa_control_handle_gpu_reset_pre(kbdev);
+ spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
+ }
/* Tell hardware counters a reset is about to occur.
* If the backend is in an unrecoverable error state (e.g. due to
@@ -376,7 +372,9 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic
mutex_lock(&kbdev->mmu_hw_mutex);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
kbase_ctx_sched_restore_all_as(kbdev);
- kbase_ipa_control_handle_gpu_reset_post(kbdev);
+ {
+ kbase_ipa_control_handle_gpu_reset_post(kbdev);
+ }
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
mutex_unlock(&kbdev->mmu_hw_mutex);
@@ -466,16 +464,14 @@ err:
static void kbase_csf_reset_gpu_worker(struct work_struct *data)
{
- struct kbase_device *kbdev = container_of(data, struct kbase_device,
- csf.reset.work);
+ struct kbase_device *kbdev = container_of(data, struct kbase_device, csf.reset.work);
bool gpu_sleep_mode_active = false;
bool firmware_inited;
unsigned long flags;
int err = 0;
const enum kbase_csf_reset_gpu_state initial_reset_state =
atomic_read(&kbdev->csf.reset.state);
- const bool silent =
- kbase_csf_reset_state_is_silent(initial_reset_state);
+ const bool silent = kbase_csf_reset_state_is_silent(initial_reset_state);
struct gpu_uevent evt;
/* Ensure any threads (e.g. executing the CSF scheduler) have finished
@@ -506,22 +502,17 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data)
err = kbase_csf_reset_gpu_now(kbdev, firmware_inited, silent);
#endif
- } else if (!kbase_pm_context_active_handle_suspend(kbdev,
- KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) {
+ } else if (!kbase_pm_context_active_handle_suspend(
+ kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) {
err = kbase_csf_reset_gpu_now(kbdev, firmware_inited, silent);
kbase_pm_context_idle(kbdev);
}
kbase_disjoint_state_down(kbdev);
- if (err) {
- evt.type = GPU_UEVENT_TYPE_GPU_RESET;
- evt.info = GPU_UEVENT_INFO_CSF_RESET_FAILED;
- } else {
- evt.type = GPU_UEVENT_TYPE_GPU_RESET;
- evt.info = GPU_UEVENT_INFO_CSF_RESET_OK;
- }
- if (!silent)
+ evt.type = GPU_UEVENT_TYPE_GPU_RESET;
+ evt.info = err ? GPU_UEVENT_INFO_CSF_RESET_FAILED : GPU_UEVENT_INFO_CSF_RESET_OK;
+ if (!silent || err)
pixel_gpu_uevent_send(kbdev, &evt);
/* Allow other threads to once again use the GPU */
@@ -531,25 +522,25 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data)
bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev, unsigned int flags)
{
if (flags & RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)
- kbase_hwcnt_backend_csf_on_unrecoverable_error(
- &kbdev->hwcnt_gpu_iface);
+ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);
- if (atomic_cmpxchg(&kbdev->csf.reset.state,
- KBASE_CSF_RESET_GPU_NOT_PENDING,
- KBASE_CSF_RESET_GPU_PREPARED) !=
- KBASE_CSF_RESET_GPU_NOT_PENDING)
+ if (atomic_cmpxchg(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_NOT_PENDING,
+ KBASE_CSF_RESET_GPU_PREPARED) != KBASE_CSF_RESET_GPU_NOT_PENDING)
/* Some other thread is already resetting the GPU */
return false;
if (flags & RESET_FLAGS_FORCE_PM_HW_RESET)
kbdev->csf.reset.force_pm_hw_reset = true;
+ /* Issue the wake up of threads waiting for PM state transition.
+ * They might want to exit the wait since GPU reset has been triggered.
+ */
+ wake_up(&kbdev->pm.backend.gpu_in_desired_state_wait);
return true;
}
KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu);
-bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev,
- unsigned int flags)
+bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev, unsigned int flags)
{
lockdep_assert_held(&kbdev->hwaccess_lock);
@@ -561,8 +552,7 @@ void kbase_reset_gpu(struct kbase_device *kbdev)
/* Note this is a WARN/atomic_set because it is a software issue for
* a race to be occurring here
*/
- if (WARN_ON(atomic_read(&kbdev->csf.reset.state) !=
- KBASE_RESET_GPU_PREPARED))
+ if (WARN_ON(atomic_read(&kbdev->csf.reset.state) != KBASE_RESET_GPU_PREPARED))
return;
atomic_set(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_COMMITTED);
@@ -583,10 +573,9 @@ void kbase_reset_gpu_locked(struct kbase_device *kbdev)
int kbase_reset_gpu_silent(struct kbase_device *kbdev)
{
- if (atomic_cmpxchg(&kbdev->csf.reset.state,
- KBASE_CSF_RESET_GPU_NOT_PENDING,
- KBASE_CSF_RESET_GPU_COMMITTED_SILENT) !=
- KBASE_CSF_RESET_GPU_NOT_PENDING) {
+ if (atomic_cmpxchg(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_NOT_PENDING,
+ KBASE_CSF_RESET_GPU_COMMITTED_SILENT) !=
+ KBASE_CSF_RESET_GPU_NOT_PENDING) {
/* Some other thread is already resetting the GPU */
return -EAGAIN;
}
@@ -601,8 +590,7 @@ KBASE_EXPORT_TEST_API(kbase_reset_gpu_silent);
bool kbase_reset_gpu_is_active(struct kbase_device *kbdev)
{
- enum kbase_csf_reset_gpu_state reset_state =
- atomic_read(&kbdev->csf.reset.state);
+ enum kbase_csf_reset_gpu_state reset_state = atomic_read(&kbdev->csf.reset.state);
/* For CSF, the reset is considered active only when the reset worker
* is actually executing and other threads would have to wait for it to
@@ -637,10 +625,8 @@ int kbase_reset_gpu_wait(struct kbase_device *kbdev)
remaining = wait_event_timeout(
kbdev->csf.reset.wait,
- (atomic_read(&kbdev->csf.reset.state) ==
- KBASE_CSF_RESET_GPU_NOT_PENDING) ||
- (atomic_read(&kbdev->csf.reset.state) ==
- KBASE_CSF_RESET_GPU_FAILED),
+ (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_NOT_PENDING) ||
+ (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_FAILED),
wait_timeout);
if (!remaining) {
@@ -648,8 +634,7 @@ int kbase_reset_gpu_wait(struct kbase_device *kbdev)
return -ETIMEDOUT;
- } else if (atomic_read(&kbdev->csf.reset.state) ==
- KBASE_CSF_RESET_GPU_FAILED) {
+ } else if (atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_FAILED) {
return -ENOMEM;
}