Re: DWC eDMA weirdness
Koichiro Den <[email protected]> Thu, 30 Jul 2026 17:39:46 +0900
| Newsgroups | org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <egai6rd3umstjhkuelrnemr2ywjlfccfk4tipaxodav426wxex@kuu76gvznusa> |
On Wed, Jul 29, 2026 at 10:49:56PM +0200, Niklas Cassel wrote: > On Wed, Jul 29, 2026 at 10:28:22PM +0200, Niklas Cassel wrote: > > Getting two IRQs when we are only expecting a single IRQ is a very > > serious error, and suggests that something is very wrong in the EPC > > driver. > > > > Scream loudly so that EPC driver developers can see the problem, > > which might otherwise be very hard to detect. > > > > Signed-off-by: Niklas Cassel <[email protected]> > > --- > > drivers/misc/pci_endpoint_test.c | 13 +++++++++++++ > > 1 file changed, 13 insertions(+) > > > > diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c > > index 3635741c3e7a..a212e53654c6 100644 > > --- a/drivers/misc/pci_endpoint_test.c > > +++ b/drivers/misc/pci_endpoint_test.c > > @@ -178,6 +178,19 @@ static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) > > if (reg & STATUS_IRQ_RAISED) { > > test->last_irq = irq; > > complete(&test->irq_raised); > > + /* > > + * The endpoint test driver performs all testing sequentially. > > + * This means that test->irq_raised.done should never exceed 1. > > + * If it does, then we received two IRQs in a row, without a > > + * successful wait_for_completion_timeout() call in between. > > + * > > + * While complete() increases test->irq_raised.done by one, > > + * wait_for_completion_timeout() reduces test->irq_raised.done > > + * by one on success. > > + * > > + * Please debug your EPC driver if you see this warning. > > + */ > > + WARN_ON(test->irq_raised.done > 1); > > } > > > > return IRQ_HANDLED; > > -- > > 2.55.0 > > > > Hello Koichiro, > > I created this patch in response to a problem that I saw on v7.2-rc5. > > When running the pci_endpoint selftest: > # /pcitest > (snip) > # RUN pcie_ep_doorbell.DOORBELL_TEST ... > [ 215.256772] pci-endpoint-test 0000:01:00.0: Failed to trigger doorbell in endpoint > # OK pcie_ep_doorbell.DOORBELL_TEST > ok 23 pcie_ep_doorbell.DOORBELL_TEST > # FAILED: 19 / 23 tests passed. > # 2 skipped test(s) detected. Consider enabling relevant config options to improve coverage. > # Totals: pass:17 fail:4 xfail:0 xpass:0 skip:2 error:0 > > > I saw the weird error: > "Failed to trigger doorbell in endpoint" > > Ignore that the test case leaves things to be desired, since it passes even > though we see this warning. > > > The problem seems to be that the embedded doorbell IRQ handler is executed twice, > in response to a single writel() which rings the doorbell. > > diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c > index 4802d4f80f78..7f4360579ffb 100644 > --- a/drivers/pci/endpoint/functions/pci-epf-test.c > +++ b/drivers/pci/endpoint/functions/pci-epf-test.c > @@ -714,6 +714,7 @@ static irqreturn_t pci_epf_test_doorbell_handler(int irq, void *data) > > status |= STATUS_DOORBELL_SUCCESS; > reg->status = cpu_to_le32(status); > + trace_printk("calling pci_epf_test_raise_irq()\n"); > pci_epf_test_raise_irq(epf_test, reg); > > return IRQ_HANDLED; > > > As you can see: > irq/58-pci-ep-t-221 [006] ..... 58.601020: pci_epf_test_doorbell_handler: calling pci_epf_test_raise_irq() > irq/58-pci-ep-t-221 [006] ..... 58.601421: pci_epf_test_doorbell_handler: calling pci_epf_test_raise_irq() > > It is called twice for a single doorbell ring. > > Note that you might need to run the whole selftest test a few times to trigger > the WARN_ON(), even if you can see the trace printks every time. > (Using printks instead of trace printks seems to affect the timing too much.) > > > My first thought was that we should add reinit_completion() calls after each > wait_for_completion_timeout() in pci_endpoint_test_doorbell(), but after > reading up on complete() and wait_for_completion_timeout(), this should > actually not be needed, and if we did, it would simply hide the read problem, > which appears to be that the embedded doorbell IRQ handler on the EP side is > called twice for a single writel() that rings the doorbell. Hi Niklas, I was struggling to reproduce this, but I think I figured out what triggers it. It happens when the 'dma' variant runs before DOORBELL_TEST, e.g. when running the full test suite with no arguments, or by running '-v dma' first. I think the following patch fixes it: diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 89a4c498a17b..ec097c68cf5f 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -755,6 +755,7 @@ static int dw_edma_emul_irq_alloc(struct dw_edma *dw) return virq; irq_set_chip_and_handler(virq, &dw_edma_emul_irqchip, handle_level_irq); + irq_set_status_flags(virq, IRQ_LEVEL); irq_set_chip_data(virq, dw); irq_set_noprobe(virq); Could you test this? Best regards, Koichiro > > > Kind regards, > Niklas