mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 15:11:16 +00:00
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>
This commit is contained in:
parent
66bbbb7754
commit
c38a9ec2b2
2 changed files with 63 additions and 11 deletions
|
@ -34,6 +34,7 @@
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
|
#include <asm/local.h>
|
||||||
|
|
||||||
#include "coresight-etm4x.h"
|
#include "coresight-etm4x.h"
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ static int etm4_trace_id(struct coresight_device *csdev)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int trace_id = -1;
|
int trace_id = -1;
|
||||||
|
|
||||||
if (!drvdata->enable)
|
if (!local_read(&drvdata->mode))
|
||||||
return drvdata->trcid;
|
return drvdata->trcid;
|
||||||
|
|
||||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||||
|
@ -188,8 +189,7 @@ static void etm4_enable_hw(void *info)
|
||||||
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
|
dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int etm4_enable(struct coresight_device *csdev,
|
static int etm4_enable_sysfs(struct coresight_device *csdev)
|
||||||
struct perf_event_attr *attr, u32 mode)
|
|
||||||
{
|
{
|
||||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -204,18 +204,46 @@ static int etm4_enable(struct coresight_device *csdev,
|
||||||
etm4_enable_hw, drvdata, 1);
|
etm4_enable_hw, drvdata, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
drvdata->enable = true;
|
|
||||||
drvdata->sticky_enable = true;
|
|
||||||
|
|
||||||
|
drvdata->sticky_enable = true;
|
||||||
spin_unlock(&drvdata->spinlock);
|
spin_unlock(&drvdata->spinlock);
|
||||||
|
|
||||||
dev_info(drvdata->dev, "ETM tracing enabled\n");
|
dev_info(drvdata->dev, "ETM tracing enabled\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
spin_unlock(&drvdata->spinlock);
|
spin_unlock(&drvdata->spinlock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int etm4_enable(struct coresight_device *csdev,
|
||||||
|
struct perf_event_attr *attr, u32 mode)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||||
|
|
||||||
|
val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
|
||||||
|
|
||||||
|
/* Someone is already using the tracer */
|
||||||
|
if (val)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case CS_MODE_SYSFS:
|
||||||
|
ret = etm4_enable_sysfs(csdev);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The tracer didn't start */
|
||||||
|
if (ret)
|
||||||
|
local_set(&drvdata->mode, CS_MODE_DISABLED);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void etm4_disable_hw(void *info)
|
static void etm4_disable_hw(void *info)
|
||||||
{
|
{
|
||||||
u32 control;
|
u32 control;
|
||||||
|
@ -238,7 +266,7 @@ static void etm4_disable_hw(void *info)
|
||||||
dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
|
dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void etm4_disable(struct coresight_device *csdev)
|
static void etm4_disable_sysfs(struct coresight_device *csdev)
|
||||||
{
|
{
|
||||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||||
|
|
||||||
|
@ -256,7 +284,6 @@ static void etm4_disable(struct coresight_device *csdev)
|
||||||
* ensures that register writes occur when cpu is powered.
|
* ensures that register writes occur when cpu is powered.
|
||||||
*/
|
*/
|
||||||
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
|
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
|
||||||
drvdata->enable = false;
|
|
||||||
|
|
||||||
spin_unlock(&drvdata->spinlock);
|
spin_unlock(&drvdata->spinlock);
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
|
@ -264,6 +291,30 @@ static void etm4_disable(struct coresight_device *csdev)
|
||||||
dev_info(drvdata->dev, "ETM tracing disabled\n");
|
dev_info(drvdata->dev, "ETM tracing disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void etm4_disable(struct coresight_device *csdev)
|
||||||
|
{
|
||||||
|
u32 mode;
|
||||||
|
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For as long as the tracer isn't disabled another entity can't
|
||||||
|
* change its status. As such we can read the status here without
|
||||||
|
* fearing it will change under us.
|
||||||
|
*/
|
||||||
|
mode = local_read(&drvdata->mode);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case CS_MODE_DISABLED:
|
||||||
|
break;
|
||||||
|
case CS_MODE_SYSFS:
|
||||||
|
etm4_disable_sysfs(csdev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode)
|
||||||
|
local_set(&drvdata->mode, CS_MODE_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct coresight_ops_source etm4_source_ops = {
|
static const struct coresight_ops_source etm4_source_ops = {
|
||||||
.cpu_id = etm4_cpu_id,
|
.cpu_id = etm4_cpu_id,
|
||||||
.trace_id = etm4_trace_id,
|
.trace_id = etm4_trace_id,
|
||||||
|
@ -531,7 +582,7 @@ static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
|
||||||
etmdrvdata[cpu]->os_unlock = true;
|
etmdrvdata[cpu]->os_unlock = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (etmdrvdata[cpu]->enable)
|
if (local_read(&etmdrvdata[cpu]->mode))
|
||||||
etm4_enable_hw(etmdrvdata[cpu]);
|
etm4_enable_hw(etmdrvdata[cpu]);
|
||||||
spin_unlock(&etmdrvdata[cpu]->spinlock);
|
spin_unlock(&etmdrvdata[cpu]->spinlock);
|
||||||
break;
|
break;
|
||||||
|
@ -544,7 +595,7 @@ static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
|
||||||
|
|
||||||
case CPU_DYING:
|
case CPU_DYING:
|
||||||
spin_lock(&etmdrvdata[cpu]->spinlock);
|
spin_lock(&etmdrvdata[cpu]->spinlock);
|
||||||
if (etmdrvdata[cpu]->enable)
|
if (local_read(&etmdrvdata[cpu]->mode))
|
||||||
etm4_disable_hw(etmdrvdata[cpu]);
|
etm4_disable_hw(etmdrvdata[cpu]);
|
||||||
spin_unlock(&etmdrvdata[cpu]->spinlock);
|
spin_unlock(&etmdrvdata[cpu]->spinlock);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#ifndef _CORESIGHT_CORESIGHT_ETM_H
|
#ifndef _CORESIGHT_CORESIGHT_ETM_H
|
||||||
#define _CORESIGHT_CORESIGHT_ETM_H
|
#define _CORESIGHT_CORESIGHT_ETM_H
|
||||||
|
|
||||||
|
#include <asm/local.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include "coresight-priv.h"
|
#include "coresight-priv.h"
|
||||||
|
|
||||||
|
@ -290,6 +291,7 @@ struct etmv4_config {
|
||||||
* @dev: The device entity associated to this component.
|
* @dev: The device entity associated to this component.
|
||||||
* @csdev: Component vitals needed by the framework.
|
* @csdev: Component vitals needed by the framework.
|
||||||
* @spinlock: Only one at a time pls.
|
* @spinlock: Only one at a time pls.
|
||||||
|
* @mode: This tracer's mode, i.e sysFS, Perf or disabled.
|
||||||
* @cpu: The cpu this component is affined to.
|
* @cpu: The cpu this component is affined to.
|
||||||
* @arch: ETM version number.
|
* @arch: ETM version number.
|
||||||
* @nr_pe: The number of processing entity available for tracing.
|
* @nr_pe: The number of processing entity available for tracing.
|
||||||
|
@ -316,7 +318,6 @@ struct etmv4_config {
|
||||||
* supported for the corresponding Exception level.
|
* supported for the corresponding Exception level.
|
||||||
* @ns_ex_level:In non-secure state, indicates whether instruction tracing is
|
* @ns_ex_level:In non-secure state, indicates whether instruction tracing is
|
||||||
* supported for the corresponding Exception level.
|
* supported for the corresponding Exception level.
|
||||||
* @enable: Is this ETM currently tracing.
|
|
||||||
* @sticky_enable: true if ETM base configuration has been done.
|
* @sticky_enable: true if ETM base configuration has been done.
|
||||||
* @boot_enable:True if we should start tracing at boot time.
|
* @boot_enable:True if we should start tracing at boot time.
|
||||||
* @os_unlock: True if access to management registers is allowed.
|
* @os_unlock: True if access to management registers is allowed.
|
||||||
|
@ -346,6 +347,7 @@ struct etmv4_drvdata {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct coresight_device *csdev;
|
struct coresight_device *csdev;
|
||||||
spinlock_t spinlock;
|
spinlock_t spinlock;
|
||||||
|
local_t mode;
|
||||||
int cpu;
|
int cpu;
|
||||||
u8 arch;
|
u8 arch;
|
||||||
u8 nr_pe;
|
u8 nr_pe;
|
||||||
|
@ -368,7 +370,6 @@ struct etmv4_drvdata {
|
||||||
u8 ccitmin;
|
u8 ccitmin;
|
||||||
u8 s_ex_level;
|
u8 s_ex_level;
|
||||||
u8 ns_ex_level;
|
u8 ns_ex_level;
|
||||||
bool enable;
|
|
||||||
bool sticky_enable;
|
bool sticky_enable;
|
||||||
bool boot_enable;
|
bool boot_enable;
|
||||||
bool os_unlock;
|
bool os_unlock;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue