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

Commit b0b581fa authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Clean up the halt on pagefault path



Clean up a number of pitfalls involved with enabling and using
the halt on pagefault option:

 - Set the default pagetable in the user IOMMU context
 - Program the IOMMU immediately if the pagefault policy changes
   while the GPU is active
 - Don't run the crash dumper for a snapshot that follows a halt
   on pagefault (since the IOMMU is still halted)

Change-Id: Ic0dedbad3bdc8c51cefa6607a0f69da5157a838e
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent cb54cb66
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -738,11 +738,20 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
	unsigned long wait_time;
	unsigned int reg = 0;
	unsigned int val;

	/* Jump to legacy if the crash dump script was not initialized */
	if (capturescript.gpuaddr == 0 || registers.gpuaddr == 0)
		return a5xx_legacy_snapshot_registers(device, buf, remain);

	/*
	 * If we got here because we are stalled on fault the crash dumper has
	 * won't work
	 */
	kgsl_regread(device, A5XX_RBBM_STATUS3, &val);
	if (val & BIT(24))
		return a5xx_legacy_snapshot_registers(device, buf, remain);

	if (remain < (count_registers() * 8) + sizeof(*header)) {
		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
		return 0;
+8 −32
Original line number Diff line number Diff line
@@ -1747,31 +1747,10 @@ static int dispatcher_do_fault(struct kgsl_device *device)
	int ret, i;
	int fault;
	int halt;
	unsigned int reg_rbbm_status3;

	fault = atomic_xchg(&dispatcher->fault, 0);
	if (fault == 0)
		return 0;
	/*
	 * Return early if no command inflight - can happen on
	 * false hang detects
	 */
	if (dispatcher->inflight == 0) {
		KGSL_DRV_WARN(device,
		"dispatcher_do_fault with 0 inflight commands\n");
		/*
		 * For certain faults like h/w fault the interrupts are
		 * turned off, re-enable here
		 */
		mutex_lock(&device->mutex);
		if (device->state == KGSL_STATE_AWARE)
			ret = kgsl_pwrctrl_change_state(device,
				KGSL_STATE_ACTIVE);
		else
			ret = 0;
		mutex_unlock(&device->mutex);
		return ret;
	}

	/*
	 * On A5xx, read RBBM_STATUS3:SMMU_STALLED_ON_FAULT (BIT 24) to
@@ -1779,13 +1758,12 @@ static int dispatcher_do_fault(struct kgsl_device *device)
	 * proceed if the fault handler has already run in the IRQ thread,
	 * else return early to give the fault handler a chance to run.
	 */
	if (adreno_is_a5xx(adreno_dev)) {
	if (!(fault & ADRENO_IOMMU_PAGE_FAULT) && adreno_is_a5xx(adreno_dev)) {
		unsigned int val;
		mutex_lock(&device->mutex);
		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS3,
				&reg_rbbm_status3);
		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS3, &val);
		mutex_unlock(&device->mutex);
		if (reg_rbbm_status3 & BIT(24))
			if (!(fault & ADRENO_IOMMU_PAGE_FAULT))
		if (val & BIT(24))
			return 0;
	}

@@ -1803,12 +1781,10 @@ static int dispatcher_do_fault(struct kgsl_device *device)
		ADRENO_REG_CP_RB_BASE_HI, &base);

	/*
	 * If the fault was due to a timeout then stop the CP to ensure we don't
	 * get activity while we are trying to dump the state of the system
	 * Force the CP off for anything but a hard fault to make sure it is
	 * good and stopped
	 */

	if ((fault & ADRENO_TIMEOUT_FAULT || fault & ADRENO_PREEMPT_FAULT) &&
		!(fault & ADRENO_HARD_FAULT)) {
	if (!(fault & ADRENO_HARD_FAULT)) {
		adreno_readreg(adreno_dev, ADRENO_REG_CP_ME_CNTL, &reg);
		if (adreno_is_a5xx(adreno_dev))
			reg |= 1 | (1 << 1);
+8 −1
Original line number Diff line number Diff line
@@ -54,9 +54,16 @@ static int _ft_pagefault_policy_store(struct adreno_device *adreno_dev,
		unsigned int val)
{
	struct kgsl_device *device = &adreno_dev->dev;
	int ret = 0;

	mutex_lock(&device->mutex);
	val &= KGSL_FT_PAGEFAULT_MASK;

	if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
		ret = kgsl_mmu_set_pagefault_policy(&device->mmu,
			(unsigned long) val);

	if (ret == 0)
		adreno_dev->ft_pf_policy = val;

	mutex_unlock(&device->mutex);
+0 −1
Original line number Diff line number Diff line
@@ -999,7 +999,6 @@ static int _setup_user_context(struct kgsl_mmu *mmu)
		return ret;

	kgsl_iommu_enable_clk(mmu);
	KGSL_IOMMU_SET_CTX_REG(ctx, TLBIALL, 1);

	sctlr_val = KGSL_IOMMU_GET_CTX_REG(ctx, SCTLR);