summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOvidiu Panait <ovidiu.panait.oss@gmail.com>2025-09-12 13:13:22 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-09-12 16:21:46 +0200
commit82a051e2553b9e297cba82a975d9c538b882c79e (patch)
treeed4d5b67afdf8684ad87f4bfb6b5d98bc166f82c
parent6d07bee10e4bdd043ec7152cbbb9deb27033c9e2 (diff)
staging: axis-fifo: flush RX FIFO on read errors
Flush stale data from the RX FIFO in case of errors, to avoid reading old data when new packets arrive. Commit c6e8d85fafa7 ("staging: axis-fifo: Remove hardware resets for user errors") removed full FIFO resets from the read error paths, which fixed potential TX data losses, but introduced this RX issue. Fixes: c6e8d85fafa7 ("staging: axis-fifo: Remove hardware resets for user errors") Cc: stable@vger.kernel.org Signed-off-by: Ovidiu Panait <ovidiu.panait.oss@gmail.com> Link: https://lore.kernel.org/r/20250912101322.1282507-2-ovidiu.panait.oss@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c
index c03b961896b9..b6261b96e465 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -227,6 +227,7 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
}
bytes_available = ioread32(fifo->base_addr + XLLF_RLR_OFFSET);
+ words_available = bytes_available / sizeof(u32);
if (!bytes_available) {
dev_err(fifo->dt_device, "received a packet of length 0\n");
ret = -EIO;
@@ -237,7 +238,7 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu)\n",
bytes_available, len);
ret = -EINVAL;
- goto end_unlock;
+ goto err_flush_rx;
}
if (bytes_available % sizeof(u32)) {
@@ -246,11 +247,9 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
*/
dev_err(fifo->dt_device, "received a packet that isn't word-aligned\n");
ret = -EIO;
- goto end_unlock;
+ goto err_flush_rx;
}
- words_available = bytes_available / sizeof(u32);
-
/* read data into an intermediate buffer, copying the contents
* to userspace when the buffer is full
*/
@@ -262,18 +261,23 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf,
tmp_buf[i] = ioread32(fifo->base_addr +
XLLF_RDFD_OFFSET);
}
+ words_available -= copy;
if (copy_to_user(buf + copied * sizeof(u32), tmp_buf,
copy * sizeof(u32))) {
ret = -EFAULT;
- goto end_unlock;
+ goto err_flush_rx;
}
copied += copy;
- words_available -= copy;
}
+ mutex_unlock(&fifo->read_lock);
+
+ return bytes_available;
- ret = bytes_available;
+err_flush_rx:
+ while (words_available--)
+ ioread32(fifo->base_addr + XLLF_RDFD_OFFSET);
end_unlock:
mutex_unlock(&fifo->read_lock);