1ce5850adSLoGin use core::fmt::Debug; 2ce5850adSLoGin 3ce5850adSLoGin use alloc::{ 4e2841179SLoGin string::{String, ToString}, 5ce5850adSLoGin sync::{Arc, Weak}, 6ce5850adSLoGin vec::Vec, 7ce5850adSLoGin }; 8ce5850adSLoGin use hashbrown::HashMap; 9ce5850adSLoGin use system_error::SystemError; 10ce5850adSLoGin 11ce5850adSLoGin use crate::{ 12ce5850adSLoGin driver::{base::device::Device, open_firmware::device_node::DeviceNode}, 13e2841179SLoGin exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager}, 14*f049d1afSLoGin libs::{ 15*f049d1afSLoGin rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, 16*f049d1afSLoGin spinlock::SpinLock, 17*f049d1afSLoGin }, 18ce5850adSLoGin }; 19ce5850adSLoGin 20ce5850adSLoGin use super::{ 21338f6903SLoGin dummychip::no_irq_chip, 22338f6903SLoGin irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags}, 23338f6903SLoGin irqdata::{IrqData, IrqHandlerData}, 24*f049d1afSLoGin irqdesc::{IrqDesc, IrqFlowHandler}, 25ce5850adSLoGin HardwareIrqNumber, IrqNumber, 26ce5850adSLoGin }; 27ce5850adSLoGin 28e2841179SLoGin static mut IRQ_DOMAIN_MANAGER: Option<Arc<IrqDomainManager>> = None; 29e2841179SLoGin 30e2841179SLoGin /// 获取中断域管理器的引用 31e2841179SLoGin #[inline(always)] 32e2841179SLoGin pub fn irq_domain_manager() -> &'static Arc<IrqDomainManager> { 33e2841179SLoGin unsafe { IRQ_DOMAIN_MANAGER.as_ref().unwrap() } 34e2841179SLoGin } 35e2841179SLoGin 36e2841179SLoGin pub(super) fn irq_domain_manager_init() { 37e2841179SLoGin unsafe { 38e2841179SLoGin IRQ_DOMAIN_MANAGER = Some(Arc::new(IrqDomainManager::new())); 39e2841179SLoGin } 40e2841179SLoGin } 41e2841179SLoGin /// 中断域管理器 42e2841179SLoGin pub struct IrqDomainManager { 43e2841179SLoGin domains: SpinLock<Vec<Arc<IrqDomain>>>, 44e2841179SLoGin inner: RwLock<InnerIrqDomainManager>, 45e2841179SLoGin } 46e2841179SLoGin 47e2841179SLoGin impl IrqDomainManager { 48e2841179SLoGin pub fn new() -> IrqDomainManager { 49e2841179SLoGin IrqDomainManager { 50e2841179SLoGin domains: SpinLock::new(Vec::new()), 51e2841179SLoGin inner: RwLock::new(InnerIrqDomainManager { 52e2841179SLoGin default_domain: None, 53e2841179SLoGin }), 54e2841179SLoGin } 55e2841179SLoGin } 56e2841179SLoGin 57338f6903SLoGin /// 创建一个新的线性映射的irqdomain, 并将其添加到irqdomain管理器中 58338f6903SLoGin /// 59338f6903SLoGin /// 创建的irqdomain,中断号是线性的,即从0开始,依次递增 60338f6903SLoGin /// 61338f6903SLoGin /// ## 参数 62338f6903SLoGin /// 63338f6903SLoGin /// - `name` - 中断域的名字 64338f6903SLoGin /// - `ops` - 中断域的操作 65338f6903SLoGin /// - `irq_size` - 中断号的数量 66338f6903SLoGin #[allow(dead_code)] 67338f6903SLoGin pub fn create_and_add_linear( 68338f6903SLoGin &self, 69338f6903SLoGin name: String, 70338f6903SLoGin ops: &'static dyn IrqDomainOps, 71338f6903SLoGin irq_size: u32, 72338f6903SLoGin ) -> Option<Arc<IrqDomain>> { 73338f6903SLoGin self.create_and_add( 74338f6903SLoGin name, 75338f6903SLoGin ops, 76338f6903SLoGin IrqNumber::new(0), 77338f6903SLoGin HardwareIrqNumber::new(0), 78338f6903SLoGin irq_size, 79338f6903SLoGin ) 80338f6903SLoGin } 81338f6903SLoGin 82e2841179SLoGin /// 创建一个新的irqdomain, 并将其添加到irqdomain管理器中 83e2841179SLoGin /// 84e2841179SLoGin /// ## 参数 85e2841179SLoGin /// 86e2841179SLoGin /// - `name` - 中断域的名字 87e2841179SLoGin /// - `ops` - 中断域的操作 88e2841179SLoGin /// - `first_irq` - 起始软件中断号 89e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号 90e2841179SLoGin /// - `irq_size` - 中断号的数量 91e2841179SLoGin /// 92e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c?fi=__irq_domain_add#139 93e2841179SLoGin pub fn create_and_add( 94e2841179SLoGin &self, 95e2841179SLoGin name: String, 96e2841179SLoGin ops: &'static dyn IrqDomainOps, 97e2841179SLoGin first_irq: IrqNumber, 98e2841179SLoGin first_hwirq: HardwareIrqNumber, 99e2841179SLoGin irq_size: u32, 100e2841179SLoGin ) -> Option<Arc<IrqDomain>> { 101e2841179SLoGin let domain = IrqDomain::new( 102e2841179SLoGin None, 103e2841179SLoGin Some(name), 104e2841179SLoGin ops, 105e2841179SLoGin IrqDomainFlags::NAME_ALLOCATED, 106e2841179SLoGin IrqDomainBusToken::Any, 107e2841179SLoGin first_irq + irq_size, 108e2841179SLoGin first_hwirq + irq_size, 109e2841179SLoGin )?; 110e2841179SLoGin 111e2841179SLoGin self.add_domain(domain.clone()); 112e2841179SLoGin 113e2841179SLoGin self.domain_associate_many(&domain, first_irq, first_hwirq, irq_size); 114e2841179SLoGin 115e2841179SLoGin return Some(domain); 116e2841179SLoGin } 117e2841179SLoGin 118e2841179SLoGin fn add_domain(&self, domain: Arc<IrqDomain>) { 119e2841179SLoGin self.domains.lock_irqsave().push(domain); 120e2841179SLoGin } 121e2841179SLoGin 122e2841179SLoGin #[allow(dead_code)] 123e2841179SLoGin pub fn remove_domain(&self, domain: &Arc<IrqDomain>) { 124e2841179SLoGin let mut domains = self.domains.lock_irqsave(); 125e2841179SLoGin let index = domains 126e2841179SLoGin .iter() 127e2841179SLoGin .position(|x| Arc::ptr_eq(x, domain)) 128e2841179SLoGin .expect("domain not found"); 129e2841179SLoGin domains.remove(index); 130e2841179SLoGin } 131e2841179SLoGin 132e2841179SLoGin /// 获取默认的中断域 133e2841179SLoGin #[allow(dead_code)] 134e2841179SLoGin pub fn default_domain(&self) -> Option<Arc<IrqDomain>> { 135e2841179SLoGin self.inner.read().default_domain.clone() 136e2841179SLoGin } 137e2841179SLoGin 138e2841179SLoGin /// 设置默认的中断域 139e2841179SLoGin /// 140e2841179SLoGin /// 在创建IRQ映射的时候,如果没有指定中断域,就会使用默认的中断域 141e2841179SLoGin pub fn set_default_domain(&self, domain: Arc<IrqDomain>) { 142e2841179SLoGin self.inner.write_irqsave().default_domain = Some(domain); 143e2841179SLoGin } 144e2841179SLoGin 145e2841179SLoGin /// 将指定范围的硬件中断号与软件中断号一一对应的关联起来 146e2841179SLoGin /// 147e2841179SLoGin /// ## 参数 148e2841179SLoGin /// 149e2841179SLoGin /// - `domain` - 中断域 150e2841179SLoGin /// - `first_irq` - 起始软件中断号 151e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号 152e2841179SLoGin /// - `count` - 数量 153e2841179SLoGin pub fn domain_associate_many( 154e2841179SLoGin &self, 155e2841179SLoGin domain: &Arc<IrqDomain>, 156e2841179SLoGin first_irq: IrqNumber, 157e2841179SLoGin first_hwirq: HardwareIrqNumber, 158e2841179SLoGin count: u32, 159e2841179SLoGin ) { 160e2841179SLoGin for i in 0..count { 161e2841179SLoGin if let Err(e) = self.domain_associate(domain, first_irq + i, first_hwirq + i) { 162e2841179SLoGin kwarn!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), (first_hwirq + i).data(), (first_irq + i).data()); 163e2841179SLoGin } 164e2841179SLoGin } 165e2841179SLoGin } 166e2841179SLoGin 167e2841179SLoGin /// 将一个硬件中断号与一个软件中断号关联起来 168e2841179SLoGin /// 169e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c#562 170e2841179SLoGin pub fn domain_associate( 171e2841179SLoGin &self, 172e2841179SLoGin domain: &Arc<IrqDomain>, 173e2841179SLoGin irq: IrqNumber, 174e2841179SLoGin hwirq: HardwareIrqNumber, 175e2841179SLoGin ) -> Result<(), SystemError> { 176e2841179SLoGin if hwirq >= domain.revmap.read_irqsave().hwirq_max { 177e2841179SLoGin kwarn!( 178e2841179SLoGin "hwirq {} is out of range for domain {:?}", 179e2841179SLoGin hwirq.data(), 180e2841179SLoGin domain.name() 181e2841179SLoGin ); 182e2841179SLoGin return Err(SystemError::EINVAL); 183e2841179SLoGin } 184e2841179SLoGin let irq_data = irq_desc_manager() 185e2841179SLoGin .lookup(irq) 186e2841179SLoGin .ok_or_else(|| { 187e2841179SLoGin kwarn!("irq_desc not found for irq {}", irq.data()); 188e2841179SLoGin SystemError::EINVAL 189e2841179SLoGin })? 190e2841179SLoGin .irq_data(); 191e2841179SLoGin if irq_data.domain().is_some() { 192e2841179SLoGin kwarn!( 193e2841179SLoGin "irq {} is already associated with domain {:?}", 194e2841179SLoGin irq.data(), 195e2841179SLoGin irq_data.domain().unwrap().name() 196e2841179SLoGin ); 197e2841179SLoGin return Err(SystemError::EINVAL); 198e2841179SLoGin } 199e2841179SLoGin 200e2841179SLoGin let mut irq_data_guard = irq_data.inner(); 201e2841179SLoGin irq_data_guard.set_hwirq(hwirq); 202e2841179SLoGin irq_data_guard.set_domain(Some(domain.clone())); 203e2841179SLoGin drop(irq_data_guard); 204b5b571e0SLoGin let r = domain.ops.map(domain, hwirq, irq); 205e2841179SLoGin if let Err(e) = r { 206e2841179SLoGin if e != SystemError::ENOSYS { 207e2841179SLoGin if e != SystemError::EPERM { 208e2841179SLoGin kinfo!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), hwirq.data(), irq.data()); 209e2841179SLoGin } 210e2841179SLoGin let mut irq_data_guard = irq_data.inner(); 211e2841179SLoGin irq_data_guard.set_domain(None); 212e2841179SLoGin irq_data_guard.set_hwirq(HardwareIrqNumber::new(0)); 213e2841179SLoGin return Err(e); 214e2841179SLoGin } 215e2841179SLoGin } 216e2841179SLoGin 217e2841179SLoGin if domain.name().is_none() { 218e2841179SLoGin let chip = irq_data.chip_info_read_irqsave().chip(); 219e2841179SLoGin domain.set_name(chip.name().to_string()); 220e2841179SLoGin } 221e2841179SLoGin 222b5b571e0SLoGin self.irq_domain_set_mapping(domain, hwirq, irq_data); 223e2841179SLoGin 224e2841179SLoGin irq_manager().irq_clear_status_flags(irq, IrqLineStatus::IRQ_NOREQUEST)?; 225e2841179SLoGin 226e2841179SLoGin return Ok(()); 227e2841179SLoGin } 228e2841179SLoGin 229e2841179SLoGin fn irq_domain_set_mapping( 230e2841179SLoGin &self, 231e2841179SLoGin domain: &Arc<IrqDomain>, 232e2841179SLoGin hwirq: HardwareIrqNumber, 233e2841179SLoGin irq_data: Arc<IrqData>, 234e2841179SLoGin ) { 235e2841179SLoGin if domain.no_map() { 236e2841179SLoGin return; 237e2841179SLoGin } 238e2841179SLoGin 239e2841179SLoGin domain.revmap.write_irqsave().insert(hwirq, irq_data); 240e2841179SLoGin } 241e2841179SLoGin /// 递归调用 domain_ops->activate 以激活中断 242e2841179SLoGin /// 243e2841179SLoGin /// ## 参数 244e2841179SLoGin /// 245e2841179SLoGin /// - irq_data: 与中断关联的最外层 irq_data 246e2841179SLoGin /// - reserve: 如果为true,则仅预留一个中断向量,而不是分配一个 247e2841179SLoGin /// 248e2841179SLoGin /// 这是调用 domain_ops->activate 以编程中断控制器的第二步,以便中断实际上可以被传递。 249e2841179SLoGin pub fn activate_irq(&self, irq_data: &Arc<IrqData>, reserve: bool) -> Result<(), SystemError> { 250e2841179SLoGin let mut r = Ok(()); 251e2841179SLoGin if !irq_data.common_data().status().is_activated() { 252e2841179SLoGin r = self.do_activate_irq(Some(irq_data.clone()), reserve); 253e2841179SLoGin } 254e2841179SLoGin 255b5b571e0SLoGin if r.is_err() { 256e2841179SLoGin irq_data.common_data().status().set_activated(); 257e2841179SLoGin } 258e2841179SLoGin 259e2841179SLoGin return r; 260e2841179SLoGin } 261e2841179SLoGin 262e2841179SLoGin #[inline(never)] 263e2841179SLoGin fn do_activate_irq( 264e2841179SLoGin &self, 265e2841179SLoGin irq_data: Option<Arc<IrqData>>, 266e2841179SLoGin reserve: bool, 267e2841179SLoGin ) -> Result<(), SystemError> { 268e2841179SLoGin let mut r = Ok(()); 269e2841179SLoGin 270b5b571e0SLoGin if let Some(irq_data) = irq_data { 271b5b571e0SLoGin if let Some(domain) = irq_data.domain() { 272b5b571e0SLoGin let parent_data = irq_data.parent_data().and_then(|x| x.upgrade()); 273e2841179SLoGin if let Some(parent_data) = parent_data.clone() { 274e2841179SLoGin r = self.do_activate_irq(Some(parent_data), reserve); 275e2841179SLoGin } 276e2841179SLoGin 277e2841179SLoGin if r.is_err() { 278e2841179SLoGin let tmpr = domain.ops.activate(&domain, &irq_data, reserve); 279e2841179SLoGin if let Err(e) = tmpr { 280e2841179SLoGin if e != SystemError::ENOSYS && parent_data.is_some() { 281e2841179SLoGin self.do_deactivate_irq(parent_data); 282e2841179SLoGin } 283e2841179SLoGin } 284e2841179SLoGin } 285e2841179SLoGin } 286b5b571e0SLoGin } 287e2841179SLoGin 288e2841179SLoGin return r; 289e2841179SLoGin } 290b5b571e0SLoGin #[allow(clippy::only_used_in_recursion)] 291e2841179SLoGin fn do_deactivate_irq(&self, irq_data: Option<Arc<IrqData>>) { 292e2841179SLoGin if let Some(irq_data) = irq_data { 293e2841179SLoGin if let Some(domain) = irq_data.domain() { 294e2841179SLoGin domain.ops.deactivate(&domain, &irq_data); 295b5b571e0SLoGin let pp = irq_data.parent_data().and_then(|x| x.upgrade()); 296e2841179SLoGin 297e2841179SLoGin if pp.is_some() { 298e2841179SLoGin self.do_deactivate_irq(pp); 299e2841179SLoGin } 300e2841179SLoGin } 301e2841179SLoGin } 302e2841179SLoGin } 303338f6903SLoGin 304338f6903SLoGin /// `irq_domain_set_info` - 在 @domain 中为 @virq 设置完整的数据 305338f6903SLoGin /// 306338f6903SLoGin /// ## 参数 307338f6903SLoGin /// 308338f6903SLoGin /// - `domain`: 要匹配的中断域 309338f6903SLoGin /// - `virq`: IRQ号 310338f6903SLoGin /// - `hwirq`: 硬件中断号 311338f6903SLoGin /// - `chip`: 相关的中断芯片 312338f6903SLoGin /// - `chip_data`: 相关的中断芯片数据 313338f6903SLoGin /// - `handler`: 中断流处理器 314338f6903SLoGin /// - `handler_data`: 中断流处理程序数据 315338f6903SLoGin /// - `handler_name`: 中断处理程序名称 316b5b571e0SLoGin #[allow(clippy::too_many_arguments)] 317338f6903SLoGin pub fn domain_set_info( 318338f6903SLoGin &self, 319338f6903SLoGin domain: &Arc<IrqDomain>, 320338f6903SLoGin virq: IrqNumber, 321338f6903SLoGin hwirq: HardwareIrqNumber, 322338f6903SLoGin chip: Arc<dyn IrqChip>, 323338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>, 324338f6903SLoGin flow_handler: &'static dyn IrqFlowHandler, 325338f6903SLoGin handler_data: Option<Arc<dyn IrqHandlerData>>, 326338f6903SLoGin handler_name: Option<String>, 327338f6903SLoGin ) { 328338f6903SLoGin let r = self.domain_set_hwirq_and_chip(domain, virq, hwirq, Some(chip), chip_data); 329338f6903SLoGin if r.is_err() { 330338f6903SLoGin return; 331338f6903SLoGin } 332338f6903SLoGin irq_manager().__irq_set_handler(virq, flow_handler, false, handler_name); 333338f6903SLoGin irq_manager().irq_set_handler_data(virq, handler_data).ok(); 334338f6903SLoGin } 335338f6903SLoGin 336338f6903SLoGin /// `domain_set_hwirq_and_chip` - 在 @domain 中为 @virq 设置 hwirq 和 irqchip 337338f6903SLoGin /// 338338f6903SLoGin /// ## 参数 339338f6903SLoGin /// 340338f6903SLoGin /// - `domain`: 要匹配的中断域 341338f6903SLoGin /// - `virq`: IRQ号 342338f6903SLoGin /// - `hwirq`: hwirq号 343338f6903SLoGin /// - `chip`: 相关的中断芯片 344338f6903SLoGin /// - `chip_data`: 相关的芯片数据 345338f6903SLoGin pub fn domain_set_hwirq_and_chip( 346338f6903SLoGin &self, 347338f6903SLoGin domain: &Arc<IrqDomain>, 348338f6903SLoGin virq: IrqNumber, 349338f6903SLoGin hwirq: HardwareIrqNumber, 350338f6903SLoGin chip: Option<Arc<dyn IrqChip>>, 351338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>, 352338f6903SLoGin ) -> Result<(), SystemError> { 353338f6903SLoGin let irq_data: Arc<IrqData> = self 354338f6903SLoGin .domain_get_irq_data(domain, virq) 355338f6903SLoGin .ok_or(SystemError::ENOENT)?; 356338f6903SLoGin let mut inner = irq_data.inner(); 357338f6903SLoGin let mut chip_info = irq_data.chip_info_write_irqsave(); 358338f6903SLoGin 359338f6903SLoGin inner.set_hwirq(hwirq); 360338f6903SLoGin if let Some(chip) = chip { 361338f6903SLoGin chip_info.set_chip(Some(chip)); 362338f6903SLoGin } else { 363338f6903SLoGin chip_info.set_chip(Some(no_irq_chip())); 364338f6903SLoGin }; 365338f6903SLoGin 366338f6903SLoGin chip_info.set_chip_data(chip_data); 367338f6903SLoGin 368338f6903SLoGin return Ok(()); 369338f6903SLoGin } 370338f6903SLoGin 371338f6903SLoGin /// `irq_domain_get_irq_data` - 获取与 @virq 和 @domain 关联的 irq_data 372338f6903SLoGin /// 373338f6903SLoGin /// ## 参数 374338f6903SLoGin /// 375338f6903SLoGin /// - `domain`: 要匹配的域 376338f6903SLoGin /// - `virq`: 要获取 irq_data 的IRQ号 377338f6903SLoGin pub fn domain_get_irq_data( 378338f6903SLoGin &self, 379338f6903SLoGin domain: &Arc<IrqDomain>, 380338f6903SLoGin virq: IrqNumber, 381338f6903SLoGin ) -> Option<Arc<IrqData>> { 382338f6903SLoGin let desc = irq_desc_manager().lookup(virq)?; 383338f6903SLoGin let mut irq_data = Some(desc.irq_data()); 384338f6903SLoGin 385338f6903SLoGin while irq_data.is_some() { 386338f6903SLoGin let dt = irq_data.unwrap(); 387338f6903SLoGin if dt.domain().is_some() && Arc::ptr_eq(dt.domain().as_ref().unwrap(), domain) { 388338f6903SLoGin return Some(dt); 389338f6903SLoGin } 390b5b571e0SLoGin irq_data = dt.parent_data().and_then(|x| x.upgrade()); 391338f6903SLoGin } 392338f6903SLoGin 393338f6903SLoGin return None; 394338f6903SLoGin } 395*f049d1afSLoGin 396*f049d1afSLoGin /// `resolve_irq_mapping` - 从硬件中断号找到中断号。 397*f049d1afSLoGin /// 398*f049d1afSLoGin /// ## 参数 399*f049d1afSLoGin /// 400*f049d1afSLoGin /// - `domain`: 拥有此硬件中断的域 401*f049d1afSLoGin /// - `hwirq`: 该域空间中的硬件中断号 402*f049d1afSLoGin /// - `irq`: 如果需要,可选的指针以返回Linux中断 403*f049d1afSLoGin /// 404*f049d1afSLoGin /// ## 返回 405*f049d1afSLoGin /// 406*f049d1afSLoGin /// 返回一个元组,包含中断描述符和中断号 407*f049d1afSLoGin pub fn resolve_irq_mapping( 408*f049d1afSLoGin &self, 409*f049d1afSLoGin mut domain: Option<Arc<IrqDomain>>, 410*f049d1afSLoGin hwirq: HardwareIrqNumber, 411*f049d1afSLoGin ) -> Result<(Arc<IrqDesc>, IrqNumber), SystemError> { 412*f049d1afSLoGin if domain.is_none() { 413*f049d1afSLoGin domain = Some(self.default_domain().ok_or(SystemError::EINVAL)?); 414*f049d1afSLoGin } 415*f049d1afSLoGin 416*f049d1afSLoGin let domain = domain.unwrap(); 417*f049d1afSLoGin 418*f049d1afSLoGin if domain.no_map() { 419*f049d1afSLoGin if hwirq < domain.revmap_read_irqsave().hwirq_max { 420*f049d1afSLoGin let irq_desc = irq_desc_manager() 421*f049d1afSLoGin .lookup(IrqNumber::new(hwirq.data())) 422*f049d1afSLoGin .ok_or(SystemError::EINVAL)?; 423*f049d1afSLoGin if irq_desc.irq_data().hardware_irq() == hwirq { 424*f049d1afSLoGin let irq = irq_desc.irq_data().irq(); 425*f049d1afSLoGin return Ok((irq_desc, irq)); 426*f049d1afSLoGin } 427*f049d1afSLoGin } 428*f049d1afSLoGin 429*f049d1afSLoGin return Err(SystemError::EINVAL); 430*f049d1afSLoGin } 431*f049d1afSLoGin 432*f049d1afSLoGin let revmap = domain.revmap_read_irqsave(); 433*f049d1afSLoGin let irq_data = revmap.lookup(hwirq).ok_or(SystemError::EINVAL)?; 434*f049d1afSLoGin let irq_desc = irq_data.irq_desc().unwrap(); 435*f049d1afSLoGin return Ok((irq_desc, irq_data.irq())); 436*f049d1afSLoGin } 437e2841179SLoGin } 438e2841179SLoGin 439e2841179SLoGin struct InnerIrqDomainManager { 440e2841179SLoGin default_domain: Option<Arc<IrqDomain>>, 441e2841179SLoGin } 442e2841179SLoGin 443ce5850adSLoGin /// 中断域 444ce5850adSLoGin /// 445ce5850adSLoGin /// 用于把硬件中断号翻译为软件中断号的映射的对象 446ce5850adSLoGin /// 447ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#164 448ce5850adSLoGin #[allow(dead_code)] 449ce5850adSLoGin #[derive(Debug)] 450ce5850adSLoGin pub struct IrqDomain { 451ce5850adSLoGin /// 中断域的名字 (二选一) 452ce5850adSLoGin name: Option<&'static str>, 453e2841179SLoGin allocated_name: SpinLock<Option<String>>, 454ce5850adSLoGin /// 中断域的操作 455ce5850adSLoGin ops: &'static dyn IrqDomainOps, 456ce5850adSLoGin inner: SpinLock<InnerIrqDomain>, 457ce5850adSLoGin /// 中断号反向映射 458ce5850adSLoGin revmap: RwLock<IrqDomainRevMap>, 459ce5850adSLoGin } 460ce5850adSLoGin 461ce5850adSLoGin #[allow(dead_code)] 462ce5850adSLoGin #[derive(Debug)] 463ce5850adSLoGin struct InnerIrqDomain { 464338f6903SLoGin /// this field not touched by the core code 465338f6903SLoGin host_data: Option<Arc<dyn IrqChipData>>, 466ce5850adSLoGin /// host per irq_domain flags 467ce5850adSLoGin flags: IrqDomainFlags, 468ce5850adSLoGin /// The number of mapped interrupts 469ce5850adSLoGin mapcount: u32, 470ce5850adSLoGin bus_token: IrqDomainBusToken, 471ce5850adSLoGin /// 指向 generic chip 列表的指针。 472ce5850adSLoGin /// 有一个辅助函数用于为中断控制器驱动程序设置一个或 473ce5850adSLoGin /// 多个 generic chip,该函数使用此指针并依赖于 generic chip 库。 474ce5850adSLoGin generic_chip: Option<Arc<IrqDomainChipGeneric>>, 475ce5850adSLoGin /// Pointer to a device that the domain represent, and that will be 476ce5850adSLoGin /// used for power management purposes. 477ce5850adSLoGin device: Option<Arc<dyn Device>>, 478ce5850adSLoGin /// Pointer to parent irq_domain to support hierarchy irq_domains 479ce5850adSLoGin parent: Option<Weak<IrqDomain>>, 480ce5850adSLoGin } 481ce5850adSLoGin 482ce5850adSLoGin impl IrqDomain { 483ce5850adSLoGin #[allow(dead_code)] 484ce5850adSLoGin pub fn new( 485ce5850adSLoGin name: Option<&'static str>, 486ce5850adSLoGin allocated_name: Option<String>, 487ce5850adSLoGin ops: &'static dyn IrqDomainOps, 488ce5850adSLoGin flags: IrqDomainFlags, 489ce5850adSLoGin bus_token: IrqDomainBusToken, 490e2841179SLoGin irq_max: IrqNumber, 491e2841179SLoGin hwirq_max: HardwareIrqNumber, 492ce5850adSLoGin ) -> Option<Arc<Self>> { 493ce5850adSLoGin if name.is_none() && allocated_name.is_none() { 494ce5850adSLoGin return None; 495ce5850adSLoGin } 496ce5850adSLoGin 497ce5850adSLoGin let x = IrqDomain { 498ce5850adSLoGin name, 499e2841179SLoGin allocated_name: SpinLock::new(allocated_name), 500ce5850adSLoGin ops, 501ce5850adSLoGin inner: SpinLock::new(InnerIrqDomain { 502338f6903SLoGin host_data: None, 503ce5850adSLoGin flags, 504ce5850adSLoGin mapcount: 0, 505ce5850adSLoGin bus_token, 506ce5850adSLoGin generic_chip: None, 507ce5850adSLoGin device: None, 508ce5850adSLoGin parent: None, 509ce5850adSLoGin }), 510ce5850adSLoGin revmap: RwLock::new(IrqDomainRevMap { 511ce5850adSLoGin map: HashMap::new(), 512e2841179SLoGin hwirq_max, 513e2841179SLoGin irq_max, 514ce5850adSLoGin }), 515ce5850adSLoGin }; 516ce5850adSLoGin 517ce5850adSLoGin return Some(Arc::new(x)); 518ce5850adSLoGin } 519e2841179SLoGin 520e2841179SLoGin /// 中断域是否不对中断号进行转换 521e2841179SLoGin pub fn no_map(&self) -> bool { 522e2841179SLoGin self.inner 523e2841179SLoGin .lock_irqsave() 524e2841179SLoGin .flags 525e2841179SLoGin .contains(IrqDomainFlags::NO_MAP) 526e2841179SLoGin } 527e2841179SLoGin 528e2841179SLoGin #[allow(dead_code)] 529*f049d1afSLoGin fn revmap_read_irqsave(&self) -> RwLockReadGuard<IrqDomainRevMap> { 530*f049d1afSLoGin self.revmap.read_irqsave() 531*f049d1afSLoGin } 532*f049d1afSLoGin 533*f049d1afSLoGin #[allow(dead_code)] 534*f049d1afSLoGin fn revmap_write_irqsave(&self) -> RwLockWriteGuard<IrqDomainRevMap> { 535*f049d1afSLoGin self.revmap.write_irqsave() 536*f049d1afSLoGin } 537*f049d1afSLoGin 538*f049d1afSLoGin #[allow(dead_code)] 539e2841179SLoGin fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) { 540*f049d1afSLoGin self.revmap_write_irqsave().hwirq_max = hwirq_max; 541e2841179SLoGin } 542e2841179SLoGin 543e2841179SLoGin pub fn name(&self) -> Option<String> { 544e2841179SLoGin if let Some(name) = self.name { 545e2841179SLoGin return Some(name.to_string()); 546e2841179SLoGin } 547e2841179SLoGin return self.allocated_name.lock_irqsave().clone(); 548e2841179SLoGin } 549e2841179SLoGin 550e2841179SLoGin pub fn set_name(&self, name: String) { 551e2841179SLoGin *self.allocated_name.lock_irqsave() = Some(name); 552e2841179SLoGin } 553e2841179SLoGin 554e2841179SLoGin /// The number of mapped interrupts 555e2841179SLoGin pub fn map_count(&self) -> u32 { 556*f049d1afSLoGin self.revmap_read_irqsave().map.len() as u32 557e2841179SLoGin } 558338f6903SLoGin 559338f6903SLoGin pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> { 560338f6903SLoGin self.inner.lock_irqsave().host_data.clone() 561338f6903SLoGin } 562338f6903SLoGin 563338f6903SLoGin pub fn set_host_data(&self, host_data: Option<Arc<dyn IrqChipData>>) { 564338f6903SLoGin self.inner.lock_irqsave().host_data = host_data; 565338f6903SLoGin } 566ce5850adSLoGin } 567ce5850adSLoGin 568ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#190 569ce5850adSLoGin #[allow(dead_code)] 570ce5850adSLoGin #[derive(Debug)] 571ce5850adSLoGin struct IrqDomainRevMap { 572e2841179SLoGin map: HashMap<HardwareIrqNumber, Arc<IrqData>>, 573ce5850adSLoGin hwirq_max: HardwareIrqNumber, 574e2841179SLoGin irq_max: IrqNumber, 575e2841179SLoGin } 576e2841179SLoGin 577e2841179SLoGin impl IrqDomainRevMap { 578e2841179SLoGin fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>) { 579e2841179SLoGin self.map.insert(hwirq, irq_data); 580e2841179SLoGin } 581e2841179SLoGin 582e2841179SLoGin #[allow(dead_code)] 583e2841179SLoGin fn remove(&mut self, hwirq: HardwareIrqNumber) { 584e2841179SLoGin self.map.remove(&hwirq); 585e2841179SLoGin } 586e2841179SLoGin 587e2841179SLoGin #[allow(dead_code)] 588e2841179SLoGin fn lookup(&self, hwirq: HardwareIrqNumber) -> Option<Arc<IrqData>> { 589e2841179SLoGin self.map.get(&hwirq).cloned() 590e2841179SLoGin } 591ce5850adSLoGin } 592ce5850adSLoGin 593ce5850adSLoGin bitflags! { 594ce5850adSLoGin pub struct IrqDomainFlags: u32 { 595ce5850adSLoGin /// Irq domain is hierarchical 596ce5850adSLoGin const HIERARCHY = (1 << 0); 597ce5850adSLoGin /// Irq domain name was allocated dynamically 598ce5850adSLoGin const NAME_ALLOCATED = (1 << 1); 599ce5850adSLoGin /// Irq domain is an IPI domain with virq per cpu 600ce5850adSLoGin const IPI_PER_CPU = (1 << 2); 601ce5850adSLoGin /// Irq domain is an IPI domain with single virq 602ce5850adSLoGin const IPI_SINGLE = (1 << 3); 603ce5850adSLoGin /// Irq domain implements MSIs 604ce5850adSLoGin const MSI = (1 << 4); 605ce5850adSLoGin /// Irq domain implements MSI remapping 606ce5850adSLoGin const MSI_REMAP = (1 << 5); 607ce5850adSLoGin /// Quirk to handle MSI implementations which do not provide masking 608ce5850adSLoGin const MSI_NOMASK_QUIRK = (1 << 6); 609ce5850adSLoGin /// Irq domain doesn't translate anything 610ce5850adSLoGin const NO_MAP = (1 << 7); 611ce5850adSLoGin /// Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved 612ce5850adSLoGin /// for implementation specific purposes and ignored by the core code 613ce5850adSLoGin const NONCORE = (1 << 16); 614ce5850adSLoGin } 615ce5850adSLoGin } 616ce5850adSLoGin 617ce5850adSLoGin /// 如果多个域有相同的设备节点,但服务于不同的目的(例如,一个域用于PCI/MSI,另一个用于有线IRQs), 618ce5850adSLoGin /// 它们可以使用特定于总线的token进行区分。预计大多数域只会携带`DomainBusAny`。 619ce5850adSLoGin /// 620ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#78 621ce5850adSLoGin #[allow(dead_code)] 622ce5850adSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)] 623ce5850adSLoGin pub enum IrqDomainBusToken { 624ce5850adSLoGin Any = 0, 625ce5850adSLoGin Wired, 626ce5850adSLoGin GenericMsi, 627ce5850adSLoGin PciMsi, 628ce5850adSLoGin PlatformMsi, 629ce5850adSLoGin Nexus, 630ce5850adSLoGin Ipi, 631ce5850adSLoGin FslMcMsi, 632ce5850adSLoGin TiSciIntaMsi, 633ce5850adSLoGin Wakeup, 634ce5850adSLoGin VmdMsi, 635ce5850adSLoGin } 636ce5850adSLoGin 637ce5850adSLoGin /// IrqDomain的操作方法 638ce5850adSLoGin /// 639ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107 6403bc96fa4SLoGin pub trait IrqDomainOps: Debug + Send + Sync { 641ce5850adSLoGin /// 匹配一个中断控制器设备节点到一个主机。 642ce5850adSLoGin fn match_node( 643ce5850adSLoGin &self, 644338f6903SLoGin _irq_domain: &Arc<IrqDomain>, 645338f6903SLoGin _device_node: &Arc<DeviceNode>, 646338f6903SLoGin _bus_token: IrqDomainBusToken, 647338f6903SLoGin ) -> bool { 648338f6903SLoGin false 649338f6903SLoGin } 650ce5850adSLoGin 651ce5850adSLoGin /// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。 652ce5850adSLoGin /// 对于给定的映射,这只会被调用一次。 653e2841179SLoGin /// 654e2841179SLoGin /// 如果没有实现这个方法,那么就会返回`ENOSYS` 655ce5850adSLoGin fn map( 656ce5850adSLoGin &self, 657e2841179SLoGin _irq_domain: &Arc<IrqDomain>, 658e2841179SLoGin _hwirq: HardwareIrqNumber, 659e2841179SLoGin _virq: IrqNumber, 660e2841179SLoGin ) -> Result<(), SystemError> { 661e2841179SLoGin Err(SystemError::ENOSYS) 662e2841179SLoGin } 663ce5850adSLoGin 664ce5850adSLoGin /// 删除一个虚拟中断号与一个硬件中断号之间的映射。 665ce5850adSLoGin fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber); 666e2841179SLoGin 667e2841179SLoGin fn activate( 668e2841179SLoGin &self, 669e2841179SLoGin _domain: &Arc<IrqDomain>, 670e2841179SLoGin _irq_data: &Arc<IrqData>, 671e2841179SLoGin _reserve: bool, 672e2841179SLoGin ) -> Result<(), SystemError> { 673e2841179SLoGin Err(SystemError::ENOSYS) 674e2841179SLoGin } 675e2841179SLoGin 676e2841179SLoGin fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {} 677ce5850adSLoGin } 678ce5850adSLoGin 679ce5850adSLoGin #[allow(dead_code)] 680ce5850adSLoGin #[derive(Debug)] 681ce5850adSLoGin pub struct IrqDomainChipGeneric { 682ce5850adSLoGin inner: SpinLock<InnerIrqDomainChipGeneric>, 683ce5850adSLoGin } 684ce5850adSLoGin 685ce5850adSLoGin #[allow(dead_code)] 686ce5850adSLoGin #[derive(Debug)] 687ce5850adSLoGin struct InnerIrqDomainChipGeneric { 688ce5850adSLoGin irqs_per_chip: u32, 689ce5850adSLoGin flags_to_clear: IrqGcFlags, 690ce5850adSLoGin flags_to_set: IrqGcFlags, 691ce5850adSLoGin gc_flags: IrqGcFlags, 692ce5850adSLoGin gc: Vec<Arc<IrqChipGeneric>>, 693ce5850adSLoGin } 694