xref: /DragonOS/kernel/src/exception/resend.rs (revision 597ecc08c2444dcc8f527eb021932718b69c9cc5)
1 use system_error::SystemError;
2 
3 use crate::{exception::irqdesc::IrqDescState, libs::spinlock::SpinLockGuard};
4 
5 use super::{irqdesc::InnerIrqDesc, manage::IrqManager};
6 
7 impl IrqManager {
8     /// 检查状态并重发中断
9     ///
10     /// ## 参数
11     ///
12     /// - `desc_inner_guard`:中断描述符的锁
13     /// - `inject`:是否注入中断
14     pub(super) fn irq_check_and_resend(
15         &self,
16         desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>,
17         inject: bool,
18     ) -> Result<(), SystemError> {
19         // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/resend.c?fi=check_irq_resend#106
20 
21         /*
22          * 我们不重新发送电平触发类型的中断。电平触发类型的中断在它们仍然活动时由硬件重新发送。
23          * 清除PENDING bit,以避免suspend/resume过程中的混淆。
24          */
25         if desc_inner_guard
26             .common_data()
27             .trigger_type()
28             .is_level_type()
29         {
30             desc_inner_guard
31                 .internal_state_mut()
32                 .remove(IrqDescState::IRQS_PENDING);
33             return Err(SystemError::EINVAL);
34         }
35 
36         if desc_inner_guard
37             .internal_state()
38             .contains(IrqDescState::IRQS_REPLAY)
39         {
40             return Err(SystemError::EBUSY);
41         }
42 
43         if !desc_inner_guard
44             .internal_state()
45             .contains(IrqDescState::IRQS_PENDING)
46             && !inject
47         {
48             return Ok(());
49         }
50 
51         desc_inner_guard
52             .internal_state_mut()
53             .remove(IrqDescState::IRQS_PENDING);
54 
55         let mut ret = Ok(());
56         if self.try_retrigger(desc_inner_guard).is_err() {
57             // todo: 支持发送到tasklet
58             ret = Err(SystemError::EINVAL);
59         }
60 
61         if ret.is_ok() {
62             desc_inner_guard
63                 .internal_state_mut()
64                 .insert(IrqDescState::IRQS_REPLAY);
65         }
66 
67         return ret;
68     }
69 
70     fn try_retrigger(
71         &self,
72         desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>,
73     ) -> Result<(), SystemError> {
74         if let Err(e) = desc_inner_guard
75             .irq_data()
76             .chip_info_read_irqsave()
77             .chip()
78             .retrigger(desc_inner_guard.irq_data())
79         {
80             if e != SystemError::ENOSYS {
81                 return Err(e);
82             }
83         } else {
84             return Ok(());
85         }
86 
87         // 当前中断控制器不支持重发中断,从父中断控制器重发
88         return self.irq_chip_retrigger_hierarchy(desc_inner_guard.irq_data());
89     }
90 }
91