[PATCH 3/4] thunderbolt: stream: Do not hold the lock while busy polling
COLD20d
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Date: 2026-09-08 08:14:56
Subsystem:
the rest, thunderbolt driver · Maintainers:
Linus Torvalds, Andreas Noever, Mika Westerberg, Yehezkel Bernat
When in busy poll mode with a reader and writer, and there is nothing completed on the rings both sides keep taking and releasing the lock from each other and this can cause stalls. Avoid this by calling the new API function tb_ring_poll_pending() that only returns true if there is anything available in which case they can take the lock and know there is now work to do. Reported-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com> Assisted-by: LLM Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> --- drivers/thunderbolt/stream.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/thunderbolt/stream.c b/drivers/thunderbolt/stream.c
index 7b618d8a7d82..b4f3b1db9d82 100644
--- a/drivers/thunderbolt/stream.c
+++ b/drivers/thunderbolt/stream.c@@ -734,6 +734,22 @@ static int tbstream_dev_lock(struct tbstream_dev *sdev, bool nowait) return 0; } +/* Must not be called with @sdev->lock held */ +static int tbstream_dev_busy_poll_wait(struct tbstream_dev *sdev, + struct tbstream_ring *ring) +{ + for (;;) { + if (signal_pending(current)) + return -ERESTARTSYS; + if (tb_ring_poll_pending(ring->ring)) + return 0; + if (tbstream_dev_valid(sdev) != 0 || + tbstream_dev_closed(sdev) || tbstream_dev_removed(sdev)) + return 0; + cond_resched(); + } +} + static ssize_t tbstream_dev_fops_read_iter(struct kiocb *kiocb, struct iov_iter *to) {
@@ -777,9 +793,9 @@ tbstream_dev_fops_read_iter(struct kiocb *kiocb, struct iov_iter *to) return -EAGAIN; if (sdev->busy_poll) { - if (signal_pending(current)) - return -ERESTARTSYS; - cond_resched(); + ret = tbstream_dev_busy_poll_wait(sdev, &sdev->rx_ring); + if (ret) + return ret; } else { ret = wait_event_interruptible(sdev->wait, READ_ONCE(sdev->rx_pending) ||
@@ -891,9 +907,9 @@ tbstream_dev_fops_write_iter(struct kiocb *kiocb, struct iov_iter *from) return -EAGAIN; if (sdev->busy_poll) { - if (signal_pending(current)) - return -ERESTARTSYS; - cond_resched(); + ret = tbstream_dev_busy_poll_wait(sdev, &sdev->tx_ring); + if (ret) + return ret; } else { ret = wait_event_interruptible(sdev->wait, tbstream_ring_available(&sdev->tx_ring) ||
--
2.50.1