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

Commit 3e1dab59 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Elevate the priority of the thread during adreno start"

parents 4f042c44 3068ca73
Loading
Loading
Loading
Loading
+12 −64
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@

#define KGSL_LOG_LEVEL_DEFAULT 3

static void adreno_start_work(struct work_struct *work);
static void adreno_input_work(struct work_struct *work);

static struct devfreq_msm_adreno_tz_data adreno_tz_data = {
@@ -88,8 +87,6 @@ static struct adreno_device device_3d0 = {
	.ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY,
	.fast_hang_detect = 1,
	.long_ib_detect = 1,
	.start_work = __WORK_INITIALIZER(device_3d0.start_work,
		adreno_start_work),
	.input_work = __WORK_INITIALIZER(device_3d0.input_work,
		adreno_input_work),
	.pwrctrl_flag = BIT(ADRENO_SPTP_PC_CTRL) | BIT(ADRENO_PPD_CTRL),
@@ -111,10 +108,8 @@ static unsigned int adreno_ft_regs_default[] = {
	ADRENO_REG_CP_IB2_BUFSZ
};

static struct workqueue_struct *adreno_wq;

/* Nice level for the higher priority GPU start thread */
static unsigned int _wake_nice = -7;
static int _wake_nice = -7;

/* Number of milliseconds to stay active active after a wake on touch */
static unsigned int _wake_timeout = 100;
@@ -984,9 +979,6 @@ static int adreno_init(struct kgsl_device *device)
	if (ret)
		return ret;

	/* Make a high priority workqueue for starting the GPU */
	adreno_wq = alloc_workqueue("adreno", 0, 1);

	/* Initialize coresight for the target */
	adreno_coresight_init(adreno_dev);

@@ -1223,74 +1215,30 @@ error_rail_off:
	return status;
}

static int _status;

/**
 * _adreno_start_work() - Work handler for the low latency adreno_start
 * @work: Pointer to the work_struct for
 *
 * The work callbak for the low lantecy GPU start - this executes the core
 * _adreno_start function in the workqueue.
 */
static void adreno_start_work(struct work_struct *work)
{
	struct adreno_device *adreno_dev = container_of(work,
		struct adreno_device, start_work);
	struct kgsl_device *device = &adreno_dev->dev;

	/* Nice ourselves to be higher priority but not too high priority */
	set_user_nice(current, _wake_nice);

	mutex_lock(&device->mutex);
	/*
	 *  If adreno start is already called, no need to call it again
	 *  it can lead to unpredictable behavior if we try to start
	 *  the device that is already started.
	 *  Below is the sequence of events that can go bad without the check
	 *  1) thread 1 calls adreno_start to be scheduled on high priority wq
	 *  2) thread 2 calls adreno_start with normal priority
	 *  3) thread 1 after checking the device to be in slumber state gives
	 *     up mutex to be scheduled on high priority wq
	 *  4) thread 2 after checking the device to be in slumber state gets
	 *     the mutex and finishes adreno_start before thread 1 is scheduled
	 *     on high priority wq.
	 *  5) thread 1 gets scheduled on high priority wq and executes
	 *     adreno_start again. This leads to unpredictable behavior.
	 */
	if (!test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
		_status = _adreno_start(adreno_dev);
	else
		_status = 0;
	mutex_unlock(&device->mutex);
}

/**
 * adreno_start() - Power up and initialize the GPU
 * @device: Pointer to the KGSL device to power up
 * @priority:  Boolean flag to specify of the start should be scheduled in a low
 * latency work queue
 *
 * Power up the GPU and initialize it.  If priority is specified then queue the
 * start function in a high priority queue for lower latency.
 * Power up the GPU and initialize it.  If priority is specified then elevate
 * the thread priority for the duration of the start operation
 */
static int adreno_start(struct kgsl_device *device, int priority)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	int nice = task_nice(current);
	int ret;

	/* No priority (normal latency) call the core start function directly */
	if (!priority)
		return _adreno_start(adreno_dev);
	if (priority && (_wake_nice < nice))
		set_user_nice(current, _wake_nice);

	/*
	 * If priority is specified (low latency) then queue the work in a
	 * higher priority work queue and wait for it to finish
	 */
	queue_work(adreno_wq, &adreno_dev->start_work);
	mutex_unlock(&device->mutex);
	flush_work(&adreno_dev->start_work);
	mutex_lock(&device->mutex);
	ret = _adreno_start(adreno_dev);

	if (priority)
		set_user_nice(current, nice);

	return _status;
	return ret;
}

/**
+0 −1
Original line number Diff line number Diff line
@@ -234,7 +234,6 @@ struct adreno_device {
	struct adreno_dispatcher dispatcher;
	struct kgsl_memdesc pwron_fixup;
	unsigned int pwron_fixup_dwords;
	struct work_struct start_work;
	struct work_struct input_work;
	struct adreno_busy_data busy_data;
	unsigned int ram_cycles_lo;