[PATCH 05/15] dmaengine: dw-edma: Compose MSI messages from allocated IRQs
Koichiro Den <[email protected]> Fri, 13 Mar 2026 01:49:55 +0900
| Newsgroups | dev.linux.lists.ntb,org.kernel.vger.dmaengine,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <[email protected]> |
dw-edma caches the MSI/MSI-X message programmed into each channel so the controller can generate IMWr interrupts for completed transfers. Today that message is built inline while dw-edma requests its IRQs and implicitly assumes that the allocated vectors belong to dw-edma itself only. That becomes fragile once another frontend also requests IRQs from chip->dev and dw-edma still needs to derive the right MSI data value for its own vectors. Factor the logic into a helper that composes the MSI message from the allocated IRQ number and the owning device. For multi-vector MSI, derive the per-vector data value relative to msi_get_virq(dev, 0) instead of assuming a dw-edma-private vector block. No functional change intended for existing users. Signed-off-by: Koichiro Den <[email protected]> --- drivers/dma/dw-edma/dw-edma-core.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 6341bda4c303..c404248767e8 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -1020,6 +1020,28 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt) (*mask)++; } +static void dw_edma_compose_msi(struct device *dev, int irq, struct msi_msg *out) +{ + struct msi_desc *desc = irq_get_msi_desc(irq); + struct msi_msg msg; + unsigned int base; + + if (!desc) + return; + + get_cached_msi_msg(irq, &msg); + if (!desc->pci.msi_attrib.is_msix) { + /* + * For multi-vector MSI, the cached message corresponds to + * vector 0. Adjust msg.data by the IRQ index so that each + * vector gets a unique MSI data value for IMWr Data Register. + */ + base = msi_get_virq(dev, 0); + msg.data += (irq - base); + } + *out = msg; +} + static int dw_edma_irq_request(struct dw_edma *dw, u32 *wr_alloc, u32 *rd_alloc) { @@ -1050,8 +1072,7 @@ static int dw_edma_irq_request(struct dw_edma *dw, return err; } - if (irq_get_msi_desc(irq)) - get_cached_msi_msg(irq, &dw->irq[0].msi); + dw_edma_compose_msi(dev, irq, &dw->irq[0].msi); dw->nr_irqs = 1; } else { @@ -1077,8 +1098,7 @@ static int dw_edma_irq_request(struct dw_edma *dw, if (err) goto err_irq_free; - if (irq_get_msi_desc(irq)) - get_cached_msi_msg(irq, &dw->irq[i].msi); + dw_edma_compose_msi(dev, irq, &dw->irq[i].msi); } dw->nr_irqs = i; -- 2.51.0