PCI UDD Questions

Jeff Webb w1 at codecraftsmen.org
Sat Mar 2 13:25:02 CET 2019


I would like to write a generic UDD mini-driver that handles interrupts from a PCI card like uio_pci_generic does using the UIO framework.

In uio_pci_generic.c, I see this code:

/* Interrupt handler. Read/modify/write the command register to disable
 * the interrupt. */
static irqreturn_t irqhandler(int irq, struct uio_info *info)
{
	struct uio_pci_generic_dev *gdev =3D 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;
}

Can the pci_check_and_mask_intx() function be called like this from the UDD mini-driver in a real-time context, or is there an alternate method that should be used?  From looking at the source for the pci_* functions, I would guess that this function cannot be called from RTDM, but I am not sure.  I am not experienced with writing RTDM drivers.

Conversely, on the user-space side, what is the right way to umask the interrupt?  The example in the "Userspace I/O HOWTO" uses the "pci sysfs interface, or the libpci library that wraps it", but how to we do this in realtime?  If there is not a good way to do this directly from userspace, then it sounds like a UDD_RTIOC_IRQEN ioctl call could accomplish this if the UDD mini-driver's ioctl handler implements UDD_RTIOC_IRQEN by unmasking the interrupt in the PCI command register using something equivalent to the pci_intx() function.  Is this the best solution, or does making this ioctl call introduce additional overhead?

I could also avoid using the PCI command register entirely and just write to a device-specific mask bit in my peripheral, but I would rather implement a generic solution if there is not a performance penalty for using the PCI command register.

If the UDD_RTIOC_IRQEN/IRQDIS are implemented in the mini-driver to mask/unmask interrupts using device or PCI registers instead of masking at the IRQ controller level as described above, is there a need to call udd_enable/disable_irq() at all in the mini-driver (e.g. enable interrupts when the driver is loaded, disable when the driver is unloaded)?  It seems like disabling interrupts in this way (at the controller) wouldn't work if the IRQ line is shared with another device.  I am not sure whether interrupts are already enabled at the controller level, or if I need to enable them myself.

Also, if the default UDD ioctl handler is used, it sounds like the UDD_RTIOC_IRQEN/IRQDIS ioctls can be used to enable/disable interrupts at the controller from userspace, but this requires a switch to secondary mode, which would be problematic for real-time performance.  Is this correct?

Thanks in advance for any advice on this subject.

-Jeff




More information about the Xenomai mailing list