Commit 82a051e2 authored by Ovidiu Panait's avatar Ovidiu Panait Committed by Greg Kroah-Hartman
Browse files

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 c6e8d85f ("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: c6e8d85f ("staging: axis-fifo: Remove hardware resets for user errors")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarOvidiu Panait <ovidiu.panait.oss@gmail.com>
Link: https://lore.kernel.org/r/20250912101322.1282507-2-ovidiu.panait.oss@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6d07bee1
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -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);