[RFC] Refactored interrupt handling on ARM

Jakub Klama jakub.klama at uj.edu.pl
Sun Apr 6 22:38:26 UTC 2014


 Hello all,

 It has been a long time since my SoC 2012 ended. However, I've finally
 merged refactored interrupt handling framework to head and added SMP
 support (IPIs). Let's start:

 What is this and how does it work?

 It's a refactored interrupt handling code for ARM which supports 
 multiple,
 stacked interrupt controllers. In particular, it creates a clean way to
 support IRQ multiplexers such as GPIO controllers with interrupt 
 generation
 functionality. Approach used in this code is somewhat similar to one 
 used
 in powerpc port.

 Every interrupt controller should implement methods from pic_if.m
 interface - at least pic_config, pic_unmask, pic_mask and pic_eoi. It
 should also install IRQ handler on parent interrupt controller 
 (specified
 by interrupt-parent in FDT, defaulting to nexus).

 The root interrupt controller is nexus - on ARM it has exactly one IRQ
 line (typically nexus0:0) representing core IRQ signal (on MIPS, there
 will be probably five of them). SoC interrupt controller, such as GIC
 then installs handler on nexus0:0 IRQ and exposes itself as interrupt
 controller by calling arm_register_pic(). When the interrupt arrives,
 pic driver calls arm_dispatch_irq() function.

 So, for example, a typical SoC interrupt tree can look like that:

 nexus0 (provides 1 irq)
 |
 \-- gic0 (provides 160 irqs, uses irq nexus0:0)
     |
     \-- gpio0 (provides 8 irqs, uses irq gic0:42)
     |   |
     |   \-- mmcsd0 (uses irqs gpio0:1, gpio0:2)
     |   \-- spi0 (uses irq gpio0:3)
     |   ...
     \-- gpio1 (provides 8 irqs, uses irq gic0:43)
     \-- ehci0 (uses irq gic0:109)
     ...

 Interrupt numbers used in rman are composed of two 8-bit fields: higher
 8 bits are the pic index and lower 8 bits are IRQ line number inside
 particular pic (so there are 256 pics supported with maximum of 256
 irq lines on each). These numbers are generated using FDT_MAP_IRQ()
 macro called from FDT code.

 As you can see from the provided dmesg logs, irq numbers are printed in
 form of "pic_name:line_number", i.e: "nexus0:0" or "gic0:109".

 Of course there's still support for shared interrupt handlers - on
 LPC3250 there are 3 pics attached to one in-core IRQ line.

 There's also support for IPIs. Calls to pic_ipi_get(), pic_ipi_clear(),
 pic_ipi_send() and ..._init_secondary() are redirected to one interrupt
 controller registered as capable to do IPIs. There can be only one
 interrupt controller with IPI support registered (and certainly not the
 root one).

 Code was tested on following platforms:
 * EA3250 (arm/lpc)
 * Pandaboard (arm/ti) (both with SMP enabled and disabled)

 Merging it would not require any changes in existing ARM ports (unless
 they will be adopted to new framework and will have ARM_INTRNG option
 enabled), except for adding arm/arm/intr.c to their file lists (as it's
 now not compiled-in by default). That was tested too.

 dmesg outputs can be found there:
 * http://people.freebsd.org/~jceel/intrng/pandaboard.dmesg.txt
 * http://people.freebsd.org/~jceel/intrng/ea3250.dmesg.txt

 diff against head as of r264192:
 * http://people.freebsd.org/~jceel/intrng/intrng.diff

 git branch containing the changes:
 * https://github.com/jceel/freebsd-arm-intrng/tree/intrng

 What do you think about that? That code probably needs some 
 improvements,
 especially in IPI/SMP area, but I think it's a step further in 
 interrupt
 handling on ARM.

 I really appreciate any comments and opinions.

 Regards,
 Jakub


More information about the freebsd-arm mailing list