コード例 #1
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

	}
}
コード例 #2
0
ファイル: ue_deh.c プロジェクト: AdiPat/i9003_Kernel
/*
 *  ======== bridge_deh_notify ========
 *      DEH error notification function. Informs user about the error.
 */
void bridge_deh_notify(struct deh_mgr *hdeh_mgr, u32 ulEventMask, u32 dwErrInfo)
{
	struct deh_mgr *deh_mgr_obj = (struct deh_mgr *)hdeh_mgr;
	struct wmd_dev_context *dev_context;
	int status = 0;
	u32 mem_physical = 0;
	u32 hw_mmu_max_tlb_count = 31;
	extern u32 fault_addr;
	struct cfg_hostres *resources;
	hw_status hw_status_obj;
	u32 cnt = 0;


	if (deh_mgr_obj) {
		printk(KERN_INFO
		       "bridge_deh_notify: ********** DEVICE EXCEPTION "
		       "**********\n");
		dev_context =
		    (struct wmd_dev_context *)deh_mgr_obj->hwmd_context;
		resources = dev_context->resources;

		switch (ulEventMask) {
		case DSP_SYSERROR:
			/* reset err_info structure before use */
			deh_mgr_obj->err_info.dw_err_mask = DSP_SYSERROR;
			deh_mgr_obj->err_info.dw_val1 = 0L;
			deh_mgr_obj->err_info.dw_val2 = 0L;
			deh_mgr_obj->err_info.dw_val3 = 0L;
			deh_mgr_obj->err_info.dw_val1 = dwErrInfo;
			printk(KERN_ERR
			       "bridge_deh_notify: DSP_SYSERROR, err_info "
			       "= 0x%x\n", dwErrInfo);
			dump_dl_modules(dev_context);
			dump_dsp_stack(dev_context);

			break;
		case DSP_MMUFAULT:
			/* MMU fault routine should have set err info
			 * structure */
			deh_mgr_obj->err_info.dw_err_mask = DSP_MMUFAULT;
			printk(KERN_INFO "bridge_deh_notify: DSP_MMUFAULT,"
			       "err_info = 0x%x\n", dwErrInfo);
			printk(KERN_INFO
			       "bridge_deh_notify: DSP_MMUFAULT, High "
			       "Address = 0x%x\n",
			       (unsigned int)deh_mgr_obj->err_info.dw_val1);
			printk(KERN_INFO "bridge_deh_notify: DSP_MMUFAULT, Low "
			       "Address = 0x%x\n",
			       (unsigned int)deh_mgr_obj->err_info.dw_val2);
			printk(KERN_INFO
			       "bridge_deh_notify: DSP_MMUFAULT, fault "
			       "address = 0x%x\n", (unsigned int)fault_addr);
			dummy_va_addr = (u32) kzalloc(sizeof(char) * 0x1000,
								GFP_ATOMIC);
			mem_physical =
			    VIRT_TO_PHYS(PG_ALIGN_LOW
					 ((u32) dummy_va_addr, PG_SIZE4K));
			dev_context = (struct wmd_dev_context *)
			    deh_mgr_obj->hwmd_context;

			print_dsp_trace_buffer(dev_context);
			dump_dl_modules(dev_context);

			/* 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 (dev_context->num_tlb_entries >
			    hw_mmu_max_tlb_count) {
				dev_context->num_tlb_entries =
				    dev_context->fixed_tlb_entries;
			}
			if (DSP_SUCCEEDED(status)) {
				hw_status_obj =
				    hw_mmu_tlb_add(resources->dw_dmmu_base,
						   mem_physical, fault_addr,
						   HW_PAGE_SIZE4KB, 1,
						   &map_attrs, 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_event_ack(resources->dw_dmmu_base,
					 HW_MMU_TRANSLATION_FAULT);
			dump_dsp_stack(deh_mgr_obj->hwmd_context);
			if (timer)
				omap_dm_timer_disable(timer);
			break;
#ifdef CONFIG_BRIDGE_NTFY_PWRERR
		case DSP_PWRERROR:
			/* reset err_info structure before use */
			deh_mgr_obj->err_info.dw_err_mask = DSP_PWRERROR;
			deh_mgr_obj->err_info.dw_val1 = 0L;
			deh_mgr_obj->err_info.dw_val2 = 0L;
			deh_mgr_obj->err_info.dw_val3 = 0L;
			deh_mgr_obj->err_info.dw_val1 = dwErrInfo;
			printk(KERN_ERR
			       "bridge_deh_notify: DSP_PWRERROR, err_info "
			       "= 0x%x\n", dwErrInfo);
			break;
#endif /* CONFIG_BRIDGE_NTFY_PWRERR */
#ifdef CONFIG_BRIDGE_WDT3
		case DSP_WDTOVERFLOW:
			deh_mgr_obj->err_info.dw_err_mask = DSP_WDTOVERFLOW;
			deh_mgr_obj->err_info.dw_val1 = 0L;
			deh_mgr_obj->err_info.dw_val2 = 0L;
			deh_mgr_obj->err_info.dw_val3 = 0L;
			pr_err("bridge_deh_notify: DSP_WDTOVERFLOW\n ");
			break;
#endif
		default:
			dev_dbg(bridge, "%s: Unknown Error, err_info = 0x%x\n",
				__func__, dwErrInfo);
			break;
		}

		/* Filter subsequent notifications when an error occurs */
		if (dev_context->dw_brd_state != BRD_ERROR) {
			ntfy_notify(deh_mgr_obj->ntfy_obj, ulEventMask);
#ifdef CONFIG_BRIDGE_RECOVERY
			bridge_recover_schedule();
#endif
		}

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

	}
}