irqdata.rs 19 KB

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