Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20a71ac9 authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

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: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent 7636538f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
+26 −4
Original line number Diff line number Diff line
@@ -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));

		/* 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;

	/* 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,
+2 −0
Original line number Diff line number Diff line
@@ -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,
+6 −1
Original line number Diff line number Diff line
@@ -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",