Re: [PATCH 3/9] genericirq.tmpl: convert it to ReST

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 &amp; 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 &amp; masked)
> -		desc->irq_data.chip->irq_unmask();
> -	desc->status &amp;= ~pending;
> -	handle_irq_event(desc->action);
> -} while (status &amp; pending);
> -desc->status &amp;= ~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
>  ===============================



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux