soc: qcom: jtagv8: register for hotplug and cpu_pm notifiers

msm_jtag_save_state() and msm_jtag_restore_state() are called
directly from msm-pm driver. However msm-pm driver is going to be
deprecated when we move to PSCI framework. Add support in jtagv8
driver to rely on hotplug and cpu_pm callbacks for save and
restore functionality of Debug and ETM registers.

This commit also modifies the hotcpu callback in ETM driver to
avoid any race condition with hotcpu callback from Jtagv8 driver
that has been introduced in this commit.

Change-Id: I1261fdcb548b7a21b37090426efdbd77ea038333
Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
Signed-off-by: Xiaogang Cui <xiaogang@codeaurora.org>
This commit is contained in:
Sarangdhar Joshi 2015-05-20 17:31:45 -07:00 committed by Gerrit - the friendly Code Review server
parent 7343f1c0dc
commit 25e2db24e3
2 changed files with 99 additions and 13 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -398,6 +398,7 @@ struct etm_drvdata {
static int count;
static struct etm_drvdata *etmdrvdata[NR_CPUS];
static struct notifier_block etm_cpu_notifier;
static struct notifier_block etm_cpu_dying_notifier;
static bool etm_os_lock_present(struct etm_drvdata *drvdata)
{
@ -3345,19 +3346,14 @@ static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
clk_disable[cpu] = false;
}
break;
case CPU_DYING:
spin_lock(&etmdrvdata[cpu]->spinlock);
if (etmdrvdata[cpu]->enable)
__etm_disable(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
break;
}
out:
return NOTIFY_OK;
err1:
if (--count == 0)
if (--count == 0) {
unregister_hotcpu_notifier(&etm_cpu_notifier);
unregister_hotcpu_notifier(&etm_cpu_dying_notifier);
}
if (clk_disable[cpu]) {
clk_disable_unprepare(etmdrvdata[cpu]->clk);
clk_disable[cpu] = false;
@ -3377,6 +3373,31 @@ static struct notifier_block etm_cpu_notifier = {
.notifier_call = etm_cpu_callback,
};
static int etm_cpu_dying_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
if (!etmdrvdata[cpu])
goto out;
switch (action & (~CPU_TASKS_FROZEN)) {
case CPU_DYING:
spin_lock(&etmdrvdata[cpu]->spinlock);
if (etmdrvdata[cpu]->enable)
__etm_disable(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
break;
}
out:
return NOTIFY_OK;
}
static struct notifier_block etm_cpu_dying_notifier = {
.notifier_call = etm_cpu_dying_callback,
.priority = 1,
};
static int etm_probe(struct platform_device *pdev)
{
int ret, cpu;
@ -3441,8 +3462,10 @@ static int etm_probe(struct platform_device *pdev)
goto err0;
}
if (count++ == 0)
if (count++ == 0) {
register_hotcpu_notifier(&etm_cpu_notifier);
register_hotcpu_notifier(&etm_cpu_dying_notifier);
}
ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
if (ret)
@ -3491,8 +3514,10 @@ static int etm_probe(struct platform_device *pdev)
return 0;
err1:
if (--count == 0)
if (--count == 0) {
unregister_hotcpu_notifier(&etm_cpu_notifier);
unregister_hotcpu_notifier(&etm_cpu_dying_notifier);
}
err0:
wakeup_source_trash(&drvdata->ws);
return ret;
@ -3504,8 +3529,10 @@ static int etm_remove(struct platform_device *pdev)
if (drvdata) {
coresight_unregister(drvdata->csdev);
if (--count == 0)
if (--count == 0) {
unregister_hotcpu_notifier(&etm_cpu_notifier);
unregister_hotcpu_notifier(&etm_cpu_dying_notifier);
}
wakeup_source_trash(&drvdata->ws);
}
return 0;

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -19,6 +19,8 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
#include <linux/export.h>
#include <linux/printk.h>
#include <linux/ratelimit.h>
@ -75,6 +77,9 @@ struct dbg_ctx {
};
static struct dbg_ctx dbg;
static struct notifier_block jtag_hotcpu_save_notifier;
static struct notifier_block jtag_hotcpu_restore_notifier;
static struct notifier_block jtag_cpu_pm_notifier;
#ifdef CONFIG_ARM64
static int dbg_read_arch64_bxr(uint64_t *state, int i, int j)
@ -918,6 +923,56 @@ static inline bool dbg_arch_supported(uint8_t arch)
return true;
}
static int jtag_hotcpu_save_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
switch (action & (~CPU_TASKS_FROZEN)) {
case CPU_DYING:
msm_jtag_save_state();
break;
}
return NOTIFY_OK;
}
static struct notifier_block jtag_hotcpu_save_notifier = {
.notifier_call = jtag_hotcpu_save_callback,
};
static int jtag_hotcpu_restore_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
switch (action & (~CPU_TASKS_FROZEN)) {
case CPU_STARTING:
msm_jtag_restore_state();
break;
}
return NOTIFY_OK;
}
static struct notifier_block jtag_hotcpu_restore_notifier = {
.notifier_call = jtag_hotcpu_restore_callback,
.priority = 1,
};
static int jtag_cpu_pm_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
switch (action) {
case CPU_PM_ENTER:
msm_jtag_save_state();
break;
case CPU_PM_ENTER_FAILED:
case CPU_PM_EXIT:
msm_jtag_restore_state();
break;
}
return NOTIFY_OK;
}
static struct notifier_block jtag_cpu_pm_notifier = {
.notifier_call = jtag_cpu_pm_callback,
};
static int __init msm_jtag_dbg_init(void)
{
int ret;
@ -950,6 +1005,10 @@ static int __init msm_jtag_dbg_init(void)
ret = -ENOMEM;
goto dbg_err;
}
register_hotcpu_notifier(&jtag_hotcpu_save_notifier);
register_hotcpu_notifier(&jtag_hotcpu_restore_notifier);
cpu_pm_register_notifier(&jtag_cpu_pm_notifier);
dbg_out:
return 0;
dbg_err: