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