Ejemplo n.º 1
0
u32 MGRWRAP_Force_Recovery(union Trapped_Args *args, void *pr_ctxt)
{
	DSP_STATUS status = DSP_SOK ;
	struct DEV_OBJECT *hDevObject;
	struct WMD_DEV_CONTEXT *dwContext;

	hDevObject = DEV_GetFirst();	/* default */
	DEV_GetWMDContext(hDevObject, &dwContext);

	/* Set the Board state as ERROR */
	dwContext->dwBrdState = BRD_ERROR;
	/* Disable all the clocks that were enabled by DSP */
	(void)DSP_PeripheralClocks_Disable(dwContext, NULL);

	bridge_recovery_notify(DSP_SYSERROR) ;

	return status ;
}
Ejemplo n.º 2
0
/*
 *  ======== WMD_DEH_Notify ========
 *      DEH error notification function. Informs user about the error.
 */
void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
			 u32 dwErrInfo)
{
	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
	struct WMD_DEV_CONTEXT *pDevContext;
	u32 memPhysical = 0;
	u32 HW_MMU_MAX_TLB_COUNT = 31;
	extern u32 faultAddr;
	u32 cnt = 0;

	if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
		printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
			"**********\n");
		pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;

		switch (ulEventMask) {
		case DSP_SYSERROR:
			/* reset errInfo structure before use */
			pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
			pDehMgr->errInfo.dwVal1 = 0L;
			pDehMgr->errInfo.dwVal2 = 0L;
			pDehMgr->errInfo.dwVal3 = 0L;
			pDehMgr->errInfo.dwVal1 = dwErrInfo;
			printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
				"= 0x%x\n", dwErrInfo);

			dump_dl_modules(pDevContext);
			dump_dsp_stack(pDevContext);

			break;
		case DSP_MMUFAULT:
			/* MMU fault routine should have set err info
			 * structure */
			pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
				"errInfo = 0x%x\n", dwErrInfo);
			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
				"Address = 0x%x\n",
				(unsigned int)pDehMgr->errInfo.dwVal1);
			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
				"Address = 0x%x\n",
				(unsigned int)pDehMgr->errInfo.dwVal2);
			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
				"address = 0x%x\n", (unsigned int)faultAddr);

			PrintDspTraceBuffer(pDevContext);
			dump_dl_modules(pDevContext);

			dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
					MEM_PAGED);
			memPhysical  = VirtToPhys(PG_ALIGN_LOW((u32)dummyVaAddr,
								PG_SIZE_4K));
			pDevContext = (struct WMD_DEV_CONTEXT *)
						pDehMgr->hWmdContext;
			/* Reset the dynamic mmu index to fixed count if it
			 * exceeds 31. So that the dynmmuindex is always
			 * between the range of standard/fixed entries
			 * and 31.  */
			if (pDevContext->numTLBEntries >
			   HW_MMU_MAX_TLB_COUNT) {
				pDevContext->numTLBEntries = pDevContext->
					fixedTLBEntries;
			}

			HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase,
				memPhysical, faultAddr, HW_PAGE_SIZE_4KB, 1,
				&mapAttrs, HW_SET, HW_SET);
			/*
			 * Send a GP Timer interrupt to DSP
			 * The DSP expects a GP timer interrupt after an
			 * MMU-Fault Request GPTimer
			 */
			if (timer) {
				omap_dm_timer_enable(timer);
				/* Enable overflow interrupt */
				omap_dm_timer_set_int_enable(timer,
						GPTIMER_IRQ_OVERFLOW);
				/*
				 * Set counter value to overflow counter after
				 * one tick and start timer
				 */
				omap_dm_timer_set_load_start(timer, 0,
							0xfffffffe);

				/* Wait 80us for timer to overflow */
				udelay(80);

				/* Check interrupt status and */
				/* wait for interrupt */
				cnt = 0;
				while (!(omap_dm_timer_read_status(timer) &
					GPTIMER_IRQ_OVERFLOW)) {
					if (cnt++ >=
						GPTIMER_IRQ_WAIT_MAX_CNT) {
						pr_err("%s: GPTimer interrupt"
							" failed\n", __func__);
						break;
					}
				}
			}

			/* Clear MMU interrupt */
			HW_MMU_EventAck(pDevContext->dwDSPMmuBase,
					 HW_MMU_TRANSLATION_FAULT);

			dump_dsp_stack(hDehMgr->hWmdContext);
			if (timer)
				omap_dm_timer_disable(timer);
			break;
#ifdef CONFIG_BRIDGE_NTFY_PWRERR
		case DSP_PWRERROR:
			/* reset errInfo structure before use */
			pDehMgr->errInfo.dwErrMask = DSP_PWRERROR;
			pDehMgr->errInfo.dwVal1 = 0L;
			pDehMgr->errInfo.dwVal2 = 0L;
			pDehMgr->errInfo.dwVal3 = 0L;
			pDehMgr->errInfo.dwVal1 = dwErrInfo;
			printk(KERN_ERR "WMD_DEH_Notify: DSP_PWRERROR, errInfo "
					"= 0x%x\n", dwErrInfo);
			break;
#endif /* CONFIG_BRIDGE_NTFY_PWRERR */
#ifdef CONFIG_BRIDGE_WDT3
		case DSP_WDTOVERFLOW:
			pDehMgr->errInfo.dwErrMask = DSP_WDTOVERFLOW;
			pDehMgr->errInfo.dwVal1 = 0L;
			pDehMgr->errInfo.dwVal2 = 0L;
			pDehMgr->errInfo.dwVal3 = 0L;
			pr_err("WMD_DEH_Notify: DSP_WDTOVERFLOW \n ");
			break;
#endif
		default:
			DBG_Trace(DBG_LEVEL6,
				 "WMD_DEH_Notify: Unknown Error, errInfo = "
				 "0x%x\n", dwErrInfo);
			break;
		}

		/* Filter subsequent notifications when an error occurs */
		if (pDevContext->dwBrdState != BRD_ERROR) {
			NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
#ifdef CONFIG_BRIDGE_RECOVERY
			bridge_recover_schedule();
#endif
		}

		/* Set the Board state as ERROR */
		pDevContext->dwBrdState = BRD_ERROR;
		/* Disable all the clocks that were enabled by DSP */
		(void)DSP_PeripheralClocks_Disable(pDevContext, NULL);
#ifdef CONFIG_BRIDGE_WDT3
		/*
		 * Avoid the subsequent WDT if it happens once,
		 * also If MMU fault occurs
		 */
		dsp_wdt_enable(false);
#endif

	}
}