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

Commit 329932ad authored by Hareesh Gundu's avatar Hareesh Gundu Committed by Venkateswara Rao Tadikonda
Browse files

msm: kgsl: Improve GPU soft fault detection



Following changes been made to improve soft fault detection,
which will fix un clocked register access in dispatcher_do_fault()
and incorrect declaration of GPU soft fault.
i) Stop fault timer before entering to NAP state
ii) Don’t start fault timer if the dispatcher inflight count is zero
iii) Add ringbuffer empty check and test HANG interrupt bit in _isidle()
iv)  Add device state check in dispatcher_do_fault()

CRs-Fixed: 2012731
Change-Id: I5ce498029f389eeeb428b4ac7fb07afd84d5764c
Signed-off-by: default avatarHareesh Gundu <hareeshg@codeaurora.org>
Signed-off-by: default avatarVenkateswara Rao Tadikonda <vtadik@codeaurora.org>
parent e29926e9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2862,6 +2862,7 @@ static const struct kgsl_functable adreno_functable = {
	.pwrlevel_change_settings = adreno_pwrlevel_change_settings,
	.regulator_disable_poll = adreno_regulator_disable_poll,
	.gpu_model = adreno_gpu_model,
	.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
};

static struct platform_driver adreno_platform_driver = {
+31 −1
Original line number Diff line number Diff line
@@ -206,6 +206,10 @@ static inline bool _isidle(struct adreno_device *adreno_dev)
	if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev)))
		goto ret;

	if (test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv)
			&& adreno_rb_empty(adreno_dev->cur_rb))
		goto ret;

	/* only check rbbm status to determine if GPU is idle */
	adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, &reg_rbbm_status);

@@ -1751,6 +1755,18 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
	if (fault == 0)
		return 0;

	/*
	 * 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, read RBBM_STATUS3:SMMU_STALLED_ON_FAULT (BIT 24) to
	 * tell if this function was entered after a pagefault. If so, only
@@ -2202,7 +2218,7 @@ static void adreno_dispatcher_fault_timer(unsigned long data)
	if (!fault_detect_read_compare(adreno_dev)) {
		adreno_set_gpu_fault(adreno_dev, ADRENO_SOFT_FAULT);
		adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
	} else {
	} else if (dispatcher->inflight > 0) {
		mod_timer(&dispatcher->fault_timer,
			jiffies + msecs_to_jiffies(_fault_timer_interval));
	}
@@ -2246,6 +2262,20 @@ void adreno_dispatcher_stop(struct adreno_device *adreno_dev)
	del_timer_sync(&dispatcher->fault_timer);
}

/**
 * adreno_dispatcher_stop() - stop the dispatcher fault timer
 * @adreno_dev: pointer to the adreno device structure
 *
 * Stop the dispatcher fault timer
 */
void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;

	del_timer_sync(&dispatcher->fault_timer);
}

/**
 * adreno_dispatcher_close() - close the dispatcher
 * @adreno_dev: pointer to the adreno device structure
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2008-2017, 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
@@ -108,6 +108,7 @@ void adreno_dispatcher_close(struct adreno_device *adreno_dev);
int adreno_dispatcher_idle(struct adreno_device *adreno_dev);
void adreno_dispatcher_irq_fault(struct adreno_device *adreno_dev);
void adreno_dispatcher_stop(struct adreno_device *adreno_dev);
void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device);

int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
		struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch,
+1 −0
Original line number Diff line number Diff line
@@ -171,6 +171,7 @@ struct kgsl_functable {
	void (*regulator_disable_poll)(struct kgsl_device *device);
	void (*gpu_model)(struct kgsl_device *device, char *str,
		size_t bufsz);
	void (*stop_fault_timer)(struct kgsl_device *device);
};

struct kgsl_ioctl {
+2 −0
Original line number Diff line number Diff line
@@ -2545,6 +2545,8 @@ _nap(struct kgsl_device *device)
			return -EBUSY;
		}

		device->ftbl->stop_fault_timer(device);

		/*
		 * Read HW busy counters before going to NAP state.
		 * The data might be used by power scale governors