Loading drivers/gpu/msm/adreno_a6xx_gmu.c +56 −1 Original line number Diff line number Diff line Loading @@ -1156,13 +1156,48 @@ static int a6xx_gmu_load_firmware(struct kgsl_device *device) #define A6XX_VBIF_XIN_HALT_CTRL1_ACKS (BIT(0) | BIT(1) | BIT(2) | BIT(3)) static void do_gbif_halt(struct kgsl_device *device, u32 reg, u32 ack_reg, u32 mask, const char *client) { u32 ack; unsigned long t; kgsl_regwrite(device, reg, mask); t = jiffies + msecs_to_jiffies(100); do { kgsl_regread(device, ack_reg, &ack); if ((ack & mask) == mask) return; /* * If we are attempting recovery in case of stall-on-fault * then the halt sequence will not complete as long as SMMU * is stalled. */ kgsl_mmu_pagefault_resume(&device->mmu); usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Check one last time */ kgsl_mmu_pagefault_resume(&device->mmu); kgsl_regread(device, ack_reg, &ack); if ((ack & mask) == mask) return; dev_err(device->dev, "%s GBIF halt timed out\n", client); } static int a6xx_gmu_suspend(struct kgsl_device *device) { int ret = 0; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); /* If SPTP_RAC is on, turn off SPTP_RAC HS */ a6xx_gmu_sptprac_disable(ADRENO_DEVICE(device)); a6xx_gmu_sptprac_disable(adreno_dev); /* Disconnect GPU from BUS is not needed if CX GDSC goes off later */ Loading @@ -1176,6 +1211,26 @@ static int a6xx_gmu_suspend(struct kgsl_device *device) /* Make sure above writes are committed before we proceed to recovery */ wmb(); gmu_core_regwrite(device, A6XX_GMU_CM3_SYSRESET, 1); if (adreno_has_gbif(adreno_dev)) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Halt GX traffic */ do_gbif_halt(device, A6XX_RBBM_GBIF_HALT, A6XX_RBBM_GBIF_HALT_ACK, gpudev->gbif_gx_halt_mask, "GX"); /* Halt CX traffic */ do_gbif_halt(device, A6XX_GBIF_HALT, A6XX_GBIF_HALT_ACK, gpudev->gbif_arb_halt_mask, "CX"); } kgsl_regwrite(device, A6XX_RBBM_SW_RESET_CMD, 0x1); /* Allow the software reset to complete */ udelay(100); /* * This is based on the assumption that GMU is the only one controlling * the GX HS. This code path is the only client voting for GX through Loading drivers/gpu/msm/kgsl_iommu.c +29 −39 Original line number Diff line number Diff line Loading @@ -791,8 +791,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, if (pt->name == KGSL_MMU_SECURE_PT) ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; ctx->fault = 1; if (test_bit(KGSL_FT_PAGEFAULT_GPUHALT_ENABLE, &adreno_dev->ft_pf_policy) && (flags & IOMMU_FAULT_TRANSACTION_STALLED)) { Loading Loading @@ -883,6 +881,9 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, sctlr_val &= ~(0x1 << KGSL_IOMMU_SCTLR_CFIE_SHIFT); KGSL_IOMMU_SET_CTX_REG(ctx, SCTLR, sctlr_val); /* This is used by reset/recovery path */ ctx->stalled_on_fault = true; adreno_set_gpu_fault(adreno_dev, ADRENO_IOMMU_PAGE_FAULT); /* Go ahead with recovery*/ adreno_dispatcher_schedule(device); Loading Loading @@ -1986,7 +1987,7 @@ static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu) struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; unsigned int sctlr_val; if (ctx->default_pt != NULL) { if (ctx->default_pt != NULL && ctx->stalled_on_fault) { kgsl_iommu_enable_clk(mmu); KGSL_IOMMU_SET_CTX_REG(ctx, FSR, 0xffffffff); /* Loading @@ -2003,6 +2004,7 @@ static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu) */ wmb(); kgsl_iommu_disable_clk(mmu); ctx->stalled_on_fault = false; } } Loading @@ -2010,42 +2012,30 @@ static void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu) { struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; unsigned int fsr_val; if (ctx->default_pt != NULL && ctx->fault) { while (1) { if (ctx->default_pt != NULL && ctx->stalled_on_fault) { /* * This will only clear fault bits in FSR. FSR.SS will still * be set. Writing to RESUME (below) is the only way to clear * FSR.SS bit. */ KGSL_IOMMU_SET_CTX_REG(ctx, FSR, 0xffffffff); /* * Make sure the above register write * is not reordered across the barrier * as we use writel_relaxed to write it. * Make sure the above register write is not reordered across * the barrier as we use writel_relaxed to write it. */ wmb(); /* * Write 1 to RESUME.TnR to terminate the * stalled transaction. * Write 1 to RESUME.TnR to terminate the stalled transaction. * This will also allow the SMMU to process new transactions. */ KGSL_IOMMU_SET_CTX_REG(ctx, RESUME, 1); /* * Make sure the above register writes * are not reordered across the barrier * as we use writel_relaxed to write them * Make sure the above register writes are not reordered across * the barrier as we use writel_relaxed to write them. */ wmb(); /* * Wait for small time before checking SS bit * to allow transactions to go through after * resume and update SS bit in case more faulty * transactions are pending. */ udelay(5); fsr_val = KGSL_IOMMU_GET_CTX_REG(ctx, FSR); if (!(fsr_val & (1 << KGSL_IOMMU_FSR_SS_SHIFT))) break; } ctx->fault = 0; } } Loading drivers/gpu/msm/kgsl_iommu.h +3 −3 Original line number Diff line number Diff line Loading @@ -86,8 +86,8 @@ enum kgsl_iommu_context_id { * @cb_num: The hardware context bank number, used for calculating register * offsets. * @kgsldev: The kgsl device that uses this context. * @fault: Flag when set indicates that this iommu device has caused a page * fault * @stalled_on_fault: Flag when set indicates that this iommu device is stalled * on a page fault * @default_pt: The default pagetable for this context, * it may be changed by self programming. */ Loading @@ -97,7 +97,7 @@ struct kgsl_iommu_context { enum kgsl_iommu_context_id id; unsigned int cb_num; struct kgsl_device *kgsldev; int fault; bool stalled_on_fault; void __iomem *regbase; struct kgsl_pagetable *default_pt; }; Loading Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +56 −1 Original line number Diff line number Diff line Loading @@ -1156,13 +1156,48 @@ static int a6xx_gmu_load_firmware(struct kgsl_device *device) #define A6XX_VBIF_XIN_HALT_CTRL1_ACKS (BIT(0) | BIT(1) | BIT(2) | BIT(3)) static void do_gbif_halt(struct kgsl_device *device, u32 reg, u32 ack_reg, u32 mask, const char *client) { u32 ack; unsigned long t; kgsl_regwrite(device, reg, mask); t = jiffies + msecs_to_jiffies(100); do { kgsl_regread(device, ack_reg, &ack); if ((ack & mask) == mask) return; /* * If we are attempting recovery in case of stall-on-fault * then the halt sequence will not complete as long as SMMU * is stalled. */ kgsl_mmu_pagefault_resume(&device->mmu); usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Check one last time */ kgsl_mmu_pagefault_resume(&device->mmu); kgsl_regread(device, ack_reg, &ack); if ((ack & mask) == mask) return; dev_err(device->dev, "%s GBIF halt timed out\n", client); } static int a6xx_gmu_suspend(struct kgsl_device *device) { int ret = 0; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); /* If SPTP_RAC is on, turn off SPTP_RAC HS */ a6xx_gmu_sptprac_disable(ADRENO_DEVICE(device)); a6xx_gmu_sptprac_disable(adreno_dev); /* Disconnect GPU from BUS is not needed if CX GDSC goes off later */ Loading @@ -1176,6 +1211,26 @@ static int a6xx_gmu_suspend(struct kgsl_device *device) /* Make sure above writes are committed before we proceed to recovery */ wmb(); gmu_core_regwrite(device, A6XX_GMU_CM3_SYSRESET, 1); if (adreno_has_gbif(adreno_dev)) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Halt GX traffic */ do_gbif_halt(device, A6XX_RBBM_GBIF_HALT, A6XX_RBBM_GBIF_HALT_ACK, gpudev->gbif_gx_halt_mask, "GX"); /* Halt CX traffic */ do_gbif_halt(device, A6XX_GBIF_HALT, A6XX_GBIF_HALT_ACK, gpudev->gbif_arb_halt_mask, "CX"); } kgsl_regwrite(device, A6XX_RBBM_SW_RESET_CMD, 0x1); /* Allow the software reset to complete */ udelay(100); /* * This is based on the assumption that GMU is the only one controlling * the GX HS. This code path is the only client voting for GX through Loading
drivers/gpu/msm/kgsl_iommu.c +29 −39 Original line number Diff line number Diff line Loading @@ -791,8 +791,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, if (pt->name == KGSL_MMU_SECURE_PT) ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; ctx->fault = 1; if (test_bit(KGSL_FT_PAGEFAULT_GPUHALT_ENABLE, &adreno_dev->ft_pf_policy) && (flags & IOMMU_FAULT_TRANSACTION_STALLED)) { Loading Loading @@ -883,6 +881,9 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, sctlr_val &= ~(0x1 << KGSL_IOMMU_SCTLR_CFIE_SHIFT); KGSL_IOMMU_SET_CTX_REG(ctx, SCTLR, sctlr_val); /* This is used by reset/recovery path */ ctx->stalled_on_fault = true; adreno_set_gpu_fault(adreno_dev, ADRENO_IOMMU_PAGE_FAULT); /* Go ahead with recovery*/ adreno_dispatcher_schedule(device); Loading Loading @@ -1986,7 +1987,7 @@ static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu) struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; unsigned int sctlr_val; if (ctx->default_pt != NULL) { if (ctx->default_pt != NULL && ctx->stalled_on_fault) { kgsl_iommu_enable_clk(mmu); KGSL_IOMMU_SET_CTX_REG(ctx, FSR, 0xffffffff); /* Loading @@ -2003,6 +2004,7 @@ static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu) */ wmb(); kgsl_iommu_disable_clk(mmu); ctx->stalled_on_fault = false; } } Loading @@ -2010,42 +2012,30 @@ static void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu) { struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; unsigned int fsr_val; if (ctx->default_pt != NULL && ctx->fault) { while (1) { if (ctx->default_pt != NULL && ctx->stalled_on_fault) { /* * This will only clear fault bits in FSR. FSR.SS will still * be set. Writing to RESUME (below) is the only way to clear * FSR.SS bit. */ KGSL_IOMMU_SET_CTX_REG(ctx, FSR, 0xffffffff); /* * Make sure the above register write * is not reordered across the barrier * as we use writel_relaxed to write it. * Make sure the above register write is not reordered across * the barrier as we use writel_relaxed to write it. */ wmb(); /* * Write 1 to RESUME.TnR to terminate the * stalled transaction. * Write 1 to RESUME.TnR to terminate the stalled transaction. * This will also allow the SMMU to process new transactions. */ KGSL_IOMMU_SET_CTX_REG(ctx, RESUME, 1); /* * Make sure the above register writes * are not reordered across the barrier * as we use writel_relaxed to write them * Make sure the above register writes are not reordered across * the barrier as we use writel_relaxed to write them. */ wmb(); /* * Wait for small time before checking SS bit * to allow transactions to go through after * resume and update SS bit in case more faulty * transactions are pending. */ udelay(5); fsr_val = KGSL_IOMMU_GET_CTX_REG(ctx, FSR); if (!(fsr_val & (1 << KGSL_IOMMU_FSR_SS_SHIFT))) break; } ctx->fault = 0; } } Loading
drivers/gpu/msm/kgsl_iommu.h +3 −3 Original line number Diff line number Diff line Loading @@ -86,8 +86,8 @@ enum kgsl_iommu_context_id { * @cb_num: The hardware context bank number, used for calculating register * offsets. * @kgsldev: The kgsl device that uses this context. * @fault: Flag when set indicates that this iommu device has caused a page * fault * @stalled_on_fault: Flag when set indicates that this iommu device is stalled * on a page fault * @default_pt: The default pagetable for this context, * it may be changed by self programming. */ Loading @@ -97,7 +97,7 @@ struct kgsl_iommu_context { enum kgsl_iommu_context_id id; unsigned int cb_num; struct kgsl_device *kgsldev; int fault; bool stalled_on_fault; void __iomem *regbase; struct kgsl_pagetable *default_pt; }; Loading