From: Greg Kroah-Hartman Date: Wed, 8 Oct 2025 07:00:59 +0000 (+0200) Subject: 6.16-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c275e6a7f2282208b5434efb69c0df7aef4d1b7;p=thirdparty%2Fkernel%2Fstable-queue.git 6.16-stable patches added patches: binder-fix-double-free-in-dbitmap.patch driver-core-faux-set-power.no_pm-for-faux-devices.patch driver-core-pm-set-power.no_callbacks-along-with-power.no_pm.patch drivers-misc-amd-sbi-kconfig-select-regmap_i2c.patch nvmem-layouts-fix-automatic-module-loading.patch serial-stm32-allow-selecting-console-when-the-driver-is-module.patch staging-axis-fifo-fix-maximum-tx-packet-length-check.patch staging-axis-fifo-fix-tx-handling-on-copy_from_user-failure.patch staging-axis-fifo-flush-rx-fifo-on-read-errors.patch --- diff --git a/queue-6.16/binder-fix-double-free-in-dbitmap.patch b/queue-6.16/binder-fix-double-free-in-dbitmap.patch new file mode 100644 index 0000000000..f7182022fd --- /dev/null +++ b/queue-6.16/binder-fix-double-free-in-dbitmap.patch @@ -0,0 +1,66 @@ +From 3ebcd3460cad351f198c39c6edb4af519a0ed934 Mon Sep 17 00:00:00 2001 +From: Carlos Llamas +Date: Mon, 15 Sep 2025 22:12:47 +0000 +Subject: binder: fix double-free in dbitmap + +From: Carlos Llamas + +commit 3ebcd3460cad351f198c39c6edb4af519a0ed934 upstream. + +A process might fail to allocate a new bitmap when trying to expand its +proc->dmap. In that case, dbitmap_grow() fails and frees the old bitmap +via dbitmap_free(). However, the driver calls dbitmap_free() again when +the same process terminates, leading to a double-free error: + + ================================================================== + BUG: KASAN: double-free in binder_proc_dec_tmpref+0x2e0/0x55c + Free of addr ffff00000b7c1420 by task kworker/9:1/209 + + CPU: 9 UID: 0 PID: 209 Comm: kworker/9:1 Not tainted 6.17.0-rc6-dirty #5 PREEMPT + Hardware name: linux,dummy-virt (DT) + Workqueue: events binder_deferred_func + Call trace: + kfree+0x164/0x31c + binder_proc_dec_tmpref+0x2e0/0x55c + binder_deferred_func+0xc24/0x1120 + process_one_work+0x520/0xba4 + [...] + + Allocated by task 448: + __kmalloc_noprof+0x178/0x3c0 + bitmap_zalloc+0x24/0x30 + binder_open+0x14c/0xc10 + [...] + + Freed by task 449: + kfree+0x184/0x31c + binder_inc_ref_for_node+0xb44/0xe44 + binder_transaction+0x29b4/0x7fbc + binder_thread_write+0x1708/0x442c + binder_ioctl+0x1b50/0x2900 + [...] + ================================================================== + +Fix this issue by marking proc->map NULL in dbitmap_free(). + +Cc: stable@vger.kernel.org +Fixes: 15d9da3f818c ("binder: use bitmap for faster descriptor lookup") +Signed-off-by: Carlos Llamas +Reviewed-by: Alice Ryhl +Reviewed-by: Tiffany Yang +Link: https://lore.kernel.org/r/20250915221248.3470154-1-cmllamas@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/android/dbitmap.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/android/dbitmap.h ++++ b/drivers/android/dbitmap.h +@@ -37,6 +37,7 @@ static inline void dbitmap_free(struct d + { + dmap->nbits = 0; + kfree(dmap->map); ++ dmap->map = NULL; + } + + /* Returns the nbits that a dbitmap can shrink to, 0 if not possible. */ diff --git a/queue-6.16/driver-core-faux-set-power.no_pm-for-faux-devices.patch b/queue-6.16/driver-core-faux-set-power.no_pm-for-faux-devices.patch new file mode 100644 index 0000000000..67859cdc17 --- /dev/null +++ b/queue-6.16/driver-core-faux-set-power.no_pm-for-faux-devices.patch @@ -0,0 +1,31 @@ +From 1ad926459970444af1140f9b393f416536e1a828 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Thu, 28 Aug 2025 12:56:41 +0200 +Subject: driver core: faux: Set power.no_pm for faux devices + +From: Rafael J. Wysocki + +commit 1ad926459970444af1140f9b393f416536e1a828 upstream. + +Since faux devices are not supposed to be involved in any kind of +power management, set the no_pm flag for all of them. + +Signed-off-by: Rafael J. Wysocki +Cc: stable +Reviewed-by: Sudeep Holla +Link: https://lore.kernel.org/r/6206518.lOV4Wx5bFT@rafael.j.wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/base/faux.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/base/faux.c ++++ b/drivers/base/faux.c +@@ -155,6 +155,7 @@ struct faux_device *faux_device_create_w + dev->parent = &faux_bus_root; + dev->bus = &faux_bus_type; + dev_set_name(dev, "%s", name); ++ device_set_pm_not_required(dev); + + ret = device_add(dev); + if (ret) { diff --git a/queue-6.16/driver-core-pm-set-power.no_callbacks-along-with-power.no_pm.patch b/queue-6.16/driver-core-pm-set-power.no_callbacks-along-with-power.no_pm.patch new file mode 100644 index 0000000000..8bd5da8e30 --- /dev/null +++ b/queue-6.16/driver-core-pm-set-power.no_callbacks-along-with-power.no_pm.patch @@ -0,0 +1,41 @@ +From c2ce2453413d429e302659abc5ace634e873f6f5 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Thu, 28 Aug 2025 12:59:24 +0200 +Subject: driver core/PM: Set power.no_callbacks along with power.no_pm + +From: Rafael J. Wysocki + +commit c2ce2453413d429e302659abc5ace634e873f6f5 upstream. + +Devices with power.no_pm set are not expected to need any power +management at all, so modify device_set_pm_not_required() to set +power.no_callbacks for them too in case runtime PM will be enabled +for any of them (which in principle may be done for convenience if +such a device participates in a dependency chain). + +Since device_set_pm_not_required() must be called before device_add() +or it would not have any effect, it can update power.no_callbacks +without locking, unlike pm_runtime_no_callbacks() that can be called +after registering the target device. + +Signed-off-by: Rafael J. Wysocki +Cc: stable +Reviewed-by: Sudeep Holla +Link: https://lore.kernel.org/r/1950054.tdWV9SEqCh@rafael.j.wysocki +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/device.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -851,6 +851,9 @@ static inline bool device_pm_not_require + static inline void device_set_pm_not_required(struct device *dev) + { + dev->power.no_pm = true; ++#ifdef CONFIG_PM ++ dev->power.no_callbacks = true; ++#endif + } + + static inline void dev_pm_syscore_device(struct device *dev, bool val) diff --git a/queue-6.16/drivers-misc-amd-sbi-kconfig-select-regmap_i2c.patch b/queue-6.16/drivers-misc-amd-sbi-kconfig-select-regmap_i2c.patch new file mode 100644 index 0000000000..5d1aa82673 --- /dev/null +++ b/queue-6.16/drivers-misc-amd-sbi-kconfig-select-regmap_i2c.patch @@ -0,0 +1,51 @@ +From 5f8f84e286f11af4c954c14a57daffc80a1c3510 Mon Sep 17 00:00:00 2001 +From: Max Kellermann +Date: Fri, 29 Aug 2025 11:14:41 +0200 +Subject: drivers/misc/amd-sbi/Kconfig: select REGMAP_I2C +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Max Kellermann + +commit 5f8f84e286f11af4c954c14a57daffc80a1c3510 upstream. + +Without CONFIG_REGMAP, rmi-i2c.c fails to build because struct +regmap_config is not defined: + + drivers/misc/amd-sbi/rmi-i2c.c: In function ‘sbrmi_i2c_probe’: + drivers/misc/amd-sbi/rmi-i2c.c:57:16: error: variable ‘sbrmi_i2c_regmap_config’ has initializer but incomplete type + 57 | struct regmap_config sbrmi_i2c_regmap_config = { + | ^~~~~~~~~~~~~ + +Additionally, CONFIG_REGMAP_I2C is needed for devm_regmap_init_i2c(): + + ld: drivers/misc/amd-sbi/rmi-i2c.o: in function `sbrmi_i2c_probe': + drivers/misc/amd-sbi/rmi-i2c.c:69:(.text+0x1c0): undefined reference to `__devm_regmap_init_i2c' + +Fixes: 013f7e7131bd ("misc: amd-sbi: Use regmap subsystem") +Cc: stable@vger.kernel.org +Signed-off-by: Max Kellermann +Tested-by: Akshay Gupta +Reviewed-by: Akshay Gupta +Link: https://lore.kernel.org/r/20250829091442.1112106-1-max.kellermann@ionos.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/misc/amd-sbi/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/misc/amd-sbi/Kconfig b/drivers/misc/amd-sbi/Kconfig +index 4840831c84ca..4aae0733d0fc 100644 +--- a/drivers/misc/amd-sbi/Kconfig ++++ b/drivers/misc/amd-sbi/Kconfig +@@ -2,6 +2,7 @@ + config AMD_SBRMI_I2C + tristate "AMD side band RMI support" + depends on I2C ++ select REGMAP_I2C + help + Side band RMI over I2C support for AMD out of band management. + +-- +2.51.0 + diff --git a/queue-6.16/nvmem-layouts-fix-automatic-module-loading.patch b/queue-6.16/nvmem-layouts-fix-automatic-module-loading.patch new file mode 100644 index 0000000000..11c6edf16e --- /dev/null +++ b/queue-6.16/nvmem-layouts-fix-automatic-module-loading.patch @@ -0,0 +1,50 @@ +From 810b790033ccc795d55cbef3927668fd01efdfdf Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Fri, 12 Sep 2025 14:13:47 +0100 +Subject: nvmem: layouts: fix automatic module loading + +From: Michael Walle + +commit 810b790033ccc795d55cbef3927668fd01efdfdf upstream. + +To support loading of a layout module automatically the MODALIAS +variable in the uevent is needed. Add it. + +Fixes: fc29fd821d9a ("nvmem: core: Rework layouts to become regular devices") +Cc: stable@vger.kernel.org +Signed-off-by: Michael Walle +Reviewed-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250912131347.303345-2-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/layouts.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/nvmem/layouts.c ++++ b/drivers/nvmem/layouts.c +@@ -45,11 +45,24 @@ static void nvmem_layout_bus_remove(stru + return drv->remove(layout); + } + ++static int nvmem_layout_bus_uevent(const struct device *dev, ++ struct kobj_uevent_env *env) ++{ ++ int ret; ++ ++ ret = of_device_uevent_modalias(dev, env); ++ if (ret != ENODEV) ++ return ret; ++ ++ return 0; ++} ++ + static const struct bus_type nvmem_layout_bus_type = { + .name = "nvmem-layout", + .match = nvmem_layout_bus_match, + .probe = nvmem_layout_bus_probe, + .remove = nvmem_layout_bus_remove, ++ .uevent = nvmem_layout_bus_uevent, + }; + + int __nvmem_layout_driver_register(struct nvmem_layout_driver *drv, diff --git a/queue-6.16/serial-stm32-allow-selecting-console-when-the-driver-is-module.patch b/queue-6.16/serial-stm32-allow-selecting-console-when-the-driver-is-module.patch new file mode 100644 index 0000000000..5a1de24316 --- /dev/null +++ b/queue-6.16/serial-stm32-allow-selecting-console-when-the-driver-is-module.patch @@ -0,0 +1,32 @@ +From cc4d900d0d6d8dd5c41832a93ff3cfa629a78f9a Mon Sep 17 00:00:00 2001 +From: Raphael Gallais-Pou +Date: Fri, 22 Aug 2025 16:19:23 +0200 +Subject: serial: stm32: allow selecting console when the driver is module + +From: Raphael Gallais-Pou + +commit cc4d900d0d6d8dd5c41832a93ff3cfa629a78f9a upstream. + +Console can be enabled on the UART compile as module. +Change dependency to allow console mode when the driver is built as module. + +Fixes: 48a6092fb41fa ("serial: stm32-usart: Add STM32 USART Driver") +Cc: stable@vger.kernel.org +Signed-off-by: Raphael Gallais-Pou +Link: https://lore.kernel.org/r/20250822141923.61133-1-raphael.gallais-pou@foss.st.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -1405,7 +1405,7 @@ config SERIAL_STM32 + + config SERIAL_STM32_CONSOLE + bool "Support for console on STM32" +- depends on SERIAL_STM32=y ++ depends on SERIAL_STM32 + select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON + diff --git a/queue-6.16/series b/queue-6.16/series index a39e9f2f1c..c545803249 100644 --- a/queue-6.16/series +++ b/queue-6.16/series @@ -26,3 +26,12 @@ can-hi311x-fix-null-pointer-dereference-when-resumin.patch can-rcar_canfd-fix-controller-mode-setting.patch platform-x86-amd-pmc-add-stellaris-slim-gen6-amd-to-.patch hid-fix-i2c-read-buffer-overflow-in-raw_event-for-mcp2221.patch +nvmem-layouts-fix-automatic-module-loading.patch +drivers-misc-amd-sbi-kconfig-select-regmap_i2c.patch +binder-fix-double-free-in-dbitmap.patch +serial-stm32-allow-selecting-console-when-the-driver-is-module.patch +staging-axis-fifo-fix-maximum-tx-packet-length-check.patch +staging-axis-fifo-fix-tx-handling-on-copy_from_user-failure.patch +staging-axis-fifo-flush-rx-fifo-on-read-errors.patch +driver-core-faux-set-power.no_pm-for-faux-devices.patch +driver-core-pm-set-power.no_callbacks-along-with-power.no_pm.patch diff --git a/queue-6.16/staging-axis-fifo-fix-maximum-tx-packet-length-check.patch b/queue-6.16/staging-axis-fifo-fix-maximum-tx-packet-length-check.patch new file mode 100644 index 0000000000..44a4424f63 --- /dev/null +++ b/queue-6.16/staging-axis-fifo-fix-maximum-tx-packet-length-check.patch @@ -0,0 +1,71 @@ +From 52ff2b840bc723f3be1f096f8017c78e0515858c Mon Sep 17 00:00:00 2001 +From: Ovidiu Panait +Date: Sun, 17 Aug 2025 20:13:50 +0300 +Subject: staging: axis-fifo: fix maximum TX packet length check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ovidiu Panait + +commit 52ff2b840bc723f3be1f096f8017c78e0515858c upstream. + +Since commit 2ca34b508774 ("staging: axis-fifo: Correct handling of +tx_fifo_depth for size validation"), write() operations with packets +larger than 'tx_fifo_depth - 4' words are no longer rejected with -EINVAL. + +Fortunately, the packets are not actually getting transmitted to hardware, +otherwise they would be raising a 'Transmit Packet Overrun Error' +interrupt, which requires a reset of the TX circuit to recover from. + +Instead, the request times out inside wait_event_interruptible_timeout() +and always returns -EAGAIN, since the wake up condition can never be true +for these packets. But still, they unnecessarily block other tasks from +writing to the FIFO and the EAGAIN return code signals userspace to retry +the write() call, even though it will always fail and time out. + +According to the AXI4-Stream FIFO reference manual (PG080), the maximum +valid packet length is 'tx_fifo_depth - 4' words, so attempting to send +larger packets is invalid and should not be happening in the first place: + +> The maximum packet that can be transmitted is limited by the size of +> the FIFO, which is (C_TX_FIFO_DEPTH–4)*(data interface width/8) bytes. + +Therefore, bring back the old behavior and outright reject packets larger +than 'tx_fifo_depth - 4' with -EINVAL. Add a comment to explain why the +check is necessary. The dev_err() message was removed to avoid cluttering +the dmesg log if an invalid packet is received from userspace. + +Fixes: 2ca34b508774 ("staging: axis-fifo: Correct handling of tx_fifo_depth for size validation") +Cc: stable@vger.kernel.org +Signed-off-by: Ovidiu Panait +Link: https://lore.kernel.org/r/20250817171350.872105-1-ovidiu.panait.oss@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/axis-fifo/axis-fifo.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/staging/axis-fifo/axis-fifo.c ++++ b/drivers/staging/axis-fifo/axis-fifo.c +@@ -486,11 +486,17 @@ static ssize_t axis_fifo_write(struct fi + return -EINVAL; + } + +- if (words_to_write > fifo->tx_fifo_depth) { +- dev_err(fifo->dt_device, "tried to write more words [%u] than slots in the fifo buffer [%u]\n", +- words_to_write, fifo->tx_fifo_depth); ++ /* ++ * In 'Store-and-Forward' mode, the maximum packet that can be ++ * transmitted is limited by the size of the FIFO, which is ++ * (C_TX_FIFO_DEPTH–4)*(data interface width/8) bytes. ++ * ++ * Do not attempt to send a packet larger than 'tx_fifo_depth - 4', ++ * otherwise a 'Transmit Packet Overrun Error' interrupt will be ++ * raised, which requires a reset of the TX circuit to recover. ++ */ ++ if (words_to_write > (fifo->tx_fifo_depth - 4)) + return -EINVAL; +- } + + if (fifo->write_flags & O_NONBLOCK) { + /* diff --git a/queue-6.16/staging-axis-fifo-fix-tx-handling-on-copy_from_user-failure.patch b/queue-6.16/staging-axis-fifo-fix-tx-handling-on-copy_from_user-failure.patch new file mode 100644 index 0000000000..bfa3f30715 --- /dev/null +++ b/queue-6.16/staging-axis-fifo-fix-tx-handling-on-copy_from_user-failure.patch @@ -0,0 +1,97 @@ +From 6d07bee10e4bdd043ec7152cbbb9deb27033c9e2 Mon Sep 17 00:00:00 2001 +From: Ovidiu Panait +Date: Fri, 12 Sep 2025 13:13:21 +0300 +Subject: staging: axis-fifo: fix TX handling on copy_from_user() failure + +From: Ovidiu Panait + +commit 6d07bee10e4bdd043ec7152cbbb9deb27033c9e2 upstream. + +If copy_from_user() fails, write() currently returns -EFAULT, but any +partially written data leaves the TX FIFO in an inconsistent state. +Subsequent write() calls then fail with "transmit length mismatch" +errors. + +Once partial data is written to the hardware FIFO, it cannot be removed +without a TX reset. Commit c6e8d85fafa7 ("staging: axis-fifo: Remove +hardware resets for user errors") removed a full FIFO reset for this case, +which fixed a potential RX data loss, but introduced this TX issue. + +Fix this by introducing a bounce buffer: copy the full packet from +userspace first, and write to the hardware FIFO only if the copy +was successful. + +Fixes: c6e8d85fafa7 ("staging: axis-fifo: Remove hardware resets for user errors") +Cc: stable@vger.kernel.org +Signed-off-by: Ovidiu Panait +Link: https://lore.kernel.org/r/20250912101322.1282507-1-ovidiu.panait.oss@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/axis-fifo/axis-fifo.c | 36 +++++++++------------------------- + 1 file changed, 10 insertions(+), 26 deletions(-) + +--- a/drivers/staging/axis-fifo/axis-fifo.c ++++ b/drivers/staging/axis-fifo/axis-fifo.c +@@ -42,7 +42,6 @@ + #define DRIVER_NAME "axis_fifo" + + #define READ_BUF_SIZE 128U /* read buffer length in words */ +-#define WRITE_BUF_SIZE 128U /* write buffer length in words */ + + /* ---------------------------- + * IP register offsets +@@ -466,11 +465,8 @@ static ssize_t axis_fifo_write(struct fi + { + struct axis_fifo *fifo = (struct axis_fifo *)f->private_data; + unsigned int words_to_write; +- unsigned int copied; +- unsigned int copy; +- unsigned int i; ++ u32 *txbuf; + int ret; +- u32 tmp_buf[WRITE_BUF_SIZE]; + + if (len % sizeof(u32)) { + dev_err(fifo->dt_device, +@@ -535,32 +531,20 @@ static ssize_t axis_fifo_write(struct fi + } + } + +- /* write data from an intermediate buffer into the fifo IP, refilling +- * the buffer with userspace data as needed +- */ +- copied = 0; +- while (words_to_write > 0) { +- copy = min(words_to_write, WRITE_BUF_SIZE); +- +- if (copy_from_user(tmp_buf, buf + copied * sizeof(u32), +- copy * sizeof(u32))) { +- ret = -EFAULT; +- goto end_unlock; +- } +- +- for (i = 0; i < copy; i++) +- iowrite32(tmp_buf[i], fifo->base_addr + +- XLLF_TDFD_OFFSET); +- +- copied += copy; +- words_to_write -= copy; ++ txbuf = vmemdup_user(buf, len); ++ if (IS_ERR(txbuf)) { ++ ret = PTR_ERR(txbuf); ++ goto end_unlock; + } + +- ret = copied * sizeof(u32); ++ for (int i = 0; i < words_to_write; ++i) ++ iowrite32(txbuf[i], fifo->base_addr + XLLF_TDFD_OFFSET); + + /* write packet size to fifo */ +- iowrite32(ret, fifo->base_addr + XLLF_TLR_OFFSET); ++ iowrite32(len, fifo->base_addr + XLLF_TLR_OFFSET); + ++ ret = len; ++ kvfree(txbuf); + end_unlock: + mutex_unlock(&fifo->write_lock); + diff --git a/queue-6.16/staging-axis-fifo-flush-rx-fifo-on-read-errors.patch b/queue-6.16/staging-axis-fifo-flush-rx-fifo-on-read-errors.patch new file mode 100644 index 0000000000..e2f874a476 --- /dev/null +++ b/queue-6.16/staging-axis-fifo-flush-rx-fifo-on-read-errors.patch @@ -0,0 +1,84 @@ +From 82a051e2553b9e297cba82a975d9c538b882c79e Mon Sep 17 00:00:00 2001 +From: Ovidiu Panait +Date: Fri, 12 Sep 2025 13:13:22 +0300 +Subject: staging: axis-fifo: flush RX FIFO on read errors + +From: Ovidiu Panait + +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 +Link: https://lore.kernel.org/r/20250912101322.1282507-2-ovidiu.panait.oss@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/axis-fifo/axis-fifo.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- 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 fil + } + + 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 fil + 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 fil + */ + 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 fil + 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);