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

Commit 2be44f7c authored by Jordan Crouse's avatar Jordan Crouse
Browse files

Revert "msm: kgsl: Use IDLE interrupt to switch to NAP state"



This reverts commit 688272a0.

The HW is very strict in its definition of the word "busy". Even
register reads and writes are "busy" enough to make the GPU send
an idle interrupt when the register access is finished.  This ends
up in lots of extra interrupts in key places like initialization
and hang detection defeating the purpose of faster idle detection.

Change-Id: Ic0dedbad39dbbddd08c5a8eca7a34d4c214bd8b4
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 001053d2
Loading
Loading
Loading
Loading
+3 −17
Original line number Diff line number Diff line
@@ -3263,20 +3263,6 @@ void a3xx_fatal_err_callback(struct adreno_device *adreno_dev, int bit)
	adreno_dispatcher_irq_fault(device);
}

void a3xx_gpu_idle_callback(struct adreno_device *adreno_dev,
					int irq)
{
	struct kgsl_device *device = &adreno_dev->dev;

	if (device->requested_state == KGSL_STATE_NONE) {
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
		queue_work(device->work_queue, &device->idle_check_ws);
	}

	mod_timer_pending(&device->idle_timer,
		jiffies + device->pwrctrl.interval_timeout);
}

/*
 * a3xx_cp_callback() - CP interrupt handler
 * @adreno_dev: Adreno device pointer
@@ -3289,6 +3275,7 @@ void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
{
	struct kgsl_device *device = &adreno_dev->dev;

	device->pwrctrl.irq_last = 1;
	queue_work(device->work_queue, &device->ts_expired_ws);
	adreno_dispatcher_schedule(device);
}
@@ -3740,8 +3727,7 @@ static void a3xx_perfcounter_restore(struct adreno_device *adreno_dev)
}

#define A3XX_INT_MASK \
	((1 << A3XX_INT_RBBM_GPU_IDLE) |         \
	 (1 << A3XX_INT_RBBM_AHB_ERROR) |        \
	((1 << A3XX_INT_RBBM_AHB_ERROR) |        \
	 (1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW) | \
	 (1 << A3XX_INT_CP_T0_PACKET_IN_IB) |    \
	 (1 << A3XX_INT_CP_OPCODE_ERROR) |       \
@@ -3755,7 +3741,7 @@ static void a3xx_perfcounter_restore(struct adreno_device *adreno_dev)
	 (1 << A3XX_INT_UCHE_OOB_ACCESS))

static struct adreno_irq_funcs a3xx_irq_funcs[] = {
	ADRENO_IRQ_CALLBACK(a3xx_gpu_idle_callback), /* 0 - RBBM_GPU_IDLE */
	ADRENO_IRQ_CALLBACK(NULL),                    /* 0 - RBBM_GPU_IDLE */
	ADRENO_IRQ_CALLBACK(a3xx_a4xx_err_callback),  /* 1 - RBBM_AHB_ERROR */
	ADRENO_IRQ_CALLBACK(a3xx_a4xx_err_callback),  /* 2 - RBBM_REG_TIMEOUT */
	/* * 3 - RBBM_ME_MS_TIMEOUT */
+2 −3
Original line number Diff line number Diff line
@@ -957,8 +957,7 @@ static struct adreno_coresight a4xx_coresight = {
};

#define A4XX_INT_MASK \
	((1 << A3XX_INT_RBBM_GPU_IDLE) |		\
	 (1 << A3XX_INT_RBBM_AHB_ERROR) |		\
	((1 << A3XX_INT_RBBM_AHB_ERROR) |		\
	 (1 << A3XX_INT_RBBM_REG_TIMEOUT) |		\
	 (1 << A3XX_INT_RBBM_ME_MS_TIMEOUT) |		\
	 (1 << A3XX_INT_RBBM_PFP_MS_TIMEOUT) |		\
@@ -980,7 +979,7 @@ static struct adreno_coresight a4xx_coresight = {
	 (1 << A4XX_INT_RBBM_DPM_THERMAL_RED_ERR))

static struct adreno_irq_funcs a4xx_irq_funcs[] = {
	ADRENO_IRQ_CALLBACK(a3xx_gpu_idle_callback), /* 0 - RBBM_GPU_IDLE */
	ADRENO_IRQ_CALLBACK(NULL),                   /* 0 - RBBM_GPU_IDLE */
	ADRENO_IRQ_CALLBACK(a3xx_a4xx_err_callback), /* 1 - RBBM_AHB_ERROR */
	ADRENO_IRQ_CALLBACK(a3xx_a4xx_err_callback), /* 2 - RBBM_REG_TIMEOUT */
	/* 3 - RBBM_ME_MS_TIMEOUT */
+1 −0
Original line number Diff line number Diff line
@@ -1237,6 +1237,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
	kgsl_cff_core_idle(device);

done:
	device->pwrctrl.irq_last = 0;
	kgsl_trace_issueibcmds(device, context->id, cmdbatch,
		cmdbatch->timestamp, cmdbatch->flags, ret,
		drawctxt->type);
+38 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <mach/msm_iomap.h>
#include <mach/msm_bus.h>
#include <linux/ktime.h>
#include <linux/delay.h>

#include "kgsl.h"
#include "kgsl_pwrscale.h"
@@ -33,6 +34,16 @@
#define UPDATE_BUSY_VAL		1000000
#define UPDATE_BUSY		50

/*
 * Expected delay for post-interrupt processing on A3xx.
 * The delay may be longer, gradually increase the delay
 * to compensate.  If the GPU isn't done by max delay,
 * it's working on something other than just the final
 * command sequence so stop waiting for it to be idle.
 */
#define INIT_UDELAY		200
#define MAX_UDELAY		2000

struct clk_pair {
	const char *name;
	uint map;
@@ -1149,6 +1160,8 @@ void kgsl_pwrctrl_close(struct kgsl_device *device)
 */
void kgsl_idle_check(struct work_struct *work)
{
	int delay = INIT_UDELAY;
	int requested_state;
	struct kgsl_device *device = container_of(work, struct kgsl_device,
							idle_check_ws);
	WARN_ON(device == NULL);
@@ -1162,11 +1175,29 @@ void kgsl_idle_check(struct work_struct *work)
	if (device->state == KGSL_STATE_ACTIVE
		   || device->state ==  KGSL_STATE_NAP) {
		/*
		 * If no user is explicitly trying to use the GPU,
		 * try to sleep.
		 * If no user is explicitly trying to use the GPU
		 * (active_cnt is zero), then loop with increasing delay,
		 * waiting for the GPU to become idle.
		 */
		while (!atomic_read(&device->active_cnt) &&
			(delay < MAX_UDELAY)) {
			requested_state = device->requested_state;
			if (!kgsl_pwrctrl_sleep(device))
				break;
			/*
			 * If no new commands have been issued since the
			 * last interrupt, stay in this loop waiting for
			 * the GPU to become idle.
			 */
		if (!atomic_read(&device->active_cnt))
			kgsl_pwrctrl_sleep(device);
			if (!device->pwrctrl.irq_last)
				break;
			kgsl_pwrctrl_request_state(device, requested_state);
			mutex_unlock(&device->mutex);
			udelay(delay);
			delay *= 2;
			mutex_lock(&device->mutex);
		}


		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		if (device->state == KGSL_STATE_ACTIVE) {
@@ -1183,6 +1214,8 @@ void kgsl_idle_check(struct work_struct *work)
				kgsl_pwrctrl_busy_time(device, true);
				device->pwrctrl.clk_stats.no_nap_cnt = 0;
			}
		} else {
			device->pwrctrl.irq_last = 0;
		}
	}

+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ struct kgsl_pwrctrl {
	struct pm_qos_request pm_qos_req_dma;
	unsigned int pm_qos_latency;
	unsigned int step_mul;
	unsigned int irq_last;
};

void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);