Frank Li (1): dmaengine: dw-edma: Add support for chip-specific flags
Kory Maincent (1): dmaengine: dw-edma: eDMA: Add sync read before starting the DMA transfer in remote setup
drivers/dma/dw-edma/dw-edma-v0-core.c | 26 +++++++++++++++++++++++--- include/linux/dma/edma.h | 10 ++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-)
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/8074 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/7...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/8074 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/7...
From: Frank Li Frank.Li@nxp.com
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/?i...
--------------------------------
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 fancer.lancer@gmail.com Tested-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Frank Li Frank.Li@nxp.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Serge Semin fancer.lancer@gmail.com Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Acked-By: Vinod Koul vkoul@kernel.org
Conflicts: include/linux/dma/edma.h [wangxiongfeng: fix context conflicts] Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com --- 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; };
From: Kory Maincent kory.maincent@bootlin.com
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/?i...
--------------------------------
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 fancer.lancer@gmail.com Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Kory Maincent kory.maincent@bootlin.com Link: https://lore.kernel.org/r/20240129-b4-feature_hdma_mainline-v7-6-8e8c1acb7a4... Signed-off-by: Vinod Koul vkoul@kernel.org
Conflicts: drivers/dma/dw-edma/dw-edma-v0-core.c [wangxiongfeng: Fix context conflicts] Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com --- 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));