From: Levi Yun <yeoreum.yun@xxxxxxx>
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@xxxxxxx>
---
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;
+ }