From 09bd6899407242d323b8a8e270ab6aed09676b89 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 15 Oct 2023 22:50:04 -0400 Subject: [PATCH] Fixes for 6.1 Signed-off-by: Sasha Levin --- ...se-spin_lock_irqsave-before-wait_eve.patch | 92 +++++++++++++++++++ ...ek-fix-deadlock-caused-by-synchroniz.patch | 53 +++++++++++ ...wrong-test-in-__ptep_test_and_clear_.patch | 52 +++++++++++ ...x-pte_access_permitted-for-page_none.patch | 62 +++++++++++++ queue-6.1/series | 4 + 5 files changed, 263 insertions(+) create mode 100644 queue-6.1/dmaengine-idxd-use-spin_lock_irqsave-before-wait_eve.patch create mode 100644 queue-6.1/dmaengine-mediatek-fix-deadlock-caused-by-synchroniz.patch create mode 100644 queue-6.1/powerpc-64e-fix-wrong-test-in-__ptep_test_and_clear_.patch create mode 100644 queue-6.1/powerpc-8xx-fix-pte_access_permitted-for-page_none.patch diff --git a/queue-6.1/dmaengine-idxd-use-spin_lock_irqsave-before-wait_eve.patch b/queue-6.1/dmaengine-idxd-use-spin_lock_irqsave-before-wait_eve.patch new file mode 100644 index 00000000000..215b3b56c09 --- /dev/null +++ b/queue-6.1/dmaengine-idxd-use-spin_lock_irqsave-before-wait_eve.patch @@ -0,0 +1,92 @@ +From 3d4547ab17c3c1c67bce1e5bc895846bd2846fc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Sep 2023 14:06:19 +0800 +Subject: dmaengine: idxd: use spin_lock_irqsave before wait_event_lock_irq + +From: Rex Zhang + +[ Upstream commit c0409dd3d151f661e7e57b901a81a02565df163c ] + +In idxd_cmd_exec(), wait_event_lock_irq() explicitly calls +spin_unlock_irq()/spin_lock_irq(). If the interrupt is on before entering +wait_event_lock_irq(), it will become off status after +wait_event_lock_irq() is called. Later, wait_for_completion() may go to +sleep but irq is disabled. The scenario is warned in might_sleep(). + +Fix it by using spin_lock_irqsave() instead of the primitive spin_lock() +to save the irq status before entering wait_event_lock_irq() and using +spin_unlock_irqrestore() instead of the primitive spin_unlock() to restore +the irq status before entering wait_for_completion(). + +Before the change: +idxd_cmd_exec() { +interrupt is on +spin_lock() // interrupt is on + wait_event_lock_irq() + spin_unlock_irq() // interrupt is enabled + ... + spin_lock_irq() // interrupt is disabled +spin_unlock() // interrupt is still disabled +wait_for_completion() // report "BUG: sleeping function + // called from invalid context... + // in_atomic() irqs_disabled()" +} + +After applying spin_lock_irqsave(): +idxd_cmd_exec() { +interrupt is on +spin_lock_irqsave() // save the on state + // interrupt is disabled + wait_event_lock_irq() + spin_unlock_irq() // interrupt is enabled + ... + spin_lock_irq() // interrupt is disabled +spin_unlock_irqrestore() // interrupt is restored to on +wait_for_completion() // No Call trace +} + +Fixes: f9f4082dbc56 ("dmaengine: idxd: remove interrupt disable for cmd_lock") +Signed-off-by: Rex Zhang +Signed-off-by: Lijun Pan +Reviewed-by: Dave Jiang +Reviewed-by: Fenghua Yu +Link: https://lore.kernel.org/r/20230916060619.3744220-1-rex.zhang@intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index 3b4ad7739f9ee..188f6b8625f78 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -495,6 +495,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, + union idxd_command_reg cmd; + DECLARE_COMPLETION_ONSTACK(done); + u32 stat; ++ unsigned long flags; + + if (idxd_device_is_halted(idxd)) { + dev_warn(&idxd->pdev->dev, "Device is HALTED!\n"); +@@ -508,7 +509,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, + cmd.operand = operand; + cmd.int_req = 1; + +- spin_lock(&idxd->cmd_lock); ++ spin_lock_irqsave(&idxd->cmd_lock, flags); + wait_event_lock_irq(idxd->cmd_waitq, + !test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags), + idxd->cmd_lock); +@@ -525,7 +526,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, + * After command submitted, release lock and go to sleep until + * the command completes via interrupt. + */ +- spin_unlock(&idxd->cmd_lock); ++ spin_unlock_irqrestore(&idxd->cmd_lock, flags); + wait_for_completion(&done); + stat = ioread32(idxd->reg_base + IDXD_CMDSTS_OFFSET); + spin_lock(&idxd->cmd_lock); +-- +2.40.1 + diff --git a/queue-6.1/dmaengine-mediatek-fix-deadlock-caused-by-synchroniz.patch b/queue-6.1/dmaengine-mediatek-fix-deadlock-caused-by-synchroniz.patch new file mode 100644 index 00000000000..8b1279a67bc --- /dev/null +++ b/queue-6.1/dmaengine-mediatek-fix-deadlock-caused-by-synchroniz.patch @@ -0,0 +1,53 @@ +From 516331dc0acf580658daee4dc5cd8819590a9346 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Aug 2023 11:25:11 +0800 +Subject: dmaengine: mediatek: Fix deadlock caused by synchronize_irq() + +From: Duoming Zhou + +[ Upstream commit 01f1ae2733e2bb4de92fefcea5fda847d92aede1 ] + +The synchronize_irq(c->irq) will not return until the IRQ handler +mtk_uart_apdma_irq_handler() is completed. If the synchronize_irq() +holds a spin_lock and waits the IRQ handler to complete, but the +IRQ handler also needs the same spin_lock. The deadlock will happen. +The process is shown below: + + cpu0 cpu1 +mtk_uart_apdma_device_pause() | mtk_uart_apdma_irq_handler() + spin_lock_irqsave() | + | spin_lock_irqsave() + //hold the lock to wait | + synchronize_irq() | + +This patch reorders the synchronize_irq(c->irq) outside the spin_lock +in order to mitigate the bug. + +Fixes: 9135408c3ace ("dmaengine: mediatek: Add MediaTek UART APDMA support") +Signed-off-by: Duoming Zhou +Reviewed-by: Eugen Hristev +Link: https://lore.kernel.org/r/20230806032511.45263-1-duoming@zju.edu.cn +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/mediatek/mtk-uart-apdma.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c +index a1517ef1f4a01..0acf6a92a4ad3 100644 +--- a/drivers/dma/mediatek/mtk-uart-apdma.c ++++ b/drivers/dma/mediatek/mtk-uart-apdma.c +@@ -451,9 +451,8 @@ static int mtk_uart_apdma_device_pause(struct dma_chan *chan) + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); + +- synchronize_irq(c->irq); +- + spin_unlock_irqrestore(&c->vc.lock, flags); ++ synchronize_irq(c->irq); + + return 0; + } +-- +2.40.1 + diff --git a/queue-6.1/powerpc-64e-fix-wrong-test-in-__ptep_test_and_clear_.patch b/queue-6.1/powerpc-64e-fix-wrong-test-in-__ptep_test_and_clear_.patch new file mode 100644 index 00000000000..c7d7b0a3062 --- /dev/null +++ b/queue-6.1/powerpc-64e-fix-wrong-test-in-__ptep_test_and_clear_.patch @@ -0,0 +1,52 @@ +From 17f4bfff3463964d7c921d2ed5b7a08a25309afa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Sep 2023 20:31:16 +0200 +Subject: powerpc/64e: Fix wrong test in __ptep_test_and_clear_young() + +From: Christophe Leroy + +[ Upstream commit 5ea0bbaa32e8f54e9a57cfee4a3b8769b80be0d2 ] + +Commit 45201c879469 ("powerpc/nohash: Remove hash related code from +nohash headers.") replaced: + + if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) + return 0; + +By: + + if (pte_young(*ptep)) + return 0; + +But it should be: + + if (!pte_young(*ptep)) + return 0; + +Fix it. + +Fixes: 45201c879469 ("powerpc/nohash: Remove hash related code from nohash headers.") +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://msgid.link/8bb7f06494e21adada724ede47a4c3d97e879d40.1695659959.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/nohash/64/pgtable.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h +index 879e9a6e5a870..00a003d367523 100644 +--- a/arch/powerpc/include/asm/nohash/64/pgtable.h ++++ b/arch/powerpc/include/asm/nohash/64/pgtable.h +@@ -197,7 +197,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, + { + unsigned long old; + +- if (pte_young(*ptep)) ++ if (!pte_young(*ptep)) + return 0; + old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); + return (old & _PAGE_ACCESSED) != 0; +-- +2.40.1 + diff --git a/queue-6.1/powerpc-8xx-fix-pte_access_permitted-for-page_none.patch b/queue-6.1/powerpc-8xx-fix-pte_access_permitted-for-page_none.patch new file mode 100644 index 00000000000..1330e44c805 --- /dev/null +++ b/queue-6.1/powerpc-8xx-fix-pte_access_permitted-for-page_none.patch @@ -0,0 +1,62 @@ +From 2feb899fa27a3a74077dbc981318bd2a6ef61310 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Sep 2023 20:31:15 +0200 +Subject: powerpc/8xx: Fix pte_access_permitted() for PAGE_NONE + +From: Christophe Leroy + +[ Upstream commit 5d9cea8a552ee122e21fbd5a3c5d4eb85f648e06 ] + +On 8xx, PAGE_NONE is handled by setting _PAGE_NA instead of clearing +_PAGE_USER. + +But then pte_user() returns 1 also for PAGE_NONE. + +As _PAGE_NA prevent reads, add a specific version of pte_read() +that returns 0 when _PAGE_NA is set instead of always returning 1. + +Fixes: 351750331fc1 ("powerpc/mm: Introduce _PAGE_NA") +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://msgid.link/57bcfbe578e43123f9ed73e040229b80f1ad56ec.1695659959.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/nohash/32/pte-8xx.h | 7 +++++++ + arch/powerpc/include/asm/nohash/pgtable.h | 2 ++ + 2 files changed, 9 insertions(+) + +diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h +index 1a89ebdc3acc9..0238e6bd0d6c1 100644 +--- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h ++++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h +@@ -94,6 +94,13 @@ static inline pte_t pte_wrprotect(pte_t pte) + + #define pte_wrprotect pte_wrprotect + ++static inline int pte_read(pte_t pte) ++{ ++ return (pte_val(pte) & _PAGE_RO) != _PAGE_NA; ++} ++ ++#define pte_read pte_read ++ + static inline int pte_write(pte_t pte) + { + return !(pte_val(pte) & _PAGE_RO); +diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h +index d9067dfc531cc..3d7dce90863c2 100644 +--- a/arch/powerpc/include/asm/nohash/pgtable.h ++++ b/arch/powerpc/include/asm/nohash/pgtable.h +@@ -25,7 +25,9 @@ static inline int pte_write(pte_t pte) + return pte_val(pte) & _PAGE_RW; + } + #endif ++#ifndef pte_read + static inline int pte_read(pte_t pte) { return 1; } ++#endif + static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } + static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } + static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } +-- +2.40.1 + diff --git a/queue-6.1/series b/queue-6.1/series index 6e39a8f8d0c..565a5b79fb5 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -123,3 +123,7 @@ usb-typec-ucsi-clear-event_pending-bit-if-ucsi_send_command-fails.patch usb-gadget-udc-xilinx-replace-memcpy-with-memcpy_toio.patch usb-gadget-ncm-handle-decoding-of-multiple-ntb-s-in-unwrap-call.patch usb-cdnsp-fixes-issue-with-dequeuing-not-queued-requests.patch +dmaengine-idxd-use-spin_lock_irqsave-before-wait_eve.patch +dmaengine-mediatek-fix-deadlock-caused-by-synchroniz.patch +powerpc-8xx-fix-pte_access_permitted-for-page_none.patch +powerpc-64e-fix-wrong-test-in-__ptep_test_and_clear_.patch -- 2.47.3