diff options
| author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2026-06-17 07:42:06 +0300 |
|---|---|---|
| committer | Mika Westerberg <mika.westerberg@linux.intel.com> | 2026-08-05 05:53:57 +0200 |
| commit | 42bc6935339b913d424331a62f9e965bc72ca3df (patch) | |
| tree | afc3941f0dd4dc7a1f4637605529effc27f4db11 | |
| parent | af73a21a8eb460744d733fa5e2627935ed125081 (diff) | |
| download | linux-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.c | 40 |
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; |
