How linux know which irq number should be used? - linux

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 ??

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.

Determining Interrupt index in Linux kernel 4+

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?

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.

How can I get the corresponding MSI message in an interrupt?

We are using an FPGA on a PCIe card. I am able to reserve the proper resources and the MSI interrupt fires correctly. My problem is discerning the interrupt sources from: My Linux driver receives only a single MSI interrupt for different interrupt sources from the FPGA. Therefore the FPGA guys are sending the reason coded in the MSI message over the bus.
Questions:
Is there a possibility to access this message in order to get the information out of this frame in my ISR? (I know I could always check the FPGA's interrupt status register, but using the MSI message would be more elegant and would avoid additional bus access.)
If 1 is not possible, would switching to MSI-X solve this problem, so that I could get the information directly? (I know that MSI-X is the preferred solution, but the FPGA guys specified MSI)
Thank you for your help!
Hopefully you have got the answer you need by now, but I will attempt to contribute based on my understanding of MSI in the the windows driver, since it is a PCIe 2.2 standard behavior and should not be different. I am writing a windows PCIe driver to handle MSI interrupts originating from a TI DM8168 configured as pcie endpoint.
When the FPGA device signals a regular (non msi-x) MSI interrupt, it does not actually send a 'message' in the sense that a data structure must be filled and transmitted somewhere. MSI is achieved simply by having the FPGA write a certain data word value to one specific memory location that is shared over PCIe between host and device. The particular memory location and data value that must be written are selected by the host's bus manager, it can't just be any an arbitrary value.
A pointer to the MSI memory location and a specific, pre-defined data value to use are set up by the bus manager in PCIe config space, so that device and host can both see them. The MSI memory location is a physical bus address, so it must be translated to virtual address space both on device and host.
The maximum number of messages that regular (non msi-x) MSI can support must be an integral power of 2 with a maximum of 32 (i.e. 1, 2, 4, 8, 16, 32). For example if the FPGA supports 8 messages, then it will copy the data value (from PCIe config space) and set the lowest 3 bits to indicate the MessageID number (0-7), and then write this new value to the MSI pointer location. If the FPGA supports 16 messages, then it must modify the lower 4 bits of the data value to indicate the messageID number (0-15). The higher bits of the data value must not be changed.
On the receiving end in your ISR, you check the same lowest bits to see which MSI was signaled. There is no other data or ACK associated with MSI itself; any further data is implementation-specific and must be read from memory locations or registers agreed between you and the hardware team. In windows WDF framework drivers, this MessageID value is already masked and provided as a parameter into the EvtInterruptIsr callback function. I'm sure it is different in linux.
I'm a bit late on the response, but it might be useful in the future for someone else crossing this topic like I did in the last few weeks.

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