summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2026-09-07 16:41:18 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2026-09-14 10:53:46 +0200
commit5da91c3694b8060b651aab5d95b2e4729c6e2b56 (patch)
treeb3b824e5cb1a470b32d5ffd535ebe3577fc730db
parent7049eb52c81645df81b1867e48bda89f11e585b8 (diff)
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 <mika.westerberg@linux.intel.com>
-rw-r--r--drivers/thunderbolt/stream.c8
1 files changed, 6 insertions, 2 deletions
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;
}