summaryrefslogtreecommitdiff
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2026-09-01 11:02:22 +0100
committerSean Young <sean@mess.org>2026-09-22 14:50:16 +0100
commit29ee25fa9beb3232808e6d0b3e8ebfb0427cb820 (patch)
treeb3eb13b529ad3a9882b1978e09c54a44a488045d /drivers/media/rc
parentb3f5daf3222999d3f92f606a4eb5e35ab90fd0e4 (diff)
media: rc: mce_kbd: Fix inconsistent locking of keylock
data->keylock is taken with spin_lock() in ir_mce_kbd_decode(), which runs in the raw IR decode kthread with local interrupts enabled, but with spin_lock_irqsave() in mce_kbd_rx_timeout(), the rx_timeout timer callback, which runs in softirq context. If the decode kthread is holding keylock via spin_lock() when a timer interrupt fires on the same CPU and the softirq runs mce_kbd_rx_timeout(), the softirq spins forever waiting for a lock that only the now-preempted kthread can release, while the kthread cannot run again until the softirq gives up the CPU. This deadlocks the CPU. Fixes: 53a62800efb2 ("media: rc: mce_kbd decoder: fix race condition") Signed-off-by: Sean Young <sean@mess.org> Cc: stable@vger.kernel.org Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/ir-mce_kbd-decoder.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index bb2d7c37c263..d1c9263511b0 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -219,6 +219,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct mce_kbd_dec *data = &dev->raw->mce_kbd;
u32 scancode;
unsigned long delay;
+ unsigned long flags;
struct lirc_scancode lsc = {};
if (!is_timing_event(ev)) {
@@ -319,7 +320,7 @@ again:
scancode = data->body & 0xffffff;
dev_dbg(&dev->dev, "keyboard data 0x%08x\n",
data->body);
- spin_lock(&data->keylock);
+ spin_lock_irqsave(&data->keylock, flags);
if (scancode) {
delay = usecs_to_jiffies(dev->timeout) +
msecs_to_jiffies(100);
@@ -329,7 +330,7 @@ again:
}
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(dev, scancode);
- spin_unlock(&data->keylock);
+ spin_unlock_irqrestore(&data->keylock, flags);
lsc.rc_proto = RC_PROTO_MCIR2_KBD;
break;
case MCIR2_MOUSE_NBITS: