From: Greg Kroah-Hartman Date: Tue, 11 Feb 2025 10:34:58 +0000 (+0100) Subject: 6.6-stable patches X-Git-Tag: v6.6.78~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7354d8892816149418db7339fe73b5ab2a88e08e;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: mips-ftrace-declare-ftrace_get_parent_ra_addr-as-static.patch spi-atmel-qspi-memory-barriers-after-memory-mapped-i-o.patch spi-atmel-quadspi-create-atmel_qspi_ops-to-support-newer-soc-families.patch --- diff --git a/queue-6.6/mips-ftrace-declare-ftrace_get_parent_ra_addr-as-static.patch b/queue-6.6/mips-ftrace-declare-ftrace_get_parent_ra_addr-as-static.patch new file mode 100644 index 0000000000..33aeb3e74d --- /dev/null +++ b/queue-6.6/mips-ftrace-declare-ftrace_get_parent_ra_addr-as-static.patch @@ -0,0 +1,47 @@ +From ddd068d81445b17ac0bed084dfeb9e58b4df3ddd Mon Sep 17 00:00:00 2001 +From: WangYuli +Date: Sat, 4 Jan 2025 22:47:08 +0800 +Subject: MIPS: ftrace: Declare ftrace_get_parent_ra_addr() as static +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: WangYuli + +commit ddd068d81445b17ac0bed084dfeb9e58b4df3ddd upstream. + +Declare ftrace_get_parent_ra_addr() as static to suppress clang +compiler warning that 'no previous prototype'. This function is +not intended to be called from other parts. + +Fix follow error with clang-19: + +arch/mips/kernel/ftrace.c:251:15: error: no previous prototype for function 'ftrace_get_parent_ra_addr' [-Werror,-Wmissing-prototypes] + 251 | unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long + | ^ +arch/mips/kernel/ftrace.c:251:1: note: declare 'static' if the function is not intended to be used outside of this translation unit + 251 | unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long + | ^ + | static +1 error generated. + +Signed-off-by: WangYuli +Acked-by: Masami Hiramatsu (Google) +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kernel/ftrace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/kernel/ftrace.c ++++ b/arch/mips/kernel/ftrace.c +@@ -248,7 +248,7 @@ int ftrace_disable_ftrace_graph_caller(v + #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ + #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ + +-unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long ++static unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long + old_parent_ra, unsigned long parent_ra_addr, unsigned long fp) + { + unsigned long sp, ip, tmp; diff --git a/queue-6.6/series b/queue-6.6/series index 3aaeccdb1f..fd7fe6eeac 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -256,3 +256,6 @@ rtla-timerlat_top-stop-timerlat-tracer-on-signal.patch pinctrl-samsung-fix-fwnode-refcount-cleanup-if-platform_get_irq_optional-fails.patch ptp-ensure-info-enable-callback-is-always-set.patch rtc-zynqmp-fix-optional-clock-name-property.patch +mips-ftrace-declare-ftrace_get_parent_ra_addr-as-static.patch +spi-atmel-quadspi-create-atmel_qspi_ops-to-support-newer-soc-families.patch +spi-atmel-qspi-memory-barriers-after-memory-mapped-i-o.patch diff --git a/queue-6.6/spi-atmel-qspi-memory-barriers-after-memory-mapped-i-o.patch b/queue-6.6/spi-atmel-qspi-memory-barriers-after-memory-mapped-i-o.patch new file mode 100644 index 0000000000..32f79abd3b --- /dev/null +++ b/queue-6.6/spi-atmel-qspi-memory-barriers-after-memory-mapped-i-o.patch @@ -0,0 +1,90 @@ +From be92ab2de0ee1a13291c3b47b2d7eb24d80c0a2c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bence=20Cs=C3=B3k=C3=A1s?= +Date: Thu, 19 Dec 2024 10:12:58 +0100 +Subject: spi: atmel-qspi: Memory barriers after memory-mapped I/O +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bence Csókás + +commit be92ab2de0ee1a13291c3b47b2d7eb24d80c0a2c upstream. + +The QSPI peripheral control and status registers are +accessible via the SoC's APB bus, whereas MMIO transactions' +data travels on the AHB bus. + +Microchip documentation and even sample code from Atmel +emphasises the need for a memory barrier before the first +MMIO transaction to the AHB-connected QSPI, and before the +last write to its registers via APB. This is achieved by +the following lines in `atmel_qspi_transfer()`: + + /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */ + (void)atmel_qspi_read(aq, QSPI_IFR); + +However, the current documentation makes no mention to +synchronization requirements in the other direction, i.e. +after the last data written via AHB, and before the first +register access on APB. + +In our case, we were facing an issue where the QSPI peripheral +would cease to send any new CSR (nCS Rise) interrupts, +leading to a timeout in `atmel_qspi_wait_for_completion()` +and ultimately this panic in higher levels: + + ubi0 error: ubi_io_write: error -110 while writing 63108 bytes + to PEB 491:128, written 63104 bytes + +After months of extensive research of the codebase, fiddling +around the debugger with kgdb, and back-and-forth with +Microchip, we came to the conclusion that the issue is +probably that the peripheral is still busy receiving on AHB +when the LASTXFER bit is written to its Control Register +on APB, therefore this write gets lost, and the peripheral +still thinks there is more data to come in the MMIO transfer. +This was first formulated when we noticed that doubling the +write() of QSPI_CR_LASTXFER seemed to solve the problem. + +Ultimately, the solution is to introduce memory barriers +after the AHB-mapped MMIO transfers, to ensure ordering. + +Fixes: d5433def3153 ("mtd: spi-nor: atmel-quadspi: Add spi-mem support to atmel-quadspi") +Cc: Hari.PrasathGE@microchip.com +Cc: Mahesh.Abotula@microchip.com +Cc: Marco.Cardellini@microchip.com +Cc: stable@vger.kernel.org # c0a0203cf579: ("spi: atmel-quadspi: Create `atmel_qspi_ops`"...) +Cc: stable@vger.kernel.org # 6.x.y +Signed-off-by: Bence Csókás +Link: https://patch.msgid.link/20241219091258.395187-1-csokas.bence@prolan.hu +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/atmel-quadspi.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/spi/atmel-quadspi.c ++++ b/drivers/spi/atmel-quadspi.c +@@ -454,13 +454,20 @@ static int atmel_qspi_transfer(struct sp + (void)atmel_qspi_read(aq, QSPI_IFR); + + /* Send/Receive data */ +- if (op->data.dir == SPI_MEM_DATA_IN) ++ if (op->data.dir == SPI_MEM_DATA_IN) { + memcpy_fromio(op->data.buf.in, aq->mem + offset, + op->data.nbytes); +- else ++ ++ /* Synchronize AHB and APB accesses again */ ++ rmb(); ++ } else { + memcpy_toio(aq->mem + offset, op->data.buf.out, + op->data.nbytes); + ++ /* Synchronize AHB and APB accesses again */ ++ wmb(); ++ } ++ + /* Release the chip-select */ + atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR); + diff --git a/queue-6.6/spi-atmel-quadspi-create-atmel_qspi_ops-to-support-newer-soc-families.patch b/queue-6.6/spi-atmel-quadspi-create-atmel_qspi_ops-to-support-newer-soc-families.patch new file mode 100644 index 0000000000..929f9213d9 --- /dev/null +++ b/queue-6.6/spi-atmel-quadspi-create-atmel_qspi_ops-to-support-newer-soc-families.patch @@ -0,0 +1,207 @@ +From c0a0203cf57963792d59b3e4317a1d07b73df42a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cs=C3=B3k=C3=A1s=2C=20Bence?= +Date: Thu, 28 Nov 2024 18:43:14 +0100 +Subject: spi: atmel-quadspi: Create `atmel_qspi_ops` to support newer SoC families +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Csókás, Bence + +commit c0a0203cf57963792d59b3e4317a1d07b73df42a upstream. + +Refactor the code to introduce an ops struct, to prepare for merging +support for later SoCs, such as SAMA7G5. This code was based on the +vendor's kernel (linux4microchip). Cc'ing original contributors. + +Signed-off-by: Csókás, Bence +Link: https://patch.msgid.link/20241128174316.3209354-2-csokas.bence@prolan.hu +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/atmel-quadspi.c | 111 ++++++++++++++++++++++++++++++-------------- + 1 file changed, 77 insertions(+), 34 deletions(-) + +--- a/drivers/spi/atmel-quadspi.c ++++ b/drivers/spi/atmel-quadspi.c +@@ -138,11 +138,15 @@ + #define QSPI_WPSR_WPVSRC_MASK GENMASK(15, 8) + #define QSPI_WPSR_WPVSRC(src) (((src) << 8) & QSPI_WPSR_WPVSRC) + ++#define ATMEL_QSPI_TIMEOUT 1000 /* ms */ ++ + struct atmel_qspi_caps { + bool has_qspick; + bool has_ricr; + }; + ++struct atmel_qspi_ops; ++ + struct atmel_qspi { + void __iomem *regs; + void __iomem *mem; +@@ -150,13 +154,22 @@ struct atmel_qspi { + struct clk *qspick; + struct platform_device *pdev; + const struct atmel_qspi_caps *caps; ++ const struct atmel_qspi_ops *ops; + resource_size_t mmap_size; + u32 pending; ++ u32 irq_mask; + u32 mr; + u32 scr; + struct completion cmd_completion; + }; + ++struct atmel_qspi_ops { ++ int (*set_cfg)(struct atmel_qspi *aq, const struct spi_mem_op *op, ++ u32 *offset); ++ int (*transfer)(struct spi_mem *mem, const struct spi_mem_op *op, ++ u32 offset); ++}; ++ + struct atmel_qspi_mode { + u8 cmd_buswidth; + u8 addr_buswidth; +@@ -404,10 +417,60 @@ static int atmel_qspi_set_cfg(struct atm + return 0; + } + ++static int atmel_qspi_wait_for_completion(struct atmel_qspi *aq, u32 irq_mask) ++{ ++ int err = 0; ++ u32 sr; ++ ++ /* Poll INSTRuction End status */ ++ sr = atmel_qspi_read(aq, QSPI_SR); ++ if ((sr & irq_mask) == irq_mask) ++ return 0; ++ ++ /* Wait for INSTRuction End interrupt */ ++ reinit_completion(&aq->cmd_completion); ++ aq->pending = sr & irq_mask; ++ aq->irq_mask = irq_mask; ++ atmel_qspi_write(irq_mask, aq, QSPI_IER); ++ if (!wait_for_completion_timeout(&aq->cmd_completion, ++ msecs_to_jiffies(ATMEL_QSPI_TIMEOUT))) ++ err = -ETIMEDOUT; ++ atmel_qspi_write(irq_mask, aq, QSPI_IDR); ++ ++ return err; ++} ++ ++static int atmel_qspi_transfer(struct spi_mem *mem, ++ const struct spi_mem_op *op, u32 offset) ++{ ++ struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller); ++ ++ /* Skip to the final steps if there is no data */ ++ if (!op->data.nbytes) ++ return atmel_qspi_wait_for_completion(aq, ++ QSPI_SR_CMD_COMPLETED); ++ ++ /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */ ++ (void)atmel_qspi_read(aq, QSPI_IFR); ++ ++ /* Send/Receive data */ ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ memcpy_fromio(op->data.buf.in, aq->mem + offset, ++ op->data.nbytes); ++ else ++ memcpy_toio(aq->mem + offset, op->data.buf.out, ++ op->data.nbytes); ++ ++ /* Release the chip-select */ ++ atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR); ++ ++ return atmel_qspi_wait_for_completion(aq, QSPI_SR_CMD_COMPLETED); ++} ++ + static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + { + struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller); +- u32 sr, offset; ++ u32 offset; + int err; + + /* +@@ -416,46 +479,20 @@ static int atmel_qspi_exec_op(struct spi + * when the flash memories overrun the controller's memory space. + */ + if (op->addr.val + op->data.nbytes > aq->mmap_size) +- return -ENOTSUPP; ++ return -EOPNOTSUPP; ++ ++ if (op->addr.nbytes > 4) ++ return -EOPNOTSUPP; + + err = pm_runtime_resume_and_get(&aq->pdev->dev); + if (err < 0) + return err; + +- err = atmel_qspi_set_cfg(aq, op, &offset); ++ err = aq->ops->set_cfg(aq, op, &offset); + if (err) + goto pm_runtime_put; + +- /* Skip to the final steps if there is no data */ +- if (op->data.nbytes) { +- /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */ +- (void)atmel_qspi_read(aq, QSPI_IFR); +- +- /* Send/Receive data */ +- if (op->data.dir == SPI_MEM_DATA_IN) +- memcpy_fromio(op->data.buf.in, aq->mem + offset, +- op->data.nbytes); +- else +- memcpy_toio(aq->mem + offset, op->data.buf.out, +- op->data.nbytes); +- +- /* Release the chip-select */ +- atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR); +- } +- +- /* Poll INSTRuction End status */ +- sr = atmel_qspi_read(aq, QSPI_SR); +- if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED) +- goto pm_runtime_put; +- +- /* Wait for INSTRuction End interrupt */ +- reinit_completion(&aq->cmd_completion); +- aq->pending = sr & QSPI_SR_CMD_COMPLETED; +- atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IER); +- if (!wait_for_completion_timeout(&aq->cmd_completion, +- msecs_to_jiffies(1000))) +- err = -ETIMEDOUT; +- atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IDR); ++ err = aq->ops->transfer(mem, op, offset); + + pm_runtime_put: + pm_runtime_mark_last_busy(&aq->pdev->dev); +@@ -571,12 +608,17 @@ static irqreturn_t atmel_qspi_interrupt( + return IRQ_NONE; + + aq->pending |= pending; +- if ((aq->pending & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED) ++ if ((aq->pending & aq->irq_mask) == aq->irq_mask) + complete(&aq->cmd_completion); + + return IRQ_HANDLED; + } + ++static const struct atmel_qspi_ops atmel_qspi_ops = { ++ .set_cfg = atmel_qspi_set_cfg, ++ .transfer = atmel_qspi_transfer, ++}; ++ + static int atmel_qspi_probe(struct platform_device *pdev) + { + struct spi_controller *ctrl; +@@ -601,6 +643,7 @@ static int atmel_qspi_probe(struct platf + + init_completion(&aq->cmd_completion); + aq->pdev = pdev; ++ aq->ops = &atmel_qspi_ops; + + /* Map the registers */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base");