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