From c56d10a6d4c7f8ea8cb7ebf4e188498aa127f7b7 Mon Sep 17 00:00:00 2001 From: Carter Cooper <ccooper@codeaurora.org> Date: Wed, 3 Dec 2014 10:34:38 -0700 Subject: [PATCH] msm: kgsl: Clear pending transactions from VBIF on hang When resetting device on a hang the pending transactions in the VBIF should be cleared since the GPU is hung and unable to accept any transactions. These pending transactions can cause VBIF pipe to block the IOMMU so clear them. Signed-off-by: Carter Cooper <ccooper@codeaurora.org> Change-Id: I6e0171a6e61c0dd831ce7afdc177775b2ae3f07f --- drivers/gpu/msm/a3xx_reg.h | 5 +++++ drivers/gpu/msm/adreno.c | 38 ++++++++++++++++++++++++++++------- drivers/gpu/msm/adreno.h | 2 ++ drivers/gpu/msm/adreno_a3xx.c | 4 ++++ 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h index 676f46da39a8..36b03e2b5ba3 100644 --- a/drivers/gpu/msm/a3xx_reg.h +++ b/drivers/gpu/msm/a3xx_reg.h @@ -487,6 +487,11 @@ #define A3XX_VBIF_PERF_PWR_CNT2_LO 0x307b #define A3XX_VBIF_PERF_PWR_CNT2_HI 0x307c +#define A3XX_VBIF_XIN_HALT_CTRL0 0x3080 +#define A3XX_VBIF_XIN_HALT_CTRL0_MASK 0x3F +#define A3XX_VBIF_XIN_HALT_CTRL1 0x3081 + + /* Bit flags for RBBM_CTL */ #define RBBM_RBBM_CTL_RESET_PWR_CTR0 BIT(0) #define RBBM_RBBM_CTL_RESET_PWR_CTR1 BIT(1) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 84ab89dc3d67..0d986b7100ec 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1794,6 +1794,32 @@ error_clk_off: return status; } +/** + * adreno_vbif_clear_pending_transactions() - Clear transactions in VBIF pipe + * @device: Pointer to the device whose VBIF pipe is to be cleared + */ +static void adreno_vbif_clear_pending_transactions(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int mask = A3XX_VBIF_XIN_HALT_CTRL0_MASK; + unsigned int val; + unsigned long wait_for_vbif; + + adreno_writereg(adreno_dev, ADRENO_REG_VBIF_XIN_HALT_CTRL0, mask); + /* wait for the transactions to clear */ + wait_for_vbif = jiffies + msecs_to_jiffies(100); + while (1) { + adreno_readreg(adreno_dev, + ADRENO_REG_VBIF_XIN_HALT_CTRL1, &val); + if ((val & mask) == mask) + break; + if (time_after(jiffies, wait_for_vbif)) + break; + } + adreno_writereg(adreno_dev, ADRENO_REG_VBIF_XIN_HALT_CTRL0, 0); +} + + static int adreno_stop(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); @@ -1837,15 +1863,13 @@ static int adreno_stop(struct kgsl_device *device) int adreno_reset(struct kgsl_device *device) { int ret = -EINVAL; - struct kgsl_mmu *mmu = &device->mmu; int i = 0; - /* Try soft reset first, for non mmu fault case only */ - if (!atomic_read(&mmu->fault)) { - ret = adreno_soft_reset(device); - if (ret) - KGSL_DEV_ERR_ONCE(device, "Device soft reset failed\n"); - } + /* clear pending vbif transactions before reset */ + adreno_vbif_clear_pending_transactions(device); + + /* Try soft reset first */ + ret = adreno_soft_reset(device); if (ret) { /* If soft reset failed/skipped, then pull the power */ adreno_stop(device); diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 23309a128152..15084a086359 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -314,6 +314,8 @@ enum adreno_regs { ADRENO_REG_TP0_CHICKEN, ADRENO_REG_RBBM_RBBM_CTL, ADRENO_REG_UCHE_INVALIDATE0, + ADRENO_REG_VBIF_XIN_HALT_CTRL0, + ADRENO_REG_VBIF_XIN_HALT_CTRL1, ADRENO_REG_REGISTER_MAX, }; diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 65d1d063cd21..a68635f36f8f 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -4407,6 +4407,10 @@ static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_RBBM_CTL, A3XX_RBBM_RBBM_CTL), ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE0, A3XX_UCHE_CACHE_INVALIDATE0_REG), + ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL0, + A3XX_VBIF_XIN_HALT_CTRL0), + ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL1, + A3XX_VBIF_XIN_HALT_CTRL1), }; const struct adreno_reg_offsets a3xx_reg_offsets = { -- GitLab