Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t

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.

Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20250306121110.1647948-6-yeoreum.yun@arm.com

authored by

Yeoreum Yun and committed by
Suzuki K Poulose
6b80c0ab e3044065

+13 -13
+13 -13
drivers/hwtracing/coresight/coresight-etb10.c
··· 84 84 struct clk *atclk; 85 85 struct coresight_device *csdev; 86 86 struct miscdevice miscdev; 87 - spinlock_t spinlock; 87 + raw_spinlock_t spinlock; 88 88 local_t reading; 89 89 pid_t pid; 90 90 u8 *buf; ··· 145 145 unsigned long flags; 146 146 struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 147 147 148 - spin_lock_irqsave(&drvdata->spinlock, flags); 148 + raw_spin_lock_irqsave(&drvdata->spinlock, flags); 149 149 150 150 /* Don't messup with perf sessions. */ 151 151 if (coresight_get_mode(csdev) == CS_MODE_PERF) { ··· 163 163 164 164 csdev->refcnt++; 165 165 out: 166 - spin_unlock_irqrestore(&drvdata->spinlock, flags); 166 + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); 167 167 return ret; 168 168 } 169 169 ··· 176 176 struct perf_output_handle *handle = data; 177 177 struct cs_buffers *buf = etm_perf_sink_config(handle); 178 178 179 - spin_lock_irqsave(&drvdata->spinlock, flags); 179 + raw_spin_lock_irqsave(&drvdata->spinlock, flags); 180 180 181 181 /* No need to continue if the component is already in used by sysFS. */ 182 182 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { ··· 219 219 } 220 220 221 221 out: 222 - spin_unlock_irqrestore(&drvdata->spinlock, flags); 222 + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); 223 223 return ret; 224 224 } 225 225 ··· 352 352 struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 353 353 unsigned long flags; 354 354 355 - spin_lock_irqsave(&drvdata->spinlock, flags); 355 + raw_spin_lock_irqsave(&drvdata->spinlock, flags); 356 356 357 357 csdev->refcnt--; 358 358 if (csdev->refcnt) { 359 - spin_unlock_irqrestore(&drvdata->spinlock, flags); 359 + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); 360 360 return -EBUSY; 361 361 } 362 362 ··· 366 366 /* Dissociate from monitored process. */ 367 367 drvdata->pid = -1; 368 368 coresight_set_mode(csdev, CS_MODE_DISABLED); 369 - spin_unlock_irqrestore(&drvdata->spinlock, flags); 369 + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); 370 370 371 371 dev_dbg(&csdev->dev, "ETB disabled\n"); 372 372 return 0; ··· 443 443 444 444 capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; 445 445 446 - spin_lock_irqsave(&drvdata->spinlock, flags); 446 + raw_spin_lock_irqsave(&drvdata->spinlock, flags); 447 447 448 448 /* Don't do anything if another tracer is using this sink */ 449 449 if (csdev->refcnt != 1) ··· 566 566 __etb_enable_hw(drvdata); 567 567 CS_LOCK(drvdata->base); 568 568 out: 569 - spin_unlock_irqrestore(&drvdata->spinlock, flags); 569 + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); 570 570 571 571 return to_read; 572 572 } ··· 587 587 { 588 588 unsigned long flags; 589 589 590 - spin_lock_irqsave(&drvdata->spinlock, flags); 590 + raw_spin_lock_irqsave(&drvdata->spinlock, flags); 591 591 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { 592 592 __etb_disable_hw(drvdata); 593 593 etb_dump_hw(drvdata); 594 594 __etb_enable_hw(drvdata); 595 595 } 596 - spin_unlock_irqrestore(&drvdata->spinlock, flags); 596 + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); 597 597 598 598 dev_dbg(&drvdata->csdev->dev, "ETB dumped\n"); 599 599 } ··· 746 746 drvdata->base = base; 747 747 desc.access = CSDEV_ACCESS_IOMEM(base); 748 748 749 - spin_lock_init(&drvdata->spinlock); 749 + raw_spin_lock_init(&drvdata->spinlock); 750 750 751 751 drvdata->buffer_depth = etb_get_buffer_depth(drvdata); 752 752