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

Commit be7b93d8 authored by Thomas Yun's avatar Thomas Yun Committed by Thomas (Wonyoung) Yun
Browse files

msm: kgsl: unload/reload zap shader



Unload zap shader during device hibernation and reload it
during resume otherwise scm calls during post hibernation
GPU initialization will fail as there is possibility that
TZ driver is not aware of the hibernation.

Change-Id: I1f62fb97cbc8e6c3e3536d4d5260a543ca15b685
Signed-off-by: default avatarSuprith Malligere Shankaregowda <supgow@codeaurora.org>
Signed-off-by: default avatarThomas Yun <wyun@codeaurora.org>
parent 4c16f4bd
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -1851,7 +1851,7 @@ int adreno_set_unsecured_mode(struct adreno_device *adreno_dev,
	}

	/* GPU comes up in secured mode, make it unsecured by default */
	if (adreno_dev->zap_loaded)
	if (adreno_dev->zap_handle_ptr)
		ret = adreno_switch_to_unsecure_mode(adreno_dev, rb);
	else
		adreno_writereg(adreno_dev,
@@ -4022,6 +4022,28 @@ static void adreno_gpu_model(struct kgsl_device *device, char *str,
			 ADRENO_CHIPID_PATCH(adreno_dev->chipid) + 1);
}

static void adreno_suspend_device(struct kgsl_device *device,
				pm_message_t pm_state)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int pm_event = pm_state.event;

	adreno_dispatcher_halt(device);

	if ((pm_event != PM_EVENT_SUSPEND) &&
		(gpudev->zap_shader_unload != NULL))
		gpudev->zap_shader_unload(adreno_dev);
}

static int adreno_resume_device(struct kgsl_device *device,
				pm_message_t pm_state)
{
	adreno_dispatcher_unhalt(device);

	return 0;
}

static const struct kgsl_functable adreno_functable = {
	/* Mandatory functions */
	.regread = adreno_regread,
@@ -4063,8 +4085,8 @@ static const struct kgsl_functable adreno_functable = {
	.clk_set_options = adreno_clk_set_options,
	.gpu_model = adreno_gpu_model,
	.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
	.dispatcher_halt = adreno_dispatcher_halt,
	.dispatcher_unhalt = adreno_dispatcher_unhalt,
	.suspend_device = adreno_suspend_device,
	.resume_device = adreno_resume_device,
};

static struct platform_driver adreno_platform_driver = {
+2 −1
Original line number Diff line number Diff line
@@ -600,7 +600,7 @@ struct adreno_device {
	bool gpu_llc_slice_enable;
	void *gpuhtw_llc_slice;
	bool gpuhtw_llc_slice_enable;
	unsigned int zap_loaded;
	void *zap_handle_ptr;
	unsigned int soc_hw_rev;
	bool gaming_bin;
};
@@ -1038,6 +1038,7 @@ struct adreno_gpudev {
				bool update_reg);
	size_t (*snapshot_preemption)(struct kgsl_device *, u8 *,
				 size_t, void *);
	void (*zap_shader_unload)(struct adreno_device *);
};

/**
+20 −9
Original line number Diff line number Diff line
@@ -2186,11 +2186,11 @@ static int a5xx_gpmu_init(struct adreno_device *adreno_dev)
 */
static int a5xx_microcode_load(struct adreno_device *adreno_dev)
{
	void *ptr;
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct adreno_firmware *pm4_fw = ADRENO_FW(adreno_dev, ADRENO_FW_PM4);
	struct adreno_firmware *pfp_fw = ADRENO_FW(adreno_dev, ADRENO_FW_PFP);
	uint64_t gpuaddr;
	int ret = 0;

	gpuaddr = pm4_fw->memdesc.gpuaddr;
	kgsl_regwrite(device, A5XX_CP_PM4_INSTR_BASE_LO,
@@ -2216,9 +2216,8 @@ static int a5xx_microcode_load(struct adreno_device *adreno_dev)
	 * appropriate register,
	 * skip if retention is supported for the CPZ register
	 */
	if (adreno_dev->zap_loaded && !(ADRENO_FEATURE(adreno_dev,
	if (adreno_dev->zap_handle_ptr && !(ADRENO_FEATURE(adreno_dev,
		ADRENO_CPZ_RETENTION))) {
		int ret;
		struct scm_desc desc = {0};

		desc.args[0] = 0;
@@ -2234,16 +2233,27 @@ static int a5xx_microcode_load(struct adreno_device *adreno_dev)
	}

	/* Load the zap shader firmware through PIL if its available */
	if (adreno_dev->gpucore->zap_name && !adreno_dev->zap_loaded) {
		ptr = subsystem_get(adreno_dev->gpucore->zap_name);
	if (adreno_dev->gpucore->zap_name && !adreno_dev->zap_handle_ptr) {
		adreno_dev->zap_handle_ptr =
				subsystem_get(adreno_dev->gpucore->zap_name);

		/* Return error if the zap shader cannot be loaded */
		if (IS_ERR_OR_NULL(ptr))
			return (ptr == NULL) ? -ENODEV : PTR_ERR(ptr);
		adreno_dev->zap_loaded = 1;
		if (IS_ERR_OR_NULL(adreno_dev->zap_handle_ptr)) {
			ret = (adreno_dev->zap_handle_ptr == NULL) ?
				-ENODEV : PTR_ERR(adreno_dev->zap_handle_ptr);
			adreno_dev->zap_handle_ptr = NULL;
		}
	}

	return 0;
	return ret;
}

static void a5xx_zap_shader_unload(struct adreno_device *adreno_dev)
{
	if (!IS_ERR_OR_NULL(adreno_dev->zap_handle_ptr)) {
		subsystem_put(adreno_dev->zap_handle_ptr);
		adreno_dev->zap_handle_ptr = NULL;
	}
}

static int _me_init_ucode_workarounds(struct adreno_device *adreno_dev)
@@ -3636,4 +3646,5 @@ struct adreno_gpudev adreno_a5xx_gpudev = {
	.enable_64bit = a5xx_enable_64bit,
	.clk_set_options = a5xx_clk_set_options,
	.snapshot_preemption = a5xx_snapshot_preemption,
	.zap_shader_unload = a5xx_zap_shader_unload,
};
+16 −8
Original line number Diff line number Diff line
@@ -970,7 +970,6 @@ static int a6xx_microcode_load(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct adreno_firmware *fw = ADRENO_FW(adreno_dev, ADRENO_FW_SQE);
	uint64_t gpuaddr;
	void *zap;
	int ret = 0;

	gpuaddr = fw->memdesc.gpuaddr;
@@ -987,20 +986,28 @@ static int a6xx_microcode_load(struct adreno_device *adreno_dev)
		return 0;

	/* Load the zap shader firmware through PIL if its available */
	if (adreno_dev->gpucore->zap_name && !adreno_dev->zap_loaded) {
		zap = subsystem_get(adreno_dev->gpucore->zap_name);
	if (adreno_dev->gpucore->zap_name && !adreno_dev->zap_handle_ptr) {
		adreno_dev->zap_handle_ptr =
				subsystem_get(adreno_dev->gpucore->zap_name);

		/* Return error if the zap shader cannot be loaded */
		if (IS_ERR_OR_NULL(zap)) {
			ret = (zap == NULL) ? -ENODEV : PTR_ERR(zap);
			zap = NULL;
		} else
			adreno_dev->zap_loaded = 1;
		if (IS_ERR_OR_NULL(adreno_dev->zap_handle_ptr)) {
			ret = (adreno_dev->zap_handle_ptr == NULL) ?
				-ENODEV : PTR_ERR(adreno_dev->zap_handle_ptr);
			adreno_dev->zap_handle_ptr = NULL;
		}
	}

	return ret;
}

static void a6xx_zap_shader_unload(struct adreno_device *adreno_dev)
{
	if (!IS_ERR_OR_NULL(adreno_dev->zap_handle_ptr)) {
		subsystem_put(adreno_dev->zap_handle_ptr);
		adreno_dev->zap_handle_ptr = NULL;
	}
}

/*
 * CP_INIT_MAX_CONTEXT bit tells if the multiple hardware contexts can
@@ -3266,4 +3273,5 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
	.coresight = {&a6xx_coresight, &a6xx_coresight_cx},
	.clk_set_options = a6xx_clk_set_options,
	.snapshot_preemption = a6xx_snapshot_preemption,
	.zap_shader_unload = a6xx_zap_shader_unload,
};
+37 −7
Original line number Diff line number Diff line
@@ -836,14 +836,14 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state)
	mutex_lock(&device->mutex);
	status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
	if (status == 0 && device->state == KGSL_STATE_SUSPEND)
		device->ftbl->dispatcher_halt(device);
		device->ftbl->suspend_device(device, state);
	mutex_unlock(&device->mutex);

	KGSL_PWR_WARN(device, "suspend end\n");
	return status;
}

static int kgsl_resume_device(struct kgsl_device *device)
static int kgsl_resume_device(struct kgsl_device *device, pm_message_t state)
{
	if (!device)
		return -EINVAL;
@@ -851,7 +851,7 @@ static int kgsl_resume_device(struct kgsl_device *device)
	KGSL_PWR_WARN(device, "resume start\n");
	mutex_lock(&device->mutex);
	if (device->state == KGSL_STATE_SUSPEND) {
		device->ftbl->dispatcher_unhalt(device);
		device->ftbl->resume_device(device, state);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
	} else if (device->state != KGSL_STATE_INIT) {
		/*
@@ -874,18 +874,44 @@ static int kgsl_resume_device(struct kgsl_device *device)

static int kgsl_suspend(struct device *dev)
{
	struct kgsl_device *device = dev_get_drvdata(dev);

	return kgsl_suspend_device(device, PMSG_SUSPEND);
}

static int kgsl_freeze(struct device *dev)
{
	struct kgsl_device *device = dev_get_drvdata(dev);

	return kgsl_suspend_device(device, PMSG_FREEZE);
}

	pm_message_t arg = {0};
static int kgsl_poweroff(struct device *dev)
{
	struct kgsl_device *device = dev_get_drvdata(dev);

	return kgsl_suspend_device(device, arg);
	return kgsl_suspend_device(device, PMSG_HIBERNATE);
}

static int kgsl_resume(struct device *dev)
{
	struct kgsl_device *device = dev_get_drvdata(dev);

	return kgsl_resume_device(device);
	return kgsl_resume_device(device, PMSG_RESUME);
}

static int kgsl_thaw(struct device *dev)
{
	struct kgsl_device *device = dev_get_drvdata(dev);

	return kgsl_resume_device(device, PMSG_THAW);
}

static int kgsl_restore(struct device *dev)
{
	struct kgsl_device *device = dev_get_drvdata(dev);

	return kgsl_resume_device(device, PMSG_RESTORE);
}

static int kgsl_runtime_suspend(struct device *dev)
@@ -901,6 +927,10 @@ static int kgsl_runtime_resume(struct device *dev)
const struct dev_pm_ops kgsl_pm_ops = {
	.suspend = kgsl_suspend,
	.resume = kgsl_resume,
	.freeze = kgsl_freeze,
	.thaw = kgsl_thaw,
	.poweroff = kgsl_poweroff,
	.restore = kgsl_restore,
	.runtime_suspend = kgsl_runtime_suspend,
	.runtime_resume = kgsl_runtime_resume,
};
@@ -919,7 +949,7 @@ int kgsl_resume_driver(struct platform_device *pdev)
{
	struct kgsl_device *device = dev_get_drvdata(&pdev->dev);

	return kgsl_resume_device(device);
	return kgsl_resume_device(device, PMSG_RESUME);
}
EXPORT_SYMBOL(kgsl_resume_driver);

Loading