From 5da91c3694b8060b651aab5d95b2e4729c6e2b56 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 7 Sep 2026 16:41:18 +0300 Subject: thunderbolt: stream: Check the Rx ring before task starts sleeping In interrupt mode when tb_ring_poll_complete() is called it is possible that a frame was completed right before the ring interrupt was unmasked in which case there will be no interrupt and the task starts sleeping. Avoid this and check if there is anything completed prior putting the task to sleep. The same can happen with poll() so check the ring there too before reporting that there is nothing to read. Assisted-by: LLM Signed-off-by: Mika Westerberg --- drivers/thunderbolt/stream.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/thunderbolt/stream.c b/drivers/thunderbolt/stream.c index a8b0be27b4a1..f5b67c09ed8d 100644 --- a/drivers/thunderbolt/stream.c +++ b/drivers/thunderbolt/stream.c @@ -801,6 +801,7 @@ tbstream_dev_fops_read_iter(struct kiocb *kiocb, struct iov_iter *to) } else { ret = wait_event_interruptible(sdev->wait, READ_ONCE(sdev->rx_pending) || + tb_ring_poll_pending(sdev->rx_ring.ring) || tbstream_ring_available(&sdev->rx_ring) || tbstream_dev_valid(sdev) != 0 || tbstream_dev_closed(sdev) || @@ -979,10 +980,13 @@ tbstream_dev_fops_poll(struct file *file, struct poll_table_struct *wait) if (tbstream_ring_available(&sdev->tx_ring)) mask |= EPOLLOUT | EPOLLWRNORM; - if (tbstream_ring_available(&sdev->rx_ring)) + if (tbstream_ring_available(&sdev->rx_ring)) { mask |= EPOLLIN | EPOLLRDNORM; - else + } else { tbstream_dev_complete_rx(sdev); + if (tb_ring_poll_pending(sdev->rx_ring.ring)) + mask |= EPOLLIN | EPOLLRDNORM; + } return mask; } -- cgit v1.2.3