]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
staging: axis-fifo: flush RX FIFO on read errors
authorOvidiu Panait <ovidiu.panait.oss@gmail.com>
Fri, 12 Sep 2025 10:13:22 +0000 (13:13 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 12 Oct 2025 11:01:04 +0000 (13:01 +0200)
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>
drivers/staging/axis-fifo/axis-fifo.c

index 557188786004bfd075a276df827ca7941b6172fc..d88e026204e0523c3cb24d4be92aefc8a3e7644e 100644 (file)
@@ -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);