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

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

msm: kgsl: Halt GBIF before moving to NAP state



It has been observed that without gmu_clk, any active transactions will
cause that transaction to be stuck in QSMMU. As of now we don't halt
GBIF when moving to NAP state. So there is a possibility of transactions
inflight when gmu_clk is gated. This will cause transactions to be stuck
in QSMMU forever. This can eventually lead to GPU hang or TLB sync
timeout. So halt GBIF before moving to NAP.

Change-Id: I13bbe3b21b327d0d5c962bb2133c6d5d0f3a43c3
Signed-off-by: default avatarPuranam V G Tejaswi <pvgtejas@codeaurora.org>
parent 8e0b5e5a
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -3505,7 +3505,7 @@ static int adreno_regulator_enable(struct kgsl_device *device)
	return ret;
}

static bool adreno_is_hw_collapsible(struct kgsl_device *device)
static bool adreno_prepare_for_power_off(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	const struct adreno_gpudev *gpudev  = ADRENO_GPU_DEVICE(adreno_dev);
@@ -3519,8 +3519,16 @@ static bool adreno_is_hw_collapsible(struct kgsl_device *device)
			device->pwrctrl.ctrl_flags)
		return false;

	return adreno_isidle(adreno_dev) && (gpudev->is_sptp_idle ?
				gpudev->is_sptp_idle(adreno_dev) : true);
	if (!adreno_isidle(adreno_dev) || !(gpudev->is_sptp_idle ?
				gpudev->is_sptp_idle(adreno_dev) : true))
		return false;

	if (gpudev->clear_pending_transactions(adreno_dev))
		return false;

	adreno_dispatcher_stop_fault_timer(device);

	return true;
}

static void adreno_regulator_disable(struct kgsl_device *device)
@@ -3727,6 +3735,15 @@ static int adreno_gpu_bus_set(struct kgsl_device *device, int level, u32 ab)
	return adreno_interconnect_bus_set(adreno_dev, level, ab);
}

static void adreno_deassert_gbif_halt(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);

	if (gpudev->deassert_gbif_halt)
		gpudev->deassert_gbif_halt(adreno_dev);
}

static const struct kgsl_functable adreno_functable = {
	/* Mandatory functions */
	.regread = adreno_regread,
@@ -3761,17 +3778,17 @@ static const struct kgsl_functable adreno_functable = {
	.drawctxt_sched = adreno_drawctxt_sched,
	.resume = adreno_dispatcher_start,
	.regulator_enable = adreno_regulator_enable,
	.is_hw_collapsible = adreno_is_hw_collapsible,
	.prepare_for_power_off = adreno_prepare_for_power_off,
	.regulator_disable = adreno_regulator_disable,
	.pwrlevel_change_settings = adreno_pwrlevel_change_settings,
	.regulator_disable_poll = adreno_regulator_disable_poll,
	.clk_set_options = adreno_clk_set_options,
	.gpu_model = adreno_gpu_model,
	.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
	.query_property_list = adreno_query_property_list,
	.is_hwcg_on = adreno_is_hwcg_on,
	.gpu_clock_set = adreno_gpu_clock_set,
	.gpu_bus_set = adreno_gpu_bus_set,
	.deassert_gbif_halt = adreno_deassert_gbif_halt,
};

static const struct component_master_ops adreno_ops = {
+1 −2
Original line number Diff line number Diff line
@@ -811,6 +811,7 @@ struct adreno_gpudev {
	 */
	const struct adreno_power_ops *power_ops;
	int (*clear_pending_transactions)(struct adreno_device *adreno_dev);
	void (*deassert_gbif_halt)(struct adreno_device *adreno_dev);
};

/**
@@ -1735,8 +1736,6 @@ static inline u32 adreno_get_level(u32 priority)
int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
	enum adreno_regs offset, unsigned int val,
	unsigned int fence_mask);
int adreno_clear_pending_transactions(struct kgsl_device *device);


/**
 * adreno_get_firwmare - Load firmware into a adreno_firmware struct
+2 −0
Original line number Diff line number Diff line
@@ -2509,6 +2509,7 @@ const struct adreno_gpudev adreno_a6xx_gpudev = {
	.read_alwayson = a6xx_read_alwayson,
	.power_ops = &adreno_power_operations,
	.clear_pending_transactions = a6xx_clear_pending_transactions,
	.deassert_gbif_halt = a6xx_deassert_gbif_halt,
};

const struct adreno_gpudev adreno_a6xx_hwsched_gpudev = {
@@ -2622,6 +2623,7 @@ const struct adreno_gpudev adreno_a619_holi_gpudev = {
	.read_alwayson = a6xx_read_alwayson,
	.power_ops = &adreno_power_operations,
	.clear_pending_transactions = a6xx_clear_pending_transactions,
	.deassert_gbif_halt = a6xx_deassert_gbif_halt,
};

const struct adreno_gpudev adreno_a630_gpudev = {
+2 −2
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ struct kgsl_functable {
		struct kgsl_context *context);
	void (*resume)(struct kgsl_device *device);
	int (*regulator_enable)(struct kgsl_device *device);
	bool (*is_hw_collapsible)(struct kgsl_device *device);
	bool (*prepare_for_power_off)(struct kgsl_device *device);
	void (*regulator_disable)(struct kgsl_device *device);
	void (*pwrlevel_change_settings)(struct kgsl_device *device,
		unsigned int prelevel, unsigned int postlevel, bool post);
@@ -157,7 +157,6 @@ struct kgsl_functable {
		const char *name, struct clk *clk, bool on);
	void (*gpu_model)(struct kgsl_device *device, char *str,
		size_t bufsz);
	void (*stop_fault_timer)(struct kgsl_device *device);
	/**
	 * @query_property_list: query the list of properties
	 * supported by the device. If 'list' is NULL just return the total
@@ -171,6 +170,7 @@ struct kgsl_functable {
	int (*gpu_clock_set)(struct kgsl_device *device, u32 pwrlevel);
	/** @gpu_bus_set: Target specific function to set gpu bandwidth */
	int (*gpu_bus_set)(struct kgsl_device *device, int bus_level, u32 ab);
	void (*deassert_gbif_halt)(struct kgsl_device *device);
};

struct kgsl_ioctl {
+3 −3
Original line number Diff line number Diff line
@@ -1859,6 +1859,7 @@ static int _wake(struct kgsl_device *device)
		/* Turn on the core clocks */
		kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);

		device->ftbl->deassert_gbif_halt(device);
		/*
		 * No need to turn on/off irq here as it no longer affects
		 * power collapse
@@ -1943,12 +1944,11 @@ _nap(struct kgsl_device *device)
{
	switch (device->state) {
	case KGSL_STATE_ACTIVE:
		if (!device->ftbl->is_hw_collapsible(device)) {
		if (!device->ftbl->prepare_for_power_off(device)) {
			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
			return -EBUSY;
		}

		device->ftbl->stop_fault_timer(device);
		kgsl_pwrscale_midframe_timer_cancel(device);

		/*
@@ -2006,7 +2006,7 @@ _slumber(struct kgsl_device *device)

	switch (device->state) {
	case KGSL_STATE_ACTIVE:
		if (!device->ftbl->is_hw_collapsible(device)) {
		if (!device->ftbl->prepare_for_power_off(device)) {
			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
			return -EBUSY;
		}