xref: /DragonOS/kernel/src/exception/irqchip.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1 use core::{any::Any, fmt::Debug, intrinsics::unlikely};
2 
3 use alloc::{
4     string::{String, ToString},
5     sync::{Arc, Weak},
6     vec::Vec,
7 };
8 use log::warn;
9 use system_error::SystemError;
10 
11 use crate::{
12     exception::{
13         dummychip::no_irq_chip,
14         handle::{bad_irq_handler, mask_ack_irq},
15         irqdata::IrqStatus,
16         irqdesc::irq_desc_manager,
17         manage::irq_manager,
18     },
19     libs::{
20         cpumask::CpuMask,
21         once::Once,
22         spinlock::{SpinLock, SpinLockGuard},
23     },
24     mm::VirtAddr,
25     smp::cpu::ProcessorId,
26 };
27 
28 use super::{
29     irqdata::{IrqData, IrqHandlerData, IrqLineStatus},
30     irqdesc::{InnerIrqDesc, IrqAction, IrqDesc, IrqFlowHandler, IrqHandler, IrqReturn},
31     irqdomain::IrqDomain,
32     manage::IrqManager,
33     msi::MsiMsg,
34     IrqNumber,
35 };
36 
37 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506
38 #[allow(dead_code)]
39 pub trait IrqChip: Sync + Send + Any + Debug {
name(&self) -> &'static str40     fn name(&self) -> &'static str;
41     /// start up the interrupt (defaults to ->enable if ENOSYS)
irq_startup(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>42     fn irq_startup(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
43         Err(SystemError::ENOSYS)
44     }
45 
46     /// shut down the interrupt (defaults to ->disable if ENOSYS)
irq_shutdown(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>47     fn irq_shutdown(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
48         Err(SystemError::ENOSYS)
49     }
50 
51     /// enable the interrupt
52     ///
53     /// (defaults to ->unmask if ENOSYS)
irq_enable(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>54     fn irq_enable(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
55         Err(SystemError::ENOSYS)
56     }
57 
58     /// disable the interrupt
irq_disable(&self, irq_data: &Arc<IrqData>)59     fn irq_disable(&self, irq_data: &Arc<IrqData>);
60 
61     /// start of a new interrupt
irq_ack(&self, irq_data: &Arc<IrqData>)62     fn irq_ack(&self, irq_data: &Arc<IrqData>);
63 
64     /// mask an interrupt source
65     ///
66     /// 用于屏蔽中断
67     ///
68     /// 如果返回ENOSYS,则表明irq_mask()不支持. 那么中断机制代码将调用irq_disable()。
69     ///
70     /// 如果返回错误,那么中断的屏蔽状态将不会改变。
irq_mask(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>71     fn irq_mask(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
72         Err(SystemError::ENOSYS)
73     }
74 
75     /// 指示当前芯片是否实现了`irq_mask_ack`函数
can_mask_ack(&self) -> bool76     fn can_mask_ack(&self) -> bool;
77 
78     /// ack and mask an interrupt source
irq_mask_ack(&self, _irq_data: &Arc<IrqData>)79     fn irq_mask_ack(&self, _irq_data: &Arc<IrqData>) {}
80 
81     /// unmask an interrupt source
82     ///
83     /// 用于取消屏蔽中断
84     ///
85     /// 如果返回ENOSYS,则表明irq_unmask()不支持.
irq_unmask(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>86     fn irq_unmask(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
87         Err(SystemError::ENOSYS)
88     }
89     /// end of interrupt
irq_eoi(&self, _irq_data: &Arc<IrqData>)90     fn irq_eoi(&self, _irq_data: &Arc<IrqData>) {}
91 
92     /// 指示当前芯片是否可以设置中断亲和性。
can_set_affinity(&self) -> bool93     fn can_set_affinity(&self) -> bool;
94 
95     /// 在SMP机器上设置CPU亲和性。
96     ///
97     /// 如果force参数为真,它告诉驱动程序无条件地应用亲和性设置。
98     /// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔,其中目标CPU尚未在cpu_online_mask中设置。
irq_set_affinity( &self, _irq_data: &Arc<IrqData>, _cpu: &CpuMask, _force: bool, ) -> Result<IrqChipSetMaskResult, SystemError>99     fn irq_set_affinity(
100         &self,
101         _irq_data: &Arc<IrqData>,
102         _cpu: &CpuMask,
103         _force: bool,
104     ) -> Result<IrqChipSetMaskResult, SystemError> {
105         Err(SystemError::ENOSYS)
106     }
107 
108     /// retrigger an IRQ to the CPU
retrigger(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>109     fn retrigger(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
110         Err(SystemError::ENOSYS)
111     }
112 
113     /// 指示当前芯片是否可以设置中断流类型。
114     ///
115     /// 如果返回true,则可以调用irq_set_type()。
can_set_flow_type(&self) -> bool116     fn can_set_flow_type(&self) -> bool;
117 
118     /// set the flow type of an interrupt
119     ///
120     /// flow_type: the flow type to set
121     ///
irq_set_type( &self, _irq_data: &Arc<IrqData>, _flow_type: IrqLineStatus, ) -> Result<IrqChipSetMaskResult, SystemError>122     fn irq_set_type(
123         &self,
124         _irq_data: &Arc<IrqData>,
125         _flow_type: IrqLineStatus,
126     ) -> Result<IrqChipSetMaskResult, SystemError> {
127         Err(SystemError::ENOSYS)
128     }
129 
130     /// enable/disable power management wake-on of an interrupt
131     #[allow(dead_code)]
irq_set_wake(&self, _irq_data: &Arc<IrqData>, _on: bool) -> Result<(), SystemError>132     fn irq_set_wake(&self, _irq_data: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> {
133         Err(SystemError::ENOSYS)
134     }
135 
136     /// function to lock access to slow bus (i2c) chips
irq_bus_lock(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>137     fn irq_bus_lock(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
138         Ok(())
139     }
140 
141     /// function to sync and unlock slow bus (i2c) chips
irq_bus_sync_unlock(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>142     fn irq_bus_sync_unlock(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
143         Ok(())
144     }
145 
146     /// function called from core code on suspend once per
147     /// chip, when one or more interrupts are installed
irq_suspend(&self, _irq_data: &Arc<IrqData>)148     fn irq_suspend(&self, _irq_data: &Arc<IrqData>) {}
149 
150     /// function called from core code on resume once per chip,
151     /// when one ore more interrupts are installed
irq_resume(&self, _irq_data: &Arc<IrqData>)152     fn irq_resume(&self, _irq_data: &Arc<IrqData>) {}
153 
154     /// function called from core code on shutdown once per chip
irq_pm_shutdown(&self, _irq_data: &Arc<IrqData>)155     fn irq_pm_shutdown(&self, _irq_data: &Arc<IrqData>) {}
156 
157     /// Optional function to set irq_data.mask for special cases
irq_calc_mask(&self, _irq_data: &Arc<IrqData>)158     fn irq_calc_mask(&self, _irq_data: &Arc<IrqData>) {}
159 
160     // todo: print chip
161 
162     /// optional to request resources before calling
163     /// any other callback related to this irq
irq_request_resources(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>164     fn irq_request_resources(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
165         Ok(())
166     }
167 
168     /// optional to release resources acquired with
169     /// irq_request_resources
irq_release_resources(&self, _irq_data: &Arc<IrqData>)170     fn irq_release_resources(&self, _irq_data: &Arc<IrqData>) {}
171 
172     /// optional to compose message content for MSI
173     ///
174     /// 组装MSI消息并返回到msg中
irq_compose_msi_msg(&self, _irq_data: &Arc<IrqData>, _msg: &mut MsiMsg)175     fn irq_compose_msi_msg(&self, _irq_data: &Arc<IrqData>, _msg: &mut MsiMsg) {}
176 
177     /// optional to write message content for MSI
irq_write_msi_msg(&self, _irq_data: &Arc<IrqData>, _msg: &MsiMsg)178     fn irq_write_msi_msg(&self, _irq_data: &Arc<IrqData>, _msg: &MsiMsg) {}
179 
180     /// return the internal state of an interrupt
irqchip_state( &self, _irq_data: &Arc<IrqData>, _which: IrqChipState, ) -> Result<bool, SystemError>181     fn irqchip_state(
182         &self,
183         _irq_data: &Arc<IrqData>,
184         _which: IrqChipState,
185     ) -> Result<bool, SystemError> {
186         Err(SystemError::ENOSYS)
187     }
188 
189     /// set the internal state of an interrupt
set_irqchip_state( &self, _irq_data: &Arc<IrqData>, _which: IrqChipState, _state: bool, ) -> Result<(), SystemError>190     fn set_irqchip_state(
191         &self,
192         _irq_data: &Arc<IrqData>,
193         _which: IrqChipState,
194         _state: bool,
195     ) -> Result<(), SystemError> {
196         Err(SystemError::ENOSYS)
197     }
198 
199     // todo: set vcpu affinity
200 
201     /// send a single IPI to destination cpus
send_single_ipi(&self, _irq_data: &Arc<IrqData>, _cpu: u32)202     fn send_single_ipi(&self, _irq_data: &Arc<IrqData>, _cpu: u32) {}
203 
204     // todo: send ipi with cpu mask
205 
206     /// function called from core code before enabling an NMI
irq_nmi_setup(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError>207     fn irq_nmi_setup(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
208         Err(SystemError::ENOSYS)
209     }
210 
211     /// function called from core code after disabling an NMI
irq_nmi_teardown(&self, _irq_data: &Arc<IrqData>)212     fn irq_nmi_teardown(&self, _irq_data: &Arc<IrqData>) {}
213 
flags(&self) -> IrqChipFlags214     fn flags(&self) -> IrqChipFlags;
215 }
216 
217 #[allow(dead_code)]
218 #[derive(Debug, Clone, Copy)]
219 pub enum IrqChipState {
220     /// Is the interrupt pending?
221     Pending,
222     /// Is the interrupt in progress?
223     Active,
224     /// Is the interrupt masked?
225     Masked,
226     /// Is Irq line high?
227     LineLevel,
228 }
229 
230 /// 中断芯片的数据(per-irq的)
231 pub trait IrqChipData: Sync + Send + Any + Debug {
as_any_ref(&self) -> &dyn Any232     fn as_any_ref(&self) -> &dyn Any;
233 }
234 
235 bitflags! {
236     /// 定义 IrqGcFlags 位标志
237     pub struct IrqGcFlags: u32 {
238         /// 通过读取mask reg来初始化mask_cache
239         const IRQ_GC_INIT_MASK_CACHE = 1 << 0;
240         /// 对于需要在父irq上调用irq_set_wake()的irq芯片, 将irqs的锁类设置为嵌套。Usually GPIO implementations
241         const IRQ_GC_INIT_NESTED_LOCK = 1 << 1;
242         /// Mask cache是芯片类型私有的
243         const IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2;
244         /// 不计算irqData->mask
245         const IRQ_GC_NO_MASK = 1 << 3;
246         /// 使用大端字节序的寄存器访问(默认:小端LE)
247         const IRQ_GC_BE_IO = 1 << 4;
248     }
249 }
250 
251 #[allow(dead_code)]
252 #[derive(Debug)]
253 pub struct IrqChipGeneric {
254     inner: SpinLock<InnerIrqChipGeneric>,
255 }
256 
257 #[allow(dead_code)]
258 #[derive(Debug)]
259 struct InnerIrqChipGeneric {
260     /// Register base address
261     reg_base: VirtAddr,
262     ops: &'static dyn IrqChipGenericOps,
263     /// Interrupt base num for this chip
264     irq_base: u32,
265     /// Number of interrupts handled by this chip
266     irq_cnt: u32,
267     /// Cached mask register shared between all chip types
268     mask_cache: u32,
269     /// Cached type register
270     type_cache: u32,
271     /// Cached polarity register
272     polarity_cache: u32,
273     /// Interrupt can wakeup from suspend
274     wake_enabled: bool,
275     /// Interrupt is marked as an wakeup from suspend source
276     wake_active: bool,
277     /// Number of available irq_chip_type instances (usually 1)
278     num_chip_type: u32,
279     private_data: Option<Arc<dyn IrqChipGenericPrivateData>>,
280     installed: u64,
281     unused: u64,
282     domain: Weak<IrqDomain>,
283     chip_types: Vec<IrqChipType>,
284 }
285 
286 #[allow(dead_code)]
287 pub trait IrqChipGenericOps: Debug + Send + Sync {
288     /// Alternate I/O accessor (defaults to readl if NULL)
reg_readl(&self, addr: VirtAddr) -> u32289     unsafe fn reg_readl(&self, addr: VirtAddr) -> u32;
290 
291     /// Alternate I/O accessor (defaults to writel if NULL)
reg_writel(&self, addr: VirtAddr, val: u32)292     unsafe fn reg_writel(&self, addr: VirtAddr, val: u32);
293 
294     /// Function called from core code on suspend once per
295     /// chip; can be useful instead of irq_chip::suspend to
296     /// handle chip details even when no interrupts are in use
suspend(&self, gc: &Arc<IrqChipGeneric>)297     fn suspend(&self, gc: &Arc<IrqChipGeneric>);
298     /// Function called from core code on resume once per chip;
299     /// can be useful instead of irq_chip::resume to handle chip
300     /// details even when no interrupts are in use
resume(&self, gc: &Arc<IrqChipGeneric>)301     fn resume(&self, gc: &Arc<IrqChipGeneric>);
302 }
303 
304 pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {}
305 
306 #[derive(Debug)]
307 pub struct IrqChipType {
308     // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024
309 }
310 
311 #[allow(dead_code)]
312 #[derive(Debug)]
313 pub enum IrqChipSetMaskResult {
314     /// core updates mask ok.
315     Success,
316     /// core updates mask ok. No change.
317     NoChange,
318     /// core updates mask ok. Done.(same as SetMaskOk)
319     ///
320     /// 支持堆叠irq芯片的特殊代码, 表示跳过所有子irq芯片。
321     Done,
322 }
323 
324 bitflags! {
325     /// IrqChip specific flags
326     pub struct IrqChipFlags: u32 {
327         /// 在调用chip.irq_set_type()之前屏蔽中断
328         const IRQCHIP_SET_TYPE_MASKED = 1 << 0;
329         /// 只有在irq被处理时才发出irq_eoi()
330         const IRQCHIP_EOI_IF_HANDLED = 1 << 1;
331         /// 在挂起路径中屏蔽非唤醒irq
332         const IRQCHIP_MASK_ON_SUSPEND = 1 << 2;
333         /// 只有在irq启用时才调用irq_on/off_line回调
334         const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3;
335         /// 跳过chip.irq_set_wake(),对于这个irq芯片
336         const IRQCHIP_SKIP_SET_WAKE = 1 << 4;
337         /// 单次触发不需要屏蔽/取消屏蔽
338         const IRQCHIP_ONESHOT_SAFE = 1 << 5;
339         /// 芯片在线程模式下需要在取消屏蔽时eoi()
340         const IRQCHIP_EOI_THREADED = 1 << 6;
341         /// 芯片可以为Level MSIs提供两个门铃
342         const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7;
343         /// 芯片可以传递NMIs,仅适用于根irqchips
344         const IRQCHIP_SUPPORTS_NMI = 1 << 8;
345         /// 在挂起路径中,如果它们处于禁用状态,则调用__enable_irq()/__disable_irq()以唤醒irq
346         const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9;
347         /// 在启动前更新默认亲和性
348         const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10;
349         /// 不要在这个芯片中改变任何东西
350         const IRQCHIP_IMMUTABLE = 1 << 11;
351     }
352 }
353 
354 impl IrqManager {
355     /// Acknowledge the parent interrupt
356     #[allow(dead_code)]
irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>)357     pub fn irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>) {
358         let parent_data = irq_data.parent_data().and_then(|p| p.upgrade());
359 
360         if let Some(parent_data) = parent_data {
361             let parent_chip = parent_data.chip_info_read_irqsave().chip();
362             parent_chip.irq_ack(&parent_data);
363         }
364     }
365 
366     /// 在硬件中重新触发中断
367     ///
368     /// 遍历中断域的层次结构,并检查是否存在一个硬件重新触发函数。如果存在则调用它
irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError>369     pub fn irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
370         let mut data: Option<Arc<IrqData>> = Some(irq_data.clone());
371         while let Some(d) = data {
372             if let Err(e) = d.chip_info_read_irqsave().chip().retrigger(&d) {
373                 if e == SystemError::ENOSYS {
374                     data = d.parent_data().and_then(|p| p.upgrade());
375                 } else {
376                     return Err(e);
377                 }
378             } else {
379                 return Ok(());
380             }
381         }
382 
383         return Ok(());
384     }
385 
__irq_set_handler( &self, irq: IrqNumber, handler: &'static dyn IrqFlowHandler, is_chained: bool, name: Option<String>, )386     pub(super) fn __irq_set_handler(
387         &self,
388         irq: IrqNumber,
389         handler: &'static dyn IrqFlowHandler,
390         is_chained: bool,
391         name: Option<String>,
392     ) {
393         let r = irq_desc_manager().lookup_and_lock_bus(irq, false, false);
394         if r.is_none() {
395             return;
396         }
397 
398         let irq_desc = r.unwrap();
399 
400         let mut desc_inner = irq_desc.inner();
401         self.__irq_do_set_handler(&irq_desc, &mut desc_inner, Some(handler), is_chained, name);
402 
403         drop(desc_inner);
404         irq_desc.chip_bus_sync_unlock();
405     }
406 
__irq_do_set_handler( &self, desc: &Arc<IrqDesc>, desc_inner: &mut SpinLockGuard<'_, InnerIrqDesc>, mut handler: Option<&'static dyn IrqFlowHandler>, is_chained: bool, name: Option<String>, )407     fn __irq_do_set_handler(
408         &self,
409         desc: &Arc<IrqDesc>,
410         desc_inner: &mut SpinLockGuard<'_, InnerIrqDesc>,
411         mut handler: Option<&'static dyn IrqFlowHandler>,
412         is_chained: bool,
413         name: Option<String>,
414     ) {
415         if handler.is_none() {
416             handler = Some(bad_irq_handler());
417         } else {
418             let mut irq_data = Some(desc_inner.irq_data().clone());
419 
420             /*
421              * 在具有中断域继承的domain中,我们可能会遇到这样的情况,
422              * 最外层的芯片还没有设置好,但是内部的芯片已经存在了。
423              * 我们选择安装处理程序,而不是退出,
424              * 但显然我们此时无法启用/启动中断。
425              */
426             while irq_data.is_some() {
427                 let dt = irq_data.as_ref().unwrap().clone();
428 
429                 let chip_info = dt.chip_info_read_irqsave();
430 
431                 if !Arc::ptr_eq(&chip_info.chip(), &no_irq_chip()) {
432                     break;
433                 }
434 
435                 /*
436                  * 如果最外层的芯片没有设置好,并且预期立即开始中断,
437                  * 则放弃。
438                  */
439                 if unlikely(is_chained) {
440                     warn!(
441                         "Chained handler for irq {} is not supported",
442                         dt.irq().data()
443                     );
444                     return;
445                 }
446 
447                 //  try the parent
448                 let parent_data = dt.parent_data().and_then(|p| p.upgrade());
449 
450                 irq_data = parent_data;
451             }
452 
453             if unlikely(
454                 irq_data.is_none()
455                     || Arc::ptr_eq(
456                         &irq_data.as_ref().unwrap().chip_info_read_irqsave().chip(),
457                         &no_irq_chip(),
458                     ),
459             ) {
460                 warn!("No irq chip for irq {}", desc_inner.irq_data().irq().data());
461                 return;
462             }
463         }
464         let handler = handler.unwrap();
465         if handler.type_id() == bad_irq_handler().type_id()
466             && Arc::ptr_eq(
467                 &desc_inner.irq_data().chip_info_read_irqsave().chip(),
468                 &no_irq_chip(),
469             )
470         {
471             let irq_data = desc_inner.irq_data();
472             mask_ack_irq(irq_data);
473 
474             irq_data.irqd_set(IrqStatus::IRQD_IRQ_DISABLED);
475 
476             if is_chained {
477                 desc_inner.clear_actions();
478             }
479             desc_inner.set_depth(1);
480         }
481         let chip = desc_inner.irq_data().chip_info_read_irqsave().chip();
482         desc.set_handler_no_lock_inner(handler, desc_inner.irq_data(), &chip);
483         desc_inner.set_name(name);
484 
485         if handler.type_id() != bad_irq_handler().type_id() && is_chained {
486             let trigger_type = desc_inner.common_data().trigger_type();
487 
488             /*
489              * 我们即将立即启动这个中断,
490              * 因此需要设置触发配置。
491              * 但是 .irq_set_type 回调可能已经覆盖了
492              * irqflowhandler,忽略了我们正在处理的
493              * 是一个链式中断。立即重置它,因为我们
494              * 确实知道更好的处理方式。
495              */
496 
497             if trigger_type != IrqLineStatus::IRQ_TYPE_NONE {
498                 irq_manager()
499                     .do_set_irq_trigger(desc.clone(), desc_inner, trigger_type)
500                     .ok();
501                 desc.set_handler(handler);
502             }
503 
504             desc_inner.set_noprobe();
505             desc_inner.set_norequest();
506             desc_inner.set_nothread();
507 
508             desc_inner.clear_actions();
509             desc_inner.add_action(chained_action());
510 
511             irq_manager()
512                 .irq_activate_and_startup(desc, desc_inner, IrqManager::IRQ_RESEND)
513                 .ok();
514         }
515 
516         return;
517     }
518 
irq_set_handler_data( &self, irq: IrqNumber, data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<(), SystemError>519     pub fn irq_set_handler_data(
520         &self,
521         irq: IrqNumber,
522         data: Option<Arc<dyn IrqHandlerData>>,
523     ) -> Result<(), SystemError> {
524         let desc = irq_desc_manager().lookup(irq).ok_or(SystemError::EINVAL)?;
525         desc.inner().common_data().inner().set_handler_data(data);
526 
527         return Ok(());
528     }
529 
irq_percpu_disable( &self, desc: &Arc<IrqDesc>, irq_data: &Arc<IrqData>, irq_chip: &Arc<dyn IrqChip>, cpu: ProcessorId, )530     pub fn irq_percpu_disable(
531         &self,
532         desc: &Arc<IrqDesc>,
533         irq_data: &Arc<IrqData>,
534         irq_chip: &Arc<dyn IrqChip>,
535         cpu: ProcessorId,
536     ) {
537         if let Err(e) = irq_chip.irq_mask(irq_data) {
538             if e == SystemError::ENOSYS {
539                 irq_chip.irq_disable(irq_data);
540             }
541         }
542 
543         desc.inner()
544             .percpu_enabled_mut()
545             .as_mut()
546             .unwrap()
547             .set(cpu, false);
548     }
549 }
550 
551 lazy_static! {
552     pub(super) static ref CHAINED_ACTION: Arc<IrqAction> = IrqAction::new(
553         IrqNumber::new(0),
554         "".to_string(),
555         Some(&ChainedActionHandler),
556         None,
557     );
558 }
559 
560 #[allow(dead_code)]
chained_action() -> Arc<IrqAction>561 pub(super) fn chained_action() -> Arc<IrqAction> {
562     CHAINED_ACTION.clone()
563 }
564 
565 /// Chained handlers 永远不应该在它们的IRQ上调用irqaction。如果发生这种情况,
566 /// 这个默认irqaction将发出警告。
567 #[derive(Debug)]
568 struct ChainedActionHandler;
569 
570 impl IrqHandler for ChainedActionHandler {
handle( &self, irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dynamic_data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<IrqReturn, SystemError>571     fn handle(
572         &self,
573         irq: IrqNumber,
574         _static_data: Option<&dyn IrqHandlerData>,
575         _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
576     ) -> Result<IrqReturn, SystemError> {
577         static ONCE: Once = Once::new();
578         ONCE.call_once(|| {
579             warn!("Chained irq {} should not call an action.", irq.data());
580         });
581 
582         Ok(IrqReturn::NotHandled)
583     }
584 }
585