On Thu, 30 Mar 2017 17:11:30 -0300 Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxxxxx> wrote: [Reordering things a bit] > +========================== > +Linux generic IRQ handling > +========================== > + > +:Copyright: |copy| 2005-2010: Thomas Gleixner > +:Copyright: |copy| 2005-2006: Ingo Molnar It seems maybe they should have been CC'd on this one? Adding them now (and leaving the full patch for their amusement). > Brainless conversion of genericirq.tmpl book to ReST, via > Documentation/sphinx/tmplcvt In general this seems good, but I have to wonder how current this material is at this point? The last substantive change was in 2013 (3.11), and I've seen a certain amount of IRQ work going by since then. I'm not opposed to this move at all, but perhaps if it's outdated we should add a note to that effect? Thanks, jon > Copyright information inserted manually. > > Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxxxxx> > --- > Documentation/DocBook/Makefile | 2 +- > Documentation/DocBook/genericirq.tmpl | 520 ---------------------------------- > Documentation/core-api/genericirq.rst | 445 +++++++++++++++++++++++++++++ > Documentation/core-api/index.rst | 1 + > 4 files changed, 447 insertions(+), 521 deletions(-) > delete mode 100644 Documentation/DocBook/genericirq.tmpl > create mode 100644 Documentation/core-api/genericirq.rst > > diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile > index 7d94db2b53cd..e0c13655f770 100644 > --- a/Documentation/DocBook/Makefile > +++ b/Documentation/DocBook/Makefile > @@ -11,7 +11,7 @@ DOCBOOKS := z8530book.xml \ > networking.xml \ > kernel-api.xml filesystems.xml lsm.xml kgdb.xml \ > libata.xml mtdnand.xml librs.xml rapidio.xml \ > - genericirq.xml s390-drivers.xml scsi.xml \ > + s390-drivers.xml scsi.xml \ > sh.xml w1.xml > > ifeq ($(DOCBOOKS),) > diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl > deleted file mode 100644 > index 59fb5c077541..000000000000 > --- a/Documentation/DocBook/genericirq.tmpl > +++ /dev/null > @@ -1,520 +0,0 @@ > -<?xml version="1.0" encoding="UTF-8"?> > -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" > - "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> > - > -<book id="Generic-IRQ-Guide"> > - <bookinfo> > - <title>Linux generic IRQ handling</title> > - > - <authorgroup> > - <author> > - <firstname>Thomas</firstname> > - <surname>Gleixner</surname> > - <affiliation> > - <address> > - <email>tglx@xxxxxxxxxxxxx</email> > - </address> > - </affiliation> > - </author> > - <author> > - <firstname>Ingo</firstname> > - <surname>Molnar</surname> > - <affiliation> > - <address> > - <email>mingo@xxxxxxx</email> > - </address> > - </affiliation> > - </author> > - </authorgroup> > - > - <copyright> > - <year>2005-2010</year> > - <holder>Thomas Gleixner</holder> > - </copyright> > - <copyright> > - <year>2005-2006</year> > - <holder>Ingo Molnar</holder> > - </copyright> > - > - <legalnotice> > - <para> > - This documentation is free software; you can redistribute > - it and/or modify it under the terms of the GNU General Public > - License version 2 as published by the Free Software Foundation. > - </para> > - > - <para> > - This program is distributed in the hope that it will be > - useful, but WITHOUT ANY WARRANTY; without even the implied > - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > - See the GNU General Public License for more details. > - </para> > - > - <para> > - You should have received a copy of the GNU General Public > - License along with this program; if not, write to the Free > - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, > - MA 02111-1307 USA > - </para> > - > - <para> > - For more details see the file COPYING in the source > - distribution of Linux. > - </para> > - </legalnotice> > - </bookinfo> > - > -<toc></toc> > - > - <chapter id="intro"> > - <title>Introduction</title> > - <para> > - The generic interrupt handling layer is designed to provide a > - complete abstraction of interrupt handling for device drivers. > - It is able to handle all the different types of interrupt controller > - hardware. Device drivers use generic API functions to request, enable, > - disable and free interrupts. The drivers do not have to know anything > - about interrupt hardware details, so they can be used on different > - platforms without code changes. > - </para> > - <para> > - This documentation is provided to developers who want to implement > - an interrupt subsystem based for their architecture, with the help > - of the generic IRQ handling layer. > - </para> > - </chapter> > - > - <chapter id="rationale"> > - <title>Rationale</title> > - <para> > - The original implementation of interrupt handling in Linux uses > - the __do_IRQ() super-handler, which is able to deal with every > - type of interrupt logic. > - </para> > - <para> > - Originally, Russell King identified different types of handlers to > - build a quite universal set for the ARM interrupt handler > - implementation in Linux 2.5/2.6. He distinguished between: > - <itemizedlist> > - <listitem><para>Level type</para></listitem> > - <listitem><para>Edge type</para></listitem> > - <listitem><para>Simple type</para></listitem> > - </itemizedlist> > - During the implementation we identified another type: > - <itemizedlist> > - <listitem><para>Fast EOI type</para></listitem> > - </itemizedlist> > - In the SMP world of the __do_IRQ() super-handler another type > - was identified: > - <itemizedlist> > - <listitem><para>Per CPU type</para></listitem> > - </itemizedlist> > - </para> > - <para> > - This split implementation of high-level IRQ handlers allows us to > - optimize the flow of the interrupt handling for each specific > - interrupt type. This reduces complexity in that particular code path > - and allows the optimized handling of a given type. > - </para> > - <para> > - The original general IRQ implementation used hw_interrupt_type > - structures and their ->ack(), ->end() [etc.] callbacks to > - differentiate the flow control in the super-handler. This leads to > - a mix of flow logic and low-level hardware logic, and it also leads > - to unnecessary code duplication: for example in i386, there is an > - ioapic_level_irq and an ioapic_edge_irq IRQ-type which share many > - of the low-level details but have different flow handling. > - </para> > - <para> > - A more natural abstraction is the clean separation of the > - 'irq flow' and the 'chip details'. > - </para> > - <para> > - Analysing a couple of architecture's IRQ subsystem implementations > - reveals that most of them can use a generic set of 'irq flow' > - methods and only need to add the chip-level specific code. > - The separation is also valuable for (sub)architectures > - which need specific quirks in the IRQ flow itself but not in the > - chip details - and thus provides a more transparent IRQ subsystem > - design. > - </para> > - <para> > - Each interrupt descriptor is assigned its own high-level flow > - handler, which is normally one of the generic > - implementations. (This high-level flow handler implementation also > - makes it simple to provide demultiplexing handlers which can be > - found in embedded platforms on various architectures.) > - </para> > - <para> > - The separation makes the generic interrupt handling layer more > - flexible and extensible. For example, an (sub)architecture can > - use a generic IRQ-flow implementation for 'level type' interrupts > - and add a (sub)architecture specific 'edge type' implementation. > - </para> > - <para> > - To make the transition to the new model easier and prevent the > - breakage of existing implementations, the __do_IRQ() super-handler > - is still available. This leads to a kind of duality for the time > - being. Over time the new model should be used in more and more > - architectures, as it enables smaller and cleaner IRQ subsystems. > - It's deprecated for three years now and about to be removed. > - </para> > - </chapter> > - <chapter id="bugs"> > - <title>Known Bugs And Assumptions</title> > - <para> > - None (knock on wood). > - </para> > - </chapter> > - > - <chapter id="Abstraction"> > - <title>Abstraction layers</title> > - <para> > - There are three main levels of abstraction in the interrupt code: > - <orderedlist> > - <listitem><para>High-level driver API</para></listitem> > - <listitem><para>High-level IRQ flow handlers</para></listitem> > - <listitem><para>Chip-level hardware encapsulation</para></listitem> > - </orderedlist> > - </para> > - <sect1 id="Interrupt_control_flow"> > - <title>Interrupt control flow</title> > - <para> > - Each interrupt is described by an interrupt descriptor structure > - irq_desc. The interrupt is referenced by an 'unsigned int' numeric > - value which selects the corresponding interrupt description structure > - in the descriptor structures array. > - The descriptor structure contains status information and pointers > - to the interrupt flow method and the interrupt chip structure > - which are assigned to this interrupt. > - </para> > - <para> > - Whenever an interrupt triggers, the low-level architecture code calls > - into the generic interrupt code by calling desc->handle_irq(). > - This high-level IRQ handling function only uses desc->irq_data.chip > - primitives referenced by the assigned chip descriptor structure. > - </para> > - </sect1> > - <sect1 id="Highlevel_Driver_API"> > - <title>High-level Driver API</title> > - <para> > - The high-level Driver API consists of following functions: > - <itemizedlist> > - <listitem><para>request_irq()</para></listitem> > - <listitem><para>free_irq()</para></listitem> > - <listitem><para>disable_irq()</para></listitem> > - <listitem><para>enable_irq()</para></listitem> > - <listitem><para>disable_irq_nosync() (SMP only)</para></listitem> > - <listitem><para>synchronize_irq() (SMP only)</para></listitem> > - <listitem><para>irq_set_irq_type()</para></listitem> > - <listitem><para>irq_set_irq_wake()</para></listitem> > - <listitem><para>irq_set_handler_data()</para></listitem> > - <listitem><para>irq_set_chip()</para></listitem> > - <listitem><para>irq_set_chip_data()</para></listitem> > - </itemizedlist> > - See the autogenerated function documentation for details. > - </para> > - </sect1> > - <sect1 id="Highlevel_IRQ_flow_handlers"> > - <title>High-level IRQ flow handlers</title> > - <para> > - The generic layer provides a set of pre-defined irq-flow methods: > - <itemizedlist> > - <listitem><para>handle_level_irq</para></listitem> > - <listitem><para>handle_edge_irq</para></listitem> > - <listitem><para>handle_fasteoi_irq</para></listitem> > - <listitem><para>handle_simple_irq</para></listitem> > - <listitem><para>handle_percpu_irq</para></listitem> > - <listitem><para>handle_edge_eoi_irq</para></listitem> > - <listitem><para>handle_bad_irq</para></listitem> > - </itemizedlist> > - The interrupt flow handlers (either pre-defined or architecture > - specific) are assigned to specific interrupts by the architecture > - either during bootup or during device initialization. > - </para> > - <sect2 id="Default_flow_implementations"> > - <title>Default flow implementations</title> > - <sect3 id="Helper_functions"> > - <title>Helper functions</title> > - <para> > - The helper functions call the chip primitives and > - are used by the default flow implementations. > - The following helper functions are implemented (simplified excerpt): > - <programlisting> > -default_enable(struct irq_data *data) > -{ > - desc->irq_data.chip->irq_unmask(data); > -} > - > -default_disable(struct irq_data *data) > -{ > - if (!delay_disable(data)) > - desc->irq_data.chip->irq_mask(data); > -} > - > -default_ack(struct irq_data *data) > -{ > - chip->irq_ack(data); > -} > - > -default_mask_ack(struct irq_data *data) > -{ > - if (chip->irq_mask_ack) { > - chip->irq_mask_ack(data); > - } else { > - chip->irq_mask(data); > - chip->irq_ack(data); > - } > -} > - > -noop(struct irq_data *data)) > -{ > -} > - > - </programlisting> > - </para> > - </sect3> > - </sect2> > - <sect2 id="Default_flow_handler_implementations"> > - <title>Default flow handler implementations</title> > - <sect3 id="Default_Level_IRQ_flow_handler"> > - <title>Default Level IRQ flow handler</title> > - <para> > - handle_level_irq provides a generic implementation > - for level-triggered interrupts. > - </para> > - <para> > - The following control flow is implemented (simplified excerpt): > - <programlisting> > -desc->irq_data.chip->irq_mask_ack(); > -handle_irq_event(desc->action); > -desc->irq_data.chip->irq_unmask(); > - </programlisting> > - </para> > - </sect3> > - <sect3 id="Default_FASTEOI_IRQ_flow_handler"> > - <title>Default Fast EOI IRQ flow handler</title> > - <para> > - handle_fasteoi_irq provides a generic implementation > - for interrupts, which only need an EOI at the end of > - the handler. > - </para> > - <para> > - The following control flow is implemented (simplified excerpt): > - <programlisting> > -handle_irq_event(desc->action); > -desc->irq_data.chip->irq_eoi(); > - </programlisting> > - </para> > - </sect3> > - <sect3 id="Default_Edge_IRQ_flow_handler"> > - <title>Default Edge IRQ flow handler</title> > - <para> > - handle_edge_irq provides a generic implementation > - for edge-triggered interrupts. > - </para> > - <para> > - The following control flow is implemented (simplified excerpt): > - <programlisting> > -if (desc->status & running) { > - desc->irq_data.chip->irq_mask_ack(); > - desc->status |= pending | masked; > - return; > -} > -desc->irq_data.chip->irq_ack(); > -desc->status |= running; > -do { > - if (desc->status & masked) > - desc->irq_data.chip->irq_unmask(); > - desc->status &= ~pending; > - handle_irq_event(desc->action); > -} while (status & pending); > -desc->status &= ~running; > - </programlisting> > - </para> > - </sect3> > - <sect3 id="Default_simple_IRQ_flow_handler"> > - <title>Default simple IRQ flow handler</title> > - <para> > - handle_simple_irq provides a generic implementation > - for simple interrupts. > - </para> > - <para> > - Note: The simple flow handler does not call any > - handler/chip primitives. > - </para> > - <para> > - The following control flow is implemented (simplified excerpt): > - <programlisting> > -handle_irq_event(desc->action); > - </programlisting> > - </para> > - </sect3> > - <sect3 id="Default_per_CPU_flow_handler"> > - <title>Default per CPU flow handler</title> > - <para> > - handle_percpu_irq provides a generic implementation > - for per CPU interrupts. > - </para> > - <para> > - Per CPU interrupts are only available on SMP and > - the handler provides a simplified version without > - locking. > - </para> > - <para> > - The following control flow is implemented (simplified excerpt): > - <programlisting> > -if (desc->irq_data.chip->irq_ack) > - desc->irq_data.chip->irq_ack(); > -handle_irq_event(desc->action); > -if (desc->irq_data.chip->irq_eoi) > - desc->irq_data.chip->irq_eoi(); > - </programlisting> > - </para> > - </sect3> > - <sect3 id="EOI_Edge_IRQ_flow_handler"> > - <title>EOI Edge IRQ flow handler</title> > - <para> > - handle_edge_eoi_irq provides an abnomination of the edge > - handler which is solely used to tame a badly wreckaged > - irq controller on powerpc/cell. > - </para> > - </sect3> > - <sect3 id="BAD_IRQ_flow_handler"> > - <title>Bad IRQ flow handler</title> > - <para> > - handle_bad_irq is used for spurious interrupts which > - have no real handler assigned.. > - </para> > - </sect3> > - </sect2> > - <sect2 id="Quirks_and_optimizations"> > - <title>Quirks and optimizations</title> > - <para> > - The generic functions are intended for 'clean' architectures and chips, > - which have no platform-specific IRQ handling quirks. If an architecture > - needs to implement quirks on the 'flow' level then it can do so by > - overriding the high-level irq-flow handler. > - </para> > - </sect2> > - <sect2 id="Delayed_interrupt_disable"> > - <title>Delayed interrupt disable</title> > - <para> > - This per interrupt selectable feature, which was introduced by Russell > - King in the ARM interrupt implementation, does not mask an interrupt > - at the hardware level when disable_irq() is called. The interrupt is > - kept enabled and is masked in the flow handler when an interrupt event > - happens. This prevents losing edge interrupts on hardware which does > - not store an edge interrupt event while the interrupt is disabled at > - the hardware level. When an interrupt arrives while the IRQ_DISABLED > - flag is set, then the interrupt is masked at the hardware level and > - the IRQ_PENDING bit is set. When the interrupt is re-enabled by > - enable_irq() the pending bit is checked and if it is set, the > - interrupt is resent either via hardware or by a software resend > - mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when > - you want to use the delayed interrupt disable feature and your > - hardware is not capable of retriggering an interrupt.) > - The delayed interrupt disable is not configurable. > - </para> > - </sect2> > - </sect1> > - <sect1 id="Chiplevel_hardware_encapsulation"> > - <title>Chip-level hardware encapsulation</title> > - <para> > - The chip-level hardware descriptor structure irq_chip > - contains all the direct chip relevant functions, which > - can be utilized by the irq flow implementations. > - <itemizedlist> > - <listitem><para>irq_ack()</para></listitem> > - <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem> > - <listitem><para>irq_mask()</para></listitem> > - <listitem><para>irq_unmask()</para></listitem> > - <listitem><para>irq_eoi() - Optional, required for EOI flow handlers</para></listitem> > - <listitem><para>irq_retrigger() - Optional</para></listitem> > - <listitem><para>irq_set_type() - Optional</para></listitem> > - <listitem><para>irq_set_wake() - Optional</para></listitem> > - </itemizedlist> > - These primitives are strictly intended to mean what they say: ack means > - ACK, masking means masking of an IRQ line, etc. It is up to the flow > - handler(s) to use these basic units of low-level functionality. > - </para> > - </sect1> > - </chapter> > - > - <chapter id="doirq"> > - <title>__do_IRQ entry point</title> > - <para> > - The original implementation __do_IRQ() was an alternative entry > - point for all types of interrupts. It no longer exists. > - </para> > - <para> > - This handler turned out to be not suitable for all > - interrupt hardware and was therefore reimplemented with split > - functionality for edge/level/simple/percpu interrupts. This is not > - only a functional optimization. It also shortens code paths for > - interrupts. > - </para> > - </chapter> > - > - <chapter id="locking"> > - <title>Locking on SMP</title> > - <para> > - The locking of chip registers is up to the architecture that > - defines the chip primitives. The per-irq structure is > - protected via desc->lock, by the generic layer. > - </para> > - </chapter> > - > - <chapter id="genericchip"> > - <title>Generic interrupt chip</title> > - <para> > - To avoid copies of identical implementations of IRQ chips the > - core provides a configurable generic interrupt chip > - implementation. Developers should check carefully whether the > - generic chip fits their needs before implementing the same > - functionality slightly differently themselves. > - </para> > -!Ekernel/irq/generic-chip.c > - </chapter> > - > - <chapter id="structs"> > - <title>Structures</title> > - <para> > - This chapter contains the autogenerated documentation of the structures which are > - used in the generic IRQ layer. > - </para> > -!Iinclude/linux/irq.h > -!Iinclude/linux/interrupt.h > - </chapter> > - > - <chapter id="pubfunctions"> > - <title>Public Functions Provided</title> > - <para> > - This chapter contains the autogenerated documentation of the kernel API functions > - which are exported. > - </para> > -!Ekernel/irq/manage.c > -!Ekernel/irq/chip.c > - </chapter> > - > - <chapter id="intfunctions"> > - <title>Internal Functions Provided</title> > - <para> > - This chapter contains the autogenerated documentation of the internal functions. > - </para> > -!Ikernel/irq/irqdesc.c > -!Ikernel/irq/handle.c > -!Ikernel/irq/chip.c > - </chapter> > - > - <chapter id="credits"> > - <title>Credits</title> > - <para> > - The following people have contributed to this document: > - <orderedlist> > - <listitem><para>Thomas Gleixner<email>tglx@xxxxxxxxxxxxx</email></para></listitem> > - <listitem><para>Ingo Molnar<email>mingo@xxxxxxx</email></para></listitem> > - </orderedlist> > - </para> > - </chapter> > -</book> > diff --git a/Documentation/core-api/genericirq.rst b/Documentation/core-api/genericirq.rst > new file mode 100644 > index 000000000000..65d023b26864 > --- /dev/null > +++ b/Documentation/core-api/genericirq.rst > @@ -0,0 +1,445 @@ > +.. include:: <isonum.txt> > + > +========================== > +Linux generic IRQ handling > +========================== > + > +:Copyright: |copy| 2005-2010: Thomas Gleixner > +:Copyright: |copy| 2005-2006: Ingo Molnar > + > +Introduction > +============ > + > +The generic interrupt handling layer is designed to provide a complete > +abstraction of interrupt handling for device drivers. It is able to > +handle all the different types of interrupt controller hardware. Device > +drivers use generic API functions to request, enable, disable and free > +interrupts. The drivers do not have to know anything about interrupt > +hardware details, so they can be used on different platforms without > +code changes. > + > +This documentation is provided to developers who want to implement an > +interrupt subsystem based for their architecture, with the help of the > +generic IRQ handling layer. > + > +Rationale > +========= > + > +The original implementation of interrupt handling in Linux uses the > +__do_IRQ() super-handler, which is able to deal with every type of > +interrupt logic. > + > +Originally, Russell King identified different types of handlers to build > +a quite universal set for the ARM interrupt handler implementation in > +Linux 2.5/2.6. He distinguished between: > + > +- Level type > + > +- Edge type > + > +- Simple type > + > +During the implementation we identified another type: > + > +- Fast EOI type > + > +In the SMP world of the __do_IRQ() super-handler another type was > +identified: > + > +- Per CPU type > + > +This split implementation of high-level IRQ handlers allows us to > +optimize the flow of the interrupt handling for each specific interrupt > +type. This reduces complexity in that particular code path and allows > +the optimized handling of a given type. > + > +The original general IRQ implementation used hw_interrupt_type > +structures and their ->ack(), ->end() [etc.] callbacks to differentiate > +the flow control in the super-handler. This leads to a mix of flow logic > +and low-level hardware logic, and it also leads to unnecessary code > +duplication: for example in i386, there is an ioapic_level_irq and an > +ioapic_edge_irq IRQ-type which share many of the low-level details but > +have different flow handling. > + > +A more natural abstraction is the clean separation of the 'irq flow' and > +the 'chip details'. > + > +Analysing a couple of architecture's IRQ subsystem implementations > +reveals that most of them can use a generic set of 'irq flow' methods > +and only need to add the chip-level specific code. The separation is > +also valuable for (sub)architectures which need specific quirks in the > +IRQ flow itself but not in the chip details - and thus provides a more > +transparent IRQ subsystem design. > + > +Each interrupt descriptor is assigned its own high-level flow handler, > +which is normally one of the generic implementations. (This high-level > +flow handler implementation also makes it simple to provide > +demultiplexing handlers which can be found in embedded platforms on > +various architectures.) > + > +The separation makes the generic interrupt handling layer more flexible > +and extensible. For example, an (sub)architecture can use a generic > +IRQ-flow implementation for 'level type' interrupts and add a > +(sub)architecture specific 'edge type' implementation. > + > +To make the transition to the new model easier and prevent the breakage > +of existing implementations, the __do_IRQ() super-handler is still > +available. This leads to a kind of duality for the time being. Over time > +the new model should be used in more and more architectures, as it > +enables smaller and cleaner IRQ subsystems. It's deprecated for three > +years now and about to be removed. > + > +Known Bugs And Assumptions > +========================== > + > +None (knock on wood). > + > +Abstraction layers > +================== > + > +There are three main levels of abstraction in the interrupt code: > + > +1. High-level driver API > + > +2. High-level IRQ flow handlers > + > +3. Chip-level hardware encapsulation > + > +Interrupt control flow > +---------------------- > + > +Each interrupt is described by an interrupt descriptor structure > +irq_desc. The interrupt is referenced by an 'unsigned int' numeric > +value which selects the corresponding interrupt description structure in > +the descriptor structures array. The descriptor structure contains > +status information and pointers to the interrupt flow method and the > +interrupt chip structure which are assigned to this interrupt. > + > +Whenever an interrupt triggers, the low-level architecture code calls > +into the generic interrupt code by calling desc->handle_irq(). This > +high-level IRQ handling function only uses desc->irq_data.chip > +primitives referenced by the assigned chip descriptor structure. > + > +High-level Driver API > +--------------------- > + > +The high-level Driver API consists of following functions: > + > +- request_irq() > + > +- free_irq() > + > +- disable_irq() > + > +- enable_irq() > + > +- disable_irq_nosync() (SMP only) > + > +- synchronize_irq() (SMP only) > + > +- irq_set_irq_type() > + > +- irq_set_irq_wake() > + > +- irq_set_handler_data() > + > +- irq_set_chip() > + > +- irq_set_chip_data() > + > +See the autogenerated function documentation for details. > + > +High-level IRQ flow handlers > +---------------------------- > + > +The generic layer provides a set of pre-defined irq-flow methods: > + > +- handle_level_irq > + > +- handle_edge_irq > + > +- handle_fasteoi_irq > + > +- handle_simple_irq > + > +- handle_percpu_irq > + > +- handle_edge_eoi_irq > + > +- handle_bad_irq > + > +The interrupt flow handlers (either pre-defined or architecture > +specific) are assigned to specific interrupts by the architecture either > +during bootup or during device initialization. > + > +Default flow implementations > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +Helper functions > +^^^^^^^^^^^^^^^^ > + > +The helper functions call the chip primitives and are used by the > +default flow implementations. The following helper functions are > +implemented (simplified excerpt):: > + > + default_enable(struct irq_data *data) > + { > + desc->irq_data.chip->irq_unmask(data); > + } > + > + default_disable(struct irq_data *data) > + { > + if (!delay_disable(data)) > + desc->irq_data.chip->irq_mask(data); > + } > + > + default_ack(struct irq_data *data) > + { > + chip->irq_ack(data); > + } > + > + default_mask_ack(struct irq_data *data) > + { > + if (chip->irq_mask_ack) { > + chip->irq_mask_ack(data); > + } else { > + chip->irq_mask(data); > + chip->irq_ack(data); > + } > + } > + > + noop(struct irq_data *data)) > + { > + } > + > + > + > +Default flow handler implementations > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +Default Level IRQ flow handler > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +handle_level_irq provides a generic implementation for level-triggered > +interrupts. > + > +The following control flow is implemented (simplified excerpt):: > + > + desc->irq_data.chip->irq_mask_ack(); > + handle_irq_event(desc->action); > + desc->irq_data.chip->irq_unmask(); > + > + > +Default Fast EOI IRQ flow handler > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +handle_fasteoi_irq provides a generic implementation for interrupts, > +which only need an EOI at the end of the handler. > + > +The following control flow is implemented (simplified excerpt):: > + > + handle_irq_event(desc->action); > + desc->irq_data.chip->irq_eoi(); > + > + > +Default Edge IRQ flow handler > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +handle_edge_irq provides a generic implementation for edge-triggered > +interrupts. > + > +The following control flow is implemented (simplified excerpt):: > + > + if (desc->status & running) { > + desc->irq_data.chip->irq_mask_ack(); > + desc->status |= pending | masked; > + return; > + } > + desc->irq_data.chip->irq_ack(); > + desc->status |= running; > + do { > + if (desc->status & masked) > + desc->irq_data.chip->irq_unmask(); > + desc->status &= ~pending; > + handle_irq_event(desc->action); > + } while (status & pending); > + desc->status &= ~running; > + > + > +Default simple IRQ flow handler > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +handle_simple_irq provides a generic implementation for simple > +interrupts. > + > +.. note:: > + > + The simple flow handler does not call any handler/chip primitives. > + > +The following control flow is implemented (simplified excerpt):: > + > + handle_irq_event(desc->action); > + > + > +Default per CPU flow handler > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +handle_percpu_irq provides a generic implementation for per CPU > +interrupts. > + > +Per CPU interrupts are only available on SMP and the handler provides a > +simplified version without locking. > + > +The following control flow is implemented (simplified excerpt):: > + > + if (desc->irq_data.chip->irq_ack) > + desc->irq_data.chip->irq_ack(); > + handle_irq_event(desc->action); > + if (desc->irq_data.chip->irq_eoi) > + desc->irq_data.chip->irq_eoi(); > + > + > +EOI Edge IRQ flow handler > +^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +handle_edge_eoi_irq provides an abnomination of the edge handler > +which is solely used to tame a badly wreckaged irq controller on > +powerpc/cell. > + > +Bad IRQ flow handler > +^^^^^^^^^^^^^^^^^^^^ > + > +handle_bad_irq is used for spurious interrupts which have no real > +handler assigned.. > + > +Quirks and optimizations > +~~~~~~~~~~~~~~~~~~~~~~~~ > + > +The generic functions are intended for 'clean' architectures and chips, > +which have no platform-specific IRQ handling quirks. If an architecture > +needs to implement quirks on the 'flow' level then it can do so by > +overriding the high-level irq-flow handler. > + > +Delayed interrupt disable > +~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +This per interrupt selectable feature, which was introduced by Russell > +King in the ARM interrupt implementation, does not mask an interrupt at > +the hardware level when disable_irq() is called. The interrupt is kept > +enabled and is masked in the flow handler when an interrupt event > +happens. This prevents losing edge interrupts on hardware which does not > +store an edge interrupt event while the interrupt is disabled at the > +hardware level. When an interrupt arrives while the IRQ_DISABLED flag > +is set, then the interrupt is masked at the hardware level and the > +IRQ_PENDING bit is set. When the interrupt is re-enabled by > +enable_irq() the pending bit is checked and if it is set, the interrupt > +is resent either via hardware or by a software resend mechanism. (It's > +necessary to enable CONFIG_HARDIRQS_SW_RESEND when you want to use > +the delayed interrupt disable feature and your hardware is not capable > +of retriggering an interrupt.) The delayed interrupt disable is not > +configurable. > + > +Chip-level hardware encapsulation > +--------------------------------- > + > +The chip-level hardware descriptor structure irq_chip contains all the > +direct chip relevant functions, which can be utilized by the irq flow > +implementations. > + > +- irq_ack() > + > +- irq_mask_ack() - Optional, recommended for performance > + > +- irq_mask() > + > +- irq_unmask() > + > +- irq_eoi() - Optional, required for EOI flow handlers > + > +- irq_retrigger() - Optional > + > +- irq_set_type() - Optional > + > +- irq_set_wake() - Optional > + > +These primitives are strictly intended to mean what they say: ack means > +ACK, masking means masking of an IRQ line, etc. It is up to the flow > +handler(s) to use these basic units of low-level functionality. > + > +__do_IRQ entry point > +==================== > + > +The original implementation __do_IRQ() was an alternative entry point > +for all types of interrupts. It no longer exists. > + > +This handler turned out to be not suitable for all interrupt hardware > +and was therefore reimplemented with split functionality for > +edge/level/simple/percpu interrupts. This is not only a functional > +optimization. It also shortens code paths for interrupts. > + > +Locking on SMP > +============== > + > +The locking of chip registers is up to the architecture that defines the > +chip primitives. The per-irq structure is protected via desc->lock, by > +the generic layer. > + > +Generic interrupt chip > +====================== > + > +To avoid copies of identical implementations of IRQ chips the core > +provides a configurable generic interrupt chip implementation. > +Developers should check carefully whether the generic chip fits their > +needs before implementing the same functionality slightly differently > +themselves. > + > +.. kernel-doc:: kernel/irq/generic-chip.c > + :export: > + > +Structures > +========== > + > +This chapter contains the autogenerated documentation of the structures > +which are used in the generic IRQ layer. > + > +.. kernel-doc:: include/linux/irq.h > + :internal: > + > +.. kernel-doc:: include/linux/interrupt.h > + :internal: > + > +Public Functions Provided > +========================= > + > +This chapter contains the autogenerated documentation of the kernel API > +functions which are exported. > + > +.. kernel-doc:: kernel/irq/manage.c > + :export: > + > +.. kernel-doc:: kernel/irq/chip.c > + :export: > + > +Internal Functions Provided > +=========================== > + > +This chapter contains the autogenerated documentation of the internal > +functions. > + > +.. kernel-doc:: kernel/irq/irqdesc.c > + :internal: > + > +.. kernel-doc:: kernel/irq/handle.c > + :internal: > + > +.. kernel-doc:: kernel/irq/chip.c > + :internal: > + > +Credits > +======= > + > +The following people have contributed to this document: > + > +1. Thomas Gleixner tglx@xxxxxxxxxxxxx > + > +2. Ingo Molnar mingo@xxxxxxx > diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst > index 0d93d8089136..c058febbd991 100644 > --- a/Documentation/core-api/index.rst > +++ b/Documentation/core-api/index.rst > @@ -16,6 +16,7 @@ Core utilities > cpu_hotplug > local_ops > workqueue > + genericirq > > Interfaces for kernel debugging > =============================== -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html