diff options
| author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2026-09-07 16:41:18 +0300 |
|---|---|---|
| committer | Mika Westerberg <mika.westerberg@linux.intel.com> | 2026-09-14 10:53:46 +0200 |
| commit | 5da91c3694b8060b651aab5d95b2e4729c6e2b56 (patch) | |
| tree | b3b824e5cb1a470b32d5ffd535ebe3577fc730db /drivers | |
| parent | 7049eb52c81645df81b1867e48bda89f11e585b8 (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>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/thunderbolt/stream.c | 8 |
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; } |
