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

Commit 7bb42e6a authored by Urvashi Agrawal's avatar Urvashi Agrawal
Browse files

msm: kgsl: Add cooperative reset



Add cooperative reset feature so that the GPU and GMU
can coordinate recovery in case of GPU hangs.

Change-Id: I5c32addfde1a238025c775b5140dc2370d8308d7
Signed-off-by: default avatarUrvashi Agrawal <urvaagra@codeaurora.org>
parent cd914bbc
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -946,6 +946,7 @@
#define A6XX_GMU_CM3_SYSRESET			0x1F800
#define A6XX_GMU_CM3_SYSRESET			0x1F800
#define A6XX_GMU_CM3_BOOT_CONFIG		0x1F801
#define A6XX_GMU_CM3_BOOT_CONFIG		0x1F801
#define A6XX_GMU_CX_GMU_WFI_CONFIG		0x1F802
#define A6XX_GMU_CX_GMU_WFI_CONFIG		0x1F802
#define A6XX_GMU_CX_GMU_WDOG_CTRL		0x1F813
#define A6XX_GMU_CM3_FW_BUSY			0x1F81A
#define A6XX_GMU_CM3_FW_BUSY			0x1F81A
#define A6XX_GMU_CM3_FW_INIT_RESULT		0x1F81C
#define A6XX_GMU_CM3_FW_INIT_RESULT		0x1F81C
#define A6XX_GMU_CM3_CFG			0x1F82D
#define A6XX_GMU_CM3_CFG			0x1F82D
+22 −0
Original line number Original line Diff line number Diff line
@@ -333,6 +333,28 @@ void adreno_fault_detect_stop(struct adreno_device *adreno_dev)
	adreno_dev->fast_hang_detect = 0;
	adreno_dev->fast_hang_detect = 0;
}
}


#define GMU_CM3_CFG_NONMASKINTR_SHIFT	9

/* Send an NMI to the GMU */
void adreno_gmu_send_nmi(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();
	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
		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();
}

/*
/*
 * A workqueue callback responsible for actually turning on the GPU after a
 * A workqueue callback responsible for actually turning on the GPU after a
 * touch event. kgsl_pwrctrl_change_state(ACTIVE) is used without any
 * touch event. kgsl_pwrctrl_change_state(ACTIVE) is used without any
+1 −0
Original line number Original line Diff line number Diff line
@@ -1812,4 +1812,5 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
	enum adreno_regs offset, unsigned int val,
	enum adreno_regs offset, unsigned int val,
	unsigned int fence_mask);
	unsigned int fence_mask);
int adreno_clear_pending_transactions(struct kgsl_device *device);
int adreno_clear_pending_transactions(struct kgsl_device *device);
void adreno_gmu_send_nmi(struct adreno_device *adreno_dev);
#endif /*__ADRENO_H */
#endif /*__ADRENO_H */
+33 −0
Original line number Original line Diff line number Diff line
@@ -1595,6 +1595,38 @@ static void a6xx_gmu_snapshot(struct kgsl_device *device,
	}
	}
}
}


static void a6xx_gmu_cooperative_reset(struct kgsl_device *device)
{

	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	unsigned int result;

	gmu_core_regwrite(device, A6XX_GMU_CX_GMU_WDOG_CTRL, 0);
	gmu_core_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, BIT(17));

	/*
	 * After triggering graceful death wait for snapshot ready
	 * indication from GMU.
	 */
	if (!timed_poll_check(device, A6XX_GMU_CM3_FW_INIT_RESULT,
				0x800, 2, 0x800))
		return;

	gmu_core_regread(device, A6XX_GMU_CM3_FW_INIT_RESULT, &result);
	dev_err(&gmu->pdev->dev,
		"GMU cooperative reset timed out 0x%x\n", result);
	/*
	 * If we dont get a snapshot ready from GMU, trigger NMI
	 * and if we still timeout then we just continue with reset.
	 */
	adreno_gmu_send_nmi(ADRENO_DEVICE(device));
	udelay(200);
	gmu_core_regread(device, A6XX_GMU_CM3_FW_INIT_RESULT, &result);
	if ((result & 0x800) != 0x800)
		dev_err(&gmu->pdev->dev,
			"GMU cooperative reset NMI timed out 0x%x\n", result);
}

static int a6xx_gmu_wait_for_active_transition(
static int a6xx_gmu_wait_for_active_transition(
	struct kgsl_device *device)
	struct kgsl_device *device)
{
{
@@ -1637,6 +1669,7 @@ struct gmu_dev_ops adreno_a6xx_gmudev = {
	.ifpc_store = a6xx_gmu_ifpc_store,
	.ifpc_store = a6xx_gmu_ifpc_store,
	.ifpc_show = a6xx_gmu_ifpc_show,
	.ifpc_show = a6xx_gmu_ifpc_show,
	.snapshot = a6xx_gmu_snapshot,
	.snapshot = a6xx_gmu_snapshot,
	.cooperative_reset = a6xx_gmu_cooperative_reset,
	.wait_for_active_transition = a6xx_gmu_wait_for_active_transition,
	.wait_for_active_transition = a6xx_gmu_wait_for_active_transition,
	.gmu2host_intr_mask = HFI_IRQ_MASK,
	.gmu2host_intr_mask = HFI_IRQ_MASK,
	.gmu_ao_intr_mask = GMU_AO_INT_MASK,
	.gmu_ao_intr_mask = GMU_AO_INT_MASK,
+6 −0
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@


#include "adreno.h"
#include "adreno.h"
#include "adreno_trace.h"
#include "adreno_trace.h"
#include "kgsl_gmu_core.h"


#define DRAWQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s))
#define DRAWQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s))


@@ -2161,6 +2162,11 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
		adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
		adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
			ADRENO_REG_CP_IB1_BASE_HI, &base);
			ADRENO_REG_CP_IB1_BASE_HI, &base);


	if (!test_bit(KGSL_FT_PAGEFAULT_GPUHALT_ENABLE,
		&adreno_dev->ft_pf_policy) &&
		ADRENO_FEATURE(ADRENO_DEVICE(device), ADRENO_COOP_RESET))
		gmu_core_dev_cooperative_reset(device);

	do_header_and_snapshot(device, fault, hung_rb, cmdobj);
	do_header_and_snapshot(device, fault, hung_rb, cmdobj);


	/* Turn off the KEEPALIVE vote from the ISR for hard fault */
	/* Turn off the KEEPALIVE vote from the ISR for hard fault */
Loading