xref: /DragonOS/kernel/src/exception/irqdata.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
1 use core::{any::Any, fmt::Debug};
2 
3 use alloc::sync::{Arc, Weak};
4 use intertrait::CastFromSync;
5 
6 use crate::libs::{
7     cpumask::CpuMask,
8     rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
9     spinlock::{SpinLock, SpinLockGuard},
10 };
11 
12 use super::{
13     irqchip::{IrqChip, IrqChipData},
14     irqdesc::IrqDesc,
15     irqdomain::IrqDomain,
16     msi::MsiDesc,
17     HardwareIrqNumber, IrqNumber,
18 };
19 
20 /// per irq chip data passed down to chip functions
21 ///
22 /// 该结构体用于表示每个Irq的私有数据,且与具体的中断芯片绑定
23 ///
24 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#179
25 #[allow(dead_code)]
26 #[derive(Debug)]
27 pub struct IrqData {
28     /// 中断号, 用于表示软件逻辑视角的中断号,全局唯一
29     irq: IrqNumber,
30     inner: SpinLock<InnerIrqData>,
31 
32     chip_info: RwLock<InnerIrqChipInfo>,
33 }
34 
35 impl IrqData {
new( irq: IrqNumber, hwirq: HardwareIrqNumber, common_data: Arc<IrqCommonData>, chip: Arc<dyn IrqChip>, ) -> Self36     pub fn new(
37         irq: IrqNumber,
38         hwirq: HardwareIrqNumber,
39         common_data: Arc<IrqCommonData>,
40         chip: Arc<dyn IrqChip>,
41     ) -> Self {
42         return IrqData {
43             irq,
44             inner: SpinLock::new(InnerIrqData {
45                 hwirq,
46                 common_data,
47                 desc: Weak::new(),
48                 domain: None,
49                 parent_data: None,
50             }),
51             chip_info: RwLock::new(InnerIrqChipInfo {
52                 chip: Some(chip),
53                 chip_data: None,
54             }),
55         };
56     }
57 
irqd_set(&self, status: IrqStatus)58     pub fn irqd_set(&self, status: IrqStatus) {
59         // clone是为了释放inner锁
60         let common_data = self.inner.lock_irqsave().common_data.clone();
61         common_data.insert_status(status);
62     }
63 
64     #[allow(dead_code)]
irqd_clear(&self, status: IrqStatus)65     pub fn irqd_clear(&self, status: IrqStatus) {
66         // clone是为了释放inner锁
67         let common_data = self.inner.lock_irqsave().common_data.clone();
68         common_data.clear_status(status);
69     }
70 
irq(&self) -> IrqNumber71     pub fn irq(&self) -> IrqNumber {
72         self.irq
73     }
74 
irq_desc(&self) -> Option<Arc<IrqDesc>>75     pub fn irq_desc(&self) -> Option<Arc<IrqDesc>> {
76         self.inner.lock_irqsave().desc.upgrade()
77     }
78 
set_irq_desc(&self, desc: Weak<IrqDesc>)79     pub fn set_irq_desc(&self, desc: Weak<IrqDesc>) {
80         self.inner.lock_irqsave().desc = desc;
81     }
82 
83     #[allow(dead_code)]
clear_irq_desc(&self)84     pub fn clear_irq_desc(&self) {
85         self.inner.lock_irqsave().desc = Weak::new();
86     }
87 
hardware_irq(&self) -> HardwareIrqNumber88     pub fn hardware_irq(&self) -> HardwareIrqNumber {
89         self.inner.lock_irqsave().hwirq
90     }
91 
92     /// 是否为电平触发
is_level_type(&self) -> bool93     pub fn is_level_type(&self) -> bool {
94         self.inner
95             .lock_irqsave()
96             .common_data
97             .inner
98             .lock_irqsave()
99             .state
100             .is_level_type()
101     }
102 
is_wakeup_set(&self) -> bool103     pub fn is_wakeup_set(&self) -> bool {
104         self.inner
105             .lock_irqsave()
106             .common_data
107             .inner
108             .lock_irqsave()
109             .state
110             .is_wakeup_set()
111     }
112 
common_data(&self) -> Arc<IrqCommonData>113     pub fn common_data(&self) -> Arc<IrqCommonData> {
114         self.inner.lock_irqsave().common_data.clone()
115     }
116 
domain(&self) -> Option<Arc<IrqDomain>>117     pub fn domain(&self) -> Option<Arc<IrqDomain>> {
118         self.inner.lock_irqsave().domain.clone()
119     }
120 
inner(&self) -> SpinLockGuard<InnerIrqData>121     pub fn inner(&self) -> SpinLockGuard<InnerIrqData> {
122         self.inner.lock_irqsave()
123     }
124 
chip_info_read(&self) -> RwLockReadGuard<InnerIrqChipInfo>125     pub fn chip_info_read(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
126         self.chip_info.read()
127     }
128 
chip_info_read_irqsave(&self) -> RwLockReadGuard<InnerIrqChipInfo>129     pub fn chip_info_read_irqsave(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
130         self.chip_info.read_irqsave()
131     }
132 
chip_info_write_irqsave(&self) -> RwLockWriteGuard<InnerIrqChipInfo>133     pub fn chip_info_write_irqsave(&self) -> RwLockWriteGuard<InnerIrqChipInfo> {
134         self.chip_info.write_irqsave()
135     }
136 
parent_data(&self) -> Option<Weak<IrqData>>137     pub fn parent_data(&self) -> Option<Weak<IrqData>> {
138         self.inner.lock_irqsave().parent_data.clone()
139     }
140 }
141 
142 #[allow(dead_code)]
143 #[derive(Debug)]
144 pub struct InnerIrqData {
145     /// 硬件中断号, 用于表示在某个IrqDomain中的中断号
146     hwirq: HardwareIrqNumber,
147     /// 涉及的所有irqchip之间共享的数据
148     common_data: Arc<IrqCommonData>,
149 
150     desc: Weak<IrqDesc>,
151 
152     /// 中断域
153     domain: Option<Arc<IrqDomain>>,
154     /// 中断的父中断(如果具有中断域继承的话)
155     parent_data: Option<Weak<IrqData>>,
156 }
157 
158 impl InnerIrqData {
set_hwirq(&mut self, hwirq: HardwareIrqNumber)159     pub fn set_hwirq(&mut self, hwirq: HardwareIrqNumber) {
160         self.hwirq = hwirq;
161     }
162 
163     #[allow(dead_code)]
domain(&self) -> Option<Arc<IrqDomain>>164     pub fn domain(&self) -> Option<Arc<IrqDomain>> {
165         self.domain.clone()
166     }
167 
set_domain(&mut self, domain: Option<Arc<IrqDomain>>)168     pub fn set_domain(&mut self, domain: Option<Arc<IrqDomain>>) {
169         self.domain = domain;
170     }
171 }
172 
173 #[derive(Debug)]
174 pub struct InnerIrqChipInfo {
175     /// 绑定到的中断芯片
176     chip: Option<Arc<dyn IrqChip>>,
177     /// 中断芯片的私有数据(与当前irq相关)
178     chip_data: Option<Arc<dyn IrqChipData>>,
179 }
180 
181 impl InnerIrqChipInfo {
set_chip(&mut self, chip: Option<Arc<dyn IrqChip>>)182     pub fn set_chip(&mut self, chip: Option<Arc<dyn IrqChip>>) {
183         self.chip = chip;
184     }
185 
set_chip_data(&mut self, chip_data: Option<Arc<dyn IrqChipData>>)186     pub fn set_chip_data(&mut self, chip_data: Option<Arc<dyn IrqChipData>>) {
187         self.chip_data = chip_data;
188     }
189 
chip(&self) -> Arc<dyn IrqChip>190     pub fn chip(&self) -> Arc<dyn IrqChip> {
191         self.chip.clone().unwrap()
192     }
193 
chip_data(&self) -> Option<Arc<dyn IrqChipData>>194     pub fn chip_data(&self) -> Option<Arc<dyn IrqChipData>> {
195         self.chip_data.clone()
196     }
197 }
198 
199 /// per irq data shared by all irqchips
200 ///
201 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#147
202 #[derive(Debug)]
203 pub struct IrqCommonData {
204     inner: SpinLock<InnerIrqCommonData>,
205 }
206 
207 impl IrqCommonData {
new() -> Self208     pub fn new() -> Self {
209         let inner = InnerIrqCommonData {
210             state: IrqStatus::empty(),
211             handler_data: None,
212             msi_desc: None,
213             affinity: CpuMask::new(),
214             effective_affinity: CpuMask::new(),
215         };
216         return IrqCommonData {
217             inner: SpinLock::new(inner),
218         };
219     }
220 
insert_status(&self, status: IrqStatus)221     pub fn insert_status(&self, status: IrqStatus) {
222         self.inner.lock_irqsave().irqd_insert(status);
223     }
224 
clear_status(&self, status: IrqStatus)225     pub fn clear_status(&self, status: IrqStatus) {
226         self.inner.lock_irqsave().irqd_clear(status);
227     }
228 
clear_managed_shutdown(&self)229     pub fn clear_managed_shutdown(&self) {
230         self.inner
231             .lock_irqsave()
232             .state
233             .remove(IrqStatus::IRQD_MANAGED_SHUTDOWN);
234     }
235 
236     #[allow(dead_code)]
masked(&self) -> bool237     pub fn masked(&self) -> bool {
238         self.inner.lock_irqsave().state.masked()
239     }
240 
set_masked(&self)241     pub fn set_masked(&self) {
242         self.inner
243             .lock_irqsave()
244             .state
245             .insert(IrqStatus::IRQD_IRQ_MASKED);
246     }
247 
clear_masked(&self)248     pub fn clear_masked(&self) {
249         self.clear_status(IrqStatus::IRQD_IRQ_MASKED);
250     }
251 
set_inprogress(&self)252     pub fn set_inprogress(&self) {
253         self.inner
254             .lock_irqsave()
255             .state
256             .insert(IrqStatus::IRQD_IRQ_INPROGRESS);
257     }
258 
clear_inprogress(&self)259     pub fn clear_inprogress(&self) {
260         self.inner
261             .lock_irqsave()
262             .state
263             .remove(IrqStatus::IRQD_IRQ_INPROGRESS);
264     }
265 
disabled(&self) -> bool266     pub fn disabled(&self) -> bool {
267         self.inner.lock_irqsave().state.disabled()
268     }
269 
270     #[allow(dead_code)]
set_disabled(&self)271     pub fn set_disabled(&self) {
272         self.inner
273             .lock_irqsave()
274             .state
275             .insert(IrqStatus::IRQD_IRQ_DISABLED);
276     }
277 
clear_disabled(&self)278     pub fn clear_disabled(&self) {
279         self.clear_status(IrqStatus::IRQD_IRQ_DISABLED);
280     }
281 
status(&self) -> IrqStatus282     pub fn status(&self) -> IrqStatus {
283         self.inner.lock_irqsave().state
284     }
285 
trigger_type(&self) -> IrqLineStatus286     pub fn trigger_type(&self) -> IrqLineStatus {
287         self.inner.lock_irqsave().state.trigger_type()
288     }
289 
set_trigger_type(&self, trigger: IrqLineStatus)290     pub fn set_trigger_type(&self, trigger: IrqLineStatus) {
291         self.inner.lock_irqsave().state.set_trigger_type(trigger);
292     }
293 
set_started(&self)294     pub fn set_started(&self) {
295         self.inner
296             .lock_irqsave()
297             .state
298             .insert(IrqStatus::IRQD_IRQ_STARTED);
299     }
300 
affinity(&self) -> CpuMask301     pub fn affinity(&self) -> CpuMask {
302         self.inner.lock_irqsave().affinity.clone()
303     }
304 
set_affinity(&self, affinity: CpuMask)305     pub fn set_affinity(&self, affinity: CpuMask) {
306         self.inner.lock_irqsave().affinity = affinity;
307     }
308 
309     #[allow(dead_code)]
set_effective_affinity(&self, affinity: CpuMask)310     pub fn set_effective_affinity(&self, affinity: CpuMask) {
311         self.inner.lock_irqsave().effective_affinity = affinity;
312     }
313 
inner(&self) -> SpinLockGuard<InnerIrqCommonData>314     pub fn inner(&self) -> SpinLockGuard<InnerIrqCommonData> {
315         self.inner.lock_irqsave()
316     }
317 }
318 
319 #[allow(dead_code)]
320 #[derive(Debug)]
321 pub struct InnerIrqCommonData {
322     /// status information for irq chip functions.
323     state: IrqStatus,
324     /// per-IRQ data for the irq_chip methods
325     handler_data: Option<Arc<dyn IrqHandlerData>>,
326     msi_desc: Option<Arc<MsiDesc>>,
327     affinity: CpuMask,
328     effective_affinity: CpuMask,
329 }
330 
331 impl InnerIrqCommonData {
irqd_insert(&mut self, status: IrqStatus)332     pub fn irqd_insert(&mut self, status: IrqStatus) {
333         self.state.insert(status);
334     }
335 
irqd_clear(&mut self, status: IrqStatus)336     pub fn irqd_clear(&mut self, status: IrqStatus) {
337         self.state.remove(status);
338     }
339 
340     #[allow(dead_code)]
set_handler_data(&mut self, handler_data: Option<Arc<dyn IrqHandlerData>>)341     pub fn set_handler_data(&mut self, handler_data: Option<Arc<dyn IrqHandlerData>>) {
342         self.handler_data = handler_data;
343     }
344 
345     #[allow(dead_code)]
handler_data(&self) -> Option<Arc<dyn IrqHandlerData>>346     pub fn handler_data(&self) -> Option<Arc<dyn IrqHandlerData>> {
347         self.handler_data.clone()
348     }
349 
350     #[allow(dead_code)]
effective_affinity(&self) -> &CpuMask351     pub fn effective_affinity(&self) -> &CpuMask {
352         &self.effective_affinity
353     }
354 }
355 
356 /// 中断处理函数传入的数据
357 pub trait IrqHandlerData: Send + Sync + Any + Debug + CastFromSync {}
358 
359 bitflags! {
360     /// 中断线状态
361     /// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h?fi=IRQ_TYPE_PROBE#77
362     #[allow(clippy::bad_bit_mask)]
363     pub struct IrqLineStatus: u32 {
364         /// 默认,未指明类型
365         const IRQ_TYPE_NONE     = 0x00000000;
366         /// 上升沿触发
367         const IRQ_TYPE_EDGE_RISING  = 0x00000001;
368         /// 下降沿触发
369         const IRQ_TYPE_EDGE_FALLING = 0x00000002;
370         /// 上升沿和下降沿触发
371         const IRQ_TYPE_EDGE_BOTH    = Self::IRQ_TYPE_EDGE_RISING.bits | Self::IRQ_TYPE_EDGE_FALLING.bits;
372         /// 高电平触发
373         const IRQ_TYPE_LEVEL_HIGH   = 0x00000004;
374         /// 低电平触发
375         const IRQ_TYPE_LEVEL_LOW    = 0x00000008;
376         /// 过滤掉电平位的掩码
377         const IRQ_TYPE_LEVEL_MASK   = Self::IRQ_TYPE_LEVEL_LOW.bits | Self::IRQ_TYPE_LEVEL_HIGH.bits;
378         /// 上述位掩码的掩码
379         const IRQ_TYPE_SENSE_MASK   = 0x0000000f;
380         /// 某些PICs使用此类型要求 `IrqChip::irq_set_type()` 设置硬件到一个合理的默认值
381         /// (由irqdomain的map()回调使用,以便为新分配的描述符同步硬件状态和软件标志位)。
382         const IRQ_TYPE_DEFAULT      = Self::IRQ_TYPE_SENSE_MASK.bits;
383 
384         /// 特定于探测的过程中的特殊标志
385         const IRQ_TYPE_PROBE        = 0x00000010;
386 
387         /// 中断是电平类型。当上述触发位通过`IrqChip::irq_set_type()` 修改时,也会在代码中更新
388         const IRQ_LEVEL     = 1 << 8;
389         /// 标记一个PER_CPU的中断。将保护其免受亲和性设置的影响
390         const IRQ_PER_CPU       = 1 << 9;
391         /// 中断不能被自动探测
392         const IRQ_NOPROBE       = 1 << 10;
393         /// 中断不能通过request_irq()请求
394         const IRQ_NOREQUEST     = 1 << 11;
395         /// 中断在request/setup_irq()中不会自动启用
396         const IRQ_NOAUTOEN      = 1 << 12;
397         /// 中断不能被平衡(亲和性设置)
398         const IRQ_NO_BALANCING      = 1 << 13;
399         /// 中断可以从进程上下文中迁移
400         const IRQ_MOVE_PCNTXT       = 1 << 14;
401         /// 中断嵌套在另一个线程中
402         const IRQ_NESTED_THREAD = 1 << 15;
403         /// 中断不能被线程化
404         const IRQ_NOTHREAD      = 1 << 16;
405         /// Dev_id是一个per-CPU变量
406         const IRQ_PER_CPU_DEVID = 1 << 17;
407         /// 总是由另一个中断轮询。将其从错误的中断检测机制和核心侧轮询中排除
408         const IRQ_IS_POLLED     = 1 << 18;
409         /// 禁用延迟的中断禁用 (Disable lazy irq disable)
410         const IRQ_DISABLE_UNLAZY    = 1 << 19;
411         /// 在/proc/interrupts中不显示
412         const IRQ_HIDDEN        = 1 << 20;
413         /// 从note_interrupt()调试中排除
414         const IRQ_NO_DEBUG      = 1 << 21;
415     }
416 
417 
418 
419 }
420 
421 impl IrqLineStatus {
trigger_bits(&self) -> u32422     pub const fn trigger_bits(&self) -> u32 {
423         self.bits & Self::IRQ_TYPE_SENSE_MASK.bits
424     }
425 
trigger_type(&self) -> Self426     pub fn trigger_type(&self) -> Self {
427         *self & Self::IRQ_TYPE_SENSE_MASK
428     }
429 
is_level_type(&self) -> bool430     pub fn is_level_type(&self) -> bool {
431         self.contains(Self::IRQ_LEVEL)
432     }
433 
434     /// 是否为高电平触发
435     ///
436     /// ## 返回
437     ///
438     /// - 如果不是电平触发类型,则返回None
439     /// - 如果是电平触发类型,则返回Some(bool),当为true时表示高电平触发
440     #[allow(dead_code)]
is_level_high(&self) -> Option<bool>441     pub fn is_level_high(&self) -> Option<bool> {
442         if !self.is_level_type() {
443             return None;
444         }
445         return Some(self.contains(Self::IRQ_TYPE_LEVEL_HIGH));
446     }
447 
448     #[allow(dead_code)]
is_per_cpu_devid(&self) -> bool449     pub fn is_per_cpu_devid(&self) -> bool {
450         self.contains(Self::IRQ_PER_CPU_DEVID)
451     }
452 }
453 
454 bitflags! {
455     /// 中断状态(存储在IrqCommonData)
456     ///
457     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#227
458     #[allow(clippy::bad_bit_mask)]
459     pub struct IrqStatus: u32 {
460         const IRQD_TRIGGER_NONE = IrqLineStatus::IRQ_TYPE_NONE.bits();
461         const IRQD_TRIGGER_RISING = IrqLineStatus::IRQ_TYPE_EDGE_RISING.bits();
462         const IRQD_TRIGGER_FALLING = IrqLineStatus::IRQ_TYPE_EDGE_FALLING.bits();
463         const IRQD_TRIGGER_HIGH = IrqLineStatus::IRQ_TYPE_LEVEL_HIGH.bits();
464         const IRQD_TRIGGER_LOW = IrqLineStatus::IRQ_TYPE_LEVEL_LOW.bits();
465 
466         /// 触发类型位的掩码
467         const IRQD_TRIGGER_MASK = 0xf;
468         /// 亲和性设置待处理
469         const IRQD_SETAFFINITY_PENDING = 1 << 8;
470         /// 中断已激活
471         const IRQD_ACTIVATED = 1 << 9;
472         /// 对此IRQ禁用平衡
473         const IRQD_NO_BALANCING = 1 << 10;
474         /// 中断是每个CPU特定的
475         const IRQD_PER_CPU = 1 << 11;
476         /// 中断亲和性已设置
477         const IRQD_AFFINITY_SET = 1 << 12;
478         /// 中断是电平触发
479         const IRQD_LEVEL = 1 << 13;
480         /// 中断配置为从挂起状态唤醒
481         const IRQD_WAKEUP_STATE = 1 << 14;
482         /// 中断可以在进程上下文中移动
483         const IRQD_MOVE_PCNTXT = 1 << 15;
484         /// 中断被禁用
485         const IRQD_IRQ_DISABLED = 1 << 16;
486         /// 中断被屏蔽
487         const IRQD_IRQ_MASKED = 1 << 17;
488         /// 中断正在处理中
489         const IRQD_IRQ_INPROGRESS = 1 << 18;
490         /// 唤醒模式已准备就绪
491         const IRQD_WAKEUP_ARMED = 1 << 19;
492         /// 中断被转发到一个虚拟CPU
493         const IRQD_FORWARDED_TO_VCPU = 1 << 20;
494         /// 亲和性由内核自动管理
495         const IRQD_AFFINITY_MANAGED = 1 << 21;
496         /// 中断已启动
497         const IRQD_IRQ_STARTED = 1 << 22;
498         /// 由于空亲和性掩码而关闭的中断。仅适用于亲和性管理的中断。
499         const IRQD_MANAGED_SHUTDOWN = 1 << 23;
500         /// IRQ只允许单个亲和性目标
501         const IRQD_SINGLE_TARGET = 1 << 24;
502         /// 默认的触发器已设置
503         const IRQD_DEFAULT_TRIGGER_SET = 1 << 25;
504         /// 可以使用保留模式
505         const IRQD_CAN_RESERVE = 1 << 26;
506         /// Non-maskable MSI quirk for affinity change required
507         const IRQD_MSI_NOMASK_QUIRK = 1 << 27;
508         /// 强制要求`handle_irq_()`只能在真实的中断上下文中调用
509         const IRQD_HANDLE_ENFORCE_IRQCTX = 1 << 28;
510         /// 激活时设置亲和性。在禁用时不要调用irq_chip::irq_set_affinity()。
511         const IRQD_AFFINITY_ON_ACTIVATE = 1 << 29;
512         /// 如果irqpm具有标志 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,则在挂起时中断被启用。
513         const IRQD_IRQ_ENABLED_ON_SUSPEND = 1 << 30;
514     }
515 }
516 
517 #[allow(dead_code)]
518 impl IrqStatus {
is_set_affinity_pending(&self) -> bool519     pub const fn is_set_affinity_pending(&self) -> bool {
520         self.contains(Self::IRQD_SETAFFINITY_PENDING)
521     }
522 
is_per_cpu(&self) -> bool523     pub const fn is_per_cpu(&self) -> bool {
524         self.contains(Self::IRQD_PER_CPU)
525     }
526 
can_balance(&self) -> bool527     pub const fn can_balance(&self) -> bool {
528         (self.bits & (Self::IRQD_PER_CPU.bits | Self::IRQD_NO_BALANCING.bits)) == 0
529     }
530 
affinity_was_set(&self) -> bool531     pub const fn affinity_was_set(&self) -> bool {
532         self.contains(Self::IRQD_AFFINITY_SET)
533     }
534 
masked(&self) -> bool535     pub fn masked(&self) -> bool {
536         self.contains(Self::IRQD_IRQ_MASKED)
537     }
538 
disabled(&self) -> bool539     pub fn disabled(&self) -> bool {
540         self.contains(Self::IRQD_IRQ_DISABLED)
541     }
542 
mark_affinity_set(&mut self)543     pub fn mark_affinity_set(&mut self) {
544         self.insert(Self::IRQD_AFFINITY_SET);
545     }
546 
trigger_type_was_set(&self) -> bool547     pub const fn trigger_type_was_set(&self) -> bool {
548         self.contains(Self::IRQD_DEFAULT_TRIGGER_SET)
549     }
550 
mark_trigger_type_set(&mut self)551     pub fn mark_trigger_type_set(&mut self) {
552         self.insert(Self::IRQD_DEFAULT_TRIGGER_SET);
553     }
554 
trigger_type(&self) -> IrqLineStatus555     pub const fn trigger_type(&self) -> IrqLineStatus {
556         IrqLineStatus::from_bits_truncate(self.bits & Self::IRQD_TRIGGER_MASK.bits)
557     }
558 
559     /// Must only be called inside irq_chip.irq_set_type() functions or
560     /// from the DT/ACPI setup code.
set_trigger_type(&mut self, trigger: IrqLineStatus)561     pub const fn set_trigger_type(&mut self, trigger: IrqLineStatus) {
562         self.bits &= !Self::IRQD_TRIGGER_MASK.bits;
563         self.bits |= trigger.bits & Self::IRQD_TRIGGER_MASK.bits;
564 
565         self.bits |= Self::IRQD_DEFAULT_TRIGGER_SET.bits;
566     }
567 
is_level_type(&self) -> bool568     pub const fn is_level_type(&self) -> bool {
569         self.contains(Self::IRQD_LEVEL)
570     }
571 
572     /// Must only be called of irqchip.irq_set_affinity() or low level
573     /// hierarchy domain allocation functions.
set_single_target(&mut self)574     pub fn set_single_target(&mut self) {
575         self.insert(Self::IRQD_SINGLE_TARGET);
576     }
577 
is_single_target(&self) -> bool578     pub const fn is_single_target(&self) -> bool {
579         self.contains(Self::IRQD_SINGLE_TARGET)
580     }
581 
set_handle_enforce_irqctx(&mut self)582     pub fn set_handle_enforce_irqctx(&mut self) {
583         self.insert(Self::IRQD_HANDLE_ENFORCE_IRQCTX);
584     }
585 
is_handle_enforce_irqctx(&self) -> bool586     pub const fn is_handle_enforce_irqctx(&self) -> bool {
587         self.contains(Self::IRQD_HANDLE_ENFORCE_IRQCTX)
588     }
589 
is_enabled_on_suspend(&self) -> bool590     pub const fn is_enabled_on_suspend(&self) -> bool {
591         self.contains(Self::IRQD_IRQ_ENABLED_ON_SUSPEND)
592     }
593 
is_wakeup_set(&self) -> bool594     pub const fn is_wakeup_set(&self) -> bool {
595         self.contains(Self::IRQD_WAKEUP_STATE)
596     }
597 
can_move_in_process_context(&self) -> bool598     pub const fn can_move_in_process_context(&self) -> bool {
599         self.contains(Self::IRQD_MOVE_PCNTXT)
600     }
601 
is_irq_in_progress(&self) -> bool602     pub const fn is_irq_in_progress(&self) -> bool {
603         self.contains(Self::IRQD_IRQ_INPROGRESS)
604     }
605 
is_wakeup_armed(&self) -> bool606     pub const fn is_wakeup_armed(&self) -> bool {
607         self.contains(Self::IRQD_WAKEUP_ARMED)
608     }
609 
is_forwarded_to_vcpu(&self) -> bool610     pub const fn is_forwarded_to_vcpu(&self) -> bool {
611         self.contains(Self::IRQD_FORWARDED_TO_VCPU)
612     }
613 
set_forwarded_to_vcpu(&mut self)614     pub fn set_forwarded_to_vcpu(&mut self) {
615         self.insert(Self::IRQD_FORWARDED_TO_VCPU);
616     }
617 
affinity_managed(&self) -> bool618     pub const fn affinity_managed(&self) -> bool {
619         self.contains(Self::IRQD_AFFINITY_MANAGED)
620     }
621 
is_activated(&self) -> bool622     pub const fn is_activated(&self) -> bool {
623         self.contains(Self::IRQD_ACTIVATED)
624     }
625 
set_activated(&mut self)626     pub fn set_activated(&mut self) {
627         self.insert(Self::IRQD_ACTIVATED);
628     }
629 
clear_activated(&mut self)630     pub fn clear_activated(&mut self) {
631         self.remove(Self::IRQD_ACTIVATED);
632     }
633 
is_started(&self) -> bool634     pub const fn is_started(&self) -> bool {
635         self.contains(Self::IRQD_IRQ_STARTED)
636     }
637 
is_managed_and_shutdown(&self) -> bool638     pub const fn is_managed_and_shutdown(&self) -> bool {
639         self.contains(Self::IRQD_MANAGED_SHUTDOWN)
640     }
641 
set_can_reserve(&mut self)642     pub fn set_can_reserve(&mut self) {
643         self.insert(Self::IRQD_CAN_RESERVE);
644     }
645 
can_reserve(&self) -> bool646     pub const fn can_reserve(&self) -> bool {
647         self.contains(Self::IRQD_CAN_RESERVE)
648     }
649 
clear_can_reserve(&mut self)650     pub fn clear_can_reserve(&mut self) {
651         self.remove(Self::IRQD_CAN_RESERVE);
652     }
653 
set_msi_nomask_quirk(&mut self)654     pub fn set_msi_nomask_quirk(&mut self) {
655         self.insert(Self::IRQD_MSI_NOMASK_QUIRK);
656     }
657 
clear_msi_nomask_quirk(&mut self)658     pub fn clear_msi_nomask_quirk(&mut self) {
659         self.remove(Self::IRQD_MSI_NOMASK_QUIRK);
660     }
661 
is_msi_nomask_quirk(&self) -> bool662     pub const fn is_msi_nomask_quirk(&self) -> bool {
663         self.contains(Self::IRQD_MSI_NOMASK_QUIRK)
664     }
665 
set_affinity_on_activate(&mut self)666     pub fn set_affinity_on_activate(&mut self) {
667         self.insert(Self::IRQD_AFFINITY_ON_ACTIVATE);
668     }
669 
is_affinity_on_activate(&self) -> bool670     pub const fn is_affinity_on_activate(&self) -> bool {
671         self.contains(Self::IRQD_AFFINITY_ON_ACTIVATE)
672     }
673 
started(&self) -> bool674     pub const fn started(&self) -> bool {
675         self.contains(Self::IRQD_IRQ_STARTED)
676     }
677 }
678