summaryrefslogtreecommitdiff
path: root/drivers/staging
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-10-12 12:57:19 +0200
commit99d67efda945a02eb29891b4d01256b46caba7a8 (patch)
treebfbebf9d72bc441c79b52418064a6863709be310 /drivers/staging
parent7441d70d5cd6c1943caa107125c54c71070c3611 (diff)
downloadlinux-99d67efda945a02eb29891b4d01256b46caba7a8.tar.gz
linux-99d67efda945a02eb29891b4d01256b46caba7a8.tar.bz2
linux-99d67efda945a02eb29891b4d01256b46caba7a8.zip
staging: axis-fifo: flush RX FIFO on read errors
commit 82a051e2553b9e297cba82a975d9c538b882c79e upstream. 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>
Diffstat (limited to 'drivers/staging')
-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 b587d1c7a724..028ed5d0ecbe 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -391,6 +391,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;
@@ -401,7 +402,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)) {
@@ -410,11 +411,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
*/
@@ -426,18 +425,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);