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

Commit 579c53a1 authored by Lucille Sylvester's avatar Lucille Sylvester
Browse files

msm: kgsl: State based power code interaction



Make all interaction between kgsl code and kgsl power code state
oriented.  Function calls between the two should change the state
and checks involving power should be against the state.  As part
of this transition add the "AWARE" state.  In this state the GPU
is powered up but timers and interrupts are disabled to maintain
the current context.  This state is used for initialization and
error conditions.

Change-Id: I743630fb14ad10f6f5e25fdb25d1ae23d85f0cbc
Signed-off-by: default avatarLucille Sylvester <lsylvest@codeaurora.org>
parent 42162e39
Loading
Loading
Loading
Loading
+23 −58
Original line number Diff line number Diff line
@@ -395,7 +395,7 @@ void adreno_hang_int_callback(struct adreno_device *adreno_dev, int bit)
	struct kgsl_device *device = &adreno_dev->dev;

	KGSL_DRV_CRIT(device, "MISC: GPU hang detected\n");
	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
	adreno_irqctrl(adreno_dev, 0);

	/* Trigger a fault in the dispatcher - this will effect a restart */
	adreno_dispatcher_irq_fault(device);
@@ -974,8 +974,8 @@ static int adreno_init(struct kgsl_device *device)
	if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv))
		return 0;

	/* Power up the device */
	ret = kgsl_pwrctrl_enable(device);
	/* Put the GPU in a responsive state */
	ret = kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE);
	if (ret)
		return ret;

@@ -985,7 +985,6 @@ static int adreno_init(struct kgsl_device *device)
	adreno_ringbuffer_read_pm4_ucode(device);
	adreno_ringbuffer_read_pfp_ucode(device);

	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
	/*
	 * Check if firmware supports the sync lock PM4 packets needed
	 * for IOMMUv1
@@ -1016,10 +1015,10 @@ static int adreno_init(struct kgsl_device *device)
	ret = adreno_perfcounter_init(adreno_dev);

	/* Power down the device */
	kgsl_pwrctrl_disable(device);
	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);

	if (ret)
		goto done;
		return ret;

	/*
	 * Enable the power on shader corruption fix
@@ -1075,7 +1074,6 @@ static int adreno_init(struct kgsl_device *device)
				&adreno_dev->priv);
	}

done:
	return ret;
}

@@ -1091,7 +1089,6 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	struct kgsl_device *device = &adreno_dev->dev;
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int status = -EINVAL;
	unsigned int state = device->state;
	unsigned int regulator_left_on = 0;
	unsigned int pmqos_wakeup_vote = device->pwrctrl.pm_qos_wakeup_latency;
	unsigned int pmqos_active_vote = device->pwrctrl.pm_qos_active_latency;
@@ -1104,8 +1101,6 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	kgsl_cffdump_open(device);

	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);

	regulator_left_on = (regulator_is_enabled(device->pwrctrl.gpu_reg) ||
				(device->pwrctrl.gpu_cx &&
				regulator_is_enabled(device->pwrctrl.gpu_cx)));
@@ -1113,17 +1108,17 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	/* Clear any GPU faults that might have been left over */
	adreno_clear_gpu_fault(adreno_dev);

	/* Power up the device */
	status = kgsl_pwrctrl_enable(device);
	/* Put the GPU in a responsive state */
	status = kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE);
	if (status)
		goto error_rail_off;
		goto error_pwr_off;

	/* Set the bit to indicate that we've just powered on */
	set_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv);

	status = kgsl_mmu_start(device);
	if (status)
		goto error_clk_off;
		goto error_pwr_off;

	status = adreno_ocmem_malloc(adreno_dev);
	if (status) {
@@ -1168,18 +1163,17 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	/* Re-initialize the coresight registers if applicable */
	adreno_coresight_start(adreno_dev);

	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
	adreno_irqctrl(adreno_dev, 1);

	status = adreno_perfcounter_start(adreno_dev);

	if (status)
		goto error_irq_off;
		goto error_mmu_off;

	status = adreno_ringbuffer_cold_start(adreno_dev);

	if (status)
		goto error_irq_off;
		goto error_mmu_off;

	/* Enable h/w power collapse feature */
	if (gpudev->enable_pc)
@@ -1202,17 +1196,11 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	return 0;

error_irq_off:
	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);

error_mmu_off:
	kgsl_mmu_stop(&device->mmu);

error_clk_off:
	kgsl_pwrctrl_disable(device);
error_rail_off:
	/* set the state back to original state */
	kgsl_pwrctrl_change_state(device, state);
error_pwr_off:
	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);

	if (pmqos_active_vote != pmqos_wakeup_vote)
		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
@@ -1283,8 +1271,6 @@ static int adreno_stop(struct kgsl_device *device)
	if (!test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
		return 0;

	kgsl_pwrctrl_enable(device);

	adreno_set_active_ctx_null(adreno_dev);

	adreno_dispatcher_stop(adreno_dev);
@@ -1292,8 +1278,6 @@ static int adreno_stop(struct kgsl_device *device)
	adreno_ringbuffer_stop(adreno_dev);

	adreno_irqctrl(adreno_dev, 0);
	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
	del_timer_sync(&device->idle_timer);

	adreno_ocmem_free(adreno_dev);

@@ -1304,9 +1288,6 @@ static int adreno_stop(struct kgsl_device *device)
	adreno_perfcounter_save(adreno_dev);

	kgsl_mmu_stop(&device->mmu);
	/* Power down the device */
	kgsl_pwrctrl_disable(device);

	kgsl_cffdump_close(device);

	clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);
@@ -1344,7 +1325,7 @@ int adreno_reset(struct kgsl_device *device)
	}
	if (ret) {
		/* If soft reset failed/skipped, then pull the power */
		adreno_stop(device);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);

		/* Keep trying to start the device until it works */
		for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) {
@@ -1368,6 +1349,8 @@ int adreno_reset(struct kgsl_device *device)

	if (atomic_read(&device->active_cnt))
		kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
	else
		kgsl_pwrctrl_change_state(device, KGSL_STATE_NAP);

	/* Set the page table back to the default page table */
	kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
@@ -1639,6 +1622,8 @@ static ssize_t _ft_hang_intr_status_store(struct device *dev,
	if (device == NULL)
		return 0;
	adreno_dev = ADRENO_DEVICE(device);
	if (adreno_dev == NULL)
		return 0;

	mutex_lock(&device->mutex);
	ret = kgsl_sysfs_store(buf, &new_setting);
@@ -1654,21 +1639,10 @@ static ssize_t _ft_hang_intr_status_store(struct device *dev,
		else
			clear_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
		/* Set the new setting based on device state */
		switch (device->state) {
		case KGSL_STATE_NAP:
		case KGSL_STATE_SLEEP:
		if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)) {
			kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
		case KGSL_STATE_ACTIVE:
			adreno_irqctrl(adreno_dev, 1);
		/*
		 * For following states setting will be picked up on device
		 * start. Still need them in switch statement to differentiate
		 * from default
		 */
		case KGSL_STATE_SLUMBER:
		case KGSL_STATE_SUSPEND:
			break;
		default:
		} else if (device->state == KGSL_STATE_INIT) {
			ret = -EACCES;
			/* reset back to old setting on error */
			if (new_setting)
@@ -2250,23 +2224,15 @@ static int adreno_soft_reset(struct kgsl_device *device)
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int ret;

	kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE);
	adreno_set_active_ctx_null(adreno_dev);

	if (kgsl_pwrctrl_isenabled(device))
	adreno_irqctrl(adreno_dev, 0);

	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);

	adreno_clear_gpu_fault(adreno_dev);
	/* since device is oficially off now clear start bit */
	clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);

	/* Delete the idle timer */
	del_timer_sync(&device->idle_timer);

	/* Make sure we are totally awake */
	kgsl_pwrctrl_enable(device);

	/* save physical performance counter values before GPU soft reset */
	adreno_perfcounter_save(adreno_dev);

@@ -2287,7 +2253,6 @@ static int adreno_soft_reset(struct kgsl_device *device)
	adreno_coresight_start(adreno_dev);

	/* Enable IRQ */
	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
	adreno_irqctrl(adreno_dev, 1);

	/* stop all ringbuffers to cancel RB events */
@@ -2324,7 +2289,7 @@ bool adreno_isidle(struct kgsl_device *device)
	struct adreno_ringbuffer *rb;
	int i;

	if (!kgsl_pwrctrl_isenabled(device))
	if (!kgsl_state_is_awake(device))
		return true;

	adreno_get_rptr(ADRENO_CURRENT_RINGBUFFER(adreno_dev));
+9 −4
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ static inline bool _isidle(struct kgsl_device *device)
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	unsigned int ts, i;

	if (!kgsl_pwrctrl_isenabled(device))
	if (!kgsl_state_is_awake(device))
		goto ret;

	/* If GPU HW status is not idle then return false */
@@ -1617,9 +1617,14 @@ static int dispatcher_do_fault(struct kgsl_device *device)
		 * For certain faults like h/w fault the interrupts are
		 * turned off, re-enable here
		 */
		if (kgsl_pwrctrl_isenabled(device))
			kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
		return 0;
		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;
	}

	/* Turn off all the timers */
+4 −3
Original line number Diff line number Diff line
@@ -1063,8 +1063,7 @@ static int kgsl_close_device(struct kgsl_device *device)
		/* Fail if the wait times out */
		BUG_ON(atomic_read(&device->active_cnt) > 0);

		result = device->ftbl->stop(device);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
		result = kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
	}
	mutex_unlock(&device->mutex);
	return result;
@@ -1155,8 +1154,10 @@ static int kgsl_open_device(struct kgsl_device *device)
	}
	device->open_count++;
err:
	if (result)
	if (result) {
		kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
		atomic_dec(&device->active_cnt);
	}

	mutex_unlock(&device->mutex);
	return result;
+10 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@
#define KGSL_STATE_NAP		0x00000004
#define KGSL_STATE_SLEEP	0x00000008
#define KGSL_STATE_SUSPEND	0x00000010
#define KGSL_STATE_HUNG		0x00000020
#define KGSL_STATE_AWARE	0x00000020
#define KGSL_STATE_SLUMBER	0x00000080

#define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK  0x1000000
@@ -663,6 +663,15 @@ static inline int kgsl_create_device_workqueue(struct kgsl_device *device)
	return 0;
}

static inline int kgsl_state_is_awake(struct kgsl_device *device)
{
	if (device->state == KGSL_STATE_ACTIVE ||
		device->state == KGSL_STATE_AWARE)
		return true;
	else
		return false;
}

int kgsl_readtimestamp(struct kgsl_device *device, void *priv,
		enum kgsl_timestamp_type type, unsigned int *timestamp);

+1 −1
Original line number Diff line number Diff line
@@ -375,7 +375,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) {
		adreno_set_gpu_fault(adreno_dev, ADRENO_IOMMU_PAGE_FAULT);
		/* turn off GPU IRQ so we don't get faults from it too */
		kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE);
		adreno_dispatcher_schedule(device);
	}

Loading