0
votes

I use uio generic driver with HW composed of PCIe device (FPGA) connected to Intel ATOM cpu.

But, on testing, although interrupt is seen in the driver, it is not delivered to userspace.

These are the steps I'm doing:

echo "10ee 0007" > /sys/bus/pci/drivers/uio_pci_generic/new_id

I use userspace application which wait for interrupt, just as described in code example here.

I than trigger an interrupt from FPGA, but no print from the userspace application is given and there is an exception:

irq 23: nobody cared (try booting with the "irqpoll" option)
[ 91.030760] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.18.16 #6
[ 91.037037] Hardware name: /conga-MA5, BIOS MA50R000 10/30/2019
[ 91.043302] Call Trace:
[ 91.045881] <IRQ>
[ 91.048002] dump_stack+0x5c/0x80
[ 91.051464] __report_bad_irq+0x35/0xaf
[ 91.055465] note_interrupt.cold.9+0xa/0x63
[ 91.059823] handle_irq_event_percpu+0x68/0x70
[ 91.064470] handle_irq_event+0x37/0x57
[ 91.068481] handle_fasteoi_irq+0x97/0x150
...
[ 91.176043] handlers:
[ 91.178419] [<00000000ec05b056>] uio_interrupt
[ 91.183054] Disabling IRQ #23

I started debugging the uio driver, and I see that interrupt handler is called, but not handled:

static irqreturn_t irqhandler(int irq, struct uio_info *info)
{
        struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
printk("here 1\n");    <<--- we get here interrupt is catched here
        if (!pci_check_and_mask_intx(gdev->pdev))
                return IRQ_NONE;
printk("here 2\n");    <<--- But we never get here
        /* UIO core will signal the user process. */
        return IRQ_HANDLED;
}

It seems that pci_check_and_mask_intx() does not detect it as an interrupt from our device!

The device appear as following:

02:00.0 RAM memory: Xilinx Corporation Default PCIe endpoint ID
        Subsystem: Xilinx Corporation Default PCIe endpoint ID
        Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Interrupt: pin A routed to IRQ 23
        Region 0: Memory at 91200000 (32-bit, non-prefetchable) [size=1M]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
                Address: 0000000000000000  Data: 0000
        Capabilities: [58] Express (v1) Endpoint, MSI 00
                DevCap: MaxPayload 256 bytes, PhantFunc 1, Latency L0s <64ns, L1 <1us
                        ExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset- SlotPowerLimit 10.000W
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag+ PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 256 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s, Exit Latency L0s unlimited
                        ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk+
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
        Capabilities: [100 v1] Device Serial Number 00-00-00-00-00-00-00-00
        Kernel driver in use: uio_pci_generic

Is it an issue of FPGA device ? or does UIO generic PCI does not support interrupts ?

1
You missed the part where you request interrupt.0andriy
What do you mean ? PCI generic handler request the interrupt as part of generic driver code.ransh
Yes, have you looked into it? It seems it uses default flags (only shared is added on top). You case more likely shows wrong polarity settings. You may add apic=debug to the kernel command line to see how IRQ #23 is being routed and what flags are in use. As test you may also replace the gdev->info.irq_flags = IRQF_SHARED; by gdev->info.irq_flags = IRQF_SHARED | IRQF_TRIGGER_LOW; (if default is active high) or gdev->info.irq_flags = IRQF_SHARED | IRQF_TRIGGER_HIGH; otherwise. If it's the case, you need to find a way how to fix your default polarity either on FPGA level or via software.0andriy
But irqhandler was called, as I mentioned above (which means that irq was probably requested correctly ). It is only the call to pci_check_and_mask_intx which returned false.ransh
Please, read carefully again what I wrote in above comment.0andriy

1 Answers

0
votes

Eventually after commenting the following lines for irqhandler,

I am able to receive interrupts from FPGA

static irqreturn_t irqhandler(int irq, struct uio_info *info)
 {
      struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
-        if (!pci_check_and_mask_intx(gdev->pdev))
-                return IRQ_NONE;
    /* UIO core will signal the user process. */
    return IRQ_HANDLED;
}

Yet, obviously it is still a workaround, and we need later to investigate why FPGA does not deliver bit status change in status register in configuration space of PCIe together with the irq.