msm: kgsl: Add postmortem dump for 2D (z180) cores
Add ringbuffer and register dump as part of postmortem dump for z180
cores. Also, add kgsl_postmortem_dump as a preparatory general function
for postmortem dump for both types of kgsl devices, adreno and z180.
Change-Id: I8b538771bfa8f6bfdfe0b1b993afa3c53f8eb8cf
Signed-off-by: Harsh Vardhan Dwivedi <hdwivedi@codeaurora.org>
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 62e1521..57a0e2b 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2570,6 +2570,83 @@
}
EXPORT_SYMBOL(kgsl_device_platform_probe);
+int kgsl_postmortem_dump(struct kgsl_device *device, int manual)
+{
+ bool saved_nap;
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+ BUG_ON(device == NULL);
+
+ kgsl_cffdump_hang(device->id);
+
+ /* For a manual dump, make sure that the system is idle */
+
+ if (manual) {
+ if (device->active_cnt != 0) {
+ mutex_unlock(&device->mutex);
+ wait_for_completion(&device->suspend_gate);
+ mutex_lock(&device->mutex);
+ }
+
+ if (device->state == KGSL_STATE_ACTIVE)
+ kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+
+ }
+ KGSL_LOG_DUMP(device, "|%s| Dump Started\n", device->name);
+ KGSL_LOG_DUMP(device, "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
+ pwr->power_flags, pwr->active_pwrlevel);
+
+ KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
+ pwr->interval_timeout);
+
+ KGSL_LOG_DUMP(device, "GRP_CLK = %lu ",
+ kgsl_get_clkrate(pwr->grp_clks[0]));
+
+ KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
+ kgsl_get_clkrate(pwr->ebi1_clk));
+
+ /* Disable the idle timer so we don't get interrupted */
+ del_timer_sync(&device->idle_timer);
+ mutex_unlock(&device->mutex);
+ flush_workqueue(device->work_queue);
+ mutex_lock(&device->mutex);
+
+ /* Turn off napping to make sure we have the clocks full
+ attention through the following process */
+ saved_nap = device->pwrctrl.nap_allowed;
+ device->pwrctrl.nap_allowed = false;
+
+ /* Force on the clocks */
+ kgsl_pwrctrl_wake(device);
+
+ /* Disable the irq */
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+
+ /*Call the device specific postmortem dump function*/
+ device->ftbl->postmortem_dump(device, manual);
+
+ /* Restore nap mode */
+ device->pwrctrl.nap_allowed = saved_nap;
+
+ /* On a manual trigger, turn on the interrupts and put
+ the clocks to sleep. They will recover themselves
+ on the next event. For a hang, leave things as they
+ are until recovery kicks in. */
+
+ if (manual) {
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
+
+ /* try to go into a sleep mode until the next event */
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
+ kgsl_pwrctrl_sleep(device);
+ }
+
+ KGSL_LOG_DUMP(device, "|%s| Dump Finished\n", device->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_postmortem_dump);
+
void kgsl_device_platform_remove(struct kgsl_device *device)
{
kgsl_device_snapshot_close(device);