staging: axis-fifo: flush RX FIFO on read errors

commit 82a051e255 upstream.

Flush stale data from the RX FIFO in case of errors, to avoid reading
old data when new packets arrive.

Commit c6e8d85faf ("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: c6e8d85faf ("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>
This commit is contained in:
Ovidiu Panait
2025-09-12 13:13:22 +03:00
committed by Greg Kroah-Hartman
parent 5873888534
commit 86bdd3deca

View File

@@ -400,6 +400,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;
@@ -410,7 +411,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)) {
@@ -419,11 +420,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
*/
@@ -435,18 +434,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);
ret = bytes_available;
return bytes_available;
err_flush_rx:
while (words_available--)
ioread32(fifo->base_addr + XLLF_RDFD_OFFSET);
end_unlock:
mutex_unlock(&fifo->read_lock);