From fcff8d4b117e1d31da5b2cf2f0684ecb72cd5e94 Mon Sep 17 00:00:00 2001 From: Thomas Yun Date: Tue, 17 Jul 2018 14:07:39 -0400 Subject: [PATCH] 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: Suprith Malligere Shankaregowda Signed-off-by: Thomas Yun --- drivers/gpu/msm/adreno.c | 25 +++++++++++++++++++++++-- drivers/gpu/msm/adreno.h | 1 + drivers/gpu/msm/adreno_a5xx.c | 19 +++++++++++++++---- drivers/gpu/msm/kgsl.c | 28 +++++++++++++++++++++++----- drivers/gpu/msm/kgsl_device.h | 6 ++++-- 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 7af2af483f10..9cb65033ed13 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2800,6 +2800,27 @@ 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_FREEZE) || + (pm_event == PM_EVENT_QUIESCE) || + (pm_event == PM_EVENT_HIBERNATE)) + if (gpudev->zap_shader_unload != NULL) + gpudev->zap_shader_unload(adreno_dev); +} + +static void adreno_resume_device(struct kgsl_device *device) +{ + adreno_dispatcher_unhalt(device); +} + static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, @@ -2839,8 +2860,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 = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 9ea50007ec38..1f598bf3d9f8 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -794,6 +794,7 @@ struct adreno_gpudev { void (*enable_64bit)(struct adreno_device *); void (*clk_set_options)(struct adreno_device *, const char *, struct clk *, bool on); + void (*zap_shader_unload)(struct adreno_device *); }; /** diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 4daf1fad6ee1..e3381bca2586 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -31,6 +31,7 @@ #include "adreno_a5xx_packets.h" static int zap_ucode_loaded; +static void *zap_handle_ptr; static int critical_packet_constructed; static struct kgsl_memdesc crit_pkts; @@ -2236,7 +2237,6 @@ static int a5xx_switch_to_unsecure_mode(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); uint64_t gpuaddr; @@ -2276,11 +2276,12 @@ 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 && !zap_ucode_loaded) { - ptr = subsystem_get(adreno_dev->gpucore->zap_name); + 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); + if (IS_ERR_OR_NULL(zap_handle_ptr)) + return (zap_handle_ptr == NULL) ? + -ENODEV : PTR_ERR(zap_handle_ptr); zap_ucode_loaded = 1; } @@ -2288,6 +2289,15 @@ static int a5xx_microcode_load(struct adreno_device *adreno_dev) return 0; } +static void a5xx_zap_shader_unload(struct adreno_device *adreno_dev) +{ + if (!IS_ERR_OR_NULL(zap_handle_ptr)) { + subsystem_put(zap_handle_ptr); + zap_handle_ptr = NULL; + zap_ucode_loaded = 0; + } +} + static int _me_init_ucode_workarounds(struct adreno_device *adreno_dev) { switch (ADRENO_GPUREV(adreno_dev)) { @@ -3698,4 +3708,5 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .preemption_schedule = a5xx_preemption_schedule, .enable_64bit = a5xx_enable_64bit, .clk_set_options = a5xx_clk_set_options, + .zap_shader_unload = a5xx_zap_shader_unload, }; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 4eed26b64577..02f0cb7eb16c 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -746,7 +746,7 @@ 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->ftbl->dispatcher_halt(device); + device->ftbl->suspend_device(device, state); mutex_unlock(&device->mutex); return status; @@ -759,7 +759,7 @@ static int kgsl_resume_device(struct kgsl_device *device) mutex_lock(&device->mutex); if (device->state == KGSL_STATE_SUSPEND) { - device->ftbl->dispatcher_unhalt(device); + device->ftbl->resume_device(device); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); } else if (device->state != KGSL_STATE_INIT) { /* @@ -782,10 +782,23 @@ 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) @@ -805,7 +818,12 @@ static int kgsl_runtime_resume(struct device *dev) } const struct dev_pm_ops kgsl_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(kgsl_suspend, kgsl_resume) + .suspend = kgsl_suspend, + .resume = kgsl_resume, + .freeze = kgsl_freeze, + .thaw = kgsl_resume, + .poweroff = kgsl_poweroff, + .restore = kgsl_resume, .runtime_suspend = kgsl_runtime_suspend, .runtime_resume = kgsl_runtime_resume, }; diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 57d4fe4d9120..078109af99fe 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -171,8 +172,9 @@ struct kgsl_functable { void (*gpu_model)(struct kgsl_device *device, char *str, size_t bufsz); void (*stop_fault_timer)(struct kgsl_device *device); - void (*dispatcher_halt)(struct kgsl_device *device); - void (*dispatcher_unhalt)(struct kgsl_device *device); + void (*suspend_device)(struct kgsl_device *device, + pm_message_t pm_state); + void (*resume_device)(struct kgsl_device *device); }; struct kgsl_ioctl { -- 2.11.0