diff --git a/drivers/gpu/msm/adreno_a6xx.h b/drivers/gpu/msm/adreno_a6xx.h index a12e3d3ce91a..5ec497b2272f 100644 --- a/drivers/gpu/msm/adreno_a6xx.h +++ b/drivers/gpu/msm/adreno_a6xx.h @@ -260,6 +260,21 @@ static inline int timed_poll_check(struct kgsl_device *device, return 0; } +/** + * a6xx_is_smmu_stalled() - Check whether smmu is stalled or not + * @device: Pointer to KGSL device + * + * Return - True if smmu is stalled or false otherwise + */ +static inline bool a6xx_is_smmu_stalled(struct kgsl_device *device) +{ + u32 val; + + kgsl_regread(device, A6XX_RBBM_STATUS3, &val); + + return val & BIT(24); +} + /* Preemption functions */ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 4be6ff6b4c55..598eebf6c905 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -1903,6 +1903,22 @@ static void a6xx_gmu_send_nmi(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); u32 val; + if (!a6xx_gmu_gx_is_on(device)) + goto done; + + /* + * Do not send NMI if the SMMU is stalled because GMU will not be able + * to save cm3 state to DDR. + */ + if (a6xx_is_smmu_stalled(device)) { + struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); + + dev_err(&gmu->pdev->dev, + "Skipping NMI because SMMU is stalled\n"); + return; + } + +done: /* Mask so there's no interrupt caused by NMI */ gmu_core_regwrite(device, A6XX_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF); diff --git a/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c b/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c index e00977a165ec..cc7ad875a598 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c @@ -5,6 +5,7 @@ #include "a6xx_reg.h" #include "adreno.h" +#include "adreno_a6xx.h" #include "adreno_a6xx_gmu.h" #include "adreno_snapshot.h" #include "kgsl_device.h" @@ -379,14 +380,10 @@ void a6xx_gmu_device_snapshot(struct kgsl_device *device, { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); - unsigned int val; kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY, snapshot, a6xx_gmu_snapshot_itcm, gmu); - kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY, - snapshot, a6xx_gmu_snapshot_dtcm, gmu); - a6xx_gmu_snapshot_versions(device, gmu, snapshot); a6xx_gmu_snapshot_memories(device, gmu, snapshot); @@ -409,15 +406,25 @@ void a6xx_gmu_device_snapshot(struct kgsl_device *device, snapshot_rscc_registers(adreno_dev, snapshot); if (!a6xx_gmu_gx_is_on(device)) - return; + goto dtcm; /* Set fence to ALLOW mode so registers can be read */ kgsl_regwrite(device, A6XX_GMU_AO_AHB_FENCE_CTRL, 0); /* Make sure the previous write posted before reading */ wmb(); - kgsl_regread(device, A6XX_GMU_AO_AHB_FENCE_CTRL, &val); adreno_snapshot_registers(device, snapshot, a6xx_gmu_gx_registers, ARRAY_SIZE(a6xx_gmu_gx_registers) / 2); + + /* A stalled SMMU can lead to NoC timeouts when host accesses DTCM */ + if (a6xx_is_smmu_stalled(device)) { + dev_err(&gmu->pdev->dev, + "Not dumping dtcm because SMMU is stalled\n"); + return; + } + +dtcm: + kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY, + snapshot, a6xx_gmu_snapshot_dtcm, gmu); } diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 6cf2d66eebc1..4322cc87572d 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -1566,7 +1566,6 @@ static void _a6xx_do_crashdump(struct kgsl_device *device) { unsigned long wait_time; unsigned int reg = 0; - unsigned int val; crash_dump_valid = false; @@ -1578,8 +1577,7 @@ static void _a6xx_do_crashdump(struct kgsl_device *device) return; /* IF the SMMU is stalled we cannot do a crash dump */ - kgsl_regread(device, A6XX_RBBM_STATUS3, &val); - if (val & BIT(24)) + if (a6xx_is_smmu_stalled(device)) return; /* Turn on APRIV for legacy targets so we can access the buffers */