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