summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2010-12-20 14:33:10 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2010-12-21 03:52:08 -0800
commit2605df86defb61667131a6b42dc101ecefaf4138 (patch)
tree3b6bc783a23c766f41a0fabe72c07d95d908a649
parentba2891ed491f531517e717274e1144bf442e13b9 (diff)
video: tegra: host: add suspend instrumentation
cherry-picked and merged http://git-master.nvidia.com/r/6641 and http://git-master.nvidia.com/r/7081 from tegra-2010-07 branch Change-Id: I926062d2d949b4095ad1d5c88145c99a29cec122 Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/13795 Reviewed-by: Andrew Howe <ahowe@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--drivers/video/tegra/host/dev.c2
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c38
-rw-r--r--drivers/video/tegra/host/nvhost_acm.h2
-rw-r--r--drivers/video/tegra/host/nvhost_cpuaccess.c2
-rw-r--r--drivers/video/tegra/host/nvhost_cpuaccess.h1
-rw-r--r--drivers/video/tegra/host/nvhost_hardware.h2
6 files changed, 41 insertions, 6 deletions
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index 20a4eda0fb53..c9c88b0171a7 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -741,7 +741,7 @@ static int nvhost_suspend(struct platform_device *pdev, pm_message_t state)
{
struct nvhost_master *host = platform_get_drvdata(pdev);
dev_info(&pdev->dev, "suspending\n");
- nvhost_module_suspend(&host->mod);
+ nvhost_module_suspend(&host->mod, true);
clk_enable(host->mod.clk[0]);
nvhost_syncpt_save(&host->syncpt);
clk_disable(host->mod.clk[0]);
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index c4ac035a26ec..9b56365bb44f 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -20,7 +20,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "nvhost_acm.h"
+#include "dev.h"
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/err.h>
@@ -155,17 +155,49 @@ static int is_module_idle(struct nvhost_module *mod)
return (count == 0);
}
-void nvhost_module_suspend(struct nvhost_module *mod)
+static void debug_not_idle(struct nvhost_module *mod)
{
+ int i;
+ bool lock_released = true;
+ struct nvhost_master *dev = container_of(mod, struct nvhost_master, mod);
+
+ for (i = 0; i < NVHOST_NUMCHANNELS; i++) {
+ struct nvhost_module *m = &dev->channels[i].mod;
+ if (m->name)
+ printk("tegra_grhost: %s: refcnt %d\n",
+ m->name, atomic_read(&m->refcount));
+ }
+
+ for (i = 0; i < NV_HOST1X_SYNC_MLOCK_NUM; i++) {
+ int c = atomic_read(&dev->cpuaccess.lock_counts[i]);
+ if (c) {
+ printk("tegra_grhost: lock id %d: refcnt %d\n", i, c);
+ lock_released = false;
+ }
+ }
+ if (lock_released)
+ printk("tegra_grhost: all locks released\n");
+}
+
+void nvhost_module_suspend(struct nvhost_module *mod, bool system_suspend)
+{
+ if (system_suspend && (!is_module_idle(mod)))
+ debug_not_idle(mod);
+
wait_event(mod->idle, is_module_idle(mod));
+ if (system_suspend)
+ printk("tegra_grhost: entered idle\n");
+
flush_delayed_work(&mod->powerdown);
+ if (system_suspend)
+ printk("tegra_grhost: flushed delayed work\n");
BUG_ON(mod->powered);
}
void nvhost_module_deinit(struct nvhost_module *mod)
{
int i;
- nvhost_module_suspend(mod);
+ nvhost_module_suspend(mod, false);
for (i = 0; i < mod->num_clks; i++)
clk_put(mod->clk[i]);
}
diff --git a/drivers/video/tegra/host/nvhost_acm.h b/drivers/video/tegra/host/nvhost_acm.h
index 57dcc2989113..c765d983afb4 100644
--- a/drivers/video/tegra/host/nvhost_acm.h
+++ b/drivers/video/tegra/host/nvhost_acm.h
@@ -57,7 +57,7 @@ int nvhost_module_init(struct nvhost_module *mod, const char *name,
nvhost_modulef func, struct nvhost_module *parent,
struct device *dev);
void nvhost_module_deinit(struct nvhost_module *mod);
-void nvhost_module_suspend(struct nvhost_module *mod);
+void nvhost_module_suspend(struct nvhost_module *mod, bool system_suspend);
void nvhost_module_busy(struct nvhost_module *mod);
void nvhost_module_idle_mult(struct nvhost_module *mod, int refs);
diff --git a/drivers/video/tegra/host/nvhost_cpuaccess.c b/drivers/video/tegra/host/nvhost_cpuaccess.c
index 9114dad97783..4a5c34d593fc 100644
--- a/drivers/video/tegra/host/nvhost_cpuaccess.c
+++ b/drivers/video/tegra/host/nvhost_cpuaccess.c
@@ -71,6 +71,7 @@ int nvhost_mutex_try_lock(struct nvhost_cpuaccess *ctx, unsigned int idx)
nvhost_module_idle(&dev->mod);
return -ERESTARTSYS;
}
+ atomic_inc(&ctx->lock_counts[idx]);
return 0;
}
@@ -80,6 +81,7 @@ void nvhost_mutex_unlock(struct nvhost_cpuaccess *ctx, unsigned int idx)
void __iomem *sync_regs = dev->sync_aperture;
writel(0, sync_regs + (HOST1X_SYNC_MLOCK_0 + idx * 4));
nvhost_module_idle(&dev->mod);
+ atomic_dec(&ctx->lock_counts[idx]);
}
void nvhost_read_module_regs(struct nvhost_cpuaccess *ctx, u32 module,
diff --git a/drivers/video/tegra/host/nvhost_cpuaccess.h b/drivers/video/tegra/host/nvhost_cpuaccess.h
index d7d6c99cd416..98ea1e1e1f8f 100644
--- a/drivers/video/tegra/host/nvhost_cpuaccess.h
+++ b/drivers/video/tegra/host/nvhost_cpuaccess.h
@@ -45,6 +45,7 @@ enum nvhost_module_id {
struct nvhost_cpuaccess {
struct resource *reg_mem[NVHOST_MODULE_NUM];
void __iomem *regs[NVHOST_MODULE_NUM];
+ atomic_t lock_counts[NV_HOST1X_SYNC_MLOCK_NUM];
};
int nvhost_cpuaccess_init(struct nvhost_cpuaccess *ctx,
diff --git a/drivers/video/tegra/host/nvhost_hardware.h b/drivers/video/tegra/host/nvhost_hardware.h
index f69f467dd64e..a7663489727e 100644
--- a/drivers/video/tegra/host/nvhost_hardware.h
+++ b/drivers/video/tegra/host/nvhost_hardware.h
@@ -38,7 +38,7 @@ enum {
#define NV_HOST1X_CHANNELS 8
#define NV_HOST1X_CHANNEL0_BASE 0
#define NV_HOST1X_CHANNEL_MAP_SIZE_BYTES 16384
-
+#define NV_HOST1X_SYNC_MLOCK_NUM 16
#define HOST1X_CHANNEL_FIFOSTAT 0x00
#define HOST1X_CHANNEL_INDDATA 0x0c