Commit | Line | Data |
---|---|---|
11c869ea TG |
1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" | |
3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> | |
4 | ||
5 | <book id="Generic-IRQ-Guide"> | |
6 | <bookinfo> | |
7 | <title>Linux generic IRQ handling</title> | |
8 | ||
9 | <authorgroup> | |
10 | <author> | |
11 | <firstname>Thomas</firstname> | |
12 | <surname>Gleixner</surname> | |
13 | <affiliation> | |
14 | <address> | |
15 | <email>tglx@linutronix.de</email> | |
16 | </address> | |
17 | </affiliation> | |
18 | </author> | |
19 | <author> | |
20 | <firstname>Ingo</firstname> | |
21 | <surname>Molnar</surname> | |
22 | <affiliation> | |
23 | <address> | |
24 | <email>mingo@elte.hu</email> | |
25 | </address> | |
26 | </affiliation> | |
27 | </author> | |
28 | </authorgroup> | |
29 | ||
30 | <copyright> | |
25ade601 | 31 | <year>2005-2010</year> |
11c869ea TG |
32 | <holder>Thomas Gleixner</holder> |
33 | </copyright> | |
34 | <copyright> | |
35 | <year>2005-2006</year> | |
36 | <holder>Ingo Molnar</holder> | |
37 | </copyright> | |
38 | ||
39 | <legalnotice> | |
40 | <para> | |
41 | This documentation is free software; you can redistribute | |
42 | it and/or modify it under the terms of the GNU General Public | |
43 | License version 2 as published by the Free Software Foundation. | |
44 | </para> | |
45 | ||
46 | <para> | |
47 | This program is distributed in the hope that it will be | |
48 | useful, but WITHOUT ANY WARRANTY; without even the implied | |
49 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
50 | See the GNU General Public License for more details. | |
51 | </para> | |
52 | ||
53 | <para> | |
54 | You should have received a copy of the GNU General Public | |
55 | License along with this program; if not, write to the Free | |
56 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
57 | MA 02111-1307 USA | |
58 | </para> | |
59 | ||
60 | <para> | |
61 | For more details see the file COPYING in the source | |
62 | distribution of Linux. | |
63 | </para> | |
64 | </legalnotice> | |
65 | </bookinfo> | |
66 | ||
67 | <toc></toc> | |
68 | ||
69 | <chapter id="intro"> | |
70 | <title>Introduction</title> | |
71 | <para> | |
72 | The generic interrupt handling layer is designed to provide a | |
73 | complete abstraction of interrupt handling for device drivers. | |
74 | It is able to handle all the different types of interrupt controller | |
75 | hardware. Device drivers use generic API functions to request, enable, | |
76 | disable and free interrupts. The drivers do not have to know anything | |
77 | about interrupt hardware details, so they can be used on different | |
78 | platforms without code changes. | |
79 | </para> | |
80 | <para> | |
81 | This documentation is provided to developers who want to implement | |
82 | an interrupt subsystem based for their architecture, with the help | |
83 | of the generic IRQ handling layer. | |
84 | </para> | |
85 | </chapter> | |
86 | ||
87 | <chapter id="rationale"> | |
88 | <title>Rationale</title> | |
89 | <para> | |
fd2f3b7e | 90 | The original implementation of interrupt handling in Linux uses |
11c869ea TG |
91 | the __do_IRQ() super-handler, which is able to deal with every |
92 | type of interrupt logic. | |
93 | </para> | |
94 | <para> | |
95 | Originally, Russell King identified different types of handlers to | |
96 | build a quite universal set for the ARM interrupt handler | |
97 | implementation in Linux 2.5/2.6. He distinguished between: | |
98 | <itemizedlist> | |
99 | <listitem><para>Level type</para></listitem> | |
100 | <listitem><para>Edge type</para></listitem> | |
101 | <listitem><para>Simple type</para></listitem> | |
102 | </itemizedlist> | |
25ade601 TG |
103 | During the implementation we identified another type: |
104 | <itemizedlist> | |
105 | <listitem><para>Fast EOI type</para></listitem> | |
106 | </itemizedlist> | |
11c869ea TG |
107 | In the SMP world of the __do_IRQ() super-handler another type |
108 | was identified: | |
109 | <itemizedlist> | |
110 | <listitem><para>Per CPU type</para></listitem> | |
111 | </itemizedlist> | |
112 | </para> | |
113 | <para> | |
fd2f3b7e | 114 | This split implementation of high-level IRQ handlers allows us to |
11c869ea | 115 | optimize the flow of the interrupt handling for each specific |
fd2f3b7e | 116 | interrupt type. This reduces complexity in that particular code path |
11c869ea TG |
117 | and allows the optimized handling of a given type. |
118 | </para> | |
119 | <para> | |
120 | The original general IRQ implementation used hw_interrupt_type | |
121 | structures and their ->ack(), ->end() [etc.] callbacks to | |
122 | differentiate the flow control in the super-handler. This leads to | |
fd2f3b7e RD |
123 | a mix of flow logic and low-level hardware logic, and it also leads |
124 | to unnecessary code duplication: for example in i386, there is an | |
125 | ioapic_level_irq and an ioapic_edge_irq IRQ-type which share many | |
126 | of the low-level details but have different flow handling. | |
11c869ea TG |
127 | </para> |
128 | <para> | |
129 | A more natural abstraction is the clean separation of the | |
130 | 'irq flow' and the 'chip details'. | |
131 | </para> | |
132 | <para> | |
133 | Analysing a couple of architecture's IRQ subsystem implementations | |
134 | reveals that most of them can use a generic set of 'irq flow' | |
fd2f3b7e | 135 | methods and only need to add the chip-level specific code. |
11c869ea | 136 | The separation is also valuable for (sub)architectures |
fd2f3b7e RD |
137 | which need specific quirks in the IRQ flow itself but not in the |
138 | chip details - and thus provides a more transparent IRQ subsystem | |
11c869ea TG |
139 | design. |
140 | </para> | |
141 | <para> | |
fd2f3b7e | 142 | Each interrupt descriptor is assigned its own high-level flow |
11c869ea | 143 | handler, which is normally one of the generic |
fd2f3b7e | 144 | implementations. (This high-level flow handler implementation also |
11c869ea TG |
145 | makes it simple to provide demultiplexing handlers which can be |
146 | found in embedded platforms on various architectures.) | |
147 | </para> | |
148 | <para> | |
149 | The separation makes the generic interrupt handling layer more | |
150 | flexible and extensible. For example, an (sub)architecture can | |
fd2f3b7e | 151 | use a generic IRQ-flow implementation for 'level type' interrupts |
11c869ea TG |
152 | and add a (sub)architecture specific 'edge type' implementation. |
153 | </para> | |
154 | <para> | |
155 | To make the transition to the new model easier and prevent the | |
156 | breakage of existing implementations, the __do_IRQ() super-handler | |
157 | is still available. This leads to a kind of duality for the time | |
158 | being. Over time the new model should be used in more and more | |
159 | architectures, as it enables smaller and cleaner IRQ subsystems. | |
25ade601 | 160 | It's deprecated for three years now and about to be removed. |
11c869ea TG |
161 | </para> |
162 | </chapter> | |
163 | <chapter id="bugs"> | |
164 | <title>Known Bugs And Assumptions</title> | |
165 | <para> | |
166 | None (knock on wood). | |
167 | </para> | |
168 | </chapter> | |
169 | ||
170 | <chapter id="Abstraction"> | |
171 | <title>Abstraction layers</title> | |
172 | <para> | |
173 | There are three main levels of abstraction in the interrupt code: | |
174 | <orderedlist> | |
fd2f3b7e RD |
175 | <listitem><para>High-level driver API</para></listitem> |
176 | <listitem><para>High-level IRQ flow handlers</para></listitem> | |
177 | <listitem><para>Chip-level hardware encapsulation</para></listitem> | |
11c869ea TG |
178 | </orderedlist> |
179 | </para> | |
aa9128f3 | 180 | <sect1 id="Interrupt_control_flow"> |
11c869ea TG |
181 | <title>Interrupt control flow</title> |
182 | <para> | |
183 | Each interrupt is described by an interrupt descriptor structure | |
184 | irq_desc. The interrupt is referenced by an 'unsigned int' numeric | |
0ba4f6e4 | 185 | value which selects the corresponding interrupt description structure |
11c869ea TG |
186 | in the descriptor structures array. |
187 | The descriptor structure contains status information and pointers | |
188 | to the interrupt flow method and the interrupt chip structure | |
189 | which are assigned to this interrupt. | |
190 | </para> | |
191 | <para> | |
fd2f3b7e RD |
192 | Whenever an interrupt triggers, the low-level architecture code calls |
193 | into the generic interrupt code by calling desc->handle_irq(). | |
194 | This high-level IRQ handling function only uses desc->irq_data.chip | |
ee430599 | 195 | primitives referenced by the assigned chip descriptor structure. |
11c869ea TG |
196 | </para> |
197 | </sect1> | |
aa9128f3 | 198 | <sect1 id="Highlevel_Driver_API"> |
fd2f3b7e | 199 | <title>High-level Driver API</title> |
11c869ea | 200 | <para> |
fd2f3b7e | 201 | The high-level Driver API consists of following functions: |
11c869ea TG |
202 | <itemizedlist> |
203 | <listitem><para>request_irq()</para></listitem> | |
204 | <listitem><para>free_irq()</para></listitem> | |
205 | <listitem><para>disable_irq()</para></listitem> | |
206 | <listitem><para>enable_irq()</para></listitem> | |
207 | <listitem><para>disable_irq_nosync() (SMP only)</para></listitem> | |
208 | <listitem><para>synchronize_irq() (SMP only)</para></listitem> | |
ee430599 GU |
209 | <listitem><para>irq_set_irq_type()</para></listitem> |
210 | <listitem><para>irq_set_irq_wake()</para></listitem> | |
211 | <listitem><para>irq_set_handler_data()</para></listitem> | |
212 | <listitem><para>irq_set_chip()</para></listitem> | |
213 | <listitem><para>irq_set_chip_data()</para></listitem> | |
11c869ea TG |
214 | </itemizedlist> |
215 | See the autogenerated function documentation for details. | |
216 | </para> | |
217 | </sect1> | |
aa9128f3 | 218 | <sect1 id="Highlevel_IRQ_flow_handlers"> |
fd2f3b7e | 219 | <title>High-level IRQ flow handlers</title> |
11c869ea TG |
220 | <para> |
221 | The generic layer provides a set of pre-defined irq-flow methods: | |
222 | <itemizedlist> | |
223 | <listitem><para>handle_level_irq</para></listitem> | |
224 | <listitem><para>handle_edge_irq</para></listitem> | |
25ade601 | 225 | <listitem><para>handle_fasteoi_irq</para></listitem> |
11c869ea TG |
226 | <listitem><para>handle_simple_irq</para></listitem> |
227 | <listitem><para>handle_percpu_irq</para></listitem> | |
ee430599 GU |
228 | <listitem><para>handle_edge_eoi_irq</para></listitem> |
229 | <listitem><para>handle_bad_irq</para></listitem> | |
11c869ea | 230 | </itemizedlist> |
fd2f3b7e | 231 | The interrupt flow handlers (either pre-defined or architecture |
11c869ea TG |
232 | specific) are assigned to specific interrupts by the architecture |
233 | either during bootup or during device initialization. | |
234 | </para> | |
aa9128f3 | 235 | <sect2 id="Default_flow_implementations"> |
11c869ea | 236 | <title>Default flow implementations</title> |
aa9128f3 | 237 | <sect3 id="Helper_functions"> |
11c869ea TG |
238 | <title>Helper functions</title> |
239 | <para> | |
240 | The helper functions call the chip primitives and | |
241 | are used by the default flow implementations. | |
242 | The following helper functions are implemented (simplified excerpt): | |
243 | <programlisting> | |
25ade601 | 244 | default_enable(struct irq_data *data) |
11c869ea | 245 | { |
ee430599 | 246 | desc->irq_data.chip->irq_unmask(data); |
11c869ea TG |
247 | } |
248 | ||
25ade601 | 249 | default_disable(struct irq_data *data) |
11c869ea | 250 | { |
25ade601 | 251 | if (!delay_disable(data)) |
ee430599 | 252 | desc->irq_data.chip->irq_mask(data); |
11c869ea TG |
253 | } |
254 | ||
25ade601 | 255 | default_ack(struct irq_data *data) |
11c869ea | 256 | { |
25ade601 | 257 | chip->irq_ack(data); |
11c869ea TG |
258 | } |
259 | ||
25ade601 | 260 | default_mask_ack(struct irq_data *data) |
11c869ea | 261 | { |
25ade601 TG |
262 | if (chip->irq_mask_ack) { |
263 | chip->irq_mask_ack(data); | |
11c869ea | 264 | } else { |
25ade601 TG |
265 | chip->irq_mask(data); |
266 | chip->irq_ack(data); | |
11c869ea TG |
267 | } |
268 | } | |
269 | ||
25ade601 | 270 | noop(struct irq_data *data)) |
11c869ea TG |
271 | { |
272 | } | |
273 | ||
274 | </programlisting> | |
275 | </para> | |
276 | </sect3> | |
277 | </sect2> | |
aa9128f3 | 278 | <sect2 id="Default_flow_handler_implementations"> |
11c869ea | 279 | <title>Default flow handler implementations</title> |
aa9128f3 | 280 | <sect3 id="Default_Level_IRQ_flow_handler"> |
11c869ea TG |
281 | <title>Default Level IRQ flow handler</title> |
282 | <para> | |
283 | handle_level_irq provides a generic implementation | |
284 | for level-triggered interrupts. | |
285 | </para> | |
286 | <para> | |
287 | The following control flow is implemented (simplified excerpt): | |
288 | <programlisting> | |
ee430599 GU |
289 | desc->irq_data.chip->irq_mask_ack(); |
290 | handle_irq_event(desc->action); | |
291 | desc->irq_data.chip->irq_unmask(); | |
11c869ea TG |
292 | </programlisting> |
293 | </para> | |
25ade601 TG |
294 | </sect3> |
295 | <sect3 id="Default_FASTEOI_IRQ_flow_handler"> | |
296 | <title>Default Fast EOI IRQ flow handler</title> | |
297 | <para> | |
298 | handle_fasteoi_irq provides a generic implementation | |
299 | for interrupts, which only need an EOI at the end of | |
fd2f3b7e | 300 | the handler. |
25ade601 TG |
301 | </para> |
302 | <para> | |
303 | The following control flow is implemented (simplified excerpt): | |
304 | <programlisting> | |
ee430599 GU |
305 | handle_irq_event(desc->action); |
306 | desc->irq_data.chip->irq_eoi(); | |
25ade601 TG |
307 | </programlisting> |
308 | </para> | |
309 | </sect3> | |
aa9128f3 | 310 | <sect3 id="Default_Edge_IRQ_flow_handler"> |
11c869ea TG |
311 | <title>Default Edge IRQ flow handler</title> |
312 | <para> | |
313 | handle_edge_irq provides a generic implementation | |
314 | for edge-triggered interrupts. | |
315 | </para> | |
316 | <para> | |
317 | The following control flow is implemented (simplified excerpt): | |
318 | <programlisting> | |
319 | if (desc->status & running) { | |
ee430599 | 320 | desc->irq_data.chip->irq_mask_ack(); |
11c869ea TG |
321 | desc->status |= pending | masked; |
322 | return; | |
323 | } | |
ee430599 | 324 | desc->irq_data.chip->irq_ack(); |
11c869ea TG |
325 | desc->status |= running; |
326 | do { | |
327 | if (desc->status & masked) | |
ee430599 | 328 | desc->irq_data.chip->irq_unmask(); |
b06824ce | 329 | desc->status &= ~pending; |
ee430599 | 330 | handle_irq_event(desc->action); |
11c869ea | 331 | } while (status & pending); |
b06824ce | 332 | desc->status &= ~running; |
11c869ea TG |
333 | </programlisting> |
334 | </para> | |
335 | </sect3> | |
aa9128f3 | 336 | <sect3 id="Default_simple_IRQ_flow_handler"> |
11c869ea TG |
337 | <title>Default simple IRQ flow handler</title> |
338 | <para> | |
339 | handle_simple_irq provides a generic implementation | |
340 | for simple interrupts. | |
341 | </para> | |
342 | <para> | |
343 | Note: The simple flow handler does not call any | |
344 | handler/chip primitives. | |
345 | </para> | |
346 | <para> | |
347 | The following control flow is implemented (simplified excerpt): | |
348 | <programlisting> | |
ee430599 | 349 | handle_irq_event(desc->action); |
11c869ea TG |
350 | </programlisting> |
351 | </para> | |
352 | </sect3> | |
aa9128f3 | 353 | <sect3 id="Default_per_CPU_flow_handler"> |
11c869ea TG |
354 | <title>Default per CPU flow handler</title> |
355 | <para> | |
356 | handle_percpu_irq provides a generic implementation | |
357 | for per CPU interrupts. | |
358 | </para> | |
359 | <para> | |
360 | Per CPU interrupts are only available on SMP and | |
361 | the handler provides a simplified version without | |
362 | locking. | |
363 | </para> | |
364 | <para> | |
365 | The following control flow is implemented (simplified excerpt): | |
366 | <programlisting> | |
ee430599 GU |
367 | if (desc->irq_data.chip->irq_ack) |
368 | desc->irq_data.chip->irq_ack(); | |
369 | handle_irq_event(desc->action); | |
370 | if (desc->irq_data.chip->irq_eoi) | |
371 | desc->irq_data.chip->irq_eoi(); | |
11c869ea TG |
372 | </programlisting> |
373 | </para> | |
374 | </sect3> | |
ee430599 GU |
375 | <sect3 id="EOI_Edge_IRQ_flow_handler"> |
376 | <title>EOI Edge IRQ flow handler</title> | |
377 | <para> | |
378 | handle_edge_eoi_irq provides an abnomination of the edge | |
379 | handler which is solely used to tame a badly wreckaged | |
380 | irq controller on powerpc/cell. | |
381 | </para> | |
382 | </sect3> | |
383 | <sect3 id="BAD_IRQ_flow_handler"> | |
384 | <title>Bad IRQ flow handler</title> | |
385 | <para> | |
386 | handle_bad_irq is used for spurious interrupts which | |
387 | have no real handler assigned.. | |
388 | </para> | |
389 | </sect3> | |
11c869ea | 390 | </sect2> |
aa9128f3 | 391 | <sect2 id="Quirks_and_optimizations"> |
11c869ea TG |
392 | <title>Quirks and optimizations</title> |
393 | <para> | |
394 | The generic functions are intended for 'clean' architectures and chips, | |
395 | which have no platform-specific IRQ handling quirks. If an architecture | |
396 | needs to implement quirks on the 'flow' level then it can do so by | |
fd2f3b7e | 397 | overriding the high-level irq-flow handler. |
11c869ea TG |
398 | </para> |
399 | </sect2> | |
aa9128f3 | 400 | <sect2 id="Delayed_interrupt_disable"> |
11c869ea TG |
401 | <title>Delayed interrupt disable</title> |
402 | <para> | |
403 | This per interrupt selectable feature, which was introduced by Russell | |
404 | King in the ARM interrupt implementation, does not mask an interrupt | |
405 | at the hardware level when disable_irq() is called. The interrupt is | |
406 | kept enabled and is masked in the flow handler when an interrupt event | |
407 | happens. This prevents losing edge interrupts on hardware which does | |
408 | not store an edge interrupt event while the interrupt is disabled at | |
409 | the hardware level. When an interrupt arrives while the IRQ_DISABLED | |
410 | flag is set, then the interrupt is masked at the hardware level and | |
411 | the IRQ_PENDING bit is set. When the interrupt is re-enabled by | |
412 | enable_irq() the pending bit is checked and if it is set, the | |
413 | interrupt is resent either via hardware or by a software resend | |
414 | mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when | |
415 | you want to use the delayed interrupt disable feature and your | |
416 | hardware is not capable of retriggering an interrupt.) | |
25ade601 | 417 | The delayed interrupt disable is not configurable. |
11c869ea TG |
418 | </para> |
419 | </sect2> | |
420 | </sect1> | |
aa9128f3 | 421 | <sect1 id="Chiplevel_hardware_encapsulation"> |
fd2f3b7e | 422 | <title>Chip-level hardware encapsulation</title> |
11c869ea | 423 | <para> |
fd2f3b7e | 424 | The chip-level hardware descriptor structure irq_chip |
11c869ea TG |
425 | contains all the direct chip relevant functions, which |
426 | can be utilized by the irq flow implementations. | |
427 | <itemizedlist> | |
25ade601 TG |
428 | <listitem><para>irq_ack()</para></listitem> |
429 | <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem> | |
430 | <listitem><para>irq_mask()</para></listitem> | |
431 | <listitem><para>irq_unmask()</para></listitem> | |
fd2f3b7e | 432 | <listitem><para>irq_eoi() - Optional, required for EOI flow handlers</para></listitem> |
25ade601 TG |
433 | <listitem><para>irq_retrigger() - Optional</para></listitem> |
434 | <listitem><para>irq_set_type() - Optional</para></listitem> | |
435 | <listitem><para>irq_set_wake() - Optional</para></listitem> | |
11c869ea TG |
436 | </itemizedlist> |
437 | These primitives are strictly intended to mean what they say: ack means | |
438 | ACK, masking means masking of an IRQ line, etc. It is up to the flow | |
fd2f3b7e | 439 | handler(s) to use these basic units of low-level functionality. |
11c869ea TG |
440 | </para> |
441 | </sect1> | |
442 | </chapter> | |
443 | ||
444 | <chapter id="doirq"> | |
445 | <title>__do_IRQ entry point</title> | |
446 | <para> | |
ee430599 | 447 | The original implementation __do_IRQ() was an alternative entry |
fd2f3b7e | 448 | point for all types of interrupts. It no longer exists. |
11c869ea TG |
449 | </para> |
450 | <para> | |
451 | This handler turned out to be not suitable for all | |
452 | interrupt hardware and was therefore reimplemented with split | |
ee430599 | 453 | functionality for edge/level/simple/percpu interrupts. This is not |
11c869ea TG |
454 | only a functional optimization. It also shortens code paths for |
455 | interrupts. | |
456 | </para> | |
11c869ea TG |
457 | </chapter> |
458 | ||
459 | <chapter id="locking"> | |
460 | <title>Locking on SMP</title> | |
461 | <para> | |
462 | The locking of chip registers is up to the architecture that | |
ee430599 GU |
463 | defines the chip primitives. The per-irq structure is |
464 | protected via desc->lock, by the generic layer. | |
11c869ea TG |
465 | </para> |
466 | </chapter> | |
ccc414f8 TG |
467 | |
468 | <chapter id="genericchip"> | |
469 | <title>Generic interrupt chip</title> | |
470 | <para> | |
fd2f3b7e | 471 | To avoid copies of identical implementations of IRQ chips the |
ccc414f8 | 472 | core provides a configurable generic interrupt chip |
0ba4f6e4 | 473 | implementation. Developers should check carefully whether the |
ccc414f8 | 474 | generic chip fits their needs before implementing the same |
fd2f3b7e | 475 | functionality slightly differently themselves. |
ccc414f8 TG |
476 | </para> |
477 | !Ekernel/irq/generic-chip.c | |
478 | </chapter> | |
479 | ||
11c869ea TG |
480 | <chapter id="structs"> |
481 | <title>Structures</title> | |
482 | <para> | |
483 | This chapter contains the autogenerated documentation of the structures which are | |
484 | used in the generic IRQ layer. | |
485 | </para> | |
486 | !Iinclude/linux/irq.h | |
a9d0a1a3 | 487 | !Iinclude/linux/interrupt.h |
11c869ea TG |
488 | </chapter> |
489 | ||
490 | <chapter id="pubfunctions"> | |
491 | <title>Public Functions Provided</title> | |
492 | <para> | |
493 | This chapter contains the autogenerated documentation of the kernel API functions | |
494 | which are exported. | |
495 | </para> | |
496 | !Ekernel/irq/manage.c | |
497 | !Ekernel/irq/chip.c | |
498 | </chapter> | |
499 | ||
500 | <chapter id="intfunctions"> | |
501 | <title>Internal Functions Provided</title> | |
502 | <para> | |
503 | This chapter contains the autogenerated documentation of the internal functions. | |
504 | </para> | |
25ade601 | 505 | !Ikernel/irq/irqdesc.c |
11c869ea TG |
506 | !Ikernel/irq/handle.c |
507 | !Ikernel/irq/chip.c | |
508 | </chapter> | |
509 | ||
510 | <chapter id="credits"> | |
511 | <title>Credits</title> | |
512 | <para> | |
513 | The following people have contributed to this document: | |
514 | <orderedlist> | |
515 | <listitem><para>Thomas Gleixner<email>tglx@linutronix.de</email></para></listitem> | |
516 | <listitem><para>Ingo Molnar<email>mingo@elte.hu</email></para></listitem> | |
517 | </orderedlist> | |
518 | </para> | |
519 | </chapter> | |
520 | </book> |