From e6f027e00d80da97c7b0aa605fc338770effdd60 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 28 May 2024 09:46:55 +0800 Subject: [PATCH 1/2] dmaengine: dw-edma: Add support for chip-specific flags mainline inclusion from mainline-v6.0-rc1 commit d6b03171f9fc8127b3a7adfd4e74ee5d4dae5d14 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9Q8OH CVE: CVE-2024-27408 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d6b03171f9fc8127b3a7adfd4e74ee5d4dae5d14 -------------------------------- Add a "flags" field to the "struct dw_edma_chip" so that the controller drivers can pass flags that are relevant to the platform. DW_EDMA_CHIP_LOCAL - Used by the controller drivers accessing eDMA locally. Local eDMA access doesn't require generating MSIs to the remote. Link: https://lore.kernel.org/r/20220524152159.2370739-8-Frank.Li@nxp.com Tested-by: Serge Semin Tested-by: Manivannan Sadhasivam Signed-off-by: Frank Li Signed-off-by: Bjorn Helgaas Reviewed-by: Serge Semin Reviewed-by: Manivannan Sadhasivam Acked-By: Vinod Koul Conflicts: include/linux/dma/edma.h [wangxiongfeng: fix context conflicts] Signed-off-by: Xiongfeng Wang --- drivers/dma/dw-edma/dw-edma-v0-core.c | 9 ++++++--- include/linux/dma/edma.h | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 692de47b1670..a75fc40fd86e 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -192,6 +192,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir) static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) { struct dw_edma_burst *child; + struct dw_edma_chan *chan = chunk->chan; struct dw_edma_v0_lli __iomem *lli; struct dw_edma_v0_llp __iomem *llp; u32 control = 0, i = 0; @@ -205,9 +206,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) j = chunk->bursts_alloc; list_for_each_entry(child, &chunk->burst->list, list) { j--; - if (!j) - control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE); - + if (!j) { + control |= DW_EDMA_V0_LIE; + if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL)) + control |= DW_EDMA_V0_RIE; + } /* Channel control */ SET_LL(&lli[i].control, control); /* Transfer size */ diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h index cab6e18773da..0cda04f9f610 100644 --- a/include/linux/dma/edma.h +++ b/include/linux/dma/edma.h @@ -14,17 +14,27 @@ struct dw_edma; +/** + * enum dw_edma_chip_flags - Flags specific to an eDMA chip + * @DW_EDMA_CHIP_LOCAL: eDMA is used locally by an endpoint + */ +enum dw_edma_chip_flags { + DW_EDMA_CHIP_LOCAL = BIT(0), +}; + /** * struct dw_edma_chip - representation of DesignWare eDMA controller hardware * @dev: struct device of the eDMA controller * @id: instance ID * @irq: irq line * @dw: struct dw_edma that is filed by dw_edma_probe() + * @flags dw_edma_chip_flags */ struct dw_edma_chip { struct device *dev; int id; int irq; + u32 flags; struct dw_edma *dw; }; -- Gitee From 9cccfe88cc98dbdd16e86836465946b3356214d1 Mon Sep 17 00:00:00 2001 From: Kory Maincent Date: Tue, 28 May 2024 09:46:56 +0800 Subject: [PATCH 2/2] dmaengine: dw-edma: eDMA: Add sync read before starting the DMA transfer in remote setup mainline inclusion from mainline-v6.8-rc7 commit bbcc1c83f343e580c3aa1f2a8593343bf7b55bba category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9Q8OH CVE: CVE-2024-27408 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bbcc1c83f343e580c3aa1f2a8593343bf7b55bba -------------------------------- The Linked list element and pointer are not stored in the same memory as the eDMA controller register. If the doorbell register is toggled before the full write of the linked list a race condition error will occur. In remote setup we can only use a readl to the memory to assure the full write has occurred. Fixes: 7e4b8a4fbe2c ("dmaengine: Add Synopsys eDMA IP version 0 support") Reviewed-by: Serge Semin Reviewed-by: Manivannan Sadhasivam Signed-off-by: Kory Maincent Link: https://lore.kernel.org/r/20240129-b4-feature_hdma_mainline-v7-6-8e8c1acb7a46@bootlin.com Signed-off-by: Vinod Koul Conflicts: drivers/dma/dw-edma/dw-edma-v0-core.c [wangxiongfeng: Fix context conflicts] Signed-off-by: Xiongfeng Wang --- drivers/dma/dw-edma/dw-edma-v0-core.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index a75fc40fd86e..783ae763f445 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -236,6 +236,20 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) SET_LL(&llp->llp_high, upper_32_bits(chunk->ll_region.paddr)); } +static void dw_edma_v0_sync_ll_data(struct dw_edma_chunk *chunk) +{ + /* + * In case of remote eDMA engine setup, the DW PCIe RP/EP internal + * configuration registers and application memory are normally accessed + * over different buses. Ensure LL-data reaches the memory before the + * doorbell register is toggled by issuing the dummy-read from the remote + * LL memory in a hope that the MRd TLP will return only after the + * last MWr TLP is completed + */ + if (!(chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL)) + readl(chunk->ll_region.vaddr.io); +} + void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) { struct dw_edma_chan *chan = chunk->chan; @@ -265,6 +279,9 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) SET_CH(dw, chan->dir, chan->id, llp_high, upper_32_bits(chunk->ll_region.paddr)); } + + dw_edma_v0_sync_ll_data(chunk); + /* Doorbell */ SET_RW(dw, chan->dir, doorbell, FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id)); -- Gitee