Determining Interrupt index in Linux kernel 4+ - linux

I have an interrupt connected to the GIC of an ARM processor in a Xilinx Zynq-7000. Previously, the recommended way to use an interrupt in Linux would be to use
request_irq(INTERRUPT_INDEX,interrupt_handler,0,DEVICE_NAME,DEVICE_ID);
where INTERRUPT_INDEX would be a number you could obtain from your hw_definition file.
However, in more recent Linux kernels, apparently IRQs use virtual indicies, which means the number listed in the hw_definition file no longer corresponds to the interrupt I am trying to monitor.
How can I determine the proper values to use for INTERRUPT_INDEX, DEVICE_NAME, and DEVICE_ID in order to register an interrupt handler to a given GIC interrupt?

Related

relationship between controller interrupt no and interrupt no in linux kernel

I am developing our own CAN kernel module in i.mx6 processor. Now we want to write ISR for CAN TX and RX. We are able to write ISR, but my question is for register my ISR using request_irq function, what is the irq no i have to give. What is the relation between interrupt no specified in controller datasheet and irq no in the above function.
Thanks in advance,
NSN
Are we talking about on-chip FlexCAN or is this an externally connected CAN controller like MCP2515? There is already a FlexCAN driver available in the kernel. For on-chip peripherals the IRQ's are already defined in the Technical Reference Manual. For iMX6D/Q have a look at Chapter 3 Interrupts and DMA events. The interrupts are specified in device tree and retrieved using request_irq. For a CAN controller, let's say connected over SPI, a GPIO can be used as interrupt and the interrupt would be specified in device tree using "interrupt-parents" and "interrupts" property.
For the exact relation, let's consider an example. The CAN1 node is here with the "interrupts" property having a number of 110. If you look at Section 3 of TRM, FlexCAN1 is suppose to have an IRQ number of 142. Since the ARM Cortex A9 domain numbers start from 32, just subtract this from 142 to get the number of 110.
Edit: Seems I was not fully clear and talked from the device tree POV. The IRQ number for request_irq should have come from a call to platform_get_irq which returns Linux IRQ numbers. Also see this.

How linux know which irq number should be used?

I am not a driver programmer, I don't have a clear picture of how linux assign irq number for pcie devices.
From an NIC driver example, it seems Linux already know which irq number should be used before the function of 'probe' or 'open' was excuted.
ex:
https://github.com/torvalds/linux/blob/4608f064532c28c0ea3c03fe26a3a5909852811a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c#L6608
err = ixgbe_request_irq(adapter);
ixgbe can get irq number by using the data of the 'adapter' variable, it means the irq value already inside adapter structure, it is not a generated number, it is an already existed value.
if it is read from pci/pcie configuration space, wasn't it very easy to conflict with other devices?
if it is generated/arrange by kernel, how the irq number already inside the 'adapter' variable? ( or it is assigned by BIOS ? )
For interrupt for MSI, it seems generated by kernel ??

How can I know which interrupt line is shared or not, and which interrupt line is free in Linux?

I am going to write a PCIe base serial I/O card driver in Linux.
As per my knowledge through the configuration space, it provides the interrupt line, and through the IRQF_SHARED flag we are able to share the interrupt handler with that corresponding IRQ line.
But my confusion is how can I know which line is shared or not shared?
For a device driver, there is no useful way (and especially no portable way) to find out if the interrupt line is actually shared, and this could change at any time by loading/unloading other drivers.
PCI drivers must always assume that their interrupt might be shared.
Note: PCI Express devices are supposed to support MSIs (message-signaled interrupts), which are never shared.
Your driver should enable MSIs if at all possible.
However, it is not guaranteeed that the system supports them.
Kernel-assisted probing
The Linux kernel offers a low-level facility for probing the interrupt number. It works
for only nonshared interrupts, but most hardware that is capable of working in a
shared interrupt mode provides better ways of finding the configured interrupt num-
ber anyway. The facility consists of two functions, declared in <linux/interrupt.h>
(which also describes the probing machinery):
unsigned long probe_irq_on(void);
This function returns a bit mask of unassigned interrupts. The driver must pre-
serve the returned bit mask, and pass it to probe_irq_off later. After this call, the
driver should arrange for its device to generate at least one interrupt.
int probe_irq_off(unsigned long);
After the device has requested an interrupt, the driver calls this function, passing
as its argument the bit mask previously returned by probe_irq_on. probe_irq_off
returns the number of the interrupt that was issued after “probe_on.” If no inter-
rupts occurred, 0 is returned (therefore, IRQ 0 can’t be probed for, but no cus-
tom device can use it on any of the supported architectures anyway). If more than
one interrupt occurred (ambiguous detection), probe_irq_off returns a negative
value.
The programmer should be careful to enable interrupts on the device after the call to
probe_irq_on and to disable them before calling probe_irq_off. Additionally, you
must remember to service the pending interrupt in your device after probe_irq_off.
Run cat /proc/interrupt. In the rightmost column of the output you should see your device on one of the interrupts lines. If it's shared you'll see other devices assigned to that interrupt as well.

Linux Interrupt Handling in User Space

In Linux, what are the options for handling device interrupts in user space code rather than in kernel space?
Experience tells it is possible to write good and stable user-space drivers for almost any PCI adapter. It just requires some sophistication and a small proxying layer in the kernel. UIO is a step in that direction, but If you want to correctly handle interrupts in user-space then UIO might not be enough, for example if the device doesn't support the PCI-spec's interrupt disable bit which UIO relies on.
Notice that process wakeup latencies are a few microsecs so if your implementation requires very low latency then user-space might be a drag on it.
If I were to implement a user-space driver, I would reduce the kernel ISR to just a "disable & ack & wakeup-userpace" operation, handle the interrupt inside the waked-up process, and then re-enable the interrupt (of course, by writing to mapped PCI memory from the userspace process).
There is Userspace I/O system (UIO), but handling should still be done in kernelspace. OTOH, if you just need to notice the interrupt, you don't need the kernel part.
You may like to take a look at CHAPTER 10: Interrupt Handling from Linux Device Drivers, Third Edition book.
Have to trigger userland code indirectly.
Kernel ISR indicates interrupt by writing file / setting register / signalling. User space application polls this and goes on with the appropriate code.
Edge cases: more or less interrupts than expected (time out / too many interrupts per time interval)
Linux file abstraction is used to connect kernel and user space. This is performed by character devices and ioctl() calls. Some may prefer sysfs entries for this purpose.
This can look odd because event triggered device notifications (interrupts) are hooked with 'time triggered' polling, but it is actually asyncronous blocking (read/select). Anyway some questions are arising according to performance.
So interrupts cannot be directly handled outside the kernel.
E.g. shared memory can be in user space and with some I/O permission settings addresses can be mapped, so U-I/O works, but not for direct interrupt handling.
I have found only one 'minority report' in topic vfio (http://lxr.free-electrons.com/source/Documentation/vfio.txt):
https://stackoverflow.com/a/21197797/5349798
Similar questions:
Running user thread in context of an interrupt in linux
Is it possible in linux to register a interrupt handler from any user-space program?
Linux Kernel: invoke call back function in user space from kernel space
Linux Interrupt vs. Polling
Linux user space PCI driver
How do I inform a user space application that the driver has received an interrupt in linux?

Mapping DMA interrupts in the linux kernel

I'm writing a kernel module for a powerpc SoC which contains a DMA controller. I want to map the DMA interrupts in the linux kernel. my DMA structure has two interrupts:
struct dma
{
u32 dma1;
u32 dma2;
}*dma;
I have memory mapped the DMA structure in the Kernel. I have used the function irq_of_parse_and_map() to get the virq number to the corresponding interrupts.
dma->dma1=irq_of_parse_and_map(ofdev->node,0);
dma->dma2=irq_of_parse_and_map(ofdev->node,1);
but i cant get the virq numbers for the above interrupts. What APIs might be available to access the VIRQ numbers?
PowerPC based system uses a Device Tree Blob (DTB), also referred as Device Tree Source (DTS), which is a database that represents the hardware components (Processor Configuration, Buses, Peripherals etc...) on a given board. Linux kernel during its bootup expects certain information on the hardware that it runs on. Hardware information is passed from DTB to kernel by the bootloader software (eg: u-boot) as per Open Firmware standard. Once kernel get the hardware information, it will do all the software setup as a part of the kernel initilization routine.
From here on if any kernel software component (eg: device driver) needs hardware detail, it should get it from the kernel by using a set of Open Firmware Standard Binary Interfaces. Some of them are listed below:
of_register_platform_driver() - Register driver for device
of_unregister_platform_driver() - Unregister driver for device
of_address_to_resource() - Obtain physical address of peripheral
of_get_property() - Find property with a given name for a given node
of_find_node_by_phandle() - Find a node given a phandle
irq_of_parse_and_map() - Parse and map an interrupt into linux virq space
of_irq_to_resourse() - Obtain virtual IRQ of peripheral
...
...
Now coming to the problem raised here. irq_of_parse_and_map() is used to parse and map an interrupt into linux virq space. Usually this will be done by the Interrupt Controller device driver of the system. Once the interrupt mapping is done, you can get the Interrupt Source virq by referring to of_irq_to_resource() call. This step will be required for registering interrupt handler to the interrupt source. So try using of_irq_to_resource() instead of irq_of_parse_and_map().
Ref:
Device Tree Blob: http://www.informit.com/articles/article.aspx?p=1647051&seqNum=5
Open Firmware: http://www.openfirmware.org/
OF IRQ Interface: linux-2.6/drivers/of/irq.c

Resources