From: Ayoung Sim Date: Tue, 22 Jan 2019 07:04:53 +0000 (+0900) Subject: [COMMON] media: mfc: check the MFC pending X-Git-Tag: MMI-QSAS30.62-33-3~892 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=6966602483761c39ecb404e4db52c411cb634ca5;p=GitHub%2FMotorolaMobilityLLC%2Fkernel-slsi.git [COMMON] media: mfc: check the MFC pending MFC transaction should never occur in the section where the MFC attribute is changed. (Normal <-> Secure) But transaction can be send by HWACG although clock was disabled. So, we check the pending both F/W and H/W. Change-Id: I9f5b9eafa5c94cd159142be0e906638544467072 Signed-off-by: Ayoung Sim --- diff --git a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h index a3d15bb14984..383e86cce91a 100644 --- a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h +++ b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h @@ -27,6 +27,39 @@ MFC_WRITEL(0, MFC_REG_RISC2HOST_INT); \ } while (0) +static inline int mfc_wait_pending(struct mfc_dev *dev) +{ + unsigned int status; + unsigned long timeout; + + /* Check F/W wait status */ + timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); + do { + if (time_after(jiffies, timeout)) { + mfc_err_dev("Timeout while waiting MFC F/W done\n"); + return -EIO; + } + status = MFC_READL(MFC_REG_FIRMWARE_STATUS_INFO); + } while ((status & 0x1) == 0); + + /* Check H/W pending status */ + timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); + do { + if (time_after(jiffies, timeout)) { + mfc_err_dev("Timeout while pendng clear\n"); + mfc_err_dev("MFC access pending R: %#x, BUS: %#x\n", + MFC_READL(MFC_REG_MFC_RPEND), + MFC_READL(MFC_REG_MFC_BUS_STATUS)); + return -EIO; + } + status = MFC_READL(MFC_REG_MFC_RPEND); + } while (status != 0); + + MFC_TRACE_DEV("** pending wait done\n"); + + return 0; +} + static inline int mfc_stop_bus(struct mfc_dev *dev) { unsigned int status; diff --git a/drivers/media/platform/exynos/mfc/mfc_pm.c b/drivers/media/platform/exynos/mfc/mfc_pm.c index 0172fe72148f..8c5fb3670e09 100644 --- a/drivers/media/platform/exynos/mfc/mfc_pm.c +++ b/drivers/media/platform/exynos/mfc/mfc_pm.c @@ -55,10 +55,19 @@ int mfc_pm_clock_on(struct mfc_dev *dev) * -> IP Protection enable -> clock on */ dev->pm.clock_on_steps |= 0x1 << 1; - if (dev->pm.base_type != MFCBUF_INVALID) + if (dev->pm.base_type != MFCBUF_INVALID) { + dev->pm.clock_on_steps |= 0x1 << 2; + ret = mfc_wait_pending(dev); + if (ret != 0) { + mfc_err_dev("pending wait failed (%d)\n", ret); + call_dop(dev, dump_and_stop_debug_mode, dev); + return ret; + } + dev->pm.clock_on_steps |= 0x1 << 3; mfc_set_risc_base_addr(dev, dev->pm.base_type); + } - dev->pm.clock_on_steps |= 0x1 << 2; + dev->pm.clock_on_steps |= 0x1 << 4; #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (dev->curr_ctx_is_drm) { unsigned long flags; @@ -67,7 +76,7 @@ int mfc_pm_clock_on(struct mfc_dev *dev) mfc_debug(3, "Begin: enable protection\n"); ret = exynos_smc(SMC_PROTECTION_SET, 0, dev->id, SMC_PROTECTION_ENABLE); - dev->pm.clock_on_steps |= 0x1 << 3; + dev->pm.clock_on_steps |= 0x1 << 5; if (ret != DRMDRV_OK) { mfc_err_dev("Protection Enable failed! ret(%u)\n", ret); call_dop(dev, dump_and_stop_debug_mode, dev); @@ -79,7 +88,7 @@ int mfc_pm_clock_on(struct mfc_dev *dev) } #endif - dev->pm.clock_on_steps |= 0x1 << 4; + dev->pm.clock_on_steps |= 0x1 << 6; ret = clk_enable(dev->pm.clock); if (ret < 0) { mfc_err_dev("clk_enable failed (%d)\n", ret); @@ -87,13 +96,13 @@ int mfc_pm_clock_on(struct mfc_dev *dev) return ret; } - dev->pm.clock_on_steps |= 0x1 << 5; + dev->pm.clock_on_steps |= 0x1 << 7; atomic_inc_return(&dev->clk_ref); - dev->pm.clock_on_steps |= 0x1 << 6; + dev->pm.clock_on_steps |= 0x1 << 8; state = atomic_read(&dev->clk_ref); mfc_debug(2, "+ %d\n", state); - MFC_TRACE_DEV("** clock_on end: ref state(%d)\n", state); + MFC_TRACE_DEV("** clock_on end: ref(%d) step(%#x)\n", state, dev->pm.clock_on_steps); MFC_TRACE_LOG_DEV("c+%d", state); return 0; @@ -160,7 +169,7 @@ void mfc_pm_clock_off(struct mfc_dev *dev) dev->pm.clock_off_steps |= 0x1 << 7; state = atomic_read(&dev->clk_ref); mfc_debug(2, "- %d\n", state); - MFC_TRACE_DEV("** clock_off end: ref state(%d)\n", state); + MFC_TRACE_DEV("** clock_off end: ref(%d) step(%#x)\n", state, dev->pm.clock_off_steps); MFC_TRACE_LOG_DEV("c-%d", state); } diff --git a/drivers/media/platform/exynos/mfc/mfc_regs.h b/drivers/media/platform/exynos/mfc/mfc_regs.h index f5e0368c81c1..8f22c408c4a9 100644 --- a/drivers/media/platform/exynos/mfc/mfc_regs.h +++ b/drivers/media/platform/exynos/mfc/mfc_regs.h @@ -76,6 +76,8 @@ #define MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT 0xF090 #define MFC_REG_NAL_QUEUE_INFO 0xF094 +#define MFC_REG_FIRMWARE_STATUS_INFO 0xF0A4 + /* Decoder Registers */ #define MFC_REG_D_CRC_CTRL 0xF0B0 #define MFC_REG_D_DEC_OPTIONS 0xF0B4