diff mbox

[6/9] coresight-etm3x: Fixing suspend/wake modes

Message ID 1420562233-2015-7-git-send-email-mathieu.poirier@linaro.org
State New
Headers show

Commit Message

Mathieu Poirier Jan. 6, 2015, 4:37 p.m. UTC
From: Mathieu Poirier <mathieu.poirier@linaro.org>

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@linaro.org>
---
 drivers/coresight/coresight-etm.h   |  4 ++--
 drivers/coresight/coresight-etm3x.c | 48 ++++++++++++++++++++-----------------
 2 files changed, 28 insertions(+), 24 deletions(-)
diff mbox

Patch

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]);