Skip to content

Commit 2c25a4e

Browse files
coresight: etm4x: moving etm_drvdata::enable to atomic field
Similarly to ETMv3, moving etmv4_drvdata::enable to an atomic type that gives the 'mode' of a tracer and prevents multiple, simultanious access by different subsystems. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit c38a9ec2b2c12c38abca0b7954ed793f26969835)
1 parent 17b04a9 commit 2c25a4e

2 files changed

Lines changed: 63 additions & 11 deletions

File tree

drivers/hwtracing/coresight/coresight-etm4x.c

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/pm_runtime.h>
3535
#include <linux/perf_event.h>
3636
#include <asm/sections.h>
37+
#include <asm/local.h>
3738

3839
#include "coresight-etm4x.h"
3940

@@ -76,7 +77,7 @@ static int etm4_trace_id(struct coresight_device *csdev)
7677
unsigned long flags;
7778
int trace_id = -1;
7879

79-
if (!drvdata->enable)
80+
if (!local_read(&drvdata->mode))
8081
return drvdata->trcid;
8182

8283
spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -188,8 +189,7 @@ static void etm4_enable_hw(void *info)
188189
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
189190
}
190191

191-
static int etm4_enable(struct coresight_device *csdev,
192-
struct perf_event_attr *attr, u32 mode)
192+
static int etm4_enable_sysfs(struct coresight_device *csdev)
193193
{
194194
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
195195
int ret;
@@ -204,18 +204,46 @@ static int etm4_enable(struct coresight_device *csdev,
204204
etm4_enable_hw, drvdata, 1);
205205
if (ret)
206206
goto err;
207-
drvdata->enable = true;
208-
drvdata->sticky_enable = true;
209207

208+
drvdata->sticky_enable = true;
210209
spin_unlock(&drvdata->spinlock);
211210

212211
dev_info(drvdata->dev, "ETM tracing enabled\n");
213212
return 0;
213+
214214
err:
215215
spin_unlock(&drvdata->spinlock);
216216
return ret;
217217
}
218218

219+
static int etm4_enable(struct coresight_device *csdev,
220+
struct perf_event_attr *attr, u32 mode)
221+
{
222+
int ret;
223+
u32 val;
224+
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
225+
226+
val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
227+
228+
/* Someone is already using the tracer */
229+
if (val)
230+
return -EBUSY;
231+
232+
switch (mode) {
233+
case CS_MODE_SYSFS:
234+
ret = etm4_enable_sysfs(csdev);
235+
break;
236+
default:
237+
ret = -EINVAL;
238+
}
239+
240+
/* The tracer didn't start */
241+
if (ret)
242+
local_set(&drvdata->mode, CS_MODE_DISABLED);
243+
244+
return ret;
245+
}
246+
219247
static void etm4_disable_hw(void *info)
220248
{
221249
u32 control;
@@ -238,7 +266,7 @@ static void etm4_disable_hw(void *info)
238266
dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
239267
}
240268

241-
static void etm4_disable(struct coresight_device *csdev)
269+
static void etm4_disable_sysfs(struct coresight_device *csdev)
242270
{
243271
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
244272

@@ -256,14 +284,37 @@ static void etm4_disable(struct coresight_device *csdev)
256284
* ensures that register writes occur when cpu is powered.
257285
*/
258286
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
259-
drvdata->enable = false;
260287

261288
spin_unlock(&drvdata->spinlock);
262289
put_online_cpus();
263290

264291
dev_info(drvdata->dev, "ETM tracing disabled\n");
265292
}
266293

294+
static void etm4_disable(struct coresight_device *csdev)
295+
{
296+
u32 mode;
297+
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
298+
299+
/*
300+
* For as long as the tracer isn't disabled another entity can't
301+
* change its status. As such we can read the status here without
302+
* fearing it will change under us.
303+
*/
304+
mode = local_read(&drvdata->mode);
305+
306+
switch (mode) {
307+
case CS_MODE_DISABLED:
308+
break;
309+
case CS_MODE_SYSFS:
310+
etm4_disable_sysfs(csdev);
311+
break;
312+
}
313+
314+
if (mode)
315+
local_set(&drvdata->mode, CS_MODE_DISABLED);
316+
}
317+
267318
static const struct coresight_ops_source etm4_source_ops = {
268319
.cpu_id = etm4_cpu_id,
269320
.trace_id = etm4_trace_id,
@@ -531,7 +582,7 @@ static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
531582
etmdrvdata[cpu]->os_unlock = true;
532583
}
533584

534-
if (etmdrvdata[cpu]->enable)
585+
if (local_read(&etmdrvdata[cpu]->mode))
535586
etm4_enable_hw(etmdrvdata[cpu]);
536587
spin_unlock(&etmdrvdata[cpu]->spinlock);
537588
break;
@@ -544,7 +595,7 @@ static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
544595

545596
case CPU_DYING:
546597
spin_lock(&etmdrvdata[cpu]->spinlock);
547-
if (etmdrvdata[cpu]->enable)
598+
if (local_read(&etmdrvdata[cpu]->mode))
548599
etm4_disable_hw(etmdrvdata[cpu]);
549600
spin_unlock(&etmdrvdata[cpu]->spinlock);
550601
break;

drivers/hwtracing/coresight/coresight-etm4x.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef _CORESIGHT_CORESIGHT_ETM_H
1414
#define _CORESIGHT_CORESIGHT_ETM_H
1515

16+
#include <asm/local.h>
1617
#include <linux/spinlock.h>
1718
#include "coresight-priv.h"
1819

@@ -290,6 +291,7 @@ struct etmv4_config {
290291
* @dev: The device entity associated to this component.
291292
* @csdev: Component vitals needed by the framework.
292293
* @spinlock: Only one at a time pls.
294+
* @mode: This tracer's mode, i.e sysFS, Perf or disabled.
293295
* @cpu: The cpu this component is affined to.
294296
* @arch: ETM version number.
295297
* @nr_pe: The number of processing entity available for tracing.
@@ -316,7 +318,6 @@ struct etmv4_config {
316318
* supported for the corresponding Exception level.
317319
* @ns_ex_level:In non-secure state, indicates whether instruction tracing is
318320
* supported for the corresponding Exception level.
319-
* @enable: Is this ETM currently tracing.
320321
* @sticky_enable: true if ETM base configuration has been done.
321322
* @boot_enable:True if we should start tracing at boot time.
322323
* @os_unlock: True if access to management registers is allowed.
@@ -346,6 +347,7 @@ struct etmv4_drvdata {
346347
struct device *dev;
347348
struct coresight_device *csdev;
348349
spinlock_t spinlock;
350+
local_t mode;
349351
int cpu;
350352
u8 arch;
351353
u8 nr_pe;
@@ -368,7 +370,6 @@ struct etmv4_drvdata {
368370
u8 ccitmin;
369371
u8 s_ex_level;
370372
u8 ns_ex_level;
371-
bool enable;
372373
bool sticky_enable;
373374
bool boot_enable;
374375
bool os_unlock;

0 commit comments

Comments
 (0)