* [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
@ 2024-11-25 9:48 Yeoreum Yun
2024-11-25 9:48 ` [PATCH 1/9] coresight: change coresight_device lock " Yeoreum Yun
` (10 more replies)
0 siblings, 11 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Yeoreum Yun
In some coresight drivers, drvdata->spinlock can be held during __schedule()
by perf_event_task_sched_out()/in().
Since drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this,change type drvdata->spinlock in some coresight drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.
Levi Yun (9):
coresight: change coresight_device lock type to raw_spinlock_t
coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
coresight-funnel: change funnel_drvdata spinlock's type to
raw_spinlock_t
coresight-replicator: change replicator_drvdata spinlock's type to
raw_spinlock_t
coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
coresight/ultrasoc: change cti_drvdata spinlock's type to
raw_spinlock_t
.../hwtracing/coresight/coresight-config.c | 21 +-
.../hwtracing/coresight/coresight-config.h | 2 +-
drivers/hwtracing/coresight/coresight-core.c | 2 +-
.../hwtracing/coresight/coresight-cti-core.c | 65 +-
.../hwtracing/coresight/coresight-cti-sysfs.c | 135 +++--
drivers/hwtracing/coresight/coresight-cti.h | 2 +-
drivers/hwtracing/coresight/coresight-etb10.c | 62 +-
.../coresight/coresight-etm4x-core.c | 71 ++-
.../coresight/coresight-etm4x-sysfs.c | 566 +++++++++---------
drivers/hwtracing/coresight/coresight-etm4x.h | 2 +-
.../hwtracing/coresight/coresight-funnel.c | 34 +-
.../coresight/coresight-replicator.c | 36 +-
.../hwtracing/coresight/coresight-syscfg.c | 75 ++-
.../hwtracing/coresight/coresight-tmc-core.c | 9 +-
.../hwtracing/coresight/coresight-tmc-etf.c | 195 +++---
.../hwtracing/coresight/coresight-tmc-etr.c | 199 +++---
drivers/hwtracing/coresight/coresight-tmc.h | 2 +-
.../hwtracing/coresight/coresight-trace-id.c | 93 ++-
drivers/hwtracing/coresight/ultrasoc-smb.c | 12 +-
drivers/hwtracing/coresight/ultrasoc-smb.h | 2 +-
include/linux/coresight.h | 4 +-
21 files changed, 751 insertions(+), 838 deletions(-)
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-27 17:09 ` Steven Rostedt
2024-11-25 9:48 ` [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock " Yeoreum Yun
` (9 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
coresight_device->cscfg_csdev_lock can be held during __schedule()
by perf_event_task_sched_out()/in().
Since coresight->cscfg_csdev_lock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type of coresight_device->cscfg_csdev_lock
from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
.../hwtracing/coresight/coresight-syscfg.c | 75 +++++++++----------
include/linux/coresight.h | 2 +-
2 files changed, 35 insertions(+), 42 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 11138a9762b0..b7e9fb822e8f 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -65,7 +65,6 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
{
struct cscfg_config_csdev *config_csdev = NULL;
struct cscfg_feature_csdev *feat_csdev;
- unsigned long flags;
int i;
/* look at each required feature and see if it matches any feature on the device */
@@ -89,9 +88,9 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
}
/* if matched features, add config to device.*/
if (config_csdev) {
- spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
- list_add(&config_csdev->node, &csdev->config_csdev_list);
- spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+ scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) {
+ list_add(&config_csdev->node, &csdev->config_csdev_list);
+ }
}
return 0;
@@ -177,7 +176,6 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
struct cscfg_csdev_feat_ops *ops)
{
struct cscfg_feature_csdev *feat_csdev;
- unsigned long flags;
int err;
if (!ops->load_feat)
@@ -194,9 +192,9 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
/* add to internal csdev feature list & initialise using reset call */
cscfg_reset_feat(feat_csdev);
- spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
- list_add(&feat_csdev->node, &csdev->feature_csdev_list);
- spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+ scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) {
+ list_add(&feat_csdev->node, &csdev->feature_csdev_list);
+ }
return 0;
}
@@ -765,7 +763,7 @@ static int cscfg_list_add_csdev(struct coresight_device *csdev,
INIT_LIST_HEAD(&csdev->feature_csdev_list);
INIT_LIST_HEAD(&csdev->config_csdev_list);
- spin_lock_init(&csdev->cscfg_csdev_lock);
+ raw_spin_lock_init(&csdev->cscfg_csdev_lock);
return 0;
}
@@ -853,17 +851,14 @@ EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
void cscfg_csdev_reset_feats(struct coresight_device *csdev)
{
struct cscfg_feature_csdev *feat_csdev;
- unsigned long flags;
- spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock);
+
if (list_empty(&csdev->feature_csdev_list))
- goto unlock_exit;
+ return;
list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
cscfg_reset_feat(feat_csdev);
-
-unlock_exit:
- spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
}
EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
@@ -1048,7 +1043,6 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
{
struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
const struct cscfg_config_desc *config_desc;
- unsigned long flags;
int err = 0;
/* quickly check global count */
@@ -1059,17 +1053,17 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
* Look for matching configuration - set the active configuration
* context if found.
*/
- spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
- list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
- config_desc = config_csdev_item->config_desc;
- if ((atomic_read(&config_desc->active_cnt)) &&
- ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
- config_csdev_active = config_csdev_item;
- csdev->active_cscfg_ctxt = (void *)config_csdev_active;
- break;
+ scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) {
+ list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
+ config_desc = config_csdev_item->config_desc;
+ if ((atomic_read(&config_desc->active_cnt)) &&
+ ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
+ config_csdev_active = config_csdev_item;
+ csdev->active_cscfg_ctxt = (void *)config_csdev_active;
+ break;
+ }
}
}
- spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
/*
* If found, attempt to enable
@@ -1090,12 +1084,12 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
*
* Set enabled if OK, err if not.
*/
- spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
- if (csdev->active_cscfg_ctxt)
- config_csdev_active->enabled = true;
- else
- err = -EBUSY;
- spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
+ scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) {
+ if (csdev->active_cscfg_ctxt)
+ config_csdev_active->enabled = true;
+ else
+ err = -EBUSY;
+ }
}
}
return err;
@@ -1117,23 +1111,22 @@ EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
{
struct cscfg_config_csdev *config_csdev;
- unsigned long flags;
/*
* Check if we have an active config, and that it was successfully enabled.
* If it was not enabled, we have no work to do, otherwise mark as disabled.
* Clear the active config pointer.
*/
- spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
- config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
- if (config_csdev) {
- if (!config_csdev->enabled)
- config_csdev = NULL;
- else
- config_csdev->enabled = false;
+ scoped_guard(raw_spinlock_irqsave, &csdev->cscfg_csdev_lock) {
+ config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
+ if (config_csdev) {
+ if (!config_csdev->enabled)
+ config_csdev = NULL;
+ else
+ config_csdev->enabled = false;
+ }
+ csdev->active_cscfg_ctxt = NULL;
}
- csdev->active_cscfg_ctxt = NULL;
- spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
/* true if there was an enabled active config */
if (config_csdev)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index c13342594278..924b58c343b3 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -296,7 +296,7 @@ struct coresight_device {
/* system configuration and feature lists */
struct list_head feature_csdev_list;
struct list_head config_csdev_list;
- spinlock_t cscfg_csdev_lock;
+ raw_spinlock_t cscfg_csdev_lock;
void *active_cscfg_ctxt;
};
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
2024-11-25 9:48 ` [PATCH 1/9] coresight: change coresight_device lock " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-27 16:30 ` James Clark
2024-11-25 9:48 ` [PATCH 3/9] coresight: change coresight_trace_id_map's lock " Yeoreum Yun
` (8 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In coresight-etm4x drivers, etmv4_drvdata->spinlock can be held during
__schedule() by perf_event_task_sched_out()/in().
Since etmv4_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type etmv4_drvdata->spinlock
in coresight-etm4x drivers, which can be called
by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
.../hwtracing/coresight/coresight-config.c | 21 +-
.../hwtracing/coresight/coresight-config.h | 2 +-
.../coresight/coresight-etm4x-core.c | 71 ++-
.../coresight/coresight-etm4x-sysfs.c | 566 +++++++++---------
drivers/hwtracing/coresight/coresight-etm4x.h | 2 +-
5 files changed, 345 insertions(+), 317 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
index 4723bf7402a2..e70579d4ce7f 100644
--- a/drivers/hwtracing/coresight/coresight-config.c
+++ b/drivers/hwtracing/coresight/coresight-config.c
@@ -73,28 +73,29 @@ static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev,
/* set values into the driver locations referenced in cscfg_reg_csdev */
static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
{
- unsigned long flags;
int i;
- spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
- for (i = 0; i < feat_csdev->nr_regs; i++)
- cscfg_set_reg(&feat_csdev->regs_csdev[i]);
- spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+ scoped_guard(raw_spinlock_irqsave, feat_csdev->drv_spinlock) {
+ for (i = 0; i < feat_csdev->nr_regs; i++)
+ cscfg_set_reg(&feat_csdev->regs_csdev[i]);
+ }
+
dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
feat_csdev->feat_desc->name, "set on enable");
+
return 0;
}
/* copy back values from the driver locations referenced in cscfg_reg_csdev */
static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
{
- unsigned long flags;
int i;
- spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
- for (i = 0; i < feat_csdev->nr_regs; i++)
- cscfg_save_reg(&feat_csdev->regs_csdev[i]);
- spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
+ scoped_guard(raw_spinlock_irqsave, feat_csdev->drv_spinlock) {
+ for (i = 0; i < feat_csdev->nr_regs; i++)
+ cscfg_save_reg(&feat_csdev->regs_csdev[i]);
+ }
+
dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
feat_csdev->feat_desc->name, "save on disable");
}
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 6ba013975741..b9ebc9fcfb7f 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -206,7 +206,7 @@ struct cscfg_feature_csdev {
const struct cscfg_feature_desc *feat_desc;
struct coresight_device *csdev;
struct list_head node;
- spinlock_t *drv_spinlock;
+ raw_spinlock_t *drv_spinlock;
int nr_params;
struct cscfg_parameter_csdev *params_csdev;
int nr_regs;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 66d44a404ad0..1740cf6ab956 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -807,33 +807,30 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
return ret;
}
- spin_lock(&drvdata->spinlock);
-
- /* sysfs needs to read and allocate a trace ID */
- ret = etm4_read_alloc_trace_id(drvdata);
- if (ret < 0)
- goto unlock_sysfs_enable;
-
- /*
- * Executing etm4_enable_hw on the cpu whose ETM is being enabled
- * ensures that register writes occur when cpu is powered.
- */
- arg.drvdata = drvdata;
- ret = smp_call_function_single(drvdata->cpu,
- etm4_enable_hw_smp_call, &arg, 1);
- if (!ret)
- ret = arg.rc;
- if (!ret)
- drvdata->sticky_enable = true;
-
- if (ret)
- etm4_release_trace_id(drvdata);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ /* sysfs needs to read and allocate a trace ID */
+ ret = etm4_read_alloc_trace_id(drvdata);
+ if (ret < 0)
+ return ret;
-unlock_sysfs_enable:
- spin_unlock(&drvdata->spinlock);
+ /*
+ * Executing etm4_enable_hw on the cpu whose ETM is being enabled
+ * ensures that register writes occur when cpu is powered.
+ */
+ arg.drvdata = drvdata;
+ ret = smp_call_function_single(drvdata->cpu,
+ etm4_enable_hw_smp_call, &arg, 1);
+ if (!ret) {
+ ret = arg.rc;
+ drvdata->sticky_enable = true;
+ } else {
+ etm4_release_trace_id(drvdata);
+ }
+ }
if (!ret)
dev_dbg(&csdev->dev, "ETM tracing enabled\n");
+
return ret;
}
@@ -977,15 +974,13 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
* DYING hotplug callback is serviced by the ETM driver.
*/
cpus_read_lock();
- spin_lock(&drvdata->spinlock);
-
- /*
- * Executing etm4_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, etm4_disable_hw, drvdata, 1);
-
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ /*
+ * Executing etm4_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, etm4_disable_hw, drvdata, 1);
+ }
cpus_read_unlock();
/*
@@ -1663,13 +1658,14 @@ static int etm4_starting_cpu(unsigned int cpu)
if (!etmdrvdata[cpu])
return 0;
- spin_lock(&etmdrvdata[cpu]->spinlock);
+ guard(raw_spinlock)(&etmdrvdata[cpu]->spinlock);
+
if (!etmdrvdata[cpu]->os_unlock)
etm4_os_unlock(etmdrvdata[cpu]);
if (coresight_get_mode(etmdrvdata[cpu]->csdev))
etm4_enable_hw(etmdrvdata[cpu]);
- spin_unlock(&etmdrvdata[cpu]->spinlock);
+
return 0;
}
@@ -1678,10 +1674,11 @@ static int etm4_dying_cpu(unsigned int cpu)
if (!etmdrvdata[cpu])
return 0;
- spin_lock(&etmdrvdata[cpu]->spinlock);
+ guard(raw_spinlock)(&etmdrvdata[cpu]->spinlock);
+
if (coresight_get_mode(etmdrvdata[cpu]->csdev))
etm4_disable_hw(etmdrvdata[cpu]);
- spin_unlock(&etmdrvdata[cpu]->spinlock);
+
return 0;
}
@@ -2125,7 +2122,7 @@ static int etm4_probe(struct device *dev)
return -ENOMEM;
}
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
drvdata->cpu = coresight_get_cpu(dev);
if (drvdata->cpu < 0)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index a9f19629f3f8..2e6b79c37f87 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -174,99 +174,99 @@ static ssize_t reset_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- if (val)
- config->mode = 0x0;
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ if (val)
+ config->mode = 0x0;
- /* Disable data tracing: do not trace load and store data transfers */
- config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
- config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE);
+ /* Disable data tracing: do not trace load and store data transfers */
+ config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
+ config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE);
- /* Disable data value and data address tracing */
- config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
- ETM_MODE_DATA_TRACE_VAL);
- config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV);
+ /* Disable data value and data address tracing */
+ config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
+ ETM_MODE_DATA_TRACE_VAL);
+ config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV);
- /* Disable all events tracing */
- config->eventctrl0 = 0x0;
- config->eventctrl1 = 0x0;
+ /* Disable all events tracing */
+ config->eventctrl0 = 0x0;
+ config->eventctrl1 = 0x0;
- /* Disable timestamp event */
- config->ts_ctrl = 0x0;
+ /* Disable timestamp event */
+ config->ts_ctrl = 0x0;
- /* Disable stalling */
- config->stall_ctrl = 0x0;
+ /* Disable stalling */
+ config->stall_ctrl = 0x0;
- /* Reset trace synchronization period to 2^8 = 256 bytes*/
- if (drvdata->syncpr == false)
- config->syncfreq = 0x8;
+ /* Reset trace synchronization period to 2^8 = 256 bytes*/
+ if (drvdata->syncpr == false)
+ config->syncfreq = 0x8;
- /*
- * Enable ViewInst to trace everything with start-stop logic in
- * started state. ARM recommends start-stop logic is set before
- * each trace run.
- */
- config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
- if (drvdata->nr_addr_cmp > 0) {
- config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
- /* SSSTATUS, bit[9] */
- config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
- }
+ /*
+ * Enable ViewInst to trace everything with start-stop logic in
+ * started state. ARM recommends start-stop logic is set before
+ * each trace run.
+ */
+ config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
+ if (drvdata->nr_addr_cmp > 0) {
+ config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
+ /* SSSTATUS, bit[9] */
+ config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
+ }
- /* No address range filtering for ViewInst */
- config->viiectlr = 0x0;
+ /* No address range filtering for ViewInst */
+ config->viiectlr = 0x0;
- /* No start-stop filtering for ViewInst */
- config->vissctlr = 0x0;
- config->vipcssctlr = 0x0;
+ /* No start-stop filtering for ViewInst */
+ config->vissctlr = 0x0;
+ config->vipcssctlr = 0x0;
- /* Disable seq events */
- for (i = 0; i < drvdata->nrseqstate-1; i++)
- config->seq_ctrl[i] = 0x0;
- config->seq_rst = 0x0;
- config->seq_state = 0x0;
+ /* Disable seq events */
+ for (i = 0; i < drvdata->nrseqstate-1; i++)
+ config->seq_ctrl[i] = 0x0;
+ config->seq_rst = 0x0;
+ config->seq_state = 0x0;
- /* Disable external input events */
- config->ext_inp = 0x0;
+ /* Disable external input events */
+ config->ext_inp = 0x0;
- config->cntr_idx = 0x0;
- for (i = 0; i < drvdata->nr_cntr; i++) {
- config->cntrldvr[i] = 0x0;
- config->cntr_ctrl[i] = 0x0;
- config->cntr_val[i] = 0x0;
- }
+ config->cntr_idx = 0x0;
+ for (i = 0; i < drvdata->nr_cntr; i++) {
+ config->cntrldvr[i] = 0x0;
+ config->cntr_ctrl[i] = 0x0;
+ config->cntr_val[i] = 0x0;
+ }
- config->res_idx = 0x0;
- for (i = 2; i < 2 * drvdata->nr_resource; i++)
- config->res_ctrl[i] = 0x0;
+ config->res_idx = 0x0;
+ for (i = 2; i < 2 * drvdata->nr_resource; i++)
+ config->res_ctrl[i] = 0x0;
- config->ss_idx = 0x0;
- for (i = 0; i < drvdata->nr_ss_cmp; i++) {
- config->ss_ctrl[i] = 0x0;
- config->ss_pe_cmp[i] = 0x0;
- }
+ config->ss_idx = 0x0;
+ for (i = 0; i < drvdata->nr_ss_cmp; i++) {
+ config->ss_ctrl[i] = 0x0;
+ config->ss_pe_cmp[i] = 0x0;
+ }
- config->addr_idx = 0x0;
- for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
- config->addr_val[i] = 0x0;
- config->addr_acc[i] = 0x0;
- config->addr_type[i] = ETM_ADDR_TYPE_NONE;
- }
+ config->addr_idx = 0x0;
+ for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
+ config->addr_val[i] = 0x0;
+ config->addr_acc[i] = 0x0;
+ config->addr_type[i] = ETM_ADDR_TYPE_NONE;
+ }
- config->ctxid_idx = 0x0;
- for (i = 0; i < drvdata->numcidc; i++)
- config->ctxid_pid[i] = 0x0;
+ config->ctxid_idx = 0x0;
+ for (i = 0; i < drvdata->numcidc; i++)
+ config->ctxid_pid[i] = 0x0;
- config->ctxid_mask0 = 0x0;
- config->ctxid_mask1 = 0x0;
+ config->ctxid_mask0 = 0x0;
+ config->ctxid_mask1 = 0x0;
- config->vmid_idx = 0x0;
- for (i = 0; i < drvdata->numvmidc; i++)
- config->vmid_val[i] = 0x0;
- config->vmid_mask0 = 0x0;
- config->vmid_mask1 = 0x0;
+ config->vmid_idx = 0x0;
+ for (i = 0; i < drvdata->numvmidc; i++)
+ config->vmid_val[i] = 0x0;
- spin_unlock(&drvdata->spinlock);
+ config->vmid_mask0 = 0x0;
+ config->vmid_mask1 = 0x0;
+ }
/* for sysfs - only release trace id when resetting */
etm4_release_trace_id(drvdata);
@@ -300,7 +300,8 @@ static ssize_t mode_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->mode = val & ETMv4_MODE_ALL;
if (drvdata->instrp0 == true) {
@@ -437,8 +438,6 @@ static ssize_t mode_store(struct device *dev,
if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
etm4_config_trace_mode(config);
- spin_unlock(&drvdata->spinlock);
-
return size;
}
static DEVICE_ATTR_RW(mode);
@@ -466,14 +465,14 @@ static ssize_t pe_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
if (val > drvdata->nr_pe) {
- spin_unlock(&drvdata->spinlock);
return -EINVAL;
}
config->pe_sel = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(pe);
@@ -501,7 +500,8 @@ static ssize_t event_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
switch (drvdata->nr_event) {
case 0x0:
/* EVENT0, bits[7:0] */
@@ -522,7 +522,7 @@ static ssize_t event_store(struct device *dev,
default:
break;
}
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(event);
@@ -550,7 +550,8 @@ static ssize_t event_instren_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
/* start by clearing all instruction event enable bits */
config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
switch (drvdata->nr_event) {
@@ -578,7 +579,7 @@ static ssize_t event_instren_store(struct device *dev,
default:
break;
}
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(event_instren);
@@ -739,11 +740,12 @@ static ssize_t event_vinst_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK);
config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK;
config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(event_vinst);
@@ -771,13 +773,14 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
/* clear all EXLEVEL_S bits */
config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK;
/* enable instruction tracing for corresponding exception level */
val &= drvdata->s_ex_level;
config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(s_exlevel_vinst);
@@ -806,13 +809,14 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
/* clear EXLEVEL_NS bits */
config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK;
/* enable instruction tracing for corresponding exception level */
val &= drvdata->ns_ex_level;
config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(ns_exlevel_vinst);
@@ -846,9 +850,10 @@ static ssize_t addr_idx_store(struct device *dev,
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->addr_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_idx);
@@ -862,7 +867,8 @@ static ssize_t addr_instdatatype_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]);
len = scnprintf(buf, PAGE_SIZE, "%s\n",
@@ -870,7 +876,7 @@ static ssize_t addr_instdatatype_show(struct device *dev,
(val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" :
(val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" :
"data_load_store")));
- spin_unlock(&drvdata->spinlock);
+
return len;
}
@@ -888,13 +894,13 @@ static ssize_t addr_instdatatype_store(struct device *dev,
if (sscanf(buf, "%s", str) != 1)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
if (!strcmp(str, "instr"))
/* TYPE, bits[1:0] */
config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK;
- spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(addr_instdatatype);
@@ -908,15 +914,15 @@ static ssize_t addr_single_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- idx = config->addr_idx;
- spin_lock(&drvdata->spinlock);
- if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
- spin_unlock(&drvdata->spinlock);
- return -EPERM;
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
+ if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE))
+ return -EPERM;
+
+ val = (unsigned long)config->addr_val[idx];
}
- val = (unsigned long)config->addr_val[idx];
- spin_unlock(&drvdata->spinlock);
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -932,17 +938,16 @@ static ssize_t addr_single_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
- spin_unlock(&drvdata->spinlock);
+ config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE))
return -EPERM;
- }
config->addr_val[idx] = (u64)val;
config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_single);
@@ -956,23 +961,21 @@ static ssize_t addr_range_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->addr_idx;
- if (idx % 2 != 0) {
- spin_unlock(&drvdata->spinlock);
- return -EPERM;
- }
- if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
- config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
- (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
- config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
- spin_unlock(&drvdata->spinlock);
- return -EPERM;
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
+ if (idx % 2 != 0)
+ return -EPERM;
+
+ if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+ config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+ (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+ config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE)))
+ return -EPERM;
+
+ val1 = (unsigned long)config->addr_val[idx];
+ val2 = (unsigned long)config->addr_val[idx + 1];
}
- val1 = (unsigned long)config->addr_val[idx];
- val2 = (unsigned long)config->addr_val[idx + 1];
- spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
}
@@ -995,20 +998,17 @@ static ssize_t addr_range_store(struct device *dev,
if (val1 > val2)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
- if (idx % 2 != 0) {
- spin_unlock(&drvdata->spinlock);
+ if (idx % 2 != 0)
return -EPERM;
- }
if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
(config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
- config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
- spin_unlock(&drvdata->spinlock);
+ config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE)))
return -EPERM;
- }
config->addr_val[idx] = (u64)val1;
config->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
@@ -1023,7 +1023,6 @@ static ssize_t addr_range_store(struct device *dev,
exclude = config->mode & ETM_MODE_EXCLUDE;
etm4_set_mode_exclude(drvdata, exclude ? true : false);
- spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(addr_range);
@@ -1037,17 +1036,17 @@ static ssize_t addr_start_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->addr_idx;
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
- if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
- spin_unlock(&drvdata->spinlock);
- return -EPERM;
+ if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+ return -EPERM;
+ }
+
+ val = (unsigned long)config->addr_val[idx];
}
- val = (unsigned long)config->addr_val[idx];
- spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1063,22 +1062,21 @@ static ssize_t addr_start_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
if (!drvdata->nr_addr_cmp) {
- spin_unlock(&drvdata->spinlock);
return -EINVAL;
}
if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
- spin_unlock(&drvdata->spinlock);
return -EPERM;
}
config->addr_val[idx] = (u64)val;
config->addr_type[idx] = ETM_ADDR_TYPE_START;
config->vissctlr |= BIT(idx);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_start);
@@ -1092,17 +1090,16 @@ static ssize_t addr_stop_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->addr_idx;
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
- if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
- spin_unlock(&drvdata->spinlock);
- return -EPERM;
- }
+ if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+ return -EPERM;
+ }
- val = (unsigned long)config->addr_val[idx];
- spin_unlock(&drvdata->spinlock);
+ val = (unsigned long)config->addr_val[idx];
+ }
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1118,22 +1115,21 @@ static ssize_t addr_stop_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
if (!drvdata->nr_addr_cmp) {
- spin_unlock(&drvdata->spinlock);
return -EINVAL;
}
if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
- spin_unlock(&drvdata->spinlock);
return -EPERM;
}
config->addr_val[idx] = (u64)val;
config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
config->vissctlr |= BIT(idx + 16);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_stop);
@@ -1147,14 +1143,15 @@ static ssize_t addr_ctxtype_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
/* CONTEXTTYPE, bits[3:2] */
val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]);
len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
(val == ETM_CTX_CTXID ? "ctxid" :
(val == ETM_CTX_VMID ? "vmid" : "all")));
- spin_unlock(&drvdata->spinlock);
+
return len;
}
@@ -1172,7 +1169,8 @@ static ssize_t addr_ctxtype_store(struct device *dev,
if (sscanf(buf, "%s", str) != 1)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
if (!strcmp(str, "none"))
/* start by clearing context type bits */
@@ -1199,7 +1197,7 @@ static ssize_t addr_ctxtype_store(struct device *dev,
if (drvdata->numvmidc)
config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
}
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_ctxtype);
@@ -1213,11 +1211,12 @@ static ssize_t addr_context_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->addr_idx;
- /* context ID comparator bits[6:4] */
- val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
+ /* context ID comparator bits[6:4] */
+ val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1238,12 +1237,12 @@ static ssize_t addr_context_store(struct device *dev,
drvdata->numcidc : drvdata->numvmidc))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
idx = config->addr_idx;
/* clear context ID comparator bits[6:4] */
config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK;
config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_context);
@@ -1257,10 +1256,11 @@ static ssize_t addr_exlevel_s_ns_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->addr_idx;
- val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
+ val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1279,12 +1279,13 @@ static ssize_t addr_exlevel_s_ns_store(struct device *dev,
if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK)))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->addr_idx;
/* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */
config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK;
config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(addr_exlevel_s_ns);
@@ -1307,22 +1308,23 @@ static ssize_t addr_cmp_view_show(struct device *dev,
int size = 0;
bool exclude = false;
- spin_lock(&drvdata->spinlock);
- idx = config->addr_idx;
- addr_v = config->addr_val[idx];
- addr_ctrl = config->addr_acc[idx];
- addr_type = config->addr_type[idx];
- if (addr_type == ETM_ADDR_TYPE_RANGE) {
- if (idx & 0x1) {
- idx -= 1;
- addr_v2 = addr_v;
- addr_v = config->addr_val[idx];
- } else {
- addr_v2 = config->addr_val[idx + 1];
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->addr_idx;
+ addr_v = config->addr_val[idx];
+ addr_ctrl = config->addr_acc[idx];
+ addr_type = config->addr_type[idx];
+ if (addr_type == ETM_ADDR_TYPE_RANGE) {
+ if (idx & 0x1) {
+ idx -= 1;
+ addr_v2 = addr_v;
+ addr_v = config->addr_val[idx];
+ } else {
+ addr_v2 = config->addr_val[idx + 1];
+ }
+ exclude = config->viiectlr & BIT(idx / 2 + 16);
}
- exclude = config->viiectlr & BIT(idx / 2 + 16);
}
- spin_unlock(&drvdata->spinlock);
+
if (addr_type) {
size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] %s %#lx", idx,
addr_type_names[addr_type], addr_v);
@@ -1366,9 +1368,10 @@ static ssize_t vinst_pe_cmp_start_stop_store(struct device *dev,
if (!drvdata->nr_pe_cmp)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->vipcssctlr = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(vinst_pe_cmp_start_stop);
@@ -1402,9 +1405,10 @@ static ssize_t seq_idx_store(struct device *dev,
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->seq_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(seq_idx);
@@ -1448,10 +1452,11 @@ static ssize_t seq_event_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->seq_idx;
- val = config->seq_ctrl[idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->seq_idx;
+ val = config->seq_ctrl[idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1467,11 +1472,12 @@ static ssize_t seq_event_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->seq_idx;
/* Seq control has two masks B[15:8] F[7:0] */
config->seq_ctrl[idx] = val & 0xFFFF;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(seq_event);
@@ -1535,9 +1541,10 @@ static ssize_t cntr_idx_store(struct device *dev,
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->cntr_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(cntr_idx);
@@ -1551,10 +1558,11 @@ static ssize_t cntrldvr_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->cntr_idx;
- val = config->cntrldvr[idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->cntr_idx;
+ val = config->cntrldvr[idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1572,10 +1580,11 @@ static ssize_t cntrldvr_store(struct device *dev,
if (val > ETM_CNTR_MAX_VAL)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->cntr_idx;
config->cntrldvr[idx] = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(cntrldvr);
@@ -1589,10 +1598,11 @@ static ssize_t cntr_val_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->cntr_idx;
- val = config->cntr_val[idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->cntr_idx;
+ val = config->cntr_val[idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1610,10 +1620,11 @@ static ssize_t cntr_val_store(struct device *dev,
if (val > ETM_CNTR_MAX_VAL)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->cntr_idx;
config->cntr_val[idx] = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(cntr_val);
@@ -1627,10 +1638,11 @@ static ssize_t cntr_ctrl_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->cntr_idx;
- val = config->cntr_ctrl[idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->cntr_idx;
+ val = config->cntr_ctrl[idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1646,10 +1658,11 @@ static ssize_t cntr_ctrl_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->cntr_idx;
config->cntr_ctrl[idx] = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(cntr_ctrl);
@@ -1687,9 +1700,10 @@ static ssize_t res_idx_store(struct device *dev,
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->res_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(res_idx);
@@ -1703,10 +1717,11 @@ static ssize_t res_ctrl_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- idx = config->res_idx;
- val = config->res_ctrl[idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->res_idx;
+ val = config->res_ctrl[idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1722,7 +1737,8 @@ static ssize_t res_ctrl_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->res_idx;
/* For odd idx pair inversal bit is RES0 */
if (idx % 2 != 0)
@@ -1732,7 +1748,7 @@ static ssize_t res_ctrl_store(struct device *dev,
TRCRSCTLRn_INV |
TRCRSCTLRn_GROUP_MASK |
TRCRSCTLRn_SELECT_MASK);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(res_ctrl);
@@ -1761,9 +1777,10 @@ static ssize_t sshot_idx_store(struct device *dev,
if (val >= drvdata->nr_ss_cmp)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->ss_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(sshot_idx);
@@ -1776,9 +1793,10 @@ static ssize_t sshot_ctrl_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- val = config->ss_ctrl[config->ss_idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val = config->ss_ctrl[config->ss_idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1794,12 +1812,13 @@ static ssize_t sshot_ctrl_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->ss_idx;
config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
/* must clear bit 31 in related status register on programming */
config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(sshot_ctrl);
@@ -1811,9 +1830,10 @@ static ssize_t sshot_status_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- val = config->ss_status[config->ss_idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val = config->ss_status[config->ss_idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static DEVICE_ATTR_RO(sshot_status);
@@ -1826,9 +1846,10 @@ static ssize_t sshot_pe_ctrl_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- val = config->ss_pe_cmp[config->ss_idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val = config->ss_pe_cmp[config->ss_idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1844,12 +1865,13 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->ss_idx;
config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
/* must clear bit 31 in related status register on programming */
config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(sshot_pe_ctrl);
@@ -1883,9 +1905,10 @@ static ssize_t ctxid_idx_store(struct device *dev,
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->ctxid_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(ctxid_idx);
@@ -1906,10 +1929,11 @@ static ssize_t ctxid_pid_show(struct device *dev,
if (task_active_pid_ns(current) != &init_pid_ns)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- idx = config->ctxid_idx;
- val = (unsigned long)config->ctxid_pid[idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ idx = config->ctxid_idx;
+ val = (unsigned long)config->ctxid_pid[idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1944,10 +1968,11 @@ static ssize_t ctxid_pid_store(struct device *dev,
if (kstrtoul(buf, 16, &pid))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
idx = config->ctxid_idx;
config->ctxid_pid[idx] = (u64)pid;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(ctxid_pid);
@@ -1967,10 +1992,11 @@ static ssize_t ctxid_masks_show(struct device *dev,
if (task_active_pid_ns(current) != &init_pid_ns)
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- val1 = config->ctxid_mask0;
- val2 = config->ctxid_mask1;
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val1 = config->ctxid_mask0;
+ val2 = config->ctxid_mask1;
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
}
@@ -2003,7 +2029,8 @@ static ssize_t ctxid_masks_store(struct device *dev,
if ((drvdata->numcidc > 4) && (nr_inputs != 2))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
/*
* each byte[0..3] controls mask value applied to ctxid
* comparator[0..3]
@@ -2075,7 +2102,6 @@ static ssize_t ctxid_masks_store(struct device *dev,
mask >>= 0x8;
}
- spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(ctxid_masks);
@@ -2109,9 +2135,10 @@ static ssize_t vmid_idx_store(struct device *dev,
* Use spinlock to ensure index doesn't change while it gets
* dereferenced multiple times within a spinlock block elsewhere.
*/
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->vmid_idx = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(vmid_idx);
@@ -2131,9 +2158,10 @@ static ssize_t vmid_val_show(struct device *dev,
if (!task_is_in_init_pid_ns(current))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- val = (unsigned long)config->vmid_val[config->vmid_idx];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val = (unsigned long)config->vmid_val[config->vmid_idx];
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -2161,9 +2189,10 @@ static ssize_t vmid_val_store(struct device *dev,
if (kstrtoul(buf, 16, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
config->vmid_val[config->vmid_idx] = (u64)val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(vmid_val);
@@ -2182,10 +2211,11 @@ static ssize_t vmid_masks_show(struct device *dev,
if (!task_is_in_init_pid_ns(current))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
- val1 = config->vmid_mask0;
- val2 = config->vmid_mask1;
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val1 = config->vmid_mask0;
+ val2 = config->vmid_mask1;
+ }
+
return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
}
@@ -2217,7 +2247,7 @@ static ssize_t vmid_masks_store(struct device *dev,
if ((drvdata->numvmidc > 4) && (nr_inputs != 2))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/*
* each byte[0..3] controls mask value applied to vmid
@@ -2290,7 +2320,7 @@ static ssize_t vmid_masks_store(struct device *dev,
else
mask >>= 0x8;
}
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(vmid_masks);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 9e9165f62e81..366f8f23a3e5 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -989,7 +989,7 @@ struct etmv4_drvdata {
struct clk *pclk;
void __iomem *base;
struct coresight_device *csdev;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
int cpu;
u8 arch;
u8 nr_pe;
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 3/9] coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
2024-11-25 9:48 ` [PATCH 1/9] coresight: change coresight_device lock " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-25 9:48 ` [PATCH 4/9] coresight-cti: change cti_drvdata spinlock's " Yeoreum Yun
` (7 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
coresight_trace_id_map->lock can be acquired while coresight devices'
drvdata_lock.
But the drvdata_lock can be raw_spinlock_t (i.e) coresight-etm4x.
To address this, change type of coresight_trace_id_map->lock to
raw_spinlock_t
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
drivers/hwtracing/coresight/coresight-core.c | 2 +-
.../hwtracing/coresight/coresight-trace-id.c | 93 +++++++++----------
include/linux/coresight.h | 2 +-
3 files changed, 44 insertions(+), 53 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index ea38ecf26fcb..cc2d87b2f248 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1164,7 +1164,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
- spin_lock_init(&csdev->perf_sink_id_map.lock);
+ raw_spin_lock_init(&csdev->perf_sink_id_map.lock);
csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
if (!csdev->perf_sink_id_map.cpu_map) {
kfree(csdev);
diff --git a/drivers/hwtracing/coresight/coresight-trace-id.c b/drivers/hwtracing/coresight/coresight-trace-id.c
index d98e12cb30ec..1818a353ac5f 100644
--- a/drivers/hwtracing/coresight/coresight-trace-id.c
+++ b/drivers/hwtracing/coresight/coresight-trace-id.c
@@ -16,7 +16,7 @@
static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0);
static struct coresight_trace_id_map id_map_default = {
.cpu_map = &id_map_default_cpu_ids,
- .lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock)
+ .lock = __RAW_SPIN_LOCK_UNLOCKED(id_map_default.lock)
};
/* #define TRACE_ID_DEBUG 1 */
@@ -118,50 +118,46 @@ static void coresight_trace_id_free(int id, struct coresight_trace_id_map *id_ma
*/
static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map)
{
- unsigned long flags;
int cpu;
- spin_lock_irqsave(&id_map->lock, flags);
- bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
- for_each_possible_cpu(cpu)
- atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
- spin_unlock_irqrestore(&id_map->lock, flags);
+ scoped_guard(raw_spinlock_irqsave, &id_map->lock) {
+ bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
+ for_each_possible_cpu(cpu)
+ atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
+ }
+
DUMP_ID_MAP(id_map);
}
static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
{
- unsigned long flags;
int id;
- spin_lock_irqsave(&id_map->lock, flags);
-
- /* check for existing allocation for this CPU */
- id = _coresight_trace_id_read_cpu_id(cpu, id_map);
- if (id)
- goto get_cpu_id_out_unlock;
-
- /*
- * Find a new ID.
- *
- * Use legacy values where possible in the dynamic trace ID allocator to
- * allow older tools to continue working if they are not upgraded at the
- * same time as the kernel drivers.
- *
- * If the generated legacy ID is invalid, or not available then the next
- * available dynamic ID will be used.
- */
- id = coresight_trace_id_alloc_new_id(id_map,
- CORESIGHT_LEGACY_CPU_TRACE_ID(cpu),
- false);
- if (!IS_VALID_CS_TRACE_ID(id))
- goto get_cpu_id_out_unlock;
-
- /* allocate the new id to the cpu */
- atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);
+ scoped_guard(raw_spinlock_irqsave, &id_map->lock) {
+ /* check for existing allocation for this CPU */
+ id = _coresight_trace_id_read_cpu_id(cpu, id_map);
+ if (id)
+ return id;
-get_cpu_id_out_unlock:
- spin_unlock_irqrestore(&id_map->lock, flags);
+ /*
+ * Find a new ID.
+ *
+ * Use legacy values where possible in the dynamic trace ID allocator to
+ * allow older tools to continue working if they are not upgraded at the
+ * same time as the kernel drivers.
+ *
+ * If the generated legacy ID is invalid, or not available then the next
+ * available dynamic ID will be used.
+ */
+ id = coresight_trace_id_alloc_new_id(id_map,
+ CORESIGHT_LEGACY_CPU_TRACE_ID(cpu),
+ false);
+ if (!IS_VALID_CS_TRACE_ID(id))
+ return id;
+
+ /* allocate the new id to the cpu */
+ atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);
+ }
DUMP_ID_CPU(cpu, id);
DUMP_ID_MAP(id_map);
@@ -170,7 +166,6 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map
static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
{
- unsigned long flags;
int id;
/* check for existing allocation for this CPU */
@@ -178,25 +173,23 @@ static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_ma
if (!id)
return;
- spin_lock_irqsave(&id_map->lock, flags);
-
- coresight_trace_id_free(id, id_map);
- atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
+ scoped_guard(raw_spinlock_irqsave, &id_map->lock) {
+ coresight_trace_id_free(id, id_map);
+ atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
+ }
- spin_unlock_irqrestore(&id_map->lock, flags);
DUMP_ID_CPU(cpu, id);
DUMP_ID_MAP(id_map);
}
static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *id_map)
{
- unsigned long flags;
int id;
- spin_lock_irqsave(&id_map->lock, flags);
- /* prefer odd IDs for system components to avoid legacy CPU IDS */
- id = coresight_trace_id_alloc_new_id(id_map, 0, true);
- spin_unlock_irqrestore(&id_map->lock, flags);
+ scoped_guard(raw_spinlock_irqsave, &id_map->lock) {
+ /* prefer odd IDs for system components to avoid legacy CPU IDS */
+ id = coresight_trace_id_alloc_new_id(id_map, 0, true);
+ }
DUMP_ID(id);
DUMP_ID_MAP(id_map);
@@ -205,11 +198,9 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i
static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *id_map, int id)
{
- unsigned long flags;
-
- spin_lock_irqsave(&id_map->lock, flags);
- coresight_trace_id_free(id, id_map);
- spin_unlock_irqrestore(&id_map->lock, flags);
+ scoped_guard(raw_spinlock_irqsave, &id_map->lock) {
+ coresight_trace_id_free(id, id_map);
+ }
DUMP_ID(id);
DUMP_ID_MAP(id_map);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 924b58c343b3..6446ca1f09d8 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -233,7 +233,7 @@ struct coresight_trace_id_map {
DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX);
atomic_t __percpu *cpu_map;
atomic_t perf_cs_etm_session_active;
- spinlock_t lock;
+ raw_spinlock_t lock;
};
/**
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 4/9] coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (2 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 3/9] coresight: change coresight_trace_id_map's lock " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-25 9:48 ` [PATCH 5/9] coresight-etb10: change etb_drvdata " Yeoreum Yun
` (6 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In coresight-cti drivers, cti_drvdata->spinlock can be held during __schedule()
by perf_event_task_sched_out()/in().
Since cti_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type cti_drvdata->spinlock in coresight-cti drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
.../hwtracing/coresight/coresight-cti-core.c | 65 +++------
.../hwtracing/coresight/coresight-cti-sysfs.c | 135 ++++++++++--------
drivers/hwtracing/coresight/coresight-cti.h | 2 +-
3 files changed, 96 insertions(+), 106 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index d2b5a5718c29..1f7766e9a2ea 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -90,10 +90,9 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
static int cti_enable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
- unsigned long flags;
int rc = 0;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* no need to do anything if enabled or unpowered*/
if (config->hw_enabled || !config->hw_powered)
@@ -108,7 +107,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
config->hw_enabled = true;
drvdata->config.enable_req_count++;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return rc;
cti_state_unchanged:
@@ -116,7 +114,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
/* cannot enable due to error */
cti_err_not_enabled:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return rc;
}
@@ -125,25 +122,20 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
config->hw_powered = true;
/* no need to do anything if no enable request */
if (!drvdata->config.enable_req_count)
- goto cti_hp_not_enabled;
+ return;
/* try to claim the device */
if (coresight_claim_device(drvdata->csdev))
- goto cti_hp_not_enabled;
+ return;
cti_write_all_hw_regs(drvdata);
config->hw_enabled = true;
- spin_unlock(&drvdata->spinlock);
return;
-
- /* did not re-enable due to no claim / no request */
-cti_hp_not_enabled:
- spin_unlock(&drvdata->spinlock);
}
/* disable hardware */
@@ -151,23 +143,20 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
- int ret = 0;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* don't allow negative refcounts, return an error */
- if (!drvdata->config.enable_req_count) {
- ret = -EINVAL;
- goto cti_not_disabled;
- }
+ if (!drvdata->config.enable_req_count)
+ return -EINVAL;
/* check refcount - disable on 0 */
if (--drvdata->config.enable_req_count > 0)
- goto cti_not_disabled;
+ return 0;
/* no need to do anything if disabled or cpu unpowered */
if (!config->hw_enabled || !config->hw_powered)
- goto cti_not_disabled;
+ return 0;
CS_UNLOCK(drvdata->base);
@@ -177,13 +166,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
- spin_unlock(&drvdata->spinlock);
- return ret;
-
- /* not disabled this call */
-cti_not_disabled:
- spin_unlock(&drvdata->spinlock);
- return ret;
+ return 0;
}
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)
@@ -198,11 +181,11 @@ void cti_write_intack(struct device *dev, u32 ackval)
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
/* write if enabled */
if (cti_active(config))
cti_write_single_reg(drvdata, CTIINTACK, ackval);
- spin_unlock(&drvdata->spinlock);
}
/*
@@ -369,7 +352,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
CTIOUTEN(trigger_idx));
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* read - modify write - the trigger / channel enable value */
reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
@@ -388,7 +371,6 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
/* write through if enabled */
if (cti_active(config))
cti_write_single_reg(drvdata, reg_offset, reg_value);
- spin_unlock(&drvdata->spinlock);
return 0;
}
@@ -406,7 +388,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
chan_bitmask = BIT(channel_idx);
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
reg_value = config->ctigate;
switch (op) {
case CTI_GATE_CHAN_ENABLE:
@@ -426,7 +409,6 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
if (cti_active(config))
cti_write_single_reg(drvdata, CTIGATE, reg_value);
}
- spin_unlock(&drvdata->spinlock);
return err;
}
@@ -445,7 +427,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
chan_bitmask = BIT(channel_idx);
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
reg_value = config->ctiappset;
switch (op) {
case CTI_CHAN_SET:
@@ -473,7 +456,6 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
if ((err == 0) && cti_active(config))
cti_write_single_reg(drvdata, reg_offset, reg_value);
- spin_unlock(&drvdata->spinlock);
return err;
}
@@ -676,7 +658,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
return NOTIFY_BAD;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
switch (cmd) {
case CPU_PM_ENTER:
@@ -703,7 +685,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
if (drvdata->config.enable_req_count) {
/* check we can claim the device as we re-power */
if (coresight_claim_device(csdev))
- goto cti_notify_exit;
+ return notify_res;
drvdata->config.hw_enabled = true;
cti_write_all_hw_regs(drvdata);
@@ -715,8 +697,6 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
break;
}
-cti_notify_exit:
- spin_unlock(&drvdata->spinlock);
return notify_res;
}
@@ -743,11 +723,12 @@ static int cti_dying_cpu(unsigned int cpu)
if (!drvdata)
return 0;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
coresight_disclaim_device(drvdata->csdev);
- spin_unlock(&drvdata->spinlock);
+
return 0;
}
@@ -888,7 +869,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->ctidev.ctm_id = 0;
INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
/* initialise CTI driver config values */
cti_set_default_config(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index d25dd2737b49..fa149b94a495 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -84,11 +84,11 @@ static ssize_t enable_show(struct device *dev,
bool enabled, powered;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- spin_lock(&drvdata->spinlock);
- enable_req = drvdata->config.enable_req_count;
- powered = drvdata->config.hw_powered;
- enabled = drvdata->config.hw_enabled;
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ enable_req = drvdata->config.enable_req_count;
+ powered = drvdata->config.hw_powered;
+ enabled = drvdata->config.hw_enabled;
+ }
if (powered)
return sprintf(buf, "%d\n", enabled);
@@ -134,9 +134,9 @@ static ssize_t powered_show(struct device *dev,
bool powered;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- spin_lock(&drvdata->spinlock);
- powered = drvdata->config.hw_powered;
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ powered = drvdata->config.hw_powered;
+ }
return sprintf(buf, "%d\n", powered);
}
@@ -181,10 +181,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
u32 val = 0;
pm_runtime_get_sync(dev->parent);
- spin_lock(&drvdata->spinlock);
- if (drvdata->config.hw_powered)
- val = readl_relaxed(drvdata->base + cti_attr->off);
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ if (drvdata->config.hw_powered)
+ val = readl_relaxed(drvdata->base + cti_attr->off);
+ }
pm_runtime_put_sync(dev->parent);
return sysfs_emit(buf, "0x%x\n", val);
}
@@ -202,10 +202,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
return -EINVAL;
pm_runtime_get_sync(dev->parent);
- spin_lock(&drvdata->spinlock);
- if (drvdata->config.hw_powered)
- cti_write_single_reg(drvdata, cti_attr->off, val);
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ if (drvdata->config.hw_powered)
+ cti_write_single_reg(drvdata, cti_attr->off, val);
+ }
pm_runtime_put_sync(dev->parent);
return size;
}
@@ -264,17 +264,18 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
- if ((reg_offset >= 0) && cti_active(config)) {
- CS_UNLOCK(drvdata->base);
- val = readl_relaxed(drvdata->base + reg_offset);
- if (pcached_val)
- *pcached_val = val;
- CS_LOCK(drvdata->base);
- } else if (pcached_val) {
- val = *pcached_val;
+ scoped_guard (raw_spinlock, &drvdata->spinlock) {
+ if ((reg_offset >= 0) && cti_active(config)) {
+ CS_UNLOCK(drvdata->base);
+ val = readl_relaxed(drvdata->base + reg_offset);
+ if (pcached_val)
+ *pcached_val = val;
+ CS_LOCK(drvdata->base);
+ } else if (pcached_val) {
+ val = *pcached_val;
+ }
}
- spin_unlock(&drvdata->spinlock);
+
return sprintf(buf, "%#x\n", val);
}
@@ -293,7 +294,8 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
/* local store */
if (pcached_val)
*pcached_val = (u32)val;
@@ -301,7 +303,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
/* write through if offset and enabled */
if ((reg_offset >= 0) && cti_active(config))
cti_write_single_reg(drvdata, reg_offset, val);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
@@ -349,9 +351,10 @@ static ssize_t inout_sel_store(struct device *dev,
if (val > (CTIINOUTEN_MAX - 1))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
drvdata->config.ctiinout_sel = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(inout_sel);
@@ -364,10 +367,11 @@ static ssize_t inen_show(struct device *dev,
int index;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- spin_lock(&drvdata->spinlock);
- index = drvdata->config.ctiinout_sel;
- val = drvdata->config.ctiinen[index];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ index = drvdata->config.ctiinout_sel;
+ val = drvdata->config.ctiinen[index];
+ }
+
return sprintf(buf, "%#lx\n", val);
}
@@ -383,14 +387,15 @@ static ssize_t inen_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
index = config->ctiinout_sel;
config->ctiinen[index] = val;
/* write through if enabled */
if (cti_active(config))
cti_write_single_reg(drvdata, CTIINEN(index), val);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(inen);
@@ -403,10 +408,11 @@ static ssize_t outen_show(struct device *dev,
int index;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- spin_lock(&drvdata->spinlock);
- index = drvdata->config.ctiinout_sel;
- val = drvdata->config.ctiouten[index];
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ index = drvdata->config.ctiinout_sel;
+ val = drvdata->config.ctiouten[index];
+ }
+
return sprintf(buf, "%#lx\n", val);
}
@@ -422,14 +428,15 @@ static ssize_t outen_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
index = config->ctiinout_sel;
config->ctiouten[index] = val;
/* write through if enabled */
if (cti_active(config))
cti_write_single_reg(drvdata, CTIOUTEN(index), val);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(outen);
@@ -463,7 +470,7 @@ static ssize_t appclear_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* a 1'b1 in appclr clears down the same bit in appset*/
config->ctiappset &= ~val;
@@ -471,7 +478,7 @@ static ssize_t appclear_store(struct device *dev,
/* write through if enabled */
if (cti_active(config))
cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_WO(appclear);
@@ -487,12 +494,12 @@ static ssize_t apppulse_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* write through if enabled */
if (cti_active(config))
cti_write_single_reg(drvdata, CTIAPPPULSE, val);
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_WO(apppulse);
@@ -681,9 +688,10 @@ static ssize_t trig_filter_enable_show(struct device *dev,
u32 val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- spin_lock(&drvdata->spinlock);
- val = drvdata->config.trig_filter_enable;
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val = drvdata->config.trig_filter_enable;
+ }
+
return sprintf(buf, "%d\n", val);
}
@@ -697,9 +705,10 @@ static ssize_t trig_filter_enable_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
drvdata->config.trig_filter_enable = !!val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(trig_filter_enable);
@@ -728,7 +737,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* clear the CTI trigger / channel programming registers */
for (i = 0; i < config->nr_trig_max; i++) {
@@ -747,7 +756,6 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
if (cti_active(config))
cti_write_all_hw_regs(drvdata);
- spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_WO(chan_xtrigs_reset);
@@ -768,9 +776,10 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev,
if (val > (drvdata->config.nr_ctm_channels - 1))
return -EINVAL;
- spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
+
drvdata->config.xtrig_rchan_sel = val;
- spin_unlock(&drvdata->spinlock);
+
return size;
}
@@ -781,9 +790,9 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev,
unsigned long val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- spin_lock(&drvdata->spinlock);
- val = drvdata->config.xtrig_rchan_sel;
- spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ val = drvdata->config.xtrig_rchan_sel;
+ }
return sprintf(buf, "%ld\n", val);
}
@@ -838,12 +847,12 @@ static ssize_t print_chan_list(struct device *dev,
unsigned long inuse_bits = 0, chan_mask;
/* scan regs to get bitmap of channels in use. */
- spin_lock(&drvdata->spinlock);
- for (i = 0; i < config->nr_trig_max; i++) {
- inuse_bits |= config->ctiinen[i];
- inuse_bits |= config->ctiouten[i];
+ scoped_guard(raw_spinlock, &drvdata->spinlock) {
+ for (i = 0; i < config->nr_trig_max; i++) {
+ inuse_bits |= config->ctiinen[i];
+ inuse_bits |= config->ctiouten[i];
+ }
}
- spin_unlock(&drvdata->spinlock);
/* inverse bits if printing free channels */
if (!inuse)
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index cb9ee616d01f..16e310e7e9d4 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -175,7 +175,7 @@ struct cti_drvdata {
void __iomem *base;
struct coresight_device *csdev;
struct cti_device ctidev;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
struct cti_config config;
struct list_head node;
void (*csdev_release)(struct device *dev);
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 5/9] coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (3 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 4/9] coresight-cti: change cti_drvdata spinlock's " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-25 9:48 ` [PATCH 6/9] coresight-funnel: change funnel_drvdata " Yeoreum Yun
` (5 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In coresight-etb10 drivers, etb_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().
Since etb_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type etb_drvdata->spinlock in coresight-etb10 drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
drivers/hwtracing/coresight/coresight-etb10.c | 62 +++++++------------
1 file changed, 22 insertions(+), 40 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index aea9ac9c4bd0..ec439f8fbc1e 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -84,7 +84,7 @@ struct etb_drvdata {
struct clk *atclk;
struct coresight_device *csdev;
struct miscdevice miscdev;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
local_t reading;
pid_t pid;
u8 *buf;
@@ -141,56 +141,47 @@ static int etb_enable_hw(struct etb_drvdata *drvdata)
static int etb_enable_sysfs(struct coresight_device *csdev)
{
- int ret = 0;
- unsigned long flags;
+ int ret;
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* Don't messup with perf sessions. */
- if (coresight_get_mode(csdev) == CS_MODE_PERF) {
- ret = -EBUSY;
- goto out;
- }
+ if (coresight_get_mode(csdev) == CS_MODE_PERF)
+ return -EBUSY;
if (coresight_get_mode(csdev) == CS_MODE_DISABLED) {
ret = etb_enable_hw(drvdata);
if (ret)
- goto out;
+ return ret;
coresight_set_mode(csdev, CS_MODE_SYSFS);
}
csdev->refcnt++;
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return ret;
+
+ return 0;
}
static int etb_enable_perf(struct coresight_device *csdev, void *data)
{
- int ret = 0;
+ int ret;
pid_t pid;
- unsigned long flags;
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct perf_output_handle *handle = data;
struct cs_buffers *buf = etm_perf_sink_config(handle);
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* No need to continue if the component is already in used by sysFS. */
- if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
- ret = -EBUSY;
- goto out;
- }
+ if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
+ return -EBUSY;
/* Get a handle on the pid of the process to monitor */
pid = buf->pid;
- if (drvdata->pid != -1 && drvdata->pid != pid) {
- ret = -EBUSY;
- goto out;
- }
+ if (drvdata->pid != -1 && drvdata->pid != pid)
+ return -EBUSY;
/*
* No HW configuration is needed if the sink is already in
@@ -198,7 +189,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
*/
if (drvdata->pid == pid) {
csdev->refcnt++;
- goto out;
+ return 0;
}
/*
@@ -208,7 +199,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
*/
ret = etb_set_buffer(csdev, handle);
if (ret)
- goto out;
+ return ret;
ret = etb_enable_hw(drvdata);
if (!ret) {
@@ -218,8 +209,6 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
csdev->refcnt++;
}
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return ret;
}
@@ -350,13 +339,11 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
static int etb_disable(struct coresight_device *csdev)
{
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- unsigned long flags;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
csdev->refcnt--;
if (csdev->refcnt) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return -EBUSY;
}
@@ -366,7 +353,6 @@ static int etb_disable(struct coresight_device *csdev)
/* Dissociate from monitored process. */
drvdata->pid = -1;
coresight_set_mode(csdev, CS_MODE_DISABLED);
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_dbg(&csdev->dev, "ETB disabled\n");
return 0;
@@ -434,7 +420,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
const u32 *barrier;
u32 read_ptr, write_ptr, capacity;
u32 status, read_data;
- unsigned long offset, to_read = 0, flags;
+ unsigned long offset, to_read = 0;
struct cs_buffers *buf = sink_config;
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -443,11 +429,11 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* Don't do anything if another tracer is using this sink */
if (csdev->refcnt != 1)
- goto out;
+ return 0;
__etb_disable_hw(drvdata);
CS_UNLOCK(drvdata->base);
@@ -565,8 +551,6 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
__etb_enable_hw(drvdata);
CS_LOCK(drvdata->base);
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return to_read;
}
@@ -585,15 +569,13 @@ static const struct coresight_ops etb_cs_ops = {
static void etb_dump(struct etb_drvdata *drvdata)
{
- unsigned long flags;
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
- spin_lock_irqsave(&drvdata->spinlock, flags);
if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
__etb_disable_hw(drvdata);
etb_dump_hw(drvdata);
__etb_enable_hw(drvdata);
}
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_dbg(&drvdata->csdev->dev, "ETB dumped\n");
}
@@ -746,7 +728,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 6/9] coresight-funnel: change funnel_drvdata spinlock's type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (4 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 5/9] coresight-etb10: change etb_drvdata " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-25 9:48 ` [PATCH 7/9] coresight-replicator: change replicator_drvdata " Yeoreum Yun
` (4 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In coresight-funnel drivers, cti_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().
Since funnel_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type funnel_drvdata->spinlock in
coresight-funnel drivers, which can be called by
perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
.../hwtracing/coresight/coresight-funnel.c | 34 +++++++++----------
1 file changed, 16 insertions(+), 18 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 5a819c8970fb..dbc2891a10e1 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -47,7 +47,7 @@ struct funnel_drvdata {
struct clk *pclk;
struct coresight_device *csdev;
unsigned long priority;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
};
static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
@@ -82,19 +82,18 @@ static int funnel_enable(struct coresight_device *csdev,
{
int rc = 0;
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- unsigned long flags;
bool first_enable = false;
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_read(&in->dest_refcnt) == 0) {
- if (drvdata->base)
- rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (atomic_read(&in->dest_refcnt) == 0) {
+ if (drvdata->base)
+ rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
+ if (!rc)
+ first_enable = true;
+ }
if (!rc)
- first_enable = true;
+ atomic_inc(&in->dest_refcnt);
}
- if (!rc)
- atomic_inc(&in->dest_refcnt);
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n",
@@ -126,16 +125,15 @@ static void funnel_disable(struct coresight_device *csdev,
struct coresight_connection *out)
{
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- unsigned long flags;
bool last_disable = false;
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_dec_return(&in->dest_refcnt) == 0) {
- if (drvdata->base)
- dynamic_funnel_disable_hw(drvdata, in->dest_port);
- last_disable = true;
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (atomic_dec_return(&in->dest_refcnt) == 0) {
+ if (drvdata->base)
+ dynamic_funnel_disable_hw(drvdata, in->dest_port);
+ last_disable = true;
+ }
}
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (last_disable)
dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n",
@@ -266,7 +264,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
}
dev->platform_data = pdata;
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
desc.type = CORESIGHT_DEV_TYPE_LINK;
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
desc.ops = &funnel_cs_ops;
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 7/9] coresight-replicator: change replicator_drvdata spinlock's type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (5 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 6/9] coresight-funnel: change funnel_drvdata " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-25 9:48 ` [PATCH 8/9] coresight-tmc: change tmc_drvdata " Yeoreum Yun
` (3 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In coresight-replicator drivers, replicator_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().
Since replicator_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type replicator_drvdata->spinlock in
coresight-replicator drivers, which can be called
by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
.../coresight/coresight-replicator.c | 36 +++++++++----------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 3e55be9c8418..7ff08fb70758 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -41,7 +41,7 @@ struct replicator_drvdata {
struct clk *atclk;
struct clk *pclk;
struct coresight_device *csdev;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
bool check_idfilter_val;
};
@@ -122,20 +122,19 @@ static int replicator_enable(struct coresight_device *csdev,
{
int rc = 0;
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- unsigned long flags;
bool first_enable = false;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
if (atomic_read(&out->src_refcnt) == 0) {
- if (drvdata->base)
- rc = dynamic_replicator_enable(drvdata, in->dest_port,
- out->src_port);
+ if (drvdata->base)
+ rc = dynamic_replicator_enable(drvdata, in->dest_port,
+ out->src_port);
+ if (!rc)
+ first_enable = true;
+ }
if (!rc)
- first_enable = true;
+ atomic_inc(&out->src_refcnt);
}
- if (!rc)
- atomic_inc(&out->src_refcnt);
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
dev_dbg(&csdev->dev, "REPLICATOR enabled\n");
@@ -176,17 +175,16 @@ static void replicator_disable(struct coresight_device *csdev,
struct coresight_connection *out)
{
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- unsigned long flags;
bool last_disable = false;
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (atomic_dec_return(&out->src_refcnt) == 0) {
- if (drvdata->base)
- dynamic_replicator_disable(drvdata, in->dest_port,
- out->src_port);
- last_disable = true;
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (atomic_dec_return(&out->src_refcnt) == 0) {
+ if (drvdata->base)
+ dynamic_replicator_disable(drvdata, in->dest_port,
+ out->src_port);
+ last_disable = true;
+ }
}
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (last_disable)
dev_dbg(&csdev->dev, "REPLICATOR disabled\n");
@@ -277,7 +275,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
}
dev->platform_data = pdata;
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
desc.type = CORESIGHT_DEV_TYPE_LINK;
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
desc.ops = &replicator_cs_ops;
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 8/9] coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (6 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 7/9] coresight-replicator: change replicator_drvdata " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-25 9:48 ` [PATCH 9/9] coresight/ultrasoc: change cti_drvdata " Yeoreum Yun
` (2 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In coresight-tmc drivers, tmc_drvdata->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().
Since tmc_drvdata->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type tmc_drvdata->spinlock in coresight-tmc drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
.../hwtracing/coresight/coresight-tmc-core.c | 9 +-
.../hwtracing/coresight/coresight-tmc-etf.c | 195 +++++++----------
.../hwtracing/coresight/coresight-tmc-etr.c | 199 ++++++++----------
drivers/hwtracing/coresight/coresight-tmc.h | 2 +-
4 files changed, 169 insertions(+), 236 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index 3a482fd2cb22..d6499eb14745 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -492,7 +492,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
drvdata->config_type = BMVAL(devid, 6, 7);
@@ -593,13 +593,12 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
static void tmc_shutdown(struct amba_device *adev)
{
- unsigned long flags;
struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
if (coresight_get_mode(drvdata->csdev) == CS_MODE_DISABLED)
- goto out;
+ return;
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
tmc_etr_disable_hw(drvdata);
@@ -609,8 +608,6 @@ static void tmc_shutdown(struct amba_device *adev)
* callback which is required for making coresight modular since
* the system is going down after this.
*/
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
}
static void __tmc_remove(struct device *dev)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index d4f641cd9de6..b2f97defbba2 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -182,9 +182,9 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
* If we don't have a buffer release the lock and allocate memory.
* Otherwise keep the lock and move along.
*/
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
if (!drvdata->buf) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
/* Allocating the memory here while outside of the spinlock */
buf = kzalloc(drvdata->size, GFP_KERNEL);
@@ -192,7 +192,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
return -ENOMEM;
/* Let's try again */
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
}
if (drvdata->reading) {
@@ -235,7 +235,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
used = false;
}
out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
/* Free memory outside the spinlock if need be */
if (!used)
@@ -248,12 +248,12 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
{
int ret = 0;
pid_t pid;
- unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct perf_output_handle *handle = data;
struct cs_buffers *buf = etm_perf_sink_config(handle);
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
do {
ret = -EINVAL;
if (drvdata->reading)
@@ -296,7 +296,6 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
csdev->refcnt++;
}
} while (0);
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return ret;
}
@@ -328,31 +327,24 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev,
static int tmc_disable_etf_sink(struct coresight_device *csdev)
{
- unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (drvdata->reading)
+ return -EBUSY;
- if (drvdata->reading) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
- }
+ csdev->refcnt--;
+ if (csdev->refcnt)
+ return -EBUSY;
- csdev->refcnt--;
- if (csdev->refcnt) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
+ /* Complain if we (somehow) got out of sync */
+ WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
+ tmc_etb_disable_hw(drvdata);
+ /* Dissociate from monitored process. */
+ drvdata->pid = -1;
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
}
- /* Complain if we (somehow) got out of sync */
- WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
- tmc_etb_disable_hw(drvdata);
- /* Dissociate from monitored process. */
- drvdata->pid = -1;
- coresight_set_mode(csdev, CS_MODE_DISABLED);
-
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
dev_dbg(&csdev->dev, "TMC-ETB/ETF disabled\n");
return 0;
}
@@ -362,26 +354,23 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
struct coresight_connection *out)
{
int ret = 0;
- unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
bool first_enable = false;
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
- }
-
- if (csdev->refcnt == 0) {
- ret = tmc_etf_enable_hw(drvdata);
- if (!ret) {
- coresight_set_mode(csdev, CS_MODE_SYSFS);
- first_enable = true;
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (drvdata->reading)
+ return -EBUSY;
+
+ if (csdev->refcnt == 0) {
+ ret = tmc_etf_enable_hw(drvdata);
+ if (!ret) {
+ coresight_set_mode(csdev, CS_MODE_SYSFS);
+ first_enable = true;
+ }
}
+ if (!ret)
+ csdev->refcnt++;
}
- if (!ret)
- csdev->refcnt++;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
dev_dbg(&csdev->dev, "TMC-ETF enabled\n");
@@ -392,23 +381,20 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
struct coresight_connection *in,
struct coresight_connection *out)
{
- unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
bool last_disable = false;
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return;
- }
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (drvdata->reading)
+ return;
- csdev->refcnt--;
- if (csdev->refcnt == 0) {
- tmc_etf_disable_hw(drvdata);
- coresight_set_mode(csdev, CS_MODE_DISABLED);
- last_disable = true;
+ csdev->refcnt--;
+ if (csdev->refcnt == 0) {
+ tmc_etf_disable_hw(drvdata);
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
+ last_disable = true;
+ }
}
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (last_disable)
dev_dbg(&csdev->dev, "TMC-ETF disabled\n");
@@ -477,7 +463,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
u32 *buf_ptr;
u64 read_ptr, write_ptr;
u32 status;
- unsigned long offset, to_read = 0, flags;
+ unsigned long offset, to_read = 0;
struct cs_buffers *buf = sink_config;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -488,11 +474,11 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
if (WARN_ON_ONCE(coresight_get_mode(csdev) != CS_MODE_PERF))
return 0;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* Don't do anything if another tracer is using this sink */
if (csdev->refcnt != 1)
- goto out;
+ return 0;
CS_UNLOCK(drvdata->base);
@@ -584,8 +570,6 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
* is expected by the perf ring buffer.
*/
CS_LOCK(drvdata->base);
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return to_read;
}
@@ -615,56 +599,43 @@ const struct coresight_ops tmc_etf_cs_ops = {
int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
{
enum tmc_mode mode;
- int ret = 0;
- unsigned long flags;
/* config types are set a boot time and never change */
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
drvdata->config_type != TMC_CONFIG_TYPE_ETF))
return -EINVAL;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
- if (drvdata->reading) {
- ret = -EBUSY;
- goto out;
- }
+ if (drvdata->reading)
+ return -EBUSY;
/* Don't interfere if operated from Perf */
- if (coresight_get_mode(drvdata->csdev) == CS_MODE_PERF) {
- ret = -EINVAL;
- goto out;
- }
+ if (coresight_get_mode(drvdata->csdev) == CS_MODE_PERF)
+ return -EINVAL;
/* If drvdata::buf is NULL the trace data has been read already */
- if (drvdata->buf == NULL) {
- ret = -EINVAL;
- goto out;
- }
+ if (drvdata->buf == NULL)
+ return -EINVAL;
/* Disable the TMC if need be */
if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
/* There is no point in reading a TMC in HW FIFO mode */
mode = readl_relaxed(drvdata->base + TMC_MODE);
- if (mode != TMC_MODE_CIRCULAR_BUFFER) {
- ret = -EINVAL;
- goto out;
- }
+ if (mode != TMC_MODE_CIRCULAR_BUFFER)
+ return -EINVAL;
__tmc_etb_disable_hw(drvdata);
}
drvdata->reading = true;
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return ret;
+ return 0;
}
int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
{
char *buf = NULL;
enum tmc_mode mode;
- unsigned long flags;
int rc = 0;
/* config types are set a boot time and never change */
@@ -672,41 +643,37 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
drvdata->config_type != TMC_CONFIG_TYPE_ETF))
return -EINVAL;
- spin_lock_irqsave(&drvdata->spinlock, flags);
-
- /* Re-enable the TMC if need be */
- if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
- /* There is no point in reading a TMC in HW FIFO mode */
- mode = readl_relaxed(drvdata->base + TMC_MODE);
- if (mode != TMC_MODE_CIRCULAR_BUFFER) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EINVAL;
- }
- /*
- * The trace run will continue with the same allocated trace
- * buffer. As such zero-out the buffer so that we don't end
- * up with stale data.
- *
- * Since the tracer is still enabled drvdata::buf
- * can't be NULL.
- */
- memset(drvdata->buf, 0, drvdata->size);
- rc = __tmc_etb_enable_hw(drvdata);
- if (rc) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return rc;
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ /* Re-enable the TMC if need be */
+ if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
+ /* There is no point in reading a TMC in HW FIFO mode */
+ mode = readl_relaxed(drvdata->base + TMC_MODE);
+ if (mode != TMC_MODE_CIRCULAR_BUFFER)
+ return -EINVAL;
+
+ /*
+ * The trace run will continue with the same allocated trace
+ * buffer. As such zero-out the buffer so that we don't end
+ * up with stale data.
+ *
+ * Since the tracer is still enabled drvdata::buf
+ * can't be NULL.
+ */
+ memset(drvdata->buf, 0, drvdata->size);
+ rc = __tmc_etb_enable_hw(drvdata);
+ if (rc)
+ return rc;
+ } else {
+ /*
+ * The ETB/ETF is not tracing and the buffer was just read.
+ * As such prepare to free the trace buffer.
+ */
+ buf = drvdata->buf;
+ drvdata->buf = NULL;
}
- } else {
- /*
- * The ETB/ETF is not tracing and the buffer was just read.
- * As such prepare to free the trace buffer.
- */
- buf = drvdata->buf;
- drvdata->buf = NULL;
- }
- drvdata->reading = false;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ drvdata->reading = false;
+ }
/*
* Free allocated memory outside of the spinlock. There is no need
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index a48bb85d0e7f..6672bea4d2b9 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1176,10 +1176,10 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
* buffer, provided the size matches. Any allocation has to be done
* with the lock released.
*/
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
/* Allocate memory with the locks released */
free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata);
@@ -1187,7 +1187,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
return new_buf;
/* Let's try again */
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
}
if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) {
@@ -1206,7 +1206,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
}
out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
/* Free memory outside the spinlock if need be */
if (free_buf)
@@ -1216,35 +1216,31 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
{
- int ret = 0;
- unsigned long flags;
+ int ret;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev);
if (IS_ERR(sysfs_buf))
return PTR_ERR(sysfs_buf);
- spin_lock_irqsave(&drvdata->spinlock, flags);
-
- /*
- * In sysFS mode we can have multiple writers per sink. Since this
- * sink is already enabled no memory is needed and the HW need not be
- * touched, even if the buffer size has changed.
- */
- if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
- csdev->refcnt++;
- goto out;
- }
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ /*
+ * In sysFS mode we can have multiple writers per sink. Since this
+ * sink is already enabled no memory is needed and the HW need not be
+ * touched, even if the buffer size has changed.
+ */
+ if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
+ csdev->refcnt++;
+ return 0;
+ }
- ret = tmc_etr_enable_hw(drvdata, sysfs_buf);
- if (!ret) {
- coresight_set_mode(csdev, CS_MODE_SYSFS);
- csdev->refcnt++;
+ ret = tmc_etr_enable_hw(drvdata, sysfs_buf);
+ if (!ret) {
+ coresight_set_mode(csdev, CS_MODE_SYSFS);
+ csdev->refcnt++;
+ }
}
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
if (!ret)
dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
@@ -1557,32 +1553,28 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
void *config)
{
bool lost = false;
- unsigned long flags, offset, size = 0;
+ unsigned long offset, size = 0;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct etr_perf_buffer *etr_perf = config;
struct etr_buf *etr_buf = etr_perf->etr_buf;
- spin_lock_irqsave(&drvdata->spinlock, flags);
-
- /* Don't do anything if another tracer is using this sink */
- if (csdev->refcnt != 1) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- goto out;
- }
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ /* Don't do anything if another tracer is using this sink */
+ if (csdev->refcnt != 1)
+ goto out;
- if (WARN_ON(drvdata->perf_buf != etr_buf)) {
- lost = true;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- goto out;
- }
+ if (WARN_ON(drvdata->perf_buf != etr_buf)) {
+ lost = true;
+ goto out;
+ }
- CS_UNLOCK(drvdata->base);
+ CS_UNLOCK(drvdata->base);
- tmc_flush_and_stop(drvdata);
- tmc_sync_etr_buf(drvdata);
+ tmc_flush_and_stop(drvdata);
+ tmc_sync_etr_buf(drvdata);
- CS_LOCK(drvdata->base);
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ CS_LOCK(drvdata->base);
+ }
lost = etr_buf->full;
offset = etr_buf->offset;
@@ -1644,33 +1636,27 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
{
- int rc = 0;
+ int rc;
pid_t pid;
- unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct perf_output_handle *handle = data;
struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle);
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
/* Don't use this sink if it is already claimed by sysFS */
- if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
- rc = -EBUSY;
- goto unlock_out;
- }
+ if (coresight_get_mode(csdev) == CS_MODE_SYSFS)
+ return -EBUSY;
- if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) {
- rc = -EINVAL;
- goto unlock_out;
- }
+ if (WARN_ON(!etr_perf || !etr_perf->etr_buf))
+ return -EINVAL;
/* Get a handle on the pid of the session owner */
pid = etr_perf->pid;
/* Do not proceed if this device is associated with another session */
- if (drvdata->pid != -1 && drvdata->pid != pid) {
- rc = -EBUSY;
- goto unlock_out;
- }
+ if (drvdata->pid != -1 && drvdata->pid != pid)
+ return -EBUSY;
/*
* No HW configuration is needed if the sink is already in
@@ -1678,7 +1664,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
*/
if (drvdata->pid == pid) {
csdev->refcnt++;
- goto unlock_out;
+ return 0;
}
rc = tmc_etr_enable_hw(drvdata, etr_perf->etr_buf);
@@ -1690,8 +1676,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
csdev->refcnt++;
}
-unlock_out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return rc;
}
@@ -1710,33 +1694,26 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev,
static int tmc_disable_etr_sink(struct coresight_device *csdev)
{
- unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- spin_lock_irqsave(&drvdata->spinlock, flags);
-
- if (drvdata->reading) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
- }
-
- csdev->refcnt--;
- if (csdev->refcnt) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (drvdata->reading)
+ return -EBUSY;
+
+ csdev->refcnt--;
+ if (csdev->refcnt)
+ return -EBUSY;
+
+ /* Complain if we (somehow) got out of sync */
+ WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
+ tmc_etr_disable_hw(drvdata);
+ /* Dissociate from monitored process. */
+ drvdata->pid = -1;
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
+ /* Reset perf specific data */
+ drvdata->perf_buf = NULL;
}
- /* Complain if we (somehow) got out of sync */
- WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
- tmc_etr_disable_hw(drvdata);
- /* Dissociate from monitored process. */
- drvdata->pid = -1;
- coresight_set_mode(csdev, CS_MODE_DISABLED);
- /* Reset perf specific data */
- drvdata->perf_buf = NULL;
-
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
dev_dbg(&csdev->dev, "TMC-ETR disabled\n");
return 0;
}
@@ -1756,70 +1733,62 @@ const struct coresight_ops tmc_etr_cs_ops = {
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
{
int ret = 0;
- unsigned long flags;
/* config types are set a boot time and never change */
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
return -EINVAL;
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- ret = -EBUSY;
- goto out;
- }
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
+ if (drvdata->reading)
+ return -EBUSY;
/*
* We can safely allow reads even if the ETR is operating in PERF mode,
* since the sysfs session is captured in mode specific data.
* If drvdata::sysfs_data is NULL the trace data has been read already.
*/
- if (!drvdata->sysfs_buf) {
- ret = -EINVAL;
- goto out;
- }
+ if (!drvdata->sysfs_buf)
+ return -EINVAL;
/* Disable the TMC if we are trying to read from a running session. */
if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
__tmc_etr_disable_hw(drvdata);
drvdata->reading = true;
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
return ret;
}
int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
{
- unsigned long flags;
struct etr_buf *sysfs_buf = NULL;
/* config types are set a boot time and never change */
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
return -EINVAL;
- spin_lock_irqsave(&drvdata->spinlock, flags);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ /* RE-enable the TMC if need be */
+ if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
+ /*
+ * The trace run will continue with the same allocated trace
+ * buffer. Since the tracer is still enabled drvdata::buf can't
+ * be NULL.
+ */
+ __tmc_etr_enable_hw(drvdata);
+ } else {
+ /*
+ * The ETR is not tracing and the buffer was just read.
+ * As such prepare to free the trace buffer.
+ */
+ sysfs_buf = drvdata->sysfs_buf;
+ drvdata->sysfs_buf = NULL;
+ }
- /* RE-enable the TMC if need be */
- if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
- /*
- * The trace run will continue with the same allocated trace
- * buffer. Since the tracer is still enabled drvdata::buf can't
- * be NULL.
- */
- __tmc_etr_enable_hw(drvdata);
- } else {
- /*
- * The ETR is not tracing and the buffer was just read.
- * As such prepare to free the trace buffer.
- */
- sysfs_buf = drvdata->sysfs_buf;
- drvdata->sysfs_buf = NULL;
+ drvdata->reading = false;
}
- drvdata->reading = false;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
/* Free allocated memory out side of the spinlock */
if (sysfs_buf)
tmc_etr_free_sysfs_buf(sysfs_buf);
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 2671926be62a..60b395025bc4 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -195,7 +195,7 @@ struct tmc_drvdata {
void __iomem *base;
struct coresight_device *csdev;
struct miscdevice miscdev;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
pid_t pid;
bool reading;
union {
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 9/9] coresight/ultrasoc: change cti_drvdata spinlock's type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (7 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 8/9] coresight-tmc: change tmc_drvdata " Yeoreum Yun
@ 2024-11-25 9:48 ` Yeoreum Yun
2024-11-27 16:44 ` [PATCH 0/9] coresight: change some driver' spinlock " James Clark
2024-11-28 10:55 ` James Clark
10 siblings, 0 replies; 22+ messages in thread
From: Yeoreum Yun @ 2024-11-25 9:48 UTC (permalink / raw)
To: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, rostedt
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
Levi Yun
From: Levi Yun <yeoreum.yun@arm.com>
In ultrasoc-smb drivers, smb_drv_data->spinlock can be held
during __schedule() by perf_event_task_sched_out()/in().
Since smb__drv_data->spinlock type is spinlock_t and
perf_event_task_sched_out()/in() is called after acquiring rq_lock,
which is raw_spinlock_t (an unsleepable lock),
this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
To address this, change type smb_drv_data->spinlock in ultrasoc-smb drivers,
which can be called by perf_event_task_sched_out()/in(),
from spinlock_t to raw_spinlock_t.
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
drivers/hwtracing/coresight/ultrasoc-smb.c | 12 ++++++------
drivers/hwtracing/coresight/ultrasoc-smb.h | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index ef7f560f0ffa..9ab4aec6955e 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -98,7 +98,7 @@ static int smb_open(struct inode *inode, struct file *file)
struct smb_drv_data *drvdata = container_of(file->private_data,
struct smb_drv_data, miscdev);
- guard(spinlock)(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
if (drvdata->reading)
return -EBUSY;
@@ -152,7 +152,7 @@ static int smb_release(struct inode *inode, struct file *file)
struct smb_drv_data *drvdata = container_of(file->private_data,
struct smb_drv_data, miscdev);
- guard(spinlock)(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
drvdata->reading = false;
return 0;
@@ -245,7 +245,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret = 0;
- guard(spinlock)(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* Do nothing, the trace data is reading by other interface now */
if (drvdata->reading)
@@ -280,7 +280,7 @@ static int smb_disable(struct coresight_device *csdev)
{
struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
- guard(spinlock)(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
if (drvdata->reading)
return -EBUSY;
@@ -378,7 +378,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev,
if (!buf)
return 0;
- guard(spinlock)(&drvdata->spinlock);
+ guard(raw_spinlock)(&drvdata->spinlock);
/* Don't do anything if another tracer is using this sink. */
if (csdev->refcnt != 1)
@@ -563,7 +563,7 @@ static int smb_probe(struct platform_device *pdev)
smb_reset_buffer(drvdata);
platform_set_drvdata(pdev, drvdata);
- spin_lock_init(&drvdata->spinlock);
+ raw_spin_lock_init(&drvdata->spinlock);
drvdata->pid = -1;
ret = smb_register_sink(pdev, drvdata);
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h
index a91d39cfccb8..c4c111275627 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.h
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.h
@@ -115,7 +115,7 @@ struct smb_drv_data {
struct coresight_device *csdev;
struct smb_data_buffer sdb;
struct miscdevice miscdev;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
bool reading;
pid_t pid;
};
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
2024-11-25 9:48 ` [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock " Yeoreum Yun
@ 2024-11-27 16:30 ` James Clark
2024-11-28 6:39 ` Yeo Reum Yun
0 siblings, 1 reply; 22+ messages in thread
From: James Clark @ 2024-11-27 16:30 UTC (permalink / raw)
To: Yeoreum Yun, suzuki.poulose, mike.leach
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
alexander.shishkin, bigeasy, clrkwllms, rostedt
On 25/11/2024 9:48 am, Yeoreum Yun wrote:
> From: Levi Yun <yeoreum.yun@arm.com>
>
> In coresight-etm4x drivers, etmv4_drvdata->spinlock can be held during
> __schedule() by perf_event_task_sched_out()/in().
>
> Since etmv4_drvdata->spinlock type is spinlock_t and
> perf_event_task_sched_out()/in() is called after acquiring rq_lock,
> which is raw_spinlock_t (an unsleepable lock),
> this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
>
> To address this, change type etmv4_drvdata->spinlock
> in coresight-etm4x drivers, which can be called
> by perf_event_task_sched_out()/in(), from spinlock_t to raw_spinlock_t.
>
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
[...]
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index a9f19629f3f8..2e6b79c37f87 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -174,99 +174,99 @@ static ssize_t reset_store(struct device *dev,
> if (kstrtoul(buf, 16, &val))
> return -EINVAL;
>
> - spin_lock(&drvdata->spinlock);
> - if (val)
> - config->mode = 0x0;
> + scoped_guard(raw_spinlock, &drvdata->spinlock) {
> + if (val)
> + config->mode = 0x0;
>
> - /* Disable data tracing: do not trace load and store data transfers */
> - config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
> - config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE);
> + /* Disable data tracing: do not trace load and store data transfers */
> + config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
> + config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE);
>
> - /* Disable data value and data address tracing */
> - config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
> - ETM_MODE_DATA_TRACE_VAL);
> - config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV);
> + /* Disable data value and data address tracing */
> + config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
> + ETM_MODE_DATA_TRACE_VAL);
> + config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV);
>
> - /* Disable all events tracing */
> - config->eventctrl0 = 0x0;
> - config->eventctrl1 = 0x0;
> + /* Disable all events tracing */
> + config->eventctrl0 = 0x0;
> + config->eventctrl1 = 0x0;
>
> - /* Disable timestamp event */
> - config->ts_ctrl = 0x0;
> + /* Disable timestamp event */
> + config->ts_ctrl = 0x0;
>
> - /* Disable stalling */
> - config->stall_ctrl = 0x0;
> + /* Disable stalling */
> + config->stall_ctrl = 0x0;
>
> - /* Reset trace synchronization period to 2^8 = 256 bytes*/
> - if (drvdata->syncpr == false)
> - config->syncfreq = 0x8;
> + /* Reset trace synchronization period to 2^8 = 256 bytes*/
> + if (drvdata->syncpr == false)
> + config->syncfreq = 0x8;
>
> - /*
> - * Enable ViewInst to trace everything with start-stop logic in
> - * started state. ARM recommends start-stop logic is set before
> - * each trace run.
> - */
> - config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
> - if (drvdata->nr_addr_cmp > 0) {
> - config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
> - /* SSSTATUS, bit[9] */
> - config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
> - }
> + /*
> + * Enable ViewInst to trace everything with start-stop logic in
> + * started state. ARM recommends start-stop logic is set before
> + * each trace run.
> + */
> + config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
> + if (drvdata->nr_addr_cmp > 0) {
> + config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
> + /* SSSTATUS, bit[9] */
> + config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
> + }
>
> - /* No address range filtering for ViewInst */
> - config->viiectlr = 0x0;
> + /* No address range filtering for ViewInst */
> + config->viiectlr = 0x0;
>
> - /* No start-stop filtering for ViewInst */
> - config->vissctlr = 0x0;
> - config->vipcssctlr = 0x0;
> + /* No start-stop filtering for ViewInst */
> + config->vissctlr = 0x0;
> + config->vipcssctlr = 0x0;
>
> - /* Disable seq events */
> - for (i = 0; i < drvdata->nrseqstate-1; i++)
> - config->seq_ctrl[i] = 0x0;
> - config->seq_rst = 0x0;
> - config->seq_state = 0x0;
> + /* Disable seq events */
> + for (i = 0; i < drvdata->nrseqstate-1; i++)
> + config->seq_ctrl[i] = 0x0;
> + config->seq_rst = 0x0;
> + config->seq_state = 0x0;
>
> - /* Disable external input events */
> - config->ext_inp = 0x0;
> + /* Disable external input events */
> + config->ext_inp = 0x0;
>
> - config->cntr_idx = 0x0;
> - for (i = 0; i < drvdata->nr_cntr; i++) {
> - config->cntrldvr[i] = 0x0;
> - config->cntr_ctrl[i] = 0x0;
> - config->cntr_val[i] = 0x0;
> - }
> + config->cntr_idx = 0x0;
> + for (i = 0; i < drvdata->nr_cntr; i++) {
> + config->cntrldvr[i] = 0x0;
> + config->cntr_ctrl[i] = 0x0;
> + config->cntr_val[i] = 0x0;
> + }
>
> - config->res_idx = 0x0;
> - for (i = 2; i < 2 * drvdata->nr_resource; i++)
> - config->res_ctrl[i] = 0x0;
> + config->res_idx = 0x0;
> + for (i = 2; i < 2 * drvdata->nr_resource; i++)
> + config->res_ctrl[i] = 0x0;
>
> - config->ss_idx = 0x0;
> - for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> - config->ss_ctrl[i] = 0x0;
> - config->ss_pe_cmp[i] = 0x0;
> - }
> + config->ss_idx = 0x0;
> + for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> + config->ss_ctrl[i] = 0x0;
> + config->ss_pe_cmp[i] = 0x0;
> + }
>
> - config->addr_idx = 0x0;
> - for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
> - config->addr_val[i] = 0x0;
> - config->addr_acc[i] = 0x0;
> - config->addr_type[i] = ETM_ADDR_TYPE_NONE;
> - }
> + config->addr_idx = 0x0;
> + for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
> + config->addr_val[i] = 0x0;
> + config->addr_acc[i] = 0x0;
> + config->addr_type[i] = ETM_ADDR_TYPE_NONE;
> + }
>
> - config->ctxid_idx = 0x0;
> - for (i = 0; i < drvdata->numcidc; i++)
> - config->ctxid_pid[i] = 0x0;
> + config->ctxid_idx = 0x0;
> + for (i = 0; i < drvdata->numcidc; i++)
> + config->ctxid_pid[i] = 0x0;
>
> - config->ctxid_mask0 = 0x0;
> - config->ctxid_mask1 = 0x0;
> + config->ctxid_mask0 = 0x0;
> + config->ctxid_mask1 = 0x0;
>
> - config->vmid_idx = 0x0;
> - for (i = 0; i < drvdata->numvmidc; i++)
> - config->vmid_val[i] = 0x0;
> - config->vmid_mask0 = 0x0;
> - config->vmid_mask1 = 0x0;
> + config->vmid_idx = 0x0;
> + for (i = 0; i < drvdata->numvmidc; i++)
> + config->vmid_val[i] = 0x0;
>
> - spin_unlock(&drvdata->spinlock);
> + config->vmid_mask0 = 0x0;
> + config->vmid_mask1 = 0x0;
> + }
There's a lot of churn in this function just to use the new scoped
guard, but there was only one lock and unlock anyway. There are a few
other cases of this in the whole set.
The scoped guards make it easier to write correct code, but I'm not sure
we gain anything here other than a bigger diff and more to review by
changing already working code. Having said that I did review all the
changes and I'm pretty sure they're all ok, so I'm on the fence about
whether it's worth going back and undoing all of them.
Surely updating to raw spinlocks is a search and replace to fix a
specific problem, and the scoped guard stuff can be done on a case by
case basis when anything is re-written in the future?
I don't know if we're considering a fixes tag, if PREEMPT_RT is 6.12?
It's probably not necessary but if so we definitely want to minimise the
change.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (8 preceding siblings ...)
2024-11-25 9:48 ` [PATCH 9/9] coresight/ultrasoc: change cti_drvdata " Yeoreum Yun
@ 2024-11-27 16:44 ` James Clark
2024-11-28 6:23 ` Yeo Reum Yun
2024-11-28 10:55 ` James Clark
10 siblings, 1 reply; 22+ messages in thread
From: James Clark @ 2024-11-27 16:44 UTC (permalink / raw)
To: Yeoreum Yun, suzuki.poulose, mike.leach
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
alexander.shishkin, bigeasy, clrkwllms, rostedt
On 25/11/2024 9:48 am, Yeoreum Yun wrote:
> In some coresight drivers, drvdata->spinlock can be held during __schedule()
> by perf_event_task_sched_out()/in().
>
> Since drvdata->spinlock type is spinlock_t and
> perf_event_task_sched_out()/in() is called after acquiring rq_lock,
> which is raw_spinlock_t (an unsleepable lock),
> this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
>
> To address this,change type drvdata->spinlock in some coresight drivers,
> which can be called by perf_event_task_sched_out()/in(),
> from spinlock_t to raw_spinlock_t.
>
> Levi Yun (9):
> coresight: change coresight_device lock type to raw_spinlock_t
> coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
> coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
> coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
> coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
> coresight-funnel: change funnel_drvdata spinlock's type to
> raw_spinlock_t
> coresight-replicator: change replicator_drvdata spinlock's type to
> raw_spinlock_t
> coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
> coresight/ultrasoc: change cti_drvdata spinlock's type to
> raw_spinlock_t
>
> .../hwtracing/coresight/coresight-config.c | 21 +-
> .../hwtracing/coresight/coresight-config.h | 2 +-
> drivers/hwtracing/coresight/coresight-core.c | 2 +-
> .../hwtracing/coresight/coresight-cti-core.c | 65 +-
> .../hwtracing/coresight/coresight-cti-sysfs.c | 135 +++--
> drivers/hwtracing/coresight/coresight-cti.h | 2 +-
> drivers/hwtracing/coresight/coresight-etb10.c | 62 +-
> .../coresight/coresight-etm4x-core.c | 71 ++-
> .../coresight/coresight-etm4x-sysfs.c | 566 +++++++++---------
> drivers/hwtracing/coresight/coresight-etm4x.h | 2 +-
> .../hwtracing/coresight/coresight-funnel.c | 34 +-
> .../coresight/coresight-replicator.c | 36 +-
> .../hwtracing/coresight/coresight-syscfg.c | 75 ++-
> .../hwtracing/coresight/coresight-tmc-core.c | 9 +-
> .../hwtracing/coresight/coresight-tmc-etf.c | 195 +++---
> .../hwtracing/coresight/coresight-tmc-etr.c | 199 +++---
> drivers/hwtracing/coresight/coresight-tmc.h | 2 +-
> .../hwtracing/coresight/coresight-trace-id.c | 93 ++-
> drivers/hwtracing/coresight/ultrasoc-smb.c | 12 +-
> drivers/hwtracing/coresight/ultrasoc-smb.h | 2 +-
> include/linux/coresight.h | 4 +-
> 21 files changed, 751 insertions(+), 838 deletions(-)
>
> --
> LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
>
Reviewed-by: James Clark <james.clark@linaro.org>
Somewhat related to this change, but not something that needs to be done
now:
All of the spinlocks for the syfs store/read functions don't need to be
raw spinlocks, or spinlocks at all. They're never called from the
scheduling code and can be locked by coresight_mutex instead.
coresight_mutex is held on the sysfs enable/disable path when those
values are actually used.
Same point as here:
https://lore.kernel.org/linux-arm-kernel/9a637e74-d81d-405c-bad0-c97ec1aa4b77@linaro.org/
Probably needs a review of which values in each device might be shared
between perf mode and sysfs mode when they shouldn't be, as there was
one in the link above.
I thought the only thing shared between sysfs and perf should be the
'mode' which is taken with a compare and swap without locking anyway.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-11-25 9:48 ` [PATCH 1/9] coresight: change coresight_device lock " Yeoreum Yun
@ 2024-11-27 17:09 ` Steven Rostedt
2024-11-28 7:39 ` Yeo Reum Yun
0 siblings, 1 reply; 22+ messages in thread
From: Steven Rostedt @ 2024-11-27 17:09 UTC (permalink / raw)
To: Yeoreum Yun
Cc: suzuki.poulose, mike.leach, james.clark, alexander.shishkin,
bigeasy, clrkwllms, coresight, linux-arm-kernel, linux-kernel,
linux-rt-devel, nd
On Mon, 25 Nov 2024 09:48:08 +0000
Yeoreum Yun <yeoreum.yun@arm.com> wrote:
> @@ -853,17 +851,14 @@ EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
> void cscfg_csdev_reset_feats(struct coresight_device *csdev)
> {
> struct cscfg_feature_csdev *feat_csdev;
> - unsigned long flags;
>
> - spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
> + guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock);
> +
> if (list_empty(&csdev->feature_csdev_list))
> - goto unlock_exit;
> + return;
>
> list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
> cscfg_reset_feat(feat_csdev);
We should start documenting what is not real-time "safe". That is, if this
code is executed, we have a loop here that holds a raw spin lock. This
appears to make the time the raw spin lock held to be non deterministic.
If someone is running PREEMPT_RT and expects deterministic behavior, they
cannot be using this code. That is fine, but we should probably create a
document somewhere that notes this.
-- Steve
> -
> -unlock_exit:
> - spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
> }
> EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
2024-11-27 16:44 ` [PATCH 0/9] coresight: change some driver' spinlock " James Clark
@ 2024-11-28 6:23 ` Yeo Reum Yun
0 siblings, 0 replies; 22+ messages in thread
From: Yeo Reum Yun @ 2024-11-28 6:23 UTC (permalink / raw)
To: James Clark, Suzuki Poulose, mike.leach@linaro.org
Cc: coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, rostedt@goodmis.org
Hi James,
Thanks for your review.
> Somewhat related to this change, but not something that needs to be done
> now:
> All of the spinlocks for the syfs store/read functions don't need to be
> raw spinlocks, or spinlocks at all. They're never called from the
> scheduling code and can be locked by coresight_mutex instead.
> coresight_mutex is held on the sysfs enable/disable path when those
> values are actually used.
> Same point as here:
> https://lore.kernel.org/linux-arm-kernel/9a637e74-d81d-405c-bad0-c97ec1aa4b77@linaro.org/
> Probably needs a review of which values in each device might be shared
> between perf mode and sysfs mode when they shouldn't be, as there was
> one in the link above.
> I thought the only thing shared between sysfs and perf should be the
> 'mode' which is taken with a compare and swap without locking anyway.
I think it seems bit of hard while sysfs exports interface to modify configuration.
Think about one source enabling via "PERF" and other process try to call reset via "SYSFS"
wihtout locking enabled "PERF" event can have different configuration
because "SYSFS" can change the configuration while applying "PERF" configuration configured by perf event.
(CPU0 - enabling some coresight device with PERF and configuration from perf-event
CPU1 - reset configuration via "SYSFS")
I think it seems hard to shared only "mode" between PERF and SYSFS mode.
Suppose one soure device's mode is DISABLED, and
- one process setting the configuration via SYSFS interface
- one process enabling source device via PERF according to configuration saved in perf_event.
wihtout locking, how to prevent "SYSFS"'s change of configuration while it saw "DISABLED state"?
I think wihtout lock, It falls to enabled perf event with inconsistent configuration.
IMHO, only shared cannot be mode unless sysfs provides interface to config something
which can affects function of hardware.....
Thanks.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
2024-11-27 16:30 ` James Clark
@ 2024-11-28 6:39 ` Yeo Reum Yun
0 siblings, 0 replies; 22+ messages in thread
From: Yeo Reum Yun @ 2024-11-28 6:39 UTC (permalink / raw)
To: James Clark, Suzuki Poulose, mike.leach@linaro.org
Cc: coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, rostedt@goodmis.org
Hi James,
> There's a lot of churn in this function just to use the new scoped
> guard, but there was only one lock and unlock anyway. There are a few
> other cases of this in the whole set.
>
> The scoped guards make it easier to write correct code, but I'm not sure
> we gain anything here other than a bigger diff and more to review by
> changing already working code. Having said that I did review all the
> changes and I'm pretty sure they're all ok, so I'm on the fence about
> whether it's worth going back and undoing all of them.
>
> Surely updating to raw spinlocks is a search and replace to fix a
> specific problem, and the scoped guard stuff can be done on a case by
> case basis when anything is re-written in the future?
>
> I don't know if we're considering a fixes tag, if PREEMPT_RT is 6.12?
> It's probably not necessary but if so we definitely want to minimise the
> change.
At first, thanks to review :) and as you said there's no functional change
except change of locktype.
But I thougt making seperate patchset to change locktype and
apply scoped_guard to two patchset makes people do duplicate review for
the same code and almost same posittion.
Since there's no functional change and reviewed,
I think it doesn't need to seperate..?
Thanks.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-11-27 17:09 ` Steven Rostedt
@ 2024-11-28 7:39 ` Yeo Reum Yun
2024-12-02 15:38 ` Steven Rostedt
0 siblings, 1 reply; 22+ messages in thread
From: Yeo Reum Yun @ 2024-11-28 7:39 UTC (permalink / raw)
To: Steven Rostedt
Cc: Suzuki Poulose, mike.leach@linaro.org, james.clark@linaro.org,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd
Hi Steven,
> We should start documenting what is not real-time "safe". That is, if this
> code is executed, we have a loop here that holds a raw spin lock. This
> appears to make the time the raw spin lock held to be non deterministic.
>
> If someone is running PREEMPT_RT and expects deterministic behavior, they
> cannot be using this code. That is fine, but we should probably create a
> document somewhere that notes this.
>
> -- Steve
I think it's quite deterministic becase the number of loop currently
determined by the number of preload_feats.
Also, I don't think the number of feats will be loaded as much as
it can do undeterministic behavior since
the number is not many and it is quite predictable.
Thanks.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
` (9 preceding siblings ...)
2024-11-27 16:44 ` [PATCH 0/9] coresight: change some driver' spinlock " James Clark
@ 2024-11-28 10:55 ` James Clark
2024-11-28 11:48 ` Yeo Reum Yun
10 siblings, 1 reply; 22+ messages in thread
From: James Clark @ 2024-11-28 10:55 UTC (permalink / raw)
To: Yeoreum Yun, suzuki.poulose, mike.leach
Cc: coresight, linux-arm-kernel, linux-kernel, linux-rt-devel, nd,
alexander.shishkin, bigeasy, clrkwllms, rostedt
On 25/11/2024 9:48 am, Yeoreum Yun wrote:
> In some coresight drivers, drvdata->spinlock can be held during __schedule()
> by perf_event_task_sched_out()/in().
>
> Since drvdata->spinlock type is spinlock_t and
> perf_event_task_sched_out()/in() is called after acquiring rq_lock,
> which is raw_spinlock_t (an unsleepable lock),
> this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable.
>
> To address this,change type drvdata->spinlock in some coresight drivers,
> which can be called by perf_event_task_sched_out()/in(),
> from spinlock_t to raw_spinlock_t.
>
> Levi Yun (9):
> coresight: change coresight_device lock type to raw_spinlock_t
> coresight-etm4x: change etmv4_drvdata spinlock type to raw_spinlock_t
> coresight: change coresight_trace_id_map's lock type to raw_spinlock_t
> coresight-cti: change cti_drvdata spinlock's type to raw_spinlock_t
> coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t
> coresight-funnel: change funnel_drvdata spinlock's type to
> raw_spinlock_t
> coresight-replicator: change replicator_drvdata spinlock's type to
> raw_spinlock_t
> coresight-tmc: change tmc_drvdata spinlock's type to raw_spinlock_t
> coresight/ultrasoc: change cti_drvdata spinlock's type to
> raw_spinlock_t
>
> .../hwtracing/coresight/coresight-config.c | 21 +-
> .../hwtracing/coresight/coresight-config.h | 2 +-
> drivers/hwtracing/coresight/coresight-core.c | 2 +-
> .../hwtracing/coresight/coresight-cti-core.c | 65 +-
> .../hwtracing/coresight/coresight-cti-sysfs.c | 135 +++--
> drivers/hwtracing/coresight/coresight-cti.h | 2 +-
> drivers/hwtracing/coresight/coresight-etb10.c | 62 +-
> .../coresight/coresight-etm4x-core.c | 71 ++-
> .../coresight/coresight-etm4x-sysfs.c | 566 +++++++++---------
> drivers/hwtracing/coresight/coresight-etm4x.h | 2 +-
> .../hwtracing/coresight/coresight-funnel.c | 34 +-
> .../coresight/coresight-replicator.c | 36 +-
> .../hwtracing/coresight/coresight-syscfg.c | 75 ++-
> .../hwtracing/coresight/coresight-tmc-core.c | 9 +-
> .../hwtracing/coresight/coresight-tmc-etf.c | 195 +++---
> .../hwtracing/coresight/coresight-tmc-etr.c | 199 +++---
> drivers/hwtracing/coresight/coresight-tmc.h | 2 +-
> .../hwtracing/coresight/coresight-trace-id.c | 93 ++-
> drivers/hwtracing/coresight/ultrasoc-smb.c | 12 +-
> drivers/hwtracing/coresight/ultrasoc-smb.h | 2 +-
> include/linux/coresight.h | 4 +-
> 21 files changed, 751 insertions(+), 838 deletions(-)
>
> --
> LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
>
Can TPIU be used as a sink with Perf? If so that one is missing the update.
Makes me wonder if something like a "perf_component" flag in
coresight_device or a #define would make sense. Then the lock type gets
auto picked. Seems like in a few years we will have completely forgotten
why some of the coresight locks are raw and others aren't.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t
2024-11-28 10:55 ` James Clark
@ 2024-11-28 11:48 ` Yeo Reum Yun
0 siblings, 0 replies; 22+ messages in thread
From: Yeo Reum Yun @ 2024-11-28 11:48 UTC (permalink / raw)
To: James Clark, Suzuki Poulose, mike.leach@linaro.org
Cc: coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, rostedt@goodmis.org
Hi James,
> Can TPIU be used as a sink with Perf? If so that one is missing the update.
No. IIRC from feedback from Suzuki, TPIU not used in perf mode.
> Makes me wonder if something like a "perf_component" flag in
> coresight_device or a #define would make sense. Then the lock type gets
> auto picked. Seems like in a few years we will have completely forgotten
> why some of the coresight locks are raw and others aren't.
I think later then do define new flags to solve
sharing data between perf and sysfs (i.e. etm4x config),
it would be more resonable seperate config for perf and sysfs.
so that, sysfs shared data could be manged with inside of SYSFS subsystem
and it can have sepearte lock to synchronize under SYSFS.
it doesn't need to define that lock type as raw_spin_lock_t and
solve the data modifying between perf and sysfs setup.
But, This is another story.
And I'll seperate this patchset to two part.
- Change locktype from spin_lock_t to raw_spin_lock_t
- Apply scoped_guard
so that backward portiable.
Thanks for your review again :)
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-11-28 7:39 ` Yeo Reum Yun
@ 2024-12-02 15:38 ` Steven Rostedt
2024-12-03 8:31 ` Yeo Reum Yun
0 siblings, 1 reply; 22+ messages in thread
From: Steven Rostedt @ 2024-12-02 15:38 UTC (permalink / raw)
To: Yeo Reum Yun
Cc: Suzuki Poulose, mike.leach@linaro.org, james.clark@linaro.org,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd
On Thu, 28 Nov 2024 07:39:22 +0000
Yeo Reum Yun <YeoReum.Yun@arm.com> wrote:
> Hi Steven,
>
> > We should start documenting what is not real-time "safe". That is, if this
> > code is executed, we have a loop here that holds a raw spin lock. This
> > appears to make the time the raw spin lock held to be non deterministic.
> >
> > If someone is running PREEMPT_RT and expects deterministic behavior, they
> > cannot be using this code. That is fine, but we should probably create a
> > document somewhere that notes this.
> >
> > -- Steve
>
> I think it's quite deterministic becase the number of loop currently
> determined by the number of preload_feats.
>
> Also, I don't think the number of feats will be loaded as much as
> it can do undeterministic behavior since
> the number is not many and it is quite predictable.
Still should be documented somewhere. It should describe the maximum number
of feats that will ever be loaded. If there's a max, it makes it back to
O(1). With a 'k' of how long it takes to process the max number of feats.
-- Steve
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-12-02 15:38 ` Steven Rostedt
@ 2024-12-03 8:31 ` Yeo Reum Yun
2024-12-03 15:20 ` Steven Rostedt
0 siblings, 1 reply; 22+ messages in thread
From: Yeo Reum Yun @ 2024-12-03 8:31 UTC (permalink / raw)
To: Steven Rostedt
Cc: Suzuki Poulose, mike.leach@linaro.org, james.clark@linaro.org,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd
Hi Steve,
> Still should be documented somewhere. It should describe the maximum number
> of feats that will ever be loaded. If there's a max, it makes it back to
> O(1). With a 'k' of how long it takes to process the max number of feats.
But with other patchset seems better
since not only this function, but also for other functions too.
BTW, is there any example describing this I can refer?
Thanks
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-12-03 8:31 ` Yeo Reum Yun
@ 2024-12-03 15:20 ` Steven Rostedt
2024-12-03 15:30 ` Yeo Reum Yun
0 siblings, 1 reply; 22+ messages in thread
From: Steven Rostedt @ 2024-12-03 15:20 UTC (permalink / raw)
To: Yeo Reum Yun
Cc: Suzuki Poulose, mike.leach@linaro.org, james.clark@linaro.org,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd
On Tue, 3 Dec 2024 08:31:54 +0000
Yeo Reum Yun <YeoReum.Yun@arm.com> wrote:
> Hi Steve,
>
> > Still should be documented somewhere. It should describe the maximum number
> > of feats that will ever be loaded. If there's a max, it makes it back to
> > O(1). With a 'k' of how long it takes to process the max number of feats.
>
> But with other patchset seems better
> since not only this function, but also for other functions too.
Which other patchset?
>
> BTW, is there any example describing this I can refer?
No, it's on our todo list for RT. To document the RT behavior of the
kernel. This is just one location.
-- Steve
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/9] coresight: change coresight_device lock type to raw_spinlock_t
2024-12-03 15:20 ` Steven Rostedt
@ 2024-12-03 15:30 ` Yeo Reum Yun
0 siblings, 0 replies; 22+ messages in thread
From: Yeo Reum Yun @ 2024-12-03 15:30 UTC (permalink / raw)
To: Steven Rostedt
Cc: Suzuki Poulose, mike.leach@linaro.org, james.clark@linaro.org,
alexander.shishkin@linux.intel.com, bigeasy@linutronix.de,
clrkwllms@kernel.org, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, nd
Hi Steve,
> > > Still should be documented somewhere. It should describe the maximum number
> > > of feats that will ever be loaded. If there's a max, it makes it back to
> > > O(1). With a 'k' of how long it takes to process the max number of feats.
> >
> > But with other patchset seems better
> > since not only this function, but also for other functions too.
> Which other patchset?
I mean I'll send with seperate patchset to documents this.
Because I'm not sure documents here or in other file...
>
> BTW, is there any example describing this I can refer?
> No, it's on our todo list for RT. To document the RT behavior of the
> kernel. This is just one location.
Thanks to let me know :)
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2024-12-03 16:44 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-25 9:48 [PATCH 0/9] coresight: change some driver' spinlock type to raw_spinlock_t Yeoreum Yun
2024-11-25 9:48 ` [PATCH 1/9] coresight: change coresight_device lock " Yeoreum Yun
2024-11-27 17:09 ` Steven Rostedt
2024-11-28 7:39 ` Yeo Reum Yun
2024-12-02 15:38 ` Steven Rostedt
2024-12-03 8:31 ` Yeo Reum Yun
2024-12-03 15:20 ` Steven Rostedt
2024-12-03 15:30 ` Yeo Reum Yun
2024-11-25 9:48 ` [PATCH 2/9] coresight-etm4x: change etmv4_drvdata spinlock " Yeoreum Yun
2024-11-27 16:30 ` James Clark
2024-11-28 6:39 ` Yeo Reum Yun
2024-11-25 9:48 ` [PATCH 3/9] coresight: change coresight_trace_id_map's lock " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 4/9] coresight-cti: change cti_drvdata spinlock's " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 5/9] coresight-etb10: change etb_drvdata " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 6/9] coresight-funnel: change funnel_drvdata " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 7/9] coresight-replicator: change replicator_drvdata " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 8/9] coresight-tmc: change tmc_drvdata " Yeoreum Yun
2024-11-25 9:48 ` [PATCH 9/9] coresight/ultrasoc: change cti_drvdata " Yeoreum Yun
2024-11-27 16:44 ` [PATCH 0/9] coresight: change some driver' spinlock " James Clark
2024-11-28 6:23 ` Yeo Reum Yun
2024-11-28 10:55 ` James Clark
2024-11-28 11:48 ` Yeo Reum Yun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox