From: Greg Kroah-Hartman Date: Mon, 17 Aug 2020 12:56:05 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.19.140~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dd74710930ae90621c775902fd27683c92bc3a67;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: arm-8992-1-fix-unwind_frame-for-clang-built-kernels.patch include-asm-generic-vmlinux.lds.h-align-ro_after_init.patch irqdomain-treewide-free-firmware-node-after-domain-removal.patch mtd-rawnand-qcom-avoid-write-to-unavailable-register.patch parisc-implement-__smp_store_release-and-__smp_load_acquire-barriers.patch parisc-mask-out-enable-and-reserved-bits-from-sba-imask.patch spi-spidev-align-buffers-for-dma.patch --- diff --git a/queue-4.19/arm-8992-1-fix-unwind_frame-for-clang-built-kernels.patch b/queue-4.19/arm-8992-1-fix-unwind_frame-for-clang-built-kernels.patch new file mode 100644 index 00000000000..6ac98d59524 --- /dev/null +++ b/queue-4.19/arm-8992-1-fix-unwind_frame-for-clang-built-kernels.patch @@ -0,0 +1,80 @@ +From b4d5ec9b39f8b31d98f65bc5577b5d15d93795d7 Mon Sep 17 00:00:00 2001 +From: Nathan Huckleberry +Date: Fri, 10 Jul 2020 20:23:37 +0100 +Subject: ARM: 8992/1: Fix unwind_frame for clang-built kernels + +From: Nathan Huckleberry + +commit b4d5ec9b39f8b31d98f65bc5577b5d15d93795d7 upstream. + +Since clang does not push pc and sp in function prologues, the current +implementation of unwind_frame does not work. By using the previous +frame's lr/fp instead of saved pc/sp we get valid unwinds on clang-built +kernels. + +The bounds check on next frame pointer must be changed as well since +there are 8 less bytes between frames. + +This fixes /proc//stack. + +Link: https://github.com/ClangBuiltLinux/linux/issues/912 + +Reported-by: Miles Chen +Tested-by: Miles Chen +Cc: stable@vger.kernel.org +Reviewed-by: Nick Desaulniers +Signed-off-by: Nathan Huckleberry +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/kernel/stacktrace.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/arch/arm/kernel/stacktrace.c ++++ b/arch/arm/kernel/stacktrace.c +@@ -21,6 +21,19 @@ + * A simple function epilogue looks like this: + * ldm sp, {fp, sp, pc} + * ++ * When compiled with clang, pc and sp are not pushed. A simple function ++ * prologue looks like this when built with clang: ++ * ++ * stmdb {..., fp, lr} ++ * add fp, sp, #x ++ * sub sp, sp, #y ++ * ++ * A simple function epilogue looks like this when built with clang: ++ * ++ * sub sp, fp, #x ++ * ldm {..., fp, pc} ++ * ++ * + * Note that with framepointer enabled, even the leaf functions have the same + * prologue and epilogue, therefore we can ignore the LR value in this case. + */ +@@ -33,6 +46,16 @@ int notrace unwind_frame(struct stackfra + low = frame->sp; + high = ALIGN(low, THREAD_SIZE); + ++#ifdef CONFIG_CC_IS_CLANG ++ /* check current frame pointer is within bounds */ ++ if (fp < low + 4 || fp > high - 4) ++ return -EINVAL; ++ ++ frame->sp = frame->fp; ++ frame->fp = *(unsigned long *)(fp); ++ frame->pc = frame->lr; ++ frame->lr = *(unsigned long *)(fp + 4); ++#else + /* check current frame pointer is within bounds */ + if (fp < low + 12 || fp > high - 4) + return -EINVAL; +@@ -41,6 +64,7 @@ int notrace unwind_frame(struct stackfra + frame->fp = *(unsigned long *)(fp - 12); + frame->sp = *(unsigned long *)(fp - 8); + frame->pc = *(unsigned long *)(fp - 4); ++#endif + + return 0; + } diff --git a/queue-4.19/include-asm-generic-vmlinux.lds.h-align-ro_after_init.patch b/queue-4.19/include-asm-generic-vmlinux.lds.h-align-ro_after_init.patch new file mode 100644 index 00000000000..efa99494f2e --- /dev/null +++ b/queue-4.19/include-asm-generic-vmlinux.lds.h-align-ro_after_init.patch @@ -0,0 +1,48 @@ +From 7f897acbe5d57995438c831670b7c400e9c0dc00 Mon Sep 17 00:00:00 2001 +From: Romain Naour +Date: Fri, 14 Aug 2020 17:31:57 -0700 +Subject: include/asm-generic/vmlinux.lds.h: align ro_after_init + +From: Romain Naour + +commit 7f897acbe5d57995438c831670b7c400e9c0dc00 upstream. + +Since the patch [1], building the kernel using a toolchain built with +binutils 2.33.1 prevents booting a sh4 system under Qemu. Apply the patch +provided by Alan Modra [2] that fix alignment of rodata. + +[1] https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ebd2263ba9a9124d93bbc0ece63d7e0fae89b40e +[2] https://www.sourceware.org/ml/binutils/2019-12/msg00112.html + +Signed-off-by: Romain Naour +Signed-off-by: Andrew Morton +Cc: Alan Modra +Cc: Bin Meng +Cc: Chen Zhou +Cc: Geert Uytterhoeven +Cc: John Paul Adrian Glaubitz +Cc: Krzysztof Kozlowski +Cc: Kuninori Morimoto +Cc: Rich Felker +Cc: Sam Ravnborg +Cc: Yoshinori Sato +Cc: Arnd Bergmann +Cc: +Link: https://marc.info/?l=linux-sh&m=158429470221261 +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/asm-generic/vmlinux.lds.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -307,6 +307,7 @@ + */ + #ifndef RO_AFTER_INIT_DATA + #define RO_AFTER_INIT_DATA \ ++ . = ALIGN(8); \ + __start_ro_after_init = .; \ + *(.data..ro_after_init) \ + __end_ro_after_init = .; diff --git a/queue-4.19/irqdomain-treewide-free-firmware-node-after-domain-removal.patch b/queue-4.19/irqdomain-treewide-free-firmware-node-after-domain-removal.patch new file mode 100644 index 00000000000..6ead132da43 --- /dev/null +++ b/queue-4.19/irqdomain-treewide-free-firmware-node-after-domain-removal.patch @@ -0,0 +1,103 @@ +From ec0160891e387f4771f953b888b1fe951398e5d9 Mon Sep 17 00:00:00 2001 +From: Jon Derrick +Date: Tue, 21 Jul 2020 14:26:09 -0600 +Subject: irqdomain/treewide: Free firmware node after domain removal + +From: Jon Derrick + +commit ec0160891e387f4771f953b888b1fe951398e5d9 upstream. + +Commit 711419e504eb ("irqdomain: Add the missing assignment of +domain->fwnode for named fwnode") unintentionally caused a dangling pointer +page fault issue on firmware nodes that were freed after IRQ domain +allocation. Commit e3beca48a45b fixed that dangling pointer issue by only +freeing the firmware node after an IRQ domain allocation failure. That fix +no longer frees the firmware node immediately, but leaves the firmware node +allocated after the domain is removed. + +The firmware node must be kept around through irq_domain_remove, but should be +freed it afterwards. + +Add the missing free operations after domain removal where where appropriate. + +Fixes: e3beca48a45b ("irqdomain/treewide: Keep firmware node unconditionally allocated") +Signed-off-by: Jon Derrick +Signed-off-by: Thomas Gleixner +Reviewed-by: Andy Shevchenko +Acked-by: Bjorn Helgaas # drivers/pci +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/1595363169-7157-1-git-send-email-jonathan.derrick@intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/apic/io_apic.c | 5 +++++ + drivers/iommu/intel_irq_remapping.c | 8 ++++++++ + drivers/pci/controller/vmd.c | 3 +++ + 3 files changed, 16 insertions(+) + +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -2342,8 +2342,13 @@ static int mp_irqdomain_create(int ioapi + + static void ioapic_destroy_irqdomain(int idx) + { ++ struct ioapic_domain_cfg *cfg = &ioapics[idx].irqdomain_cfg; ++ struct fwnode_handle *fn = ioapics[idx].irqdomain->fwnode; ++ + if (ioapics[idx].irqdomain) { + irq_domain_remove(ioapics[idx].irqdomain); ++ if (!cfg->dev) ++ irq_domain_free_fwnode(fn); + ioapics[idx].irqdomain = NULL; + } + } +--- a/drivers/iommu/intel_irq_remapping.c ++++ b/drivers/iommu/intel_irq_remapping.c +@@ -601,13 +601,21 @@ out_free_table: + + static void intel_teardown_irq_remapping(struct intel_iommu *iommu) + { ++ struct fwnode_handle *fn; ++ + if (iommu && iommu->ir_table) { + if (iommu->ir_msi_domain) { ++ fn = iommu->ir_msi_domain->fwnode; ++ + irq_domain_remove(iommu->ir_msi_domain); ++ irq_domain_free_fwnode(fn); + iommu->ir_msi_domain = NULL; + } + if (iommu->ir_domain) { ++ fn = iommu->ir_domain->fwnode; ++ + irq_domain_remove(iommu->ir_domain); ++ irq_domain_free_fwnode(fn); + iommu->ir_domain = NULL; + } + free_pages((unsigned long)iommu->ir_table->base, +--- a/drivers/pci/controller/vmd.c ++++ b/drivers/pci/controller/vmd.c +@@ -718,6 +718,7 @@ static int vmd_enable_domain(struct vmd_ + if (!vmd->bus) { + pci_free_resource_list(&resources); + irq_domain_remove(vmd->irq_domain); ++ irq_domain_free_fwnode(fn); + return -ENODEV; + } + +@@ -820,6 +821,7 @@ static void vmd_cleanup_srcu(struct vmd_ + static void vmd_remove(struct pci_dev *dev) + { + struct vmd_dev *vmd = pci_get_drvdata(dev); ++ struct fwnode_handle *fn = vmd->irq_domain->fwnode; + + sysfs_remove_link(&vmd->dev->dev.kobj, "domain"); + pci_stop_root_bus(vmd->bus); +@@ -828,6 +830,7 @@ static void vmd_remove(struct pci_dev *d + vmd_teardown_dma_ops(vmd); + vmd_detach_resources(vmd); + irq_domain_remove(vmd->irq_domain); ++ irq_domain_free_fwnode(fn); + } + + #ifdef CONFIG_PM_SLEEP diff --git a/queue-4.19/mtd-rawnand-qcom-avoid-write-to-unavailable-register.patch b/queue-4.19/mtd-rawnand-qcom-avoid-write-to-unavailable-register.patch new file mode 100644 index 00000000000..90913d9efc8 --- /dev/null +++ b/queue-4.19/mtd-rawnand-qcom-avoid-write-to-unavailable-register.patch @@ -0,0 +1,68 @@ +From 443440cc4a901af462239d286cd10721aa1c7dfc Mon Sep 17 00:00:00 2001 +From: Sivaprakash Murugesan +Date: Fri, 12 Jun 2020 13:28:15 +0530 +Subject: mtd: rawnand: qcom: avoid write to unavailable register + +From: Sivaprakash Murugesan + +commit 443440cc4a901af462239d286cd10721aa1c7dfc upstream. + +SFLASHC_BURST_CFG is only available on older ipq NAND platforms, this +register has been removed when the NAND controller got implemented in +the qpic controller. + +Avoid writing this register on devices which are based on qpic NAND +controller. + +Fixes: dce84760b09f ("mtd: nand: qcom: Support for IPQ8074 QPIC NAND controller") +Cc: stable@vger.kernel.org +Signed-off-by: Sivaprakash Murugesan +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/1591948696-16015-2-git-send-email-sivaprak@codeaurora.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/nand/raw/qcom_nandc.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/nand/raw/qcom_nandc.c ++++ b/drivers/mtd/nand/raw/qcom_nandc.c +@@ -466,11 +466,13 @@ struct qcom_nand_host { + * among different NAND controllers. + * @ecc_modes - ecc mode for NAND + * @is_bam - whether NAND controller is using BAM ++ * @is_qpic - whether NAND CTRL is part of qpic IP + * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset + */ + struct qcom_nandc_props { + u32 ecc_modes; + bool is_bam; ++ bool is_qpic; + u32 dev_cmd_reg_start; + }; + +@@ -2766,7 +2768,8 @@ static int qcom_nandc_setup(struct qcom_ + u32 nand_ctrl; + + /* kill onenand */ +- nandc_write(nandc, SFLASHC_BURST_CFG, 0); ++ if (!nandc->props->is_qpic) ++ nandc_write(nandc, SFLASHC_BURST_CFG, 0); + nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD), + NAND_DEV_CMD_VLD_VAL); + +@@ -3022,12 +3025,14 @@ static const struct qcom_nandc_props ipq + static const struct qcom_nandc_props ipq4019_nandc_props = { + .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), + .is_bam = true, ++ .is_qpic = true, + .dev_cmd_reg_start = 0x0, + }; + + static const struct qcom_nandc_props ipq8074_nandc_props = { + .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), + .is_bam = true, ++ .is_qpic = true, + .dev_cmd_reg_start = 0x7000, + }; + diff --git a/queue-4.19/parisc-implement-__smp_store_release-and-__smp_load_acquire-barriers.patch b/queue-4.19/parisc-implement-__smp_store_release-and-__smp_load_acquire-barriers.patch new file mode 100644 index 00000000000..8cbcfec6002 --- /dev/null +++ b/queue-4.19/parisc-implement-__smp_store_release-and-__smp_load_acquire-barriers.patch @@ -0,0 +1,92 @@ +From e96ebd589debd9a6a793608c4ec7019c38785dea Mon Sep 17 00:00:00 2001 +From: John David Anglin +Date: Thu, 30 Jul 2020 08:59:12 -0400 +Subject: parisc: Implement __smp_store_release and __smp_load_acquire barriers + +From: John David Anglin + +commit e96ebd589debd9a6a793608c4ec7019c38785dea upstream. + +This patch implements the __smp_store_release and __smp_load_acquire barriers +using ordered stores and loads. This avoids the sync instruction present in +the generic implementation. + +Cc: # 4.14+ +Signed-off-by: Dave Anglin +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/parisc/include/asm/barrier.h | 61 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +--- a/arch/parisc/include/asm/barrier.h ++++ b/arch/parisc/include/asm/barrier.h +@@ -26,6 +26,67 @@ + #define __smp_rmb() mb() + #define __smp_wmb() mb() + ++#define __smp_store_release(p, v) \ ++do { \ ++ typeof(p) __p = (p); \ ++ union { typeof(*p) __val; char __c[1]; } __u = \ ++ { .__val = (__force typeof(*p)) (v) }; \ ++ compiletime_assert_atomic_type(*p); \ ++ switch (sizeof(*p)) { \ ++ case 1: \ ++ asm volatile("stb,ma %0,0(%1)" \ ++ : : "r"(*(__u8 *)__u.__c), "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ case 2: \ ++ asm volatile("sth,ma %0,0(%1)" \ ++ : : "r"(*(__u16 *)__u.__c), "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ case 4: \ ++ asm volatile("stw,ma %0,0(%1)" \ ++ : : "r"(*(__u32 *)__u.__c), "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ case 8: \ ++ if (IS_ENABLED(CONFIG_64BIT)) \ ++ asm volatile("std,ma %0,0(%1)" \ ++ : : "r"(*(__u64 *)__u.__c), "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ } \ ++} while (0) ++ ++#define __smp_load_acquire(p) \ ++({ \ ++ union { typeof(*p) __val; char __c[1]; } __u; \ ++ typeof(p) __p = (p); \ ++ compiletime_assert_atomic_type(*p); \ ++ switch (sizeof(*p)) { \ ++ case 1: \ ++ asm volatile("ldb,ma 0(%1),%0" \ ++ : "=r"(*(__u8 *)__u.__c) : "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ case 2: \ ++ asm volatile("ldh,ma 0(%1),%0" \ ++ : "=r"(*(__u16 *)__u.__c) : "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ case 4: \ ++ asm volatile("ldw,ma 0(%1),%0" \ ++ : "=r"(*(__u32 *)__u.__c) : "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ case 8: \ ++ if (IS_ENABLED(CONFIG_64BIT)) \ ++ asm volatile("ldd,ma 0(%1),%0" \ ++ : "=r"(*(__u64 *)__u.__c) : "r"(__p) \ ++ : "memory"); \ ++ break; \ ++ } \ ++ __u.__val; \ ++}) + #include + + #endif /* !__ASSEMBLY__ */ diff --git a/queue-4.19/parisc-mask-out-enable-and-reserved-bits-from-sba-imask.patch b/queue-4.19/parisc-mask-out-enable-and-reserved-bits-from-sba-imask.patch new file mode 100644 index 00000000000..bb219e4c001 --- /dev/null +++ b/queue-4.19/parisc-mask-out-enable-and-reserved-bits-from-sba-imask.patch @@ -0,0 +1,33 @@ +From 5b24993c21cbf2de11aff077a48c5cb0505a0450 Mon Sep 17 00:00:00 2001 +From: Sven Schnelle +Date: Tue, 11 Aug 2020 18:19:19 +0200 +Subject: parisc: mask out enable and reserved bits from sba imask + +From: Sven Schnelle + +commit 5b24993c21cbf2de11aff077a48c5cb0505a0450 upstream. + +When using kexec the SBA IOMMU IBASE might still have the RE +bit set. This triggers a WARN_ON when trying to write back the +IBASE register later, and it also makes some mask calculations fail. + +Cc: +Signed-off-by: Sven Schnelle +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/parisc/sba_iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/parisc/sba_iommu.c ++++ b/drivers/parisc/sba_iommu.c +@@ -1291,7 +1291,7 @@ sba_ioc_init_pluto(struct parisc_device + ** (one that doesn't overlap memory or LMMIO space) in the + ** IBASE and IMASK registers. + */ +- ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE); ++ ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1fffffULL; + iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; + + if ((ioc->ibase < 0xfed00000UL) && ((ioc->ibase + iova_space_size) > 0xfee00000UL)) { diff --git a/queue-4.19/series b/queue-4.19/series index bddad772b73..88f2504e4f2 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -156,3 +156,10 @@ drm-ttm-nouveau-don-t-call-tt-destroy-callback-on-alloc-failure.patch nfs-don-t-move-layouts-to-plh_return_segs-list-while-in-use.patch nfs-don-t-return-layout-segments-that-are-in-use.patch cpufreq-dt-fix-oops-on-armada37xx.patch +include-asm-generic-vmlinux.lds.h-align-ro_after_init.patch +spi-spidev-align-buffers-for-dma.patch +mtd-rawnand-qcom-avoid-write-to-unavailable-register.patch +parisc-implement-__smp_store_release-and-__smp_load_acquire-barriers.patch +parisc-mask-out-enable-and-reserved-bits-from-sba-imask.patch +arm-8992-1-fix-unwind_frame-for-clang-built-kernels.patch +irqdomain-treewide-free-firmware-node-after-domain-removal.patch diff --git a/queue-4.19/spi-spidev-align-buffers-for-dma.patch b/queue-4.19/spi-spidev-align-buffers-for-dma.patch new file mode 100644 index 00000000000..cfaf6026bb8 --- /dev/null +++ b/queue-4.19/spi-spidev-align-buffers-for-dma.patch @@ -0,0 +1,94 @@ +From aa9e862d7d5bcecd4dca9f39e8b684b93dd84ee7 Mon Sep 17 00:00:00 2001 +From: Christian Eggers +Date: Tue, 28 Jul 2020 12:08:32 +0200 +Subject: spi: spidev: Align buffers for DMA + +From: Christian Eggers + +commit aa9e862d7d5bcecd4dca9f39e8b684b93dd84ee7 upstream. + +Simply copying all xfers from userspace into one bounce buffer causes +alignment problems if the SPI controller uses DMA. + +Ensure that all transfer data blocks within the rx and tx bounce buffers +are aligned for DMA (according to ARCH_KMALLOC_MINALIGN). + +Alignment may increase the usage of the bounce buffers. In some cases, +the buffers may need to be increased using the "bufsiz" module +parameter. + +Signed-off-by: Christian Eggers +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200728100832.24788-1-ceggers@arri.de +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/spi/spidev.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -232,6 +232,11 @@ static int spidev_message(struct spidev_ + for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; + n; + n--, k_tmp++, u_tmp++) { ++ /* Ensure that also following allocations from rx_buf/tx_buf will meet ++ * DMA alignment requirements. ++ */ ++ unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN); ++ + k_tmp->len = u_tmp->len; + + total += k_tmp->len; +@@ -247,17 +252,17 @@ static int spidev_message(struct spidev_ + + if (u_tmp->rx_buf) { + /* this transfer needs space in RX bounce buffer */ +- rx_total += k_tmp->len; ++ rx_total += len_aligned; + if (rx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } + k_tmp->rx_buf = rx_buf; +- rx_buf += k_tmp->len; ++ rx_buf += len_aligned; + } + if (u_tmp->tx_buf) { + /* this transfer needs space in TX bounce buffer */ +- tx_total += k_tmp->len; ++ tx_total += len_aligned; + if (tx_total > bufsiz) { + status = -EMSGSIZE; + goto done; +@@ -267,7 +272,7 @@ static int spidev_message(struct spidev_ + (uintptr_t) u_tmp->tx_buf, + u_tmp->len)) + goto done; +- tx_buf += k_tmp->len; ++ tx_buf += len_aligned; + } + + k_tmp->cs_change = !!u_tmp->cs_change; +@@ -297,16 +302,16 @@ static int spidev_message(struct spidev_ + goto done; + + /* copy any rx data out of bounce buffer */ +- rx_buf = spidev->rx_buffer; +- for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { ++ for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; ++ n; ++ n--, k_tmp++, u_tmp++) { + if (u_tmp->rx_buf) { + if (copy_to_user((u8 __user *) +- (uintptr_t) u_tmp->rx_buf, rx_buf, ++ (uintptr_t) u_tmp->rx_buf, k_tmp->rx_buf, + u_tmp->len)) { + status = -EFAULT; + goto done; + } +- rx_buf += u_tmp->len; + } + } + status = total;