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

Commit 73bf5760 authored by Sushmita Susheelendra's avatar Sushmita Susheelendra Committed by Deepak Kumar
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>
Signed-off-by: default avatarDeepak Kumar <dkumar@codeaurora.org>
parent f7434dba
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ struct gmu_vma {
	unsigned int image_start;
};

#define GMU_CM3_CFG_NONMASKINTR_SHIFT    9

struct gmu_iommu_context {
	const char *name;
	struct device *dev;
@@ -786,6 +788,24 @@ static int gmu_rpmh_init(struct gmu_device *gmu, struct kgsl_pwrctrl *pwr)
	return rpmh_arc_votes_init(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 gmu_device *gmu = data;
@@ -807,6 +827,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);
@@ -1356,19 +1383,8 @@ void gmu_snapshot(struct kgsl_device *device)
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct gmu_device *gmu = &device->gmu;

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