Back to home page

OSCL-LXR

 
 

    


0001 .. include:: ../disclaimer-zh_CN.rst
0002 
0003 :Original: Documentation/core-api/genericirq.rst
0004 
0005 :翻译:
0006 
0007  司延腾 Yanteng Si <siyanteng@loongson.cn>
0008 
0009 :校译:
0010 
0011  吴想成 Wu XiangCheng <bobwxc@email.cn>
0012 
0013 .. include:: <isonum.txt>
0014 
0015 .. _cn_core-api_genericirq:
0016 
0017 ================
0018 Linux通用IRQ处理
0019 ================
0020 
0021 :版权: |copy| 2005-2010: Thomas Gleixner
0022 :版权: |copy| 2005-2006:  Ingo Molnar
0023 
0024 简介
0025 ====
0026 
0027 通用中断处理层是为了给设备驱动程序提供一个完整的中断处理抽象(层)。它能够处
0028 理所有不同类型的中断控制器硬件。设备驱动程序使用通用API函数来请求、启用、禁
0029 用和释放中断。驱动程序不需要知道任何关于硬件处理中断的细节,所以它们可以在不同的
0030 平台上使用而不需要修改代码。
0031 
0032 本文档提供给那些希望在通用IRQ处理层的帮助下实现基于其架构的中断子系统的开发
0033 者。
0034 
0035 理论依据
0036 ========
0037 
0038 Linux中中断处理的原始实现使用__do_IRQ()超级处理程序,它能够处理每种类型的
0039 中断逻辑。
0040 
0041 最初,Russell King确定了不同类型的处理程序,以便为Linux 2.5/2.6中的ARM中
0042 断处理程序实现建立一个相当通用的集合。他区分了以下几种类型:
0043 
0044 -  电平触发型
0045 
0046 -  边沿触发型
0047 
0048 -  简单型
0049 
0050 在实现过程中,我们发现了另一种类型:
0051 
0052 -  响应EOI(end of interrupt)型
0053 
0054 在SMP的__do_IRQ()超级处理程序中,还需定义一种类型:
0055 
0056 -  每cpu型(针对CPU SMP)
0057 
0058 这种高层IRQ处理程序的拆分实现使我们能够为每个特定的中断类型优化中断处理的流
0059 程。这减少了该特定代码路径的复杂性,并允许对特定类型进行优化处理。
0060 
0061 最初的通用IRQ实现使用hw_interrupt_type结构体及其 ``->ack`` ``->end`` 等回
0062 调来区分超级处理程序中的流控制。这导致了流逻辑和低级硬件逻辑的混合,也导致了
0063 不必要的代码重复:例如i386中的 ``ioapic_level_irq`` 和 ``ioapic_edge_irq`` ,
0064 这两个IRQ类型共享许多低级的细节,但有不同的流处理。
0065 
0066 一个更自然的抽象是“irq流”和“芯片细节”的干净分离。
0067 
0068 分析一些架构的IRQ子系统的实现可以发现,他们中的大多数可以使用一套通用的“irq
0069 流”方法,只需要添加芯片级的特定代码。这种分离对于那些需要IRQ流本身而不需要芯
0070 片细节的特定(子)架构也很有价值——以提供了一个更透明的IRQ子系统设计。
0071 
0072 每个中断描述符都被分配给它自己的高层流程处理程序,这通常是一个通用的实现。(这
0073 种高层次的流程处理程序的实现也使得提供解复用处理程序变得简单,这可以在各种架
0074 构的嵌入式平台上找到。)
0075 
0076 这种分离使得通用中断处理层更加灵活和可扩展。例如,一个(子)架构可以使用通用
0077 的IRQ流实现“电平触发型”中断,并添加一个(子)架构特定的“边沿型”实现。
0078 
0079 为了使向新模型的过渡更容易,并防止破坏现有实现,__do_IRQ()超级处理程序仍然
0080 可用。这导致了一种暂时的双重性。随着时间的推移,新的模型应该在越来越多的架构中
0081 被使用,因为它能使IRQ子系统更小更干净。它已经被废弃三年了,即将被删除。
0082 
0083 已知的缺陷和假设
0084 ================
0085 
0086 没有(但愿如此)。
0087 
0088 抽象层
0089 ======
0090 
0091 中断代码中主要有三个抽象层次:
0092 
0093 1. 高级别的驱动API
0094 
0095 2. 高级别的IRQ流处理器
0096 
0097 3. 芯片级的硬件封装
0098 
0099 中断控制流
0100 ----------
0101 
0102 每个中断都由一个中断描述符结构体irq_desc来描述。中断是由一个“无符号整型”的数值来
0103 引用的,它在描述符结构体数组中选择相应的中断描述符结构体。描述符结构体包含状态
0104 信息和指向中断流方法和中断芯片结构的指针,这些都是分配给这个中断的。
0105 
0106 每当中断触发时,低级架构代码通过调用desc->handle_irq()调用到通用中断代码中。
0107 这个高层IRQ处理函数只使用由分配的芯片描述符结构体引用的desc->irq_data.chip
0108 基元。
0109 
0110 高级驱动程序API
0111 ---------------
0112 
0113 高层驱动API由以下函数组成:
0114 
0115 -  request_irq()
0116 
0117 -  request_threaded_irq()
0118 
0119 -  free_irq()
0120 
0121 -  disable_irq()
0122 
0123 -  enable_irq()
0124 
0125 -  disable_irq_nosync() (SMP only)
0126 
0127 -  synchronize_irq() (SMP only)
0128 
0129 -  irq_set_irq_type()
0130 
0131 -  irq_set_irq_wake()
0132 
0133 -  irq_set_handler_data()
0134 
0135 -  irq_set_chip()
0136 
0137 -  irq_set_chip_data()
0138 
0139 详见自动生成的函数文档。
0140 
0141 .. note::
0142 
0143     由于文档构建流程所限,中文文档中并没有引入自动生成的函数文档,所以请读者直接
0144     阅读源码注释。
0145 
0146 电平触发型IRQ流处理程序
0147 -----------------------
0148 
0149 通用层提供了一套预定义的irq-flow方法:
0150 
0151 -  handle_level_irq()
0152 
0153 -  handle_edge_irq()
0154 
0155 -  handle_fasteoi_irq()
0156 
0157 -  handle_simple_irq()
0158 
0159 -  handle_percpu_irq()
0160 
0161 -  handle_edge_eoi_irq()
0162 
0163 -  handle_bad_irq()
0164 
0165 中断流处理程序(无论是预定义的还是架构特定的)由架构在启动期间或设备初始化期间分配给
0166 特定中断。
0167 
0168 默认流实现
0169 ~~~~~~~~~~
0170 
0171 辅助函数
0172 ^^^^^^^^
0173 
0174 辅助函数调用芯片基元,并被默认流实现所使用。以下是实现的辅助函数(简化摘录)::
0175 
0176     default_enable(struct irq_data *data)
0177     {
0178         desc->irq_data.chip->irq_unmask(data);
0179     }
0180 
0181     default_disable(struct irq_data *data)
0182     {
0183         if (!delay_disable(data))
0184             desc->irq_data.chip->irq_mask(data);
0185     }
0186 
0187     default_ack(struct irq_data *data)
0188     {
0189         chip->irq_ack(data);
0190     }
0191 
0192     default_mask_ack(struct irq_data *data)
0193     {
0194         if (chip->irq_mask_ack) {
0195             chip->irq_mask_ack(data);
0196         } else {
0197             chip->irq_mask(data);
0198             chip->irq_ack(data);
0199         }
0200     }
0201 
0202     noop(struct irq_data *data))
0203     {
0204     }
0205 
0206 
0207 
0208 默认流处理程序的实现
0209 ~~~~~~~~~~~~~~~~~~~~
0210 
0211 电平触发型IRQ流处理器
0212 ^^^^^^^^^^^^^^^^^^^^^
0213 
0214 handle_level_irq为电平触发型的中断提供了一个通用实现。
0215 
0216 实现的控制流如下(简化摘录)::
0217 
0218     desc->irq_data.chip->irq_mask_ack();
0219     handle_irq_event(desc->action);
0220     desc->irq_data.chip->irq_unmask();
0221 
0222 
0223 默认的需回应IRQ流处理器
0224 ^^^^^^^^^^^^^^^^^^^^^^^
0225 
0226 handle_fasteoi_irq为中断提供了一个通用的实现,它只需要在处理程序的末端有一个EOI。
0227 
0228 实现的控制流如下(简化摘录)::
0229 
0230     handle_irq_event(desc->action);
0231     desc->irq_data.chip->irq_eoi();
0232 
0233 
0234 默认的边沿触发型IRQ流处理器
0235 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
0236 
0237 handle_edge_irq为边沿触发型的中断提供了一个通用的实现。
0238 
0239 实现的控制流如下(简化摘录)::
0240 
0241     if (desc->status & running) {
0242         desc->irq_data.chip->irq_mask_ack();
0243         desc->status |= pending | masked;
0244         return;
0245     }
0246     desc->irq_data.chip->irq_ack();
0247     desc->status |= running;
0248     do {
0249         if (desc->status & masked)
0250             desc->irq_data.chip->irq_unmask();
0251         desc->status &= ~pending;
0252         handle_irq_event(desc->action);
0253     } while (status & pending);
0254     desc->status &= ~running;
0255 
0256 
0257 默认的简单型IRQ流处理器
0258 ^^^^^^^^^^^^^^^^^^^^^^^
0259 
0260 handle_simple_irq提供了一个简单型中断的通用实现。
0261 
0262 .. note::
0263 
0264    简单型的流处理程序不调用任何处理程序/芯片基元。
0265 
0266 实现的控制流程如下(简化摘录)::
0267 
0268     handle_irq_event(desc->action);
0269 
0270 
0271 默认的每CPU型流处理程序
0272 ^^^^^^^^^^^^^^^^^^^^^^^
0273 
0274 handle_percpu_irq为每CPU型中断提供一个通用的实现。
0275 
0276 每个CPU中断只在SMP上可用,该处理程序提供了一个没有锁的简化版本。
0277 
0278 以下是控制流的实现(简化摘录)::
0279 
0280     if (desc->irq_data.chip->irq_ack)
0281         desc->irq_data.chip->irq_ack();
0282     handle_irq_event(desc->action);
0283     if (desc->irq_data.chip->irq_eoi)
0284         desc->irq_data.chip->irq_eoi();
0285 
0286 
0287 EOI边沿型IRQ流处理器
0288 ^^^^^^^^^^^^^^^^^^^^
0289 
0290 handle_edge_eoi_irq提供了一个异常的边沿触发型处理程序,它只用于拯救powerpc/cell
0291 上的一个严重失控的irq控制器。
0292 
0293 坏的IRQ流处理器
0294 ^^^^^^^^^^^^^^^
0295 
0296 handle_bad_irq用于处理没有真正分配处理程序的假中断。
0297 
0298 特殊性和优化
0299 ~~~~~~~~~~~~
0300 
0301 通用函数是为“干净”的架构和芯片设计的,它们没有平台特定的IRQ处理特殊性。如果一
0302 个架构需要在“流”的层面上实现特殊性,那么它可以通过覆盖高层的IRQ-流处理程序来实
0303 现。
0304 
0305 延迟中断禁用
0306 ~~~~~~~~~~~~
0307 
0308 每个中断可选择的功能是由Russell King在ARM中断实现中引入的,当调用disable_irq()
0309 时,不会在硬件层面上屏蔽中断。中断保持启用状态,而在中断事件发生时在流处理器中被
0310 屏蔽。这可以防止在硬件上丢失边沿中断,因为硬件上不存储边沿中断事件,而中断在硬件
0311 级被禁用。当一个中断在IRQ_DISABLED标志被设置时到达,那么该中断在硬件层面被屏蔽,
0312 IRQ_PENDING位被设置。当中断被enable_irq()重新启用时,将检查挂起位,如果它被设置,
0313 中断将通过硬件或软件重发机制重新发送。(当你想使用延迟中断禁用功能,而你的硬件又不
0314 能重新触发中断时,有必要启用CONFIG_HARDIRQS_SW_RESEND。) 延迟中断禁止功能是不可
0315 配置的。
0316 
0317 芯片级硬件封装
0318 --------------
0319 
0320 芯片级硬件描述符结构体 :c:type:`irq_chip` 包含了所有与芯片直接相关的功能,这些功
0321 能可以被irq流实现所利用。
0322 
0323 -  ``irq_ack``
0324 
0325 -  ``irq_mask_ack`` - 可选的,建议使用的性能
0326 
0327 -  ``irq_mask``
0328 
0329 -  ``irq_unmask``
0330 
0331 -  ``irq_eoi`` - 可选的,EOI流处理程序需要
0332 
0333 -  ``irq_retrigger`` - 可选的
0334 
0335 -  ``irq_set_type`` - 可选的
0336 
0337 -  ``irq_set_wake`` - 可选的
0338 
0339 这些基元的意思是严格意义上的:ack是指ACK,masking是指对IRQ线的屏蔽,等等。这取决
0340 于流处理器如何使用这些基本的低级功能单元。
0341 
0342 __do_IRQ入口点
0343 ==============
0344 
0345 最初的实现__do_IRQ()是所有类型中断的替代入口点。它已经不存在了。
0346 
0347 这个处理程序被证明不适合所有的中断硬件,因此被重新实现了边沿/级别/简单/超高速中断
0348 的拆分功能。这不仅是一个功能优化。它也缩短了中断的代码路径。
0349 
0350 在SMP上的锁
0351 ===========
0352 
0353 芯片寄存器的锁定是由定义芯片基元的架构决定的。每个寄存器的结构通过desc->lock,由
0354 通用层保护。
0355 
0356 通用中断芯片
0357 ============
0358 
0359 为了避免复制相同的IRQ芯片实现,核心提供了一个可配置的通用中断芯片实现。开发者在自
0360 己实现相同的功能之前,应该仔细检查通用芯片是否符合他们的需求,并以稍微不同的方式实
0361 现相同的功能。
0362 
0363 该API在以下内核代码中:
0364 
0365 kernel/irq/generic-chip.c
0366 
0367 结构体
0368 ======
0369 
0370 本章包含自动生成的结构体文档,这些结构体在通用IRQ层中使用。
0371 
0372 该API在以下内核代码中:
0373 
0374 include/linux/irq.h
0375 
0376 include/linux/interrupt.h
0377 
0378 提供的通用函数
0379 ==============
0380 
0381 这一章包含了自动生成的内核API函数的文档,这些函数被导出。
0382 
0383 该API在以下内核代码中:
0384 
0385 kernel/irq/manage.c
0386 
0387 kernel/irq/chip.c
0388 
0389 提供的内部函数
0390 ==============
0391 
0392 本章包含自动生成的内部函数的文档。
0393 
0394 该API在以下内核代码中:
0395 
0396 kernel/irq/irqdesc.c
0397 
0398 kernel/irq/handle.c
0399 
0400 kernel/irq/chip.c
0401 
0402 鸣谢
0403 ====
0404 
0405 感谢以下人士对本文档作出的贡献:
0406 
0407 1. Thomas Gleixner tglx@linutronix.de
0408 
0409 2. Ingo Molnar mingo@elte.hu