[FE training-materials-updates] kernel interrupts: clarifications, updates and simplifications

Michael Opdenacker michael.opdenacker at free-electrons.com
Thu Dec 1 06:54:13 CET 2016


Repository : git://git.free-electrons.com/training-materials.git
On branch  : master
Link       : http://git.free-electrons.com/training-materials/commit/?id=011938d50ae9a87e49cd068280b7cfc9cf4eee68

>---------------------------------------------------------------

commit 011938d50ae9a87e49cd068280b7cfc9cf4eee68
Author: Michael Opdenacker <michael.opdenacker at free-electrons.com>
Date:   Thu Dec 1 06:54:13 2016 +0100

    kernel interrupts: clarifications, updates and simplifications
    
    Signed-off-by: Michael Opdenacker <michael.opdenacker at free-electrons.com>


>---------------------------------------------------------------

011938d50ae9a87e49cd068280b7cfc9cf4eee68
 .../kernel-driver-development-interrupts.tex       | 132 +++++++++++----------
 .../kernel-driver-development-lab-interrupts.tex   |   4 +-
 2 files changed, 70 insertions(+), 66 deletions(-)

diff --git a/slides/kernel-driver-development-interrupts/kernel-driver-development-interrupts.tex b/slides/kernel-driver-development-interrupts/kernel-driver-development-interrupts.tex
index a84c88a..4314895 100644
--- a/slides/kernel-driver-development-interrupts/kernel-driver-development-interrupts.tex
+++ b/slides/kernel-driver-development-interrupts/kernel-driver-development-interrupts.tex
@@ -1,4 +1,4 @@
-\subsection{Interrupt Management}
+/\subsection{Interrupt Management}
 
 \begin{frame}[fragile]
   \frametitle{Registering an interrupt handler 1/2}
@@ -20,10 +20,11 @@ int devm_request_irq(struct device *dev,
         interrupt number.
   \item \code{handler} is a pointer to the IRQ handler
   \item \code{irq_flags} are option masks (see next slide)
-  \item \code{devname} is the registered name
-  \item {\small \code{dev_id} is a pointer to some data. It cannot be NULL
-        as it is used as an identifier for \kfunc{free_irq} when using
-      shared IRQs.}
+  \item \code{devname} is the registered name (for
+	\code{/proc/interrupts})
+  \item {\small \code{dev_id} is a pointer to per-device data.
+        It cannot be NULL as it is used as an identifier for
+	\kfunc{devm_free_irq} when using shared IRQs.}
   \end{itemize}
 \end{frame}
 
@@ -48,7 +49,10 @@ void devm_free_irq(struct device *dev,
      \item \ksym{IRQF_SHARED}
      \begin{itemize}
         \item The interrupt channel can be shared by several
-        devices. Requires a hardware status register telling whether
+        devices.
+	\item When an interrupt is received, all the interrupt
+	handlers registered on the same interrupt line are called.
+	\item This requires a hardware status register telling whether
         an IRQ was raised or not.
      \end{itemize}
   \end{itemize}
@@ -71,32 +75,40 @@ void devm_free_irq(struct device *dev,
 \end{frame}
 
 \begin{frame}[fragile]
-  \frametitle{{\tt /proc/interrupts} on a Panda board}
+  \frametitle{/proc/interrupts on Raspberry Pi 2 (ARM, Linux 4.1)}
 \begin{block}{}
-  \footnotesize
+  \tiny
 \begin{verbatim}
-        CPU0    CPU1
-39:     4       0       GIC     TWL6030-PIH
-41:     0       0       GIC     l3-dbg-irq
-42:     0       0       GIC     l3-app-irq
-43:     0       0       GIC     prcm
-44:     20294   0       GIC     DMA
-52:     0       0       GIC     gpmc
-...
-IPI0:   0       0       Timer broadcast interrupts
-IPI1:   23095   25663   Rescheduling interrupts
-IPI2:   0       0       Function call interrupts
-IPI3:   231     173     Single function call interrupts
-IPI4:   0       0       CPU stop interrupts
-LOC:    196407  136995  Local timer interrupts
-Err:    0
+           CPU0       CPU1       CPU2       CPU3
+ 16:          0          0          0          0   ARMCTRL  16 Edge bcm2708_fb dma
+ 32: 1660065960          0          0          0   ARMCTRL  32 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1
+ 49:          0          0          0          0   ARMCTRL  49 Edge 3f200000.gpio:bank0
+ 50:          0          0          0          0   ARMCTRL  50 Edge 3f200000.gpio:bank1
+ 65:      77339          0          0          0   ARMCTRL  65 Edge 3f00b880.mailbox
+ 66:          2          0          0          0   ARMCTRL  66 Edge VCHIQ doorbell
+ 75:          1          0          0          0   ARMCTRL  75 Edge
+ 77:     825261          0          0          0   ARMCTRL  77 Edge DMA IRQ
+ 82:     819926          0          0          0   ARMCTRL  82 Edge mmc0
+ 83:          6          0          0          0   ARMCTRL  83 Edge uart-pl011
+ 96:          0          0          0          0   ARMCTRL  96 Edge arch_timer
+ 97:   45040705   26523650   16191929   47339273   ARMCTRL  97 Edge arch_timer
+FIQ:              usb_fiq
+IPI0:          0          0          0          0  CPU wakeup interrupts
+IPI1:          0          0          0          0  Timer broadcast interrupts
+IPI2:   34944338   35870609   37410637   12127900  Rescheduling interrupts
+IPI3:          9         10          9         11  Function call interrupts
+IPI4:          3          3          1          1  Single function call interrupts
+IPI5:          0          0          0          0  CPU stop interrupts
+IPI6:          0          0          0          0  IRQ work interrupts
+IPI7:          0          0          0          0  completion interrupts
+Err:          0
+
 \end{verbatim}
 \end{block}
   \footnotesize
   Note: interrupt numbers shown on the left-most column are virtual
   numbers when the Device Tree is used. The real physical interrupt
-  numbers are either shown as an additional column, or can be seen in
-  \code{/sys/kernel/debug/irq_domain_mapping}.
+  numbers can be seen in \code{/sys/kernel/debug/irq_domain_mapping}.
 \end{frame}
 
 \begin{frame}[fragile]
@@ -105,14 +117,14 @@ Err:    0
   \item \mint{c}+irqreturn_t foo_interrupt(int irq, void *dev_id)+
     \begin{itemize}
     \item \code{irq}, the IRQ number
-    \item \code{dev_id}, the opaque pointer that was passed to
-      \kfunc{devm_request_irq}
+    \item \code{dev_id}, the per-device pointer that was
+      passed to \kfunc{devm_request_irq}
     \end{itemize}
   \item Return value
     \begin{itemize}
     \item \ksym{IRQ_HANDLED}: recognized and handled interrupt
     \item \ksym{IRQ_NONE}: not on a device managed by the
-      module. Useful to share interrupt channels and/or report
+      device. Useful to share interrupt channels and/or report
       spurious interrupts to the kernel.
     \end{itemize}
   \end{itemize}
@@ -125,9 +137,9 @@ Err:    0
     interrupts will be generated, or the interrupt will keep firing
     over and over again)
   \item Read/write data from/to the device
-  \item Wake up any waiting process waiting for the completion of an
-    operation, typically using wait queues
-    \code{wake_up_interruptible(&module_queue);}
+  \item Wake up any process waiting for such data, on a per-device
+    wait queue:\\
+    \code{wake_up_interruptible(&device_queue);}
 \end{itemize}
 \end{frame}
 
@@ -158,23 +170,21 @@ int devm_request_threaded_irq(
 
 \begin{frame}
   \frametitle{Top half and bottom half processing}
+  Splitting the execution of interrupt handlers in 2 parts
   \begin{itemize}
-  \item Splitting the execution of interrupt handlers in 2 parts
+  \item Top half
+    \begin{itemize}
+    \item This is the real interrupt handler, which should complete
+      as quickly as possible since all interrupts are disabled. If
+      possible, take the data out of the device and schedule a
+      bottom half to handle it.
+    \end{itemize}
+  \item Bottom half
     \begin{itemize}
-    \item Top half
-      \begin{itemize}
-      \item This is the real interrupt handler, which should complete
-        as quickly as possible since all interrupts are disabled. If
-        possible, take the data out of the device and schedule a
-        bottom half to handle it.
-      \end{itemize}
-    \item Bottom half
-      \begin{itemize}
-      \item Is the general Linux name for various mechanisms which
-        allow to postpone the handling of interrupt-related
-        work. Implemented in Linux as softirqs, tasklets or
-        workqueues.
-      \end{itemize}
+    \item Is the general Linux name for various mechanisms which
+      allow to postpone the handling of interrupt-related
+      work. Implemented in Linux as softirqs, tasklets or
+      workqueues.
     \end{itemize}
   \end{itemize}
 \end{frame}
@@ -214,13 +224,10 @@ int devm_request_threaded_irq(
   \item Tasklets are executed within the \code{HI} and \code{TASKLET}
     softirqs. They are executed with all interrupts enabled, but a
     given tasklet is guaranteed to execute on a single CPU at a time.
-  \item A tasklet can be declared statically with the
-    \kfunc{DECLARE_TASKLET} macro or dynamically with the
-    \kfunc{tasklet_init} function. A tasklet is simply implemented as
-    a function. Tasklets can easily be used by individual device
-    drivers, as opposed to softirqs.
-  \item The interrupt handler can schedule the execution of a tasklet
-    with
+  \item Tasklets are created with \kfunc{tasklet_init} function.
+    A tasklet is simply implemented as a function. Tasklets can easily
+    be used by individual device drivers, as opposed to softirqs.
+  \item The interrupt handler can schedule tasklet execution with:
     \begin{itemize}
     \item \kfunc{tasklet_schedule} to get it executed in the
       \code{TASKLET} softirq
@@ -290,25 +297,22 @@ somewhere function(...) {
   \begin{itemize}
   \item Device driver
     \begin{itemize}
-    \item When the device file is first opened, register an interrupt
-      handler for the device's interrupt channel.
+    \item In the \code{probe()} function, for each device,
+      use \kfunc{devm_request_irq} to register an interrupt handler
+      for the device's interrupt channel.
     \end{itemize}
   \item Interrupt handler
     \begin{itemize}
     \item Called when an interrupt is raised.
     \item Acknowledge the interrupt
-    \item If needed, schedule a tasklet taking care of handling
-      data. Otherwise, wake up processes waiting for the data.
-    \end{itemize}
-  \item Tasklet
-    \begin{itemize}
-    \item Process the data
-    \item Wake up processes waiting for the data
+    \item If needed, schedule a per-device tasklet taking care of handling
+      data.
+    \item Wake up processes waiting for the data on a per-device queue
     \end{itemize}
   \item Device driver
     \begin{itemize}
-    \item When the device is no longer opened by any process,
-      unregister the interrupt handler.
+    \item In the \code{remove()} function, for each device, the
+      interrupt handler is automatically unregistered.
     \end{itemize}
   \end{itemize}
 \end{frame}
diff --git a/slides/kernel-driver-development-lab-interrupts/kernel-driver-development-lab-interrupts.tex b/slides/kernel-driver-development-lab-interrupts/kernel-driver-development-lab-interrupts.tex
index 69c4a20..9dc4842 100644
--- a/slides/kernel-driver-development-lab-interrupts/kernel-driver-development-lab-interrupts.tex
+++ b/slides/kernel-driver-development-lab-interrupts/kernel-driver-development-lab-interrupts.tex
@@ -4,8 +4,8 @@
   \begin{itemize}
   \item Adding read capability to the character driver developed
     earlier.
-  \item Register an interrupt handler.
+  \item Register an interrupt handler for each device.
   \item Waiting for data to be available in the read file operation.
-  \item Waking up the code when data are available from the device.
+  \item Waking up the code when data are available from the devices.
   \end{itemize}
 }




More information about the training-materials-updates mailing list