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

Commit 3d42a450 authored by Puranam V G Tejaswi's avatar Puranam V G Tejaswi
Browse files

msm: kgsl: check kgsl state before accessing device registers



In some unfortunate scenarios it is possible that dispatcher is
scheduled when kgsl state is not awake. Consider the scenario
when GMU stop failed. During subsequent wake, GMU boot failed and
watchdog interrupt has been received. In the handler GPU fault is
set and dipatcher_do_fault() is triggered. Here device registers
are accessed and kgsl state is slumber as previous wake failed.
So check kgsl state before accessing any register.

Change-Id: Ibbc2366e34d3351af997dcd68f7e749ef2869e55
Signed-off-by: default avatarPuranam V G Tejaswi <pvgtejas@codeaurora.org>
parent 923d9dbf
Loading
Loading
Loading
Loading
+20 −17
Original line number Diff line number Diff line
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -2094,6 +2094,22 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
	if (fault == 0)
		return 0;

	mutex_lock(&device->mutex);

	/*
	 * In the very unlikely case that the power is off, do nothing - the
	 * state will be reset on power up and everybody will be happy
	 */
	if (!kgsl_state_is_awake(device)) {
		mutex_unlock(&device->mutex);
		if (fault & ADRENO_SOFT_FAULT) {
			/* Clear the existing register values */
			memset(adreno_ft_regs_val, 0,
				adreno_ft_regs_num * sizeof(unsigned int));
		}
		return 0;
	}

	/* Mask all GMU interrupts */
	if (kgsl_gmu_isenabled(device)) {
		adreno_write_gmureg(adreno_dev,
@@ -2107,17 +2123,6 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
	if (gpudev->gx_is_on)
		gx_on = gpudev->gx_is_on(adreno_dev);

	/*
	 * In the very unlikely case that the power is off, do nothing - the
	 * state will be reset on power up and everybody will be happy
	 */

	if (!kgsl_state_is_awake(device) && (fault & ADRENO_SOFT_FAULT)) {
		/* Clear the existing register values */
		memset(adreno_ft_regs_val, 0,
				adreno_ft_regs_num * sizeof(unsigned int));
		return 0;
	}

	/*
	 * On A5xx and A6xx, read RBBM_STATUS3:SMMU_STALLED_ON_FAULT (BIT 24)
@@ -2130,12 +2135,12 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
		gx_on) {
		unsigned int val;

		mutex_lock(&device->mutex);
		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS3, &val);
		if (val & BIT(24)) {
			mutex_unlock(&device->mutex);
		if (val & BIT(24))
			return 0;
		}
	}

	/* Turn off all the timers */
	del_timer_sync(&dispatcher->timer);
@@ -2147,8 +2152,6 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
	if (adreno_is_preemption_enabled(adreno_dev))
		del_timer_sync(&adreno_dev->preempt.timer);

	mutex_lock(&device->mutex);

	if (gx_on)
		adreno_readreg64(adreno_dev, ADRENO_REG_CP_RB_BASE,
			ADRENO_REG_CP_RB_BASE_HI, &base);