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

Commit 8069dc48 authored by Shubhraprakash Das's avatar Shubhraprakash Das
Browse files

msm: kgsl: Clear pending transactions from VBIF on hang



When resetting device on a hang the pending transactions in the
VBIF should be cleared since the GPU is hung and unable to accept
any transactions. These pending transactions can cause VBIF pipe
to block the IOMMU so clear them.

CRs-Fixed: 762073
Change-Id: I05b2f5ab5af0e517835dd79a9630c1ee4750020f
Signed-off-by: default avatarShubhraprakash Das <sadas@codeaurora.org>
parent 7aad09de
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -545,7 +545,17 @@
#define A3XX_VBIF_PERF_PWR_CNT2_LO 0x307b
#define A3XX_VBIF_PERF_PWR_CNT2_HI 0x307c

#define A3XX_VBIF_XIN_HALT_CTRL0 0x3080
#define A3XX_VBIF_XIN_HALT_CTRL0_MASK 0x3F

#define A3XX_VBIF_XIN_HALT_CTRL1 0x3081

/* VBIF register offsets for A306 */
#define A3XX_VBIF2_XIN_HALT_CTRL0 0x3081
#define A3XX_VBIF2_XIN_HALT_CTRL0_MASK 0x7

#define A3XX_VBIF2_XIN_HALT_CTRL1 0x3082

#define A3XX_VBIF2_PERF_CNT_EN0 0x30c0
#define A3XX_VBIF2_PERF_CNT_EN1 0x30c1
#define A3XX_VBIF2_PERF_CNT_EN2 0x30c2
+6 −0
Original line number Diff line number Diff line
@@ -662,6 +662,12 @@ enum a4xx_vfd_perfctr_vfd_sel {
#define A4XX_VBIF_IN_WR_LIM_CONF0	0x3030
#define A4XX_VBIF_IN_WR_LIM_CONF1	0x3031
#define A4XX_VBIF_ROUND_ROBIN_QOS_ARB	0x3049

#define A4XX_VBIF_XIN_HALT_CTRL0	0x3080
#define A4XX_VBIF_XIN_HALT_CTRL0_MASK	0x1F

#define A4XX_VBIF_XIN_HALT_CTRL1	0x3081

#define A4XX_VBIF_TEST_BUS_OUT_CTRL		0x3084
#define A4XX_VBIF_TEST_BUS_OUT_CTRL_EN_MASK	0x1
#define A4XX_VBIF_TEST_BUS_OUT_CTRL_EN_SHIFT	0x0
+34 −0
Original line number Diff line number Diff line
@@ -516,6 +516,8 @@ adreno_identify_gpu(struct adreno_device *adreno_dev)
		if (reg_offsets->offset_0 != i && !reg_offsets->offsets[i])
			reg_offsets->offsets[i] = ADRENO_REG_UNUSED;
	}
	if (gpudev->gpudev_init)
		gpudev->gpudev_init(adreno_dev);
}

static const struct platform_device_id adreno_id_table[] = {
@@ -1291,6 +1293,35 @@ static int adreno_start(struct kgsl_device *device, int priority)
	return _status;
}

/**
 * adreno_vbif_clear_pending_transactions() - Clear transactions in VBIF pipe
 * @device: Pointer to the device whose VBIF pipe is to be cleared
 */
static void adreno_vbif_clear_pending_transactions(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	unsigned int mask = gpudev->vbif_xin_halt_ctrl0_mask;
	unsigned int val;
	unsigned long wait_for_vbif;

	adreno_writereg(adreno_dev, ADRENO_REG_VBIF_XIN_HALT_CTRL0, mask);
	/* wait for the transactions to clear */
	wait_for_vbif = jiffies + msecs_to_jiffies(100);
	while (1) {
		adreno_readreg(adreno_dev,
			ADRENO_REG_VBIF_XIN_HALT_CTRL1, &val);
		if ((val & mask) == mask)
			break;
		if (time_after(jiffies, wait_for_vbif)) {
			KGSL_DRV_ERR(device,
				"Wait limit reached for VBIF XIN Halt\n");
			break;
		}
	}
	adreno_writereg(adreno_dev, ADRENO_REG_VBIF_XIN_HALT_CTRL0, 0);
}

static int adreno_stop(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -1344,6 +1375,9 @@ int adreno_reset(struct kgsl_device *device)
	struct kgsl_mmu *mmu = &device->mmu;
	int i = 0;

	/* clear pending vbif transactions before reset */
	adreno_vbif_clear_pending_transactions(device);

	/* Try soft reset first, for non mmu fault case only */
	if (!atomic_read(&mmu->fault)) {
		ret = adreno_soft_reset(device);
+4 −0
Original line number Diff line number Diff line
@@ -432,6 +432,8 @@ enum adreno_regs {
	ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
	ADRENO_REG_RBBM_SECVID_TRUST_CONTROL,
	ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
	ADRENO_REG_VBIF_XIN_HALT_CTRL0,
	ADRENO_REG_VBIF_XIN_HALT_CTRL1,
	ADRENO_REG_REGISTER_MAX,
};

@@ -595,9 +597,11 @@ struct adreno_gpudev {

	struct adreno_irq *irq;
	int num_prio_levels;
	unsigned int vbif_xin_halt_ctrl0_mask;
	/* GPU specific function hooks */
	void (*irq_trace)(struct adreno_device *, unsigned int status);
	void (*snapshot)(struct adreno_device *, struct kgsl_snapshot *);
	void (*gpudev_init)(struct adreno_device *);
	int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
	int (*perfcounter_init)(struct adreno_device *);
	void (*start)(struct adreno_device *);
+27 −0
Original line number Diff line number Diff line
@@ -708,6 +708,27 @@ int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev)
	return 0;
}

/*
 * a3xx_gpudev_init() - Initialize gpudev specific fields
 * @adreno_dev: Pointer to adreno device
 */
void a3xx_gpudev_init(struct adreno_device *adreno_dev)
{
	struct adreno_gpudev *gpudev;
	const struct adreno_reg_offsets *reg_offsets;

	if (adreno_is_a306(adreno_dev)) {
		gpudev = ADRENO_GPU_DEVICE(adreno_dev);
		reg_offsets = gpudev->reg_offsets;
		reg_offsets->offsets[ADRENO_REG_VBIF_XIN_HALT_CTRL0] =
			A3XX_VBIF2_XIN_HALT_CTRL0;
		reg_offsets->offsets[ADRENO_REG_VBIF_XIN_HALT_CTRL1] =
			A3XX_VBIF2_XIN_HALT_CTRL1;
		gpudev->vbif_xin_halt_ctrl0_mask =
				A3XX_VBIF2_XIN_HALT_CTRL0_MASK;
	}
}

/*
 * a3xx_rb_init() - Initialize ringbuffer
 * @adreno_dev: Pointer to adreno device
@@ -2032,6 +2053,10 @@ static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
				A3XX_RBBM_PERFCTR_LOAD_VALUE_LO),
	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
				A3XX_RBBM_PERFCTR_LOAD_VALUE_HI),
	ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL0,
				A3XX_VBIF_XIN_HALT_CTRL0),
	ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL1,
				A3XX_VBIF_XIN_HALT_CTRL1),
};

const struct adreno_reg_offsets a3xx_reg_offsets = {
@@ -2065,7 +2090,9 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
	.irq_trace = trace_kgsl_a3xx_irq_status,
	.snapshot_data = &a3xx_snapshot_data,
	.num_prio_levels = 1,
	.vbif_xin_halt_ctrl0_mask = A3XX_VBIF_XIN_HALT_CTRL0_MASK,

	.gpudev_init = a3xx_gpudev_init,
	.rb_init = a3xx_rb_init,
	.perfcounter_init = a3xx_perfcounter_init,
	.busy_cycles = a3xx_busy_cycles,
Loading