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

Commit edabeb0e authored by Sushmita Susheelendra's avatar Sushmita Susheelendra Committed by Gerrit - the friendly Code Review server
Browse files

msm: kgsl: Send NMI to GMU upon watchdog bite



Send NMI to GMU to dump CM3 system state which includes stack
being used at the time of the watchdog bite, and other key registers.
This will help record information about what instruction was executing
when the GMU watchdog bite occurred. This CM3 state is stored in both
TCM and memory, and hence will be accessible through either a snapshot
or a ramdump.

Change-Id: I396a7794ffa6391cac0b588c71d06cf357e07a2b
Signed-off-by: default avatarSushmita Susheelendra <ssusheel@codeaurora.org>
parent cadf57a6
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#define GMU_CONTEXT_KERNEL		1
#define GMU_KERNEL_ENTRIES		16

#define GMU_CM3_CFG_NONMASKINTR_SHIFT    9

struct gmu_iommu_context {
	const char *name;
	struct device *dev;
@@ -881,6 +883,24 @@ static int gmu_rpmh_init(struct kgsl_device *device,
	return rpmh_arc_votes_init(device, gmu, &cx_arc, &mx_arc, GMU_ARC_VOTE);
}

static void send_nmi_to_gmu(struct adreno_device *adreno_dev)
{
	/* Mask so there's no interrupt caused by NMI */
	adreno_write_gmureg(adreno_dev,
			ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF);

	/* Make sure the interrupt is masked before causing it */
	wmb();
	adreno_write_gmureg(adreno_dev,
		ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0);
	adreno_write_gmureg(adreno_dev,
		ADRENO_REG_GMU_CM3_CFG,
		(1 << GMU_CM3_CFG_NONMASKINTR_SHIFT));

	/* Make sure the NMI is invoked before we proceed*/
	wmb();
}

static irqreturn_t gmu_irq_handler(int irq, void *data)
{
	struct kgsl_device *device = data;
@@ -902,6 +922,13 @@ static irqreturn_t gmu_irq_handler(int irq, void *data)
				ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
				(mask | GMU_INT_WDOG_BITE));

		send_nmi_to_gmu(adreno_dev);
		/*
		 * There is sufficient delay for the GMU to have finished
		 * handling the NMI before snapshot is taken, as the fault
		 * worker is scheduled below.
		 */

		dev_err_ratelimited(&gmu->pdev->dev,
				"GMU watchdog expired interrupt received\n");
		adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
@@ -1472,19 +1499,8 @@ static void gmu_snapshot(struct kgsl_device *device)
	struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device);
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);

	/* Mask so there's no interrupt caused by NMI */
	adreno_write_gmureg(adreno_dev,
			ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF);

	/* Make sure the interrupt is masked before causing it */
	wmb();
	adreno_write_gmureg(adreno_dev,
		ADRENO_REG_GMU_NMI_CONTROL_STATUS, 0);
	adreno_write_gmureg(adreno_dev,
		ADRENO_REG_GMU_CM3_CFG, (1 << 9));

	send_nmi_to_gmu(adreno_dev);
	/* Wait for the NMI to be handled */
	wmb();
	udelay(100);
	kgsl_device_snapshot(device, NULL, true);