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

coresight/ultrasoc: change smb_drv_data spinlock's type to raw_spinlock_t

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.

Reviewed-by: James Clark <james.clark@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-10-yeoreum.yun@arm.com

authored by

Yeoreum Yun and committed by
Suzuki K Poulose
d11eb31d db11f75b

+7 -7
+6 -6
drivers/hwtracing/coresight/ultrasoc-smb.c
··· 98 98 struct smb_drv_data *drvdata = container_of(file->private_data, 99 99 struct smb_drv_data, miscdev); 100 100 101 - guard(spinlock)(&drvdata->spinlock); 101 + guard(raw_spinlock)(&drvdata->spinlock); 102 102 103 103 if (drvdata->reading) 104 104 return -EBUSY; ··· 152 152 struct smb_drv_data *drvdata = container_of(file->private_data, 153 153 struct smb_drv_data, miscdev); 154 154 155 - guard(spinlock)(&drvdata->spinlock); 155 + guard(raw_spinlock)(&drvdata->spinlock); 156 156 drvdata->reading = false; 157 157 158 158 return 0; ··· 245 245 struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); 246 246 int ret = 0; 247 247 248 - guard(spinlock)(&drvdata->spinlock); 248 + guard(raw_spinlock)(&drvdata->spinlock); 249 249 250 250 /* Do nothing, the trace data is reading by other interface now */ 251 251 if (drvdata->reading) ··· 280 280 { 281 281 struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); 282 282 283 - guard(spinlock)(&drvdata->spinlock); 283 + guard(raw_spinlock)(&drvdata->spinlock); 284 284 285 285 if (drvdata->reading) 286 286 return -EBUSY; ··· 378 378 if (!buf) 379 379 return 0; 380 380 381 - guard(spinlock)(&drvdata->spinlock); 381 + guard(raw_spinlock)(&drvdata->spinlock); 382 382 383 383 /* Don't do anything if another tracer is using this sink. */ 384 384 if (csdev->refcnt != 1) ··· 563 563 564 564 smb_reset_buffer(drvdata); 565 565 platform_set_drvdata(pdev, drvdata); 566 - spin_lock_init(&drvdata->spinlock); 566 + raw_spin_lock_init(&drvdata->spinlock); 567 567 drvdata->pid = -1; 568 568 569 569 ret = smb_register_sink(pdev, drvdata);
+1 -1
drivers/hwtracing/coresight/ultrasoc-smb.h
··· 115 115 struct coresight_device *csdev; 116 116 struct smb_data_buffer sdb; 117 117 struct miscdevice miscdev; 118 - spinlock_t spinlock; 118 + raw_spinlock_t spinlock; 119 119 bool reading; 120 120 pid_t pid; 121 121 };