summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--drivers/net/wireless/cnss2/pci.c9
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c44
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c45
8 files changed, 147 insertions, 30 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 {
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 0f4ef3712dd7..4869b33c8526 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -131,6 +131,7 @@ int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv)
cnss_pr_dbg("Suspending PCI link\n");
if (!pci_priv->pci_link_state) {
cnss_pr_info("PCI link is already suspended!\n");
+ ret = -EINVAL;
goto out;
}
@@ -393,13 +394,13 @@ static int cnss_qca6174_shutdown(struct cnss_pci_data *pci_priv)
cnss_pci_set_auto_suspended(pci_priv, 0);
ret = cnss_suspend_pci_link(pci_priv);
- if (ret)
+ if (ret) {
cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
+ return -EINVAL;
+ }
cnss_power_off_device(plat_priv);
- clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
-
return ret;
}
@@ -516,7 +517,6 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
- clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
return ret;
}
@@ -757,6 +757,7 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
cnss_pci_dev_shutdown(pci_priv);
pci_priv->driver_ops = NULL;
+ clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
return 0;
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 15c8f923d4f4..e0868ad83bf4 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -1249,7 +1249,8 @@ int ipa2_reset_hdr(bool user_only)
struct ipa_hdr_offset_entry *off_next;
struct ipa_hdr_proc_ctx_offset_entry *ctx_off_entry;
struct ipa_hdr_proc_ctx_offset_entry *ctx_off_next;
- int i;
+ int i, end = 0;
+ bool user_rule = false;
/*
* issue a reset on the routing module since routing rules point to
@@ -1287,6 +1288,9 @@ int ipa2_reset_hdr(bool user_only)
return -EFAULT;
}
+ if (entry->ipacm_installed)
+ user_rule = true;
+
if (!user_only || entry->ipacm_installed) {
if (entry->is_hdr_proc_ctx) {
dma_unmap_single(ipa_ctx->pdev,
@@ -1296,6 +1300,7 @@ int ipa2_reset_hdr(bool user_only)
entry->proc_ctx = NULL;
}
list_del(&entry->link);
+ ipa_ctx->hdr_tbl.hdr_cnt--;
entry->ref_cnt = 0;
entry->cookie = 0;
@@ -1321,6 +1326,13 @@ int ipa2_reset_hdr(bool user_only)
list_del(&off_entry->link);
kmem_cache_free(ipa_ctx->hdr_offset_cache,
off_entry);
+ } else {
+ if (off_entry->offset +
+ ipa_hdr_bin_sz[off_entry->bin] > end) {
+ end = off_entry->offset +
+ ipa_hdr_bin_sz[off_entry->bin];
+ IPADBG("replace end = %d\n", end);
+ }
}
}
list_for_each_entry_safe(off_entry, off_next,
@@ -1335,11 +1347,15 @@ int ipa2_reset_hdr(bool user_only)
}
}
}
- /* there is one header of size 8 */
- ipa_ctx->hdr_tbl.end = 8;
- ipa_ctx->hdr_tbl.hdr_cnt = 1;
+ IPADBG("hdr_tbl.end = %d\n", end);
+ if (user_rule) {
+ ipa_ctx->hdr_tbl.end = end;
+ IPADBG("hdr_tbl.end = %d\n", end);
+ }
IPADBG("reset hdr proc ctx\n");
+ user_rule = false;
+ end = 0;
list_for_each_entry_safe(
ctx_entry,
ctx_next,
@@ -1352,9 +1368,13 @@ int ipa2_reset_hdr(bool user_only)
return -EFAULT;
}
+ if (entry->ipacm_installed)
+ user_rule = true;
+
if (!user_only ||
ctx_entry->ipacm_installed) {
list_del(&ctx_entry->link);
+ ipa_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt--;
ctx_entry->ref_cnt = 0;
ctx_entry->cookie = 0;
@@ -1375,6 +1395,14 @@ int ipa2_reset_hdr(bool user_only)
kmem_cache_free(
ipa_ctx->hdr_proc_ctx_offset_cache,
ctx_off_entry);
+ } else {
+ if (ctx_off_entry->offset +
+ ipa_hdr_bin_sz[ctx_off_entry->bin]
+ > end) {
+ end = ctx_off_entry->offset +
+ ipa_hdr_bin_sz[ctx_off_entry->bin];
+ IPADBG("replace hdr_proc as %d\n", end);
+ }
}
}
list_for_each_entry_safe(ctx_off_entry, ctx_off_next,
@@ -1390,8 +1418,12 @@ int ipa2_reset_hdr(bool user_only)
}
}
}
- ipa_ctx->hdr_proc_ctx_tbl.end = 0;
- ipa_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt = 0;
+
+ IPADBG("hdr_proc_tbl.end = %d\n", end);
+ if (user_rule) {
+ ipa_ctx->hdr_proc_ctx_tbl.end = end;
+ IPADBG("hdr_proc_tbl.end = %d\n", end);
+ }
mutex_unlock(&ipa_ctx->lock);
return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index f10b2929916e..63e3f8578219 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -654,7 +654,6 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl,
return 0;
}
-
int __ipa3_del_hdr(u32 hdr_hdl, bool by_user)
{
struct ipa3_hdr_entry *entry;
@@ -994,7 +993,8 @@ int ipa3_reset_hdr(bool user_only)
struct ipa_hdr_offset_entry *off_next;
struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_entry;
struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_next;
- int i;
+ int i, end = 0;
+ bool user_rule = false;
/*
* issue a reset on the routing module since routing rules point to
@@ -1032,6 +1032,9 @@ int ipa3_reset_hdr(bool user_only)
return -EFAULT;
}
+ if (entry->ipacm_installed)
+ user_rule = true;
+
if (!user_only || entry->ipacm_installed) {
if (entry->is_hdr_proc_ctx) {
dma_unmap_single(ipa3_ctx->pdev,
@@ -1041,6 +1044,7 @@ int ipa3_reset_hdr(bool user_only)
entry->proc_ctx = NULL;
}
list_del(&entry->link);
+ ipa3_ctx->hdr_tbl.hdr_cnt--;
entry->ref_cnt = 0;
entry->cookie = 0;
@@ -1066,6 +1070,13 @@ int ipa3_reset_hdr(bool user_only)
list_del(&off_entry->link);
kmem_cache_free(ipa3_ctx->hdr_offset_cache,
off_entry);
+ } else {
+ if (off_entry->offset +
+ ipa_hdr_bin_sz[off_entry->bin] > end) {
+ end = off_entry->offset +
+ ipa_hdr_bin_sz[off_entry->bin];
+ IPADBG("replace end = %d\n", end);
+ }
}
}
list_for_each_entry_safe(off_entry, off_next,
@@ -1080,11 +1091,15 @@ int ipa3_reset_hdr(bool user_only)
}
}
}
- /* there is one header of size 8 */
- ipa3_ctx->hdr_tbl.end = 8;
- ipa3_ctx->hdr_tbl.hdr_cnt = 1;
+ IPADBG("hdr_tbl.end = %d\n", end);
+ if (user_rule) {
+ ipa3_ctx->hdr_tbl.end = end;
+ IPADBG("hdr_tbl.end = %d\n", end);
+ }
IPADBG("reset hdr proc ctx\n");
+ user_rule = false;
+ end = 0;
list_for_each_entry_safe(
ctx_entry,
ctx_next,
@@ -1097,9 +1112,13 @@ int ipa3_reset_hdr(bool user_only)
return -EFAULT;
}
+ if (entry->ipacm_installed)
+ user_rule = true;
+
if (!user_only ||
ctx_entry->ipacm_installed) {
list_del(&ctx_entry->link);
+ ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt--;
ctx_entry->ref_cnt = 0;
ctx_entry->cookie = 0;
@@ -1120,6 +1139,14 @@ int ipa3_reset_hdr(bool user_only)
kmem_cache_free(
ipa3_ctx->hdr_proc_ctx_offset_cache,
ctx_off_entry);
+ } else {
+ if (ctx_off_entry->offset +
+ ipa_hdr_bin_sz[ctx_off_entry->bin]
+ > end) {
+ end = ctx_off_entry->offset +
+ ipa_hdr_bin_sz[ctx_off_entry->bin];
+ IPADBG("replace hdr_proc as %d\n", end);
+ }
}
}
list_for_each_entry_safe(ctx_off_entry, ctx_off_next,
@@ -1135,8 +1162,12 @@ int ipa3_reset_hdr(bool user_only)
}
}
}
- ipa3_ctx->hdr_proc_ctx_tbl.end = 0;
- ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt = 0;
+
+ IPADBG("hdr_proc_tbl.end = %d\n", end);
+ if (user_rule) {
+ ipa3_ctx->hdr_proc_ctx_tbl.end = end;
+ IPADBG("hdr_proc_tbl.end = %d\n", end);
+ }
mutex_unlock(&ipa3_ctx->lock);
return 0;