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

Commit ed978a34 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Send NMI to GMU upon watchdog bite"

parents 3a276700 85830cf6
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ MODULE_PARM_DESC(noacd, "Disable GPU ACD");
#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;
@@ -926,6 +928,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;
@@ -947,6 +967,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);
@@ -1546,19 +1573,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);