[PATCH 6/9] coresight-etm3x: Fixing suspend/wake modes
From: mathieu . poirier
Date: Tue Jan 06 2015 - 11:38:34 EST
From: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
This patch makes sure power is managed properly during power state
transitions. Checks are introduced to make sure HW access functions
aren't called uselessly to avoid wasting power and accessing
blocks that may be powered down.
Lastly the CPU_ONLINE state has been removed from the cpu callback
as it wasn't useful anymore.
Signed-off-by: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx>
---
drivers/coresight/coresight-etm.h | 4 ++--
drivers/coresight/coresight-etm3x.c | 48 ++++++++++++++++++++-----------------
2 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/drivers/coresight/coresight-etm.h b/drivers/coresight/coresight-etm.h
index 501c5fac8a45..a0e30ca2e32d 100644
--- a/drivers/coresight/coresight-etm.h
+++ b/drivers/coresight/coresight-etm.h
@@ -148,7 +148,7 @@
* @arch: ETM/PTM version number.
* @use_cpu14: true if management registers need to be accessed via CP14.
* @enable: is this ETM/PTM currently tracing.
- * @sticky_enable: true if ETM base configuration has been done.
+ * @suspended: is the CPU associated to the ETM/PTM suspended?
* @boot_enable:true if we should start tracing at boot time.
* @os_unlock: true if access to management registers is allowed.
* @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR.
@@ -200,7 +200,7 @@ struct etm_drvdata {
u8 arch;
bool use_cp14;
bool enable;
- bool sticky_enable;
+ bool suspended;
bool boot_enable;
bool os_unlock;
u8 nr_addr_cmp;
diff --git a/drivers/coresight/coresight-etm3x.c b/drivers/coresight/coresight-etm3x.c
index 7df9ffc51501..e09c3ef76d16 100644
--- a/drivers/coresight/coresight-etm3x.c
+++ b/drivers/coresight/coresight-etm3x.c
@@ -254,6 +254,12 @@ static void etm_enable_hw(void *info)
u32 etmcr;
struct etm_drvdata *drvdata = info;
+ if (clk_prepare_enable(drvdata->clk)) {
+ dev_dbg(drvdata->dev, "cpu: %d can't enable hw\n",
+ drvdata->cpu);
+ return;
+ }
+
pm_runtime_get_sync(drvdata->dev);
CS_UNLOCK(drvdata->base);
@@ -314,6 +320,8 @@ static void etm_enable_hw(void *info)
etm_clr_prog(drvdata);
CS_LOCK(drvdata->base);
+ drvdata->suspended = false;
+
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
}
@@ -355,14 +363,12 @@ out:
static int etm_enable(struct coresight_device *csdev)
{
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- int ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- goto err_clk;
+ int ret = 0;
spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ goto out;
/*
* Configure the ETM only if the CPU is online. If it isn't online
* hw configuration will take place when 'CPU_STARTING' is received
@@ -372,20 +378,17 @@ static int etm_enable(struct coresight_device *csdev)
ret = smp_call_function_single(drvdata->cpu,
etm_enable_hw, drvdata, 1);
if (ret)
- goto err;
+ goto out;
}
drvdata->enable = true;
- drvdata->sticky_enable = true;
-
spin_unlock(&drvdata->spinlock);
dev_info(drvdata->dev, "ETM tracing enabled\n");
return 0;
-err:
+out:
spin_unlock(&drvdata->spinlock);
clk_disable_unprepare(drvdata->clk);
-err_clk:
return ret;
}
@@ -397,6 +400,9 @@ static void etm_disable_hw(void *info)
CS_UNLOCK(drvdata->base);
etm_set_prog(drvdata);
+ if (!drvdata->enable)
+ return;
+
/* Program trace enable to low by using always false event */
etm_writel(drvdata, ETM_HARD_WIRE_RES_A | ETM_EVENT_NOT_A, ETMTEEVR);
@@ -409,6 +415,9 @@ static void etm_disable_hw(void *info)
etm_set_pwrdwn(drvdata);
CS_LOCK(drvdata->base);
pm_runtime_put_sync(drvdata->dev);
+ clk_disable_unprepare(drvdata->clk);
+
+ drvdata->suspended = true;
dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
}
@@ -426,18 +435,20 @@ static void etm_disable(struct coresight_device *csdev)
get_online_cpus();
spin_lock(&drvdata->spinlock);
+ if (!drvdata->enable)
+ goto out;
/*
* Executing etm_disable_hw on the cpu whose ETM is being disabled
* ensures that register writes occur when cpu is powered.
*/
- smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
+ if (!drvdata->suspended)
+ smp_call_function_single(drvdata->cpu,
+ etm_disable_hw, drvdata, 1);
drvdata->enable = false;
-
+out:
spin_unlock(&drvdata->spinlock);
put_online_cpus();
- clk_disable_unprepare(drvdata->clk);
-
dev_info(drvdata->dev, "ETM tracing disabled\n");
}
@@ -1674,14 +1685,7 @@ static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
etm_enable_hw(etmdrvdata[cpu]);
spin_unlock(&etmdrvdata[cpu]->spinlock);
break;
-
- case CPU_ONLINE:
- if (etmdrvdata[cpu]->boot_enable &&
- !etmdrvdata[cpu]->sticky_enable)
- coresight_enable(etmdrvdata[cpu]->csdev);
- break;
-
- case CPU_DYING:
+ case CPU_DEAD:
spin_lock(&etmdrvdata[cpu]->spinlock);
if (etmdrvdata[cpu]->enable)
etm_disable_hw(etmdrvdata[cpu]);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/