What is chained IRQ ? What does chained_irq_enter and chained_irq_exit do, because after an interrupt is arised the IRQ line is disabled, but chained_irq_enter is calling functions related to masking interrupts. If the line is already disabled why to mask the interrupt ?
what is chained irq ?
There are two approaches how to call interrupt handlers for child devices in IRQ handler of parent (interrupt controller) device.
Chained interrupts:
"chained" means that those interrupts are just chain of function calls (for example, SoC's GPIO module interrupt handler is being called from GIC interrupt handler, just as a function call)
generic_handle_irq() is used for interrupts chaining
child IRQ handlers are being called inside of parent HW IRQ handler
you can't call functions that may sleep in chained (child) interrupt handlers, because they are still in atomic context (HW interrupt)
this approach is commonly used in drivers for SoC's internal GPIO modules
Nested interrupts
"nested" means that those interrupts can be interrupted by another interrupt; but they are not really HW IRQs, but rather threaded IRQs
handle_nested_irq() is used for creating nested interrupts
child IRQ handlers are being called inside of new thread created by handle_nested_irq() function; we need them to be run in process context, so that we can call sleeping bus functions (like I2C functions that may sleep)
you are able to call functions that may sleep inside of nested (child) interrupt handlers
this approach is commonly used in drivers for external chips, like GPIO expanders, because they are usually connected to SoC via I2C bus, and I2C functions may sleep
Speaking of drivers discussed above:
irq-gic driver uses CHAINED GPIO irqchips approach for handling systems with multiple GICs; this commit adds that functionality
gpio-omap driver (mentioned above) uses GENERIC CHAINED GPIO irqchips approach. See this commit. It was converted from using regular CHAINED GPIO irqchips so that on real-time kernel it will threaded IRQ handler, but on non-RT kernel it will be hard IRQ handler
'gpio-max732x' driver uses NESTED THREADED GPIO irqchips approach
what does chained_irq_enter and chained_irq_exit do
Those functions implement hardware interrupt flow control, i.e. notifying interrupt controller chip when to mask and unmask current interrupt.
For FastEOI interrupt controllers (most modern way):
chained_irq_enter() do nothing
chained_irq_exit() calls irq_eoi() callback to tell the interrupt controller that interrupt processing is finished
For interrupt controllers with mask/unmask/ack capabilities
chained_irq_enter() masks current interrupt, and acknowledges it if ack callback is set as well
chained_irq_exit() unmasks interrupt
because after an interrupt is arised the irq line is disabled, but chained_irq_enter is calling functions related to masking interrupts if the line is already disabled why to mask the interrupt ?
IRQ line is disabled. But we still need to write to EOI register in the end of interrupt processing. Or send ACK for edge-level interrupts.
This explains why interrupts are disabled in interrupt handler.
Read Linux kernel documentation itself for understanding these APIs:
https://www.kernel.org/doc/Documentation/gpio/driver.txt
CHAINED GPIO irqchips: these are usually the type that is embedded on
an SoC. This means that there is a fast IRQ handler for the GPIOs that
gets called in a chain from the parent IRQ handler, most typically the
system interrupt controller. This means the GPIO irqchip is registered
using irq_set_chained_handler() or the corresponding
gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
handler will be called immediately from the parent irqchip, while
holding the IRQs disabled. The GPIO irqchip will then end up calling
something like this sequence in its interrupt handler:
static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
chained_irq_enter(...);
generic_handle_irq(...);
chained_irq_exit(...);
Related
How does a Linux signal lead to the instruction stream of the X86 processor getting interrupted? So what CPU facility is used?
You have synchronous and asynchronous interrupts.
Synchronous interrupts are for issues like page faults, exceptions etc. Problems that are caused by the instructions that are executing on the CPU.
Asynchronous interrupts are from an IPI from the LAPIC, timer interrupt or for an interrupt picked up by the I/O-APIC and routed to the right LAPIC which then interrupts the processor. So these are external events.
But which X86 mechanism does the Signal use to interrupt the instruction stream and start processing the signal handler.
It isn't an asynchronous interrupt AFAIK because interrupts are handled within the kernel and signals in user-space. But its behavior is very similar to that of an asynchronous interrupt.
The kernel has to deliver a signal to user-space. You're right that that doesn't just happen on its own in hardware. That's why signal handling can respect the user-space red-zone, sigaltstack, and default actions if there's no handler registered.
As soon as the kernel has control, it can deliver the signal to user-space (or do the default action of ignoring it or killing the process).
If the signal was sent by a process running on another core, to a process running on this core, then probably it's delivered to user-space from an IPI handler, or else just at the next timer interrupt or system call that gives the kernel a chance to check for a pending signal.
When the IPI interrupt handler is preparing to return to user-space, it notices that there's a pending interrupt for the process that it's about to return to. (Either with a special case for one type of IPI, or by running the scheduler since we're in the kernel anyway). Instead of using iret to return to the interrupt frame pushed by hardware for the async interrupt, the kernel instead can iret to the address of the user-space signal handler.
The whole point of using an IPI (if that's what Linux even does) is to transfer control to the kernel sooner, instead of just waiting for it to notice the pending signal the next time it calls schedule().
If the process the signal is sent to isn't currently running on any core, then it either wakes the process up if there's a free CPU, or the signal just sits there for that task until the scheduler on some core decides to run it on this core. At that point it will notice and deliver the pending signal.
In linux, when net card receive a packet, would trigger a hard interrupt, and then in the interrupt call back function, it will raise a NET_RX_SOFTIRQ, would this softirq run at the same cpu with hard irq?
An interrupt request (IRQ) is a request for service, sent at the hardware level. Interrupts can be sent by either a dedicated hardware line, or across a hardware bus as an information packet (a Message Signaled Interrupt, or MSI).
When interrupts are enabled, receipt of an IRQ prompts a switch to interrupt context. Kernel interrupt dispatch code retrieves the IRQ number and its associated list of registered Interrupt Service Routines (ISRs), and calls each ISR in turn. The ISR acknowledges the interrupt and ignores redundant interrupts from the same IRQ, then queues a deferred handler to finish processing the interrupt and stop the ISR from ignoring future interrupts.
IRQs have an associated "affinity" property, smp_affinity, which defines the CPU cores that are allowed to execute the ISR for that IRQ. This property can be used to improve application performance by assigning both interrupt affinity and the application's thread affinity to one or more specific CPU cores. This allows cache line sharing between the specified interrupt and application threads.
# cat /proc/irq/32/smp_affinity
f
The default value for smp_affinity is f, meaning that the IRQ can be serviced on any of the CPUs in the system. Setting this value to 1, as follows, means that only CPU 0 can service this interrupt:
# echo 1 >/proc/irq/32/smp_affinity
# cat /proc/irq/32/smp_affinity
1
On systems that support interrupt steering, modifying the smp_affinity of an IRQ sets up the hardware so that the decision to service an interrupt with a particular CPU is made at the hardware level, with no intervention from the kernel.
More detailed information present at Redhat's DOC - 4.3 Interrupts and IRQ tuning
I have been working on irq handlers using the regmap irq chip implementation.
I have seen that there is high incosistency with the irq handlers execution. Especially if the irq is generated continuously during suspend. The irq chokes and never clears the interrupt source i.e handler never runs at times. Even if the handler runs half way and the system sleeps, it does not continue on resume.
Its creating serious issues. How do I handle this?
Regmap entirely uses threaded irqs. In addition, I was using i2c calls in the nested calls which are again threaded irqs. Due to this, I would always remain in user space and not in irq context. I2c tranfer has schedule in it and that brings in a completely different execution flow. In addition, there were problems in wake enabling the irq.
I'm trying to better understand the interaction between the "return IRQ_HANDLED" statement used in a GPIO pin-based interrupt handler (top-half) and the GPIO pin hardware. In particular, consider the hypothetical situation wherein a device has pulled a GPIO pin low to indicate that it needs attention. This causes the associated (top half) interrupt handler to be invoked. Now assume that the top-half handler queues up some work and then returns with "return IRQ_HANDLED" but that for whatever reason the interrupt has not been cleared on the device that generated it (i.e. the device is holding the GPIO pin in the low state). Does invocation of "return IRQ_HANDLED" cause the interrupt to be regenerated? I ask this in the context of the following article:
http://www.makelinux.net/books/lkd2/ch06lev1sec4
"Reentrancy and Interrupt Handlers
Interrupt handlers in Linux need not be reentrant. When a given interrupt handler is executing, the corresponding interrupt line is masked out on all processors, preventing another interrupt on the same line from being received. Normally all other interrupts are enabled, so other interrupts are serviced, but the current line is always disabled. Consequently, the same interrupt handler is never invoked concurrently to service a nested interrupt. This greatly simplifies writing your interrupt handler."
The above comment indicates that upon invocation of an interrupt handler, the interrupt line for that interrupt is masked. I'm trying to figure out if the invocation of "return IRQ_HANDLED" is what unmasks the interrupt line. And, with respect to the hypothetical case described above, what would happen if I "return IRQ_HANDLED" yet the device has not really had its interrupt cleared and hence is still holding the GPIO pin in a low (triggered) state. More specifically, will this cause the interrupt to be generated again such that the processor never has a chance to do the work queued when the interrupt first occurred. I.e., would this lead to an interrupt storm wherein the processor could be interrupted endlessly thus not allowing any useful processing to occur. I should add that I ask this question in the context of a single CPU linux ARM9 system (Phytec LPC3180) running kernel 2.6.10.
Thanks in advance,
Jim
PS: I'm not clear as to the difference between enabling/disabling an interrupt (in particular, an interrupt associated with a particular GPIO pin) and masking/unmasking the same GPIO interrupt.
Interrupt handlers occur asynchronously and hence cannot be called by other functions. Then, why do interrupt handlers in the linux kernel return a value ? How are the input arguments passed to it ?
Interrupt handlers have a return value for a couple of reasons.
Interrupt vectors can be shared between multiple devices. By returning IRQ_NONE/IRQ_HANDLED, an interrupt handler can indicate that the interrupt was/was not from the device it is specifically interested in. If IRQ_NONE is returned, the next handler in the list should be called.
Even if the IRQ is not shared, an interrupt handler can indicate to the interrupt subsystem that there were problems handling the interrupt and that it should be disabled to prevent system hangs from an irq loop.
Interrupt handlers are not interrupt vector. Interrupt vector is the code the processor jumps to when an interrupt is triggered. This is a gross simplification, but here is how it looks :
interrupt_vector {
num = check_interrupt_number()
f = get_interrupt_handler_func(num);
d = get_interrupt_handler_data(num);
/* call interrupt handler */
ret = f(d);
}
So handler and data are registered together, and the interrupt vector code call the registererd handler, passing the registered data, and checks the return value.
Of course, here we have a single level of handler, but you can have several, with for example one handler for all PCI Irq, that in turns checks for registered handler for a specific PCI irq and eventually calls itn passing registered data etc...
Of course, real code tends to be much more complicated. You can try this lxr link to navigate through the linux kernel sources
Interrupt vector code vs. multiple attached interrupt handlers (OS-specific) to an interrupt—handlers can return a value (which typically goes into a register like EAX on x86), so that vector code can manage a chain of handlers.