gpio: add a real time compliance checklist
Add some information about real time compliance to the driver document. Inspired by Grygorii Strashko's real time compliance patches. Cc: Grygorii Strashko <grygorii.strashko@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
85001089a7
commit
677b2ff4af
|
@ -93,22 +93,37 @@ GPIO irqchips usually fall in one of two categories:
|
|||
Chained GPIO irqchips typically can NOT set the .can_sleep flag on
|
||||
struct gpio_chip, as everything happens directly in the callbacks.
|
||||
|
||||
* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any
|
||||
other GPIO irqchip residing on the other side of a sleeping bus. Of course
|
||||
such drivers that need slow bus traffic to read out IRQ status and similar,
|
||||
traffic which may in turn incur other IRQs to happen, cannot be handled
|
||||
in a quick IRQ handler with IRQs disabled. Instead they need to spawn a
|
||||
thread and then mask the parent IRQ line until the interrupt is handled
|
||||
by the driver. The hallmark of this driver is to call something like
|
||||
this in its interrupt handler:
|
||||
NOTE: chained IRQ handlers are usually not good for real time. If you
|
||||
are submitting a new driver or refactoring a driver for real time compliance,
|
||||
consider using creating a nested/threaded irqchip instead, see below.
|
||||
|
||||
* NESTED THREADED GPIO irqchips: these are traditionally off-chip GPIO
|
||||
expanders and any other GPIO irqchip residing on the other side of a
|
||||
sleeping bus. Of course such drivers that need slow bus traffic to read
|
||||
out IRQ status and similar, traffic which may in turn incur other IRQs to
|
||||
happen, cannot be handled in a quick IRQ handler with IRQs disabled.
|
||||
|
||||
With the introduction of real time support in the Linux kernel, also other
|
||||
GPIO irqchips are encouraged to use a nested and threaded IRQ handler.
|
||||
Doing so makes the interrupts naturally preemptible on a real time
|
||||
setup, which means the system can easily be configured for real time with
|
||||
a (usually negligable) performance loss.
|
||||
|
||||
These drivers spawn a thread and then mask the parent IRQ line until the
|
||||
interrupt is handled by the driver. The hallmark of this driver is to call
|
||||
something like this in its interrupt handler:
|
||||
|
||||
static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
|
||||
...
|
||||
handle_nested_irq(irq);
|
||||
OR
|
||||
generic_handle_irq(irq);
|
||||
|
||||
The hallmark of threaded GPIO irqchips is that they set the .can_sleep
|
||||
flag on struct gpio_chip to true, indicating that this chip may sleep
|
||||
when accessing the GPIOs.
|
||||
Threaded GPIO irqchips should set the .can_sleep flag on struct gpio_chip
|
||||
to true if they are e.g. accessing the chip over I2C or SPI, indicating that
|
||||
this chip may sleep when accessing the GPIOs. irqchips that are just made
|
||||
threaded to be preemptible and thus real time compliant need not do this:
|
||||
preemption is not sleeping.
|
||||
|
||||
To help out in handling the set-up and management of GPIO irqchips and the
|
||||
associated irqdomain and resource allocation callbacks, the gpiolib has
|
||||
|
@ -125,7 +140,7 @@ symbol:
|
|||
gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
|
||||
data. (Notice handler data, since the irqchip data is likely used by the
|
||||
parent irqchip!) This is for the chained type of chip. This is also used
|
||||
to set up a nested irqchip if NULL is passed as handler.
|
||||
to set up a threaded/nested irqchip if NULL is passed as handler.
|
||||
|
||||
To use the helpers please keep the following in mind:
|
||||
|
||||
|
@ -170,6 +185,39 @@ typically be called in the .startup() and .shutdown() callbacks from the
|
|||
irqchip.
|
||||
|
||||
|
||||
Real-Time compliance for GPIO IRQ chips
|
||||
---------------------------------------
|
||||
|
||||
Any provider of irqchips needs to be carefully tailored to support Real Time
|
||||
preemption. It is desireable that all irqchips in the GPIO subsystem keep this
|
||||
in mind and does the proper testing to assure they are real time-enabled. The
|
||||
following is a checklist to follow when preparing a driver for real
|
||||
time-compliance:
|
||||
|
||||
- Nominally use raw_spinlock_t in the IRQ context path of the IRQ handler as
|
||||
we do not want these sections to be preempted.
|
||||
|
||||
- Do NOT use chained_irq_enter() or chained_irq_exit() in the IRQ handler,
|
||||
as we want the hotpath to be preemptible.
|
||||
|
||||
- Instead use nested IRQs and generic handlers such as handle_bad_irq(),
|
||||
handle_level_irq() and handle_edge_irq(). Consequentally the handler
|
||||
argument of gpiochip_set_chained_irqchip() should be NULL when using the
|
||||
gpiolib irqchip helpers.
|
||||
|
||||
- Nominally set all handlers to handle_bad_irq() in the setup call, then
|
||||
set the handler to handle_level_irq() and/or handle_edge_irq() in the irqchip
|
||||
.set_type() callback depending on what your controller supports.
|
||||
|
||||
- If you need to use the pm_runtime_get*()/pm_runtime_put*() callbacks in some
|
||||
of the irqchip callbacks, these should be moved to the .irq_bus_lock()
|
||||
and .irq_bus_unlock() callbacks respectively, as these are the only
|
||||
slowpath callbacks on an irqchip. Create the callbacks if need be.
|
||||
|
||||
- Test your driver with the apropriate in-kernel real time test cases for both
|
||||
level and edge IRQs.
|
||||
|
||||
|
||||
Requesting self-owned GPIO pins
|
||||
-------------------------------
|
||||
|
||||
|
|
Loading…
Reference in a new issue