]> www.infradead.org Git - users/hch/misc.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>
Fri, 12 Sep 2025 14:21:46 +0000 (16:21 +0200)
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 c03b961896b9ead3479216219a0eed0038bcae45..b6261b96e4651c7895fea979035033b534be5f03 100644 (file)
@@ -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);