summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-08-06 21:52:26 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2018-08-06 21:52:26 -0700
commit42570c93eca94652aa82f2c880004789606bbbe7 (patch)
treea79cfbd21c96558e14f8578545faa2e7e11b157f
parent7f6b5aa038fa25267e78b90b4eca57d4119fdb79 (diff)
parentfcff8d4b117e1d31da5b2cf2f0684ecb72cd5e94 (diff)
Merge "msm: kgsl: unload/reload zap shader"
-rw-r--r--drivers/gpu/msm/adreno.c25
-rw-r--r--drivers/gpu/msm/adreno.h1
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c19
-rw-r--r--drivers/gpu/msm/kgsl.c28
-rw-r--r--drivers/gpu/msm/kgsl_device.h6
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 <linux/slab.h>
#include <linux/idr.h>
+#include <linux/pm.h>
#include <linux/pm_qos.h>
#include <linux/sched.h>
@@ -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 {