dmaengine: dw-edma: Account for the MSI vector offset

get_cached_msi_msg() returns the base message shared by a multi-MSI
descriptor. dw-edma currently derives per-channel data from its local IRQ
index and does not adjust a common IRQ at all. Both assume eDMA starts at
the descriptor's first vector.

That is not true when eDMA receives a tail subset. Compose each message
from the IRQ offset relative to the descriptor base in both paths.

While at it, avoid reading PCI MSI attributes from descriptors owned by
non-PCI devices.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
Link: https://patch.msgid.link/20260912174023.1227397-4-den@valinux.co.jp
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Koichiro Den 2026-09-13 02:40:23 +09:00 committed by Vinod Koul
parent 9d31ad3b33
commit 742c2a8041

View File

@ -7,6 +7,7 @@
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
@ -1237,12 +1238,23 @@ static inline void dw_edma_dec_irq_alloc(int *nr_irqs, u32 *alloc, u16 cnt)
}
}
static void dw_edma_compose_msi(int irq, struct msi_msg *msi)
{
struct msi_desc *desc = irq_get_msi_desc(irq);
if (!desc)
return;
get_cached_msi_msg(irq, msi);
if (dev_is_pci(desc->dev) && !desc->pci.msi_attrib.is_msix)
msi->data += irq - desc->irq;
}
static int dw_edma_irq_request(struct dw_edma *dw,
u32 *wr_alloc, u32 *rd_alloc)
{
struct dw_edma_chip *chip = dw->chip;
struct device *dev = dw->chip->dev;
struct msi_desc *msi_desc;
int i, err = 0;
u32 ch_cnt;
int irq;
@ -1267,8 +1279,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(irq, &dw->irq[0].msi);
dw->nr_irqs = 1;
} else {
@ -1291,12 +1302,7 @@ static int dw_edma_irq_request(struct dw_edma *dw,
&dw->irq[i]);
if (err)
goto err_irq_free;
msi_desc = irq_get_msi_desc(irq);
if (msi_desc) {
get_cached_msi_msg(irq, &dw->irq[i].msi);
if (!msi_desc->pci.msi_attrib.is_msix)
dw->irq[i].msi.data = dw->irq[0].msi.data + i;
}
dw_edma_compose_msi(irq, &dw->irq[i].msi);
}
dw->nr_irqs = i;