msm: kgsl: Do not send NMI to GMU on CM3 fault

Say GMU hits a hard fault and saves critical debug state and
sends CM3 fault interrupt. It is possible that subsequent handshake
between kgsl and GMU will timeout and kgsl will trigger GMU snapshot.
This will send an NMI to GMU, which will over-write the critical debug
state. To avoid this, check if there was a CM3 fault before sending
NMI to the GMU.

Change-Id: I0d4d4af3efe31110123f614c8dd8fe8d4a04c812
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
Harshdeep Dhatt 2020-02-14 17:14:41 -07:00
commit 20a71ac909
4 changed files with 37 additions and 5 deletions

View file

@ -1104,6 +1104,9 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device,
/* Populate the GMU version info before GMU boots */
load_gmu_version_info(device);
/* Clear any previously set cm3 fault */
atomic_set(&gmu->cm3_fault, 0);
ret = a6xx_gmu_start(device);
if (ret)
return ret;

View file

@ -1014,7 +1014,17 @@ static irqreturn_t gmu_irq_handler(int irq, void *data)
ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
(mask | GMU_INT_WDOG_BITE));
adreno_gmu_send_nmi(adreno_dev);
/* make sure we're reading the latest cm3_fault */
smp_rmb();
/*
* We should not send NMI if there was a CM3 fault reported
* because we don't want to overwrite the critical CM3 state
* captured by gmu before it sent the CM3 fault interrupt.
*/
if (!atomic_read(&gmu->cm3_fault))
adreno_gmu_send_nmi(adreno_dev);
/*
* There is sufficient delay for the GMU to have finished
* handling the NMI before snapshot is taken, as the fault
@ -1532,9 +1542,21 @@ static void gmu_snapshot(struct kgsl_device *device)
if (test_and_set_bit(GMU_FAULT, &device->gmu_core.flags))
return;
adreno_gmu_send_nmi(adreno_dev);
/* Wait for the NMI to be handled */
udelay(100);
/* make sure we're reading the latest cm3_fault */
smp_rmb();
/*
* We should not send NMI if there was a CM3 fault reported because we
* don't want to overwrite the critical CM3 state captured by gmu before
* it sent the CM3 fault interrupt.
*/
if (!atomic_read(&gmu->cm3_fault)) {
adreno_gmu_send_nmi(adreno_dev);
/* Wait for the NMI to be handled */
udelay(100);
}
kgsl_device_snapshot(device, NULL, true);
adreno_write_gmureg(adreno_dev,

View file

@ -210,6 +210,8 @@ struct gmu_device {
unsigned long kmem_bitmap;
const struct gmu_vma_entry *vma;
unsigned int log_wptr_retention;
/** @cm3_fault: whether gmu received a cm3 fault interrupt */
atomic_t cm3_fault;
};
struct gmu_memdesc *gmu_get_memdesc(struct gmu_device *gmu,

View file

@ -852,9 +852,14 @@ irqreturn_t hfi_irq_handler(int irq, void *data)
if (status & HFI_IRQ_DBGQ_MASK)
tasklet_hi_schedule(&hfi->tasklet);
if (status & HFI_IRQ_CM3_FAULT_MASK)
if (status & HFI_IRQ_CM3_FAULT_MASK) {
dev_err_ratelimited(&gmu->pdev->dev,
"GMU CM3 fault interrupt received\n");
atomic_set(&gmu->cm3_fault, 1);
/* make sure other CPUs see the update */
smp_wmb();
}
if (status & ~HFI_IRQ_MASK)
dev_err_ratelimited(&gmu->pdev->dev,
"Unhandled HFI interrupts 0x%lx\n",