summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2026-06-17 07:42:06 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2026-08-05 05:53:57 +0200
commit42bc6935339b913d424331a62f9e965bc72ca3df (patch)
treeafc3941f0dd4dc7a1f4637605529effc27f4db11
parentaf73a21a8eb460744d733fa5e2627935ed125081 (diff)
downloadlinux-42bc6935339b913d424331a62f9e965bc72ca3df.tar.gz
linux-42bc6935339b913d424331a62f9e965bc72ca3df.zip
thunderbolt: stream: Support IOCB_NOWAIT in non-blocking I/O as well
For read_iter/write_iter() it is also possible to pass IOCB_NOWAIT with the kiocb to indicate non-blocking read/write. For instance io_uring does this. So take this into account on read and write paths. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-rw-r--r--drivers/thunderbolt/stream.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/thunderbolt/stream.c b/drivers/thunderbolt/stream.c
index aa606721c51e..b3fab395194e 100644
--- a/drivers/thunderbolt/stream.c
+++ b/drivers/thunderbolt/stream.c
@@ -633,10 +633,23 @@ static void tbstream_dev_stop(struct tbstream_dev *sdev)
sdev->tx_ring.ring = NULL;
}
+static int tbstream_dev_lock(struct tbstream_dev *sdev, bool nowait)
+{
+ if (nowait) {
+ if (!mutex_trylock(&sdev->lock))
+ return -EAGAIN;
+ } else {
+ if (mutex_lock_interruptible(&sdev->lock))
+ return -ERESTARTSYS;
+ }
+ return 0;
+}
+
static ssize_t
tbstream_dev_fops_read_iter(struct kiocb *kiocb, struct iov_iter *to)
{
struct file *file = kiocb->ki_filp;
+ bool nowait = file->f_flags & O_NONBLOCK || kiocb->ki_flags & IOCB_NOWAIT;
struct tbstream_dev *sdev = to_tbstream_dev(file->private_data);
size_t nbytes;
int ret;
@@ -645,14 +658,16 @@ tbstream_dev_fops_read_iter(struct kiocb *kiocb, struct iov_iter *to)
if (ret)
return ret;
- if (mutex_lock_interruptible(&sdev->lock))
- return -ERESTARTSYS;
+ ret = tbstream_dev_lock(sdev, nowait);
+ if (ret)
+ return ret;
while (!tbstream_ring_available(&sdev->rx_ring)) {
mutex_unlock(&sdev->lock);
- if (file->f_flags & O_NONBLOCK)
+ if (nowait)
return -EAGAIN;
+
ret = wait_event_interruptible(sdev->wait,
tbstream_ring_available(&sdev->rx_ring) ||
tbstream_dev_valid(sdev) != 0 ||
@@ -668,8 +683,9 @@ tbstream_dev_fops_read_iter(struct kiocb *kiocb, struct iov_iter *to)
if (tbstream_dev_closed(sdev) || tbstream_dev_removed(sdev))
return 0;
- if (mutex_lock_interruptible(&sdev->lock))
- return -ERESTARTSYS;
+ ret = tbstream_dev_lock(sdev, nowait);
+ if (ret)
+ return ret;
}
nbytes = 0;
@@ -729,6 +745,7 @@ static ssize_t
tbstream_dev_fops_write_iter(struct kiocb *kiocb, struct iov_iter *from)
{
struct file *file = kiocb->ki_filp;
+ bool nowait = file->f_flags & O_NONBLOCK || kiocb->ki_flags & IOCB_NOWAIT;
struct tbstream_dev *sdev = to_tbstream_dev(file->private_data);
size_t nbytes;
int ret;
@@ -737,14 +754,16 @@ tbstream_dev_fops_write_iter(struct kiocb *kiocb, struct iov_iter *from)
if (ret)
return ret;
- if (mutex_lock_interruptible(&sdev->lock))
- return -ERESTARTSYS;
+ ret = tbstream_dev_lock(sdev, nowait);
+ if (ret)
+ return ret;
while (!tbstream_ring_available(&sdev->tx_ring)) {
mutex_unlock(&sdev->lock);
- if (file->f_flags & O_NONBLOCK)
+ if (nowait)
return -EAGAIN;
+
ret = wait_event_interruptible(sdev->wait,
tbstream_ring_available(&sdev->tx_ring) ||
tbstream_dev_valid(sdev) != 0 ||
@@ -760,8 +779,9 @@ tbstream_dev_fops_write_iter(struct kiocb *kiocb, struct iov_iter *from)
if (tbstream_dev_closed(sdev) || tbstream_dev_removed(sdev))
return -ENXIO;
- if (mutex_lock_interruptible(&sdev->lock))
- return -ERESTARTSYS;
+ ret = tbstream_dev_lock(sdev, nowait);
+ if (ret)
+ return ret;
}
nbytes = 0;