/************************************************* * * Worker thread to dump CP crash log information. * * *****************************************************/ void ProcessCPCrashedDump(struct work_struct *work) { char crashReason[40] = { 0 }; char crashFile[40] = { 0 }; char crashThread[40] = { 0 }; char outString[512] = { 0 }; IPC_U32 *Dump; void __iomem *DumpVAddr; int cpReset = SmLocalControl.SmControl->CrashCode == IPC_CP_SILENT_RESET_READY; RpcDbgDumpHistoryLogging(0, 0); #ifdef CONFIG_KONA_SECURE_MEMC u32 *memc_handle; /* this is where any type of cp crash gets handled. * there could be a scenerio of silent-reboot of cp. * or there could be abrupt crash of cp. * either ap would be alive or ap will crash itself. * we protect cp area from following masters. * > ap * > mm * > fabric * in the event of ap/cp crash we need to give an ap * access back to the cp area for the dump. * and in the case of silent cp reset, ap will * be alive, in that case we grant an access to ap. * so that ap can load cp images and can take dump * if required. * and when cp comes up successfully and sync up with ap, * we revoke the access for ap somwhere in HandleRestartCP. */ memc_handle = get_secure_memc_handle(); if (!memc_handle) pr_err("Failed to get secure memc handle\n"); if (do_grant_region_access(memc_handle, AP)) pr_err("Failed to grant access for AP\n"); #endif #ifdef CONFIG_FB_BRCM_CP_CRASH_DUMP_IMAGE_SUPPORT if (!crash_dump_ui_on && !cpReset) { if (ramdump_enable) kona_display_crash_image(CP_RAM_DUMP_START); else kona_display_crash_image(CP_CRASH_DUMP_START); crash_dump_ui_on = 1; } #endif #ifndef CONFIG_BCM_AP_PANIC_ON_CPCRASH #ifdef CONFIG_CDEBUGGER if (ramdump_enable #ifdef CONFIG_APANIC_ON_MMC && ap_triggered == 0 #endif && !cpReset ) { /* we kill AP when CP crashes */ IPC_DEBUG(DBG_ERROR, "Crashing AP for Ramdump ...\n\n"); abort(); } #endif if ((BCMLOG_OUTDEV_PANIC == BCMLOG_GetCpCrashLogDevice() || BCMLOG_OUTDEV_NONE == BCMLOG_GetCpCrashLogDevice() || BCMLOG_OUTDEV_STM == BCMLOG_GetCpCrashLogDevice()) && !cpReset #ifdef CONFIG_APANIC_ON_MMC && !ap_triggered #endif ) { /* we kill AP when CP crashes */ IPC_DEBUG(DBG_ERROR, "Crashing AP now ...\n\n"); abort(); } #endif // CONFIG_BCM_AP_PANIC_ON_CPCRASH IPC_Dump(); #if defined(CONFIG_BRCM_CP_CRASH_DUMP_EMMC) \ || defined(CONFIG_BCM_AP_PANIC_ON_CPCRASH) while (SmLocalControl.SmControl->CrashDump == NULL) ; /* No op */ #endif /* **NOTE** for now, continue doing simple dump out IPC_DEBUG so there * is some indication of CP crash in console * (in case user not running MTT) */ Dump = (void *)SmLocalControl.SmControl->CrashDump; IPC_DEBUG(DBG_ERROR, "ioremap\n"); DumpVAddr = plat_ioremap_ns((unsigned long __force) get_vaddr(IPC_CP_CRASH_SUMMARY_AREA), IPC_CP_CRASH_SUMMARY_AREA_SZ, (phys_addr_t)Dump); if (!DumpVAddr) { IPC_DEBUG(DBG_ERROR, "ioremap failed in ProcessCPCrashedDump\n"); goto cleanUp; } IPC_DEBUG(DBG_ERROR, "Crash Summary Virtual Addr: 0x%08X\n", (unsigned int)DumpVAddr); dumped_crash_summary_ptr = (struct T_CRASH_SUMMARY *)DumpVAddr; IPC_DEBUG(DBG_ERROR, "===== COMMS_PROCESSOR crash summary =====\r\n"); if (dumped_crash_summary_ptr->link_signature) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->link_signature, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->project_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->project_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->DSP_version) { GetStringFromPA((UInt32)dumped_crash_summary_ptr->DSP_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->FW_version) { GetStringFromPA((UInt32)dumped_crash_summary_ptr->FW_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->decoder_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->decoder_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } GetStringFromPA((UInt32)dumped_crash_summary_ptr->reason, crashReason, 40); GetStringFromPA((UInt32)dumped_crash_summary_ptr->file, crashFile, 40); GetStringFromPA((UInt32)dumped_crash_summary_ptr->thread, crashThread, 40); IPC_DEBUG(DBG_ERROR, "%s f=%s l=%d v=%d/0x%x t=%s TS=%d\r\n", crashReason, crashFile, dumped_crash_summary_ptr->line, dumped_crash_summary_ptr->value, dumped_crash_summary_ptr->value, crashThread, dumped_crash_summary_ptr->time); /* notify clients about CP reset */ if (cpReset #ifdef CONFIG_BRCM_CP_CRASH_DUMP_EMMC && !ap_triggered #endif ) HandleCPResetStart(); #ifndef CONFIG_BCM_AP_PANIC_ON_CPCRASH /* done with "simple" dump, so now pull the full assert * log from CP and dump out to MTT */ DUMP_CP_assert_log(); #endif cleanUp: if (DumpVAddr) plat_iounmap_ns(get_vaddr(IPC_CP_CRASH_SUMMARY_AREA), free_size_ipc(IPC_CP_CRASH_SUMMARY_AREA_SZ)); /* crash dump is done, so trigger CP reset */ if (cpReset #ifdef CONFIG_BRCM_CP_CRASH_DUMP_EMMC && !ap_triggered #endif ) { IPC_DEBUG(DBG_INFO, "waiting for clients to ack...\n"); while (!cp_reset_clients_acked) msleep(300); cp_reset_clients_acked = 0; IPC_DEBUG(DBG_INFO, "starting cp_reset thread\n"); kthread_run(HandleRestartCP, 0, "cp_reset"); } #ifdef CONFIG_HAS_WAKELOCK else wake_unlock(&ipc_wake_lock); #endif #ifdef CONFIG_BCM_AP_PANIC_ON_CPCRASH #ifdef CONFIG_SEC_DEBUG cp_abort(); #endif /* CONFIG_SEC_DEBUG */ #endif /* CONFIG_AP_PANIC_ON_CPCRASH */ }
/************************************************* * * Worker thread to dump CP crash log information. * * *****************************************************/ void ProcessCPCrashedDump(struct work_struct *work) { char crashReason[40] = { 0 }; char crashFile[40] = { 0 }; char crashThread[40] = { 0 }; char outString[512] = { 0 }; IPC_U32 *Dump; void __iomem *DumpVAddr; int cpReset = SmLocalControl.SmControl->CrashCode == IPC_CP_SILENT_RESET_READY; #ifdef CONFIG_CDEBUGGER if (ramdump_enable #ifdef CONFIG_BRCM_CP_CRASH_DUMP_EMMC && ap_triggered == 0 #endif ) { BCMLOG_SetCpCrashLogDevice(BCMLOG_OUTDEV_NONE); /* we kill AP when CP crashes */ IPC_DEBUG(DBG_ERROR, "Crashing AP for ramdump ...\n\n"); abort(); } #endif if ((BCMLOG_OUTDEV_PANIC == BCMLOG_GetCpCrashLogDevice() || (BCMLOG_OUTDEV_RNDIS == BCMLOG_GetCpCrashLogDevice() && !cpReset)) #ifdef CONFIG_BRCM_CP_CRASH_DUMP_EMMC && !ap_triggered #endif ) { #ifdef CONFIG_CRASH_DUMP_START_UI_DISPLAY if (!dump_start_ui_on) { display_crash_dump_start_ui(); dump_start_ui_on = 1; msleep(100); } #endif /* we kill AP when CP crashes */ IPC_DEBUG(DBG_ERROR, "Crashing AP now ...\n\n"); abort(); } #ifdef CONFIG_CRASH_DUMP_START_UI_DISPLAY if ((BCMLOG_OUTDEV_SDCARD == BCMLOG_GetCpCrashLogDevice()) && cp_crashed == 1 && !cpReset) { if (!dump_start_ui_on) { display_crash_dump_start_ui(); dump_start_ui_on = 1; } } #endif IPC_Dump(); RpcDbgDumpHistoryLogging(0, 0); #if defined(CONFIG_BRCM_CP_CRASH_DUMP) \ || defined(CONFIG_BRCM_CP_CRASH_DUMP_EMMC) \ || defined(CONFIG_BCM_AP_PANIC_ON_CPCRASH) while (SmLocalControl.SmControl->CrashDump == NULL) ; /* No op */ #endif /* **NOTE** for now, continue doing simple dump out IPC_DEBUG so there * is some indication of CP crash in console * (in case user not running MTT) */ Dump = (void *)SmLocalControl.SmControl->CrashDump; IPC_DEBUG(DBG_ERROR, "ioremap_nocache\n"); DumpVAddr = ioremap_nocache((UInt32)Dump, sizeof(struct T_CRASH_SUMMARY)); if (NULL == DumpVAddr) { IPC_DEBUG(DBG_ERROR, "VirtualAlloc failed\n"); goto cleanUp; } IPC_DEBUG(DBG_ERROR, "Crash Summary Virtual Addr: 0x%08X\n", (unsigned int)DumpVAddr); dumped_crash_summary_ptr = (struct T_CRASH_SUMMARY *)DumpVAddr; IPC_DEBUG(DBG_ERROR, "===== COMMS_PROCESSOR crash summary =====\r\n"); if (dumped_crash_summary_ptr->link_signature) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->link_signature, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->project_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->project_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->DSP_version) { GetStringFromPA((UInt32)dumped_crash_summary_ptr->DSP_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->FW_version) { GetStringFromPA((UInt32)dumped_crash_summary_ptr->FW_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->decoder_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->decoder_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } GetStringFromPA((UInt32)dumped_crash_summary_ptr->reason, crashReason, 40); GetStringFromPA((UInt32)dumped_crash_summary_ptr->file, crashFile, 40); GetStringFromPA((UInt32)dumped_crash_summary_ptr->thread, crashThread, 40); IPC_DEBUG(DBG_ERROR, "%s f=%s l=%d v=%d/0x%x t=%s TS=%d\r\n", crashReason, crashFile, dumped_crash_summary_ptr->line, dumped_crash_summary_ptr->value, dumped_crash_summary_ptr->value, crashThread, dumped_crash_summary_ptr->time); /* notify clients about CP reset */ if (cpReset #ifdef CONFIG_BRCM_CP_CRASH_DUMP_EMMC && !ap_triggered #endif ) HandleCPResetStart(); #ifndef CONFIG_BCM_AP_PANIC_ON_CPCRASH /* done with "simple" dump, so now pull the full assert * log from CP and dump out to MTT */ DUMP_CP_assert_log(); #endif cleanUp: if (NULL != DumpVAddr) iounmap(DumpVAddr); /* crash dump is done, so trigger CP reset */ if (cpReset #ifdef CONFIG_BRCM_CP_CRASH_DUMP_EMMC && !ap_triggered #endif ) { IPC_DEBUG(DBG_INFO, "waiting for clients to ack...\n"); while (!cp_reset_clients_acked) msleep(300); cp_reset_clients_acked = 0; IPC_DEBUG(DBG_INFO, "starting cp_reset thread\n"); kthread_run(HandleRestartCP, 0, "cp_reset"); } #ifdef CONFIG_HAS_WAKELOCK else wake_unlock(&ipc_wake_lock); #endif #ifdef CONFIG_BCM_AP_PANIC_ON_CPCRASH IPC_DEBUG(DBG_ERROR, "CP crashed, crashing AP now..\n"); #ifdef CONFIG_SEC_DEBUG cp_abort(); #else abort(); #endif /* CONFIG_SEC_DEBUG */ #endif /* CONFIG_AP_PANIC_ON_CPCRASH */ }
/************************************************* * * Worker thread to dump CP crash log information. * * *****************************************************/ void ProcessCPCrashedDump(struct work_struct *work) { char crashReason[40] = { 0 }; char crashFile[40] = { 0 }; char crashThread[40] = { 0 }; char outString[512] = { 0 }; IPC_U32 *Dump; void __iomem *DumpVAddr; #ifdef CONFIG_FB_BRCM_CP_CRASH_DUMP_IMAGE_SUPPORT rhea_display_crash_image(CP_CRASH_DUMP_START); #endif #ifdef CONFIG_BCM_AP_PANIC_ON_CPCRASH if (BCMLOG_OUTDEV_SDCARD == BCMLOG_GetCpCrashLogDevice() #ifdef CONFIG_CDEBUGGER && ramdump_enable == 1 #endif #ifdef CONFIG_APANIC_ON_MMC && ap_triggered == 0 #endif ) { /* we kill AP when CP crashes */ IPC_DEBUG(DBG_ERROR, "Crashing AP for Ramdump ...\n\n"); #ifdef CONFIG_SEC_DEBUG cp_abort(); #else abort(); #endif /* CONFIG_SEC_DEBUG */ } if ((BCMLOG_OUTDEV_NONE == BCMLOG_GetCpCrashLogDevice() || BCMLOG_OUTDEV_PANIC == BCMLOG_GetCpCrashLogDevice() || BCMLOG_OUTDEV_STM == BCMLOG_GetCpCrashLogDevice() || BCMLOG_OUTDEV_RNDIS == BCMLOG_GetCpCrashLogDevice()) #ifdef CONFIG_APANIC_ON_MMC && ap_triggered == 0 #endif ) { /* we kill AP when CP crashes */ IPC_DEBUG(DBG_ERROR, "Crashing AP now ...\n\n"); #ifdef CONFIG_SEC_DEBUG cp_abort(); #else abort(); #endif /* CONFIG_SEC_DEBUG */ } #endif /* check for CP Reset here? Assuming CP Reset is just signified by a different crash code */ if (SmLocalControl.SmControl->CrashCode == IPC_CP_SILENT_RESET_READY) { HandleCPResetStart(); return; } IPC_Dump(); RpcDbgDumpHistoryLogging(0, 0); #if defined(CONFIG_BRCM_CP_CRASH_DUMP) \ || defined(CONFIG_BRCM_CP_CRASH_DUMP_EMMC) \ || defined(CONFIG_BCM_AP_PANIC_ON_CPCRASH) while (SmLocalControl.SmControl->CrashDump == NULL) ; /* No op */ #endif /* **NOTE** for now, continue doing simple dump out IPC_DEBUG so there * is some indication of CP crash in console * (in case user not running MTT) */ Dump = (void *)SmLocalControl.SmControl->CrashDump; IPC_DEBUG(DBG_ERROR, "ioremap_nocache\n"); DumpVAddr = ioremap_nocache((UInt32) Dump, sizeof(struct T_CRASH_SUMMARY)); if (NULL == DumpVAddr) { IPC_DEBUG(DBG_ERROR, "VirtualAlloc failed\n"); goto cleanUp; } IPC_DEBUG(DBG_ERROR, "Crash Summary Virtual Addr: 0x%08X\n", (unsigned int)DumpVAddr); dumped_crash_summary_ptr = (struct T_CRASH_SUMMARY *)DumpVAddr; IPC_DEBUG(DBG_ERROR, "===== COMMS_PROCESSOR crash summary =====\r\n"); if (dumped_crash_summary_ptr->link_signature) { GetStringFromPA((UInt32) dumped_crash_summary_ptr-> link_signature, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->project_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr-> project_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->DSP_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->DSP_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->FW_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr->FW_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } if (dumped_crash_summary_ptr->decoder_version) { GetStringFromPA((UInt32) dumped_crash_summary_ptr-> decoder_version, outString, 128); IPC_DEBUG(DBG_ERROR, "%s\r\n", outString); } GetStringFromPA((UInt32) dumped_crash_summary_ptr->reason, crashReason, 40); GetStringFromPA((UInt32) dumped_crash_summary_ptr->file, crashFile, 40); GetStringFromPA((UInt32) dumped_crash_summary_ptr->thread, crashThread, 40); IPC_DEBUG(DBG_ERROR, "%s f=%s l=%d v=%d/0x%x t=%s TS=%d\r\n", crashReason, crashFile, dumped_crash_summary_ptr->line, dumped_crash_summary_ptr->value, dumped_crash_summary_ptr->value, crashThread, dumped_crash_summary_ptr->time); #ifndef CONFIG_BCM_AP_PANIC_ON_CPCRASH /* done with "simple" dump, so now pull the full assert * log from CP and dump out to MTT */ DUMP_CP_assert_log(); #endif cleanUp: if (NULL != DumpVAddr) iounmap(DumpVAddr); #ifdef CONFIG_HAS_WAKELOCK wake_unlock(&ipc_wake_lock); #endif #ifdef CONFIG_BCM_AP_PANIC_ON_CPCRASH #ifdef CONFIG_SEC_DEBUG cp_abort(); #endif /* CONFIG_SEC_DEBUG */ #endif /* CONFIG_AP_PANIC_ON_CPCRASH */ }