/*************************************************
*
*   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 */

}
Пример #2
0
/*************************************************
*
*   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 */

}