1 use alloc::{string::ToString, sync::Arc}; 2 use log::warn; 3 use system_error::SystemError; 4 use unified_init::macros::unified_init; 5 6 use crate::{ 7 driver::base::{ 8 kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps}, 9 kset::KSet, 10 }, 11 filesystem::{ 12 sysfs::{ 13 file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport, 14 SYSFS_ATTR_MODE_RO, 15 }, 16 vfs::syscall::ModeType, 17 }, 18 init::initcall::INITCALL_POSTCORE, 19 misc::ksysfs::sys_kernel_kset, 20 }; 21 22 use super::{ 23 irqdesc::{irq_desc_manager, IrqDesc}, 24 IrqNumber, 25 }; 26 27 /// `/sys/kernel/irq`的kset 28 static mut SYS_KERNEL_IRQ_KSET_INSTANCE: Option<Arc<KSet>> = None; 29 30 #[inline(always)] 31 #[allow(dead_code)] 32 pub fn sys_kernel_irq_kset() -> Arc<KSet> { 33 unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.clone().unwrap() } 34 } 35 36 /// 中断描述符的kobjtype 37 /// 38 /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#280 39 #[derive(Debug)] 40 pub(super) struct IrqKObjType; 41 42 impl KObjType for IrqKObjType { 43 fn sysfs_ops(&self) -> Option<&dyn SysFSOps> { 44 Some(&KObjectSysFSOps) 45 } 46 47 fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { 48 Some(&[&IrqAttrGroup]) 49 } 50 51 fn release(&self, _kobj: Arc<dyn KObject>) { 52 53 // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#428 54 } 55 } 56 57 #[derive(Debug)] 58 struct IrqAttrGroup; 59 60 impl AttributeGroup for IrqAttrGroup { 61 fn name(&self) -> Option<&str> { 62 None 63 } 64 65 /// 所有的属性 66 /// 67 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268 68 fn attrs(&self) -> &[&'static dyn Attribute] { 69 // 每个irq的属性 70 // todo: 添加per_cpu_count属性 71 &[ 72 &AttrChipName, 73 &AttrHardwareIrq, 74 &AttrType, 75 &AttrWakeup, 76 &AttrName, 77 &AttrActions, 78 ] 79 } 80 81 fn is_visible( 82 &self, 83 _kobj: Arc<dyn KObject>, 84 attr: &'static dyn Attribute, 85 ) -> Option<ModeType> { 86 Some(attr.mode()) 87 } 88 } 89 90 /// 初始化irq模块在sysfs中的目录 91 /// 92 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#313 93 #[unified_init(INITCALL_POSTCORE)] 94 fn irq_sysfs_init() -> Result<(), SystemError> { 95 // todo!("irq_sysfs_init"); 96 97 let irq_kset = KSet::new("irq".to_string()); 98 irq_kset 99 .register(Some(sys_kernel_kset())) 100 .expect("register irq kset failed"); 101 unsafe { 102 SYS_KERNEL_IRQ_KSET_INSTANCE = Some(irq_kset); 103 } 104 105 // 把所有的irq都注册到/sys/kernel/irq下 106 for (irq, desc) in irq_desc_manager().iter_descs() { 107 irq_sysfs_add(irq, desc); 108 } 109 110 return Ok(()); 111 } 112 113 /// 把irqdesc添加到sysfs 114 fn irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>) { 115 if unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.is_none() } { 116 return; 117 } 118 119 let kset = sys_kernel_irq_kset(); 120 KObjectManager::add_kobj(desc.clone() as Arc<dyn KObject>, Some(kset)).unwrap_or_else(|e| { 121 warn!("Failed to add irq({irq:?}) kobject to sysfs: {:?}", e); 122 }); 123 124 desc.mark_in_sysfs(); 125 } 126 127 /// 从sysfs中删除irqdesc 128 #[allow(dead_code)] 129 pub(super) fn irq_sysfs_del(desc: &Arc<IrqDesc>) { 130 if desc.in_sysfs() { 131 KObjectManager::remove_kobj(desc.clone() as Arc<dyn KObject>); 132 desc.mark_not_in_sysfs(); 133 } 134 } 135 #[derive(Debug)] 136 struct AttrChipName; 137 138 impl Attribute for AttrChipName { 139 fn name(&self) -> &str { 140 "chip_name" 141 } 142 143 fn mode(&self) -> ModeType { 144 SYSFS_ATTR_MODE_RO 145 } 146 147 fn support(&self) -> SysFSOpsSupport { 148 SysFSOpsSupport::ATTR_SHOW 149 } 150 151 fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> { 152 let irq_desc = kobj 153 .arc_any() 154 .downcast::<IrqDesc>() 155 .map_err(|_| SystemError::EINVAL)?; 156 157 let chip = irq_desc.irq_data().chip_info_read_irqsave().chip(); 158 let name = chip.name(); 159 let len = core::cmp::min(name.len() + 1, buf.len()); 160 let name = format!("{}\n", name); 161 buf[..len].copy_from_slice(name.as_bytes()); 162 return Ok(len); 163 } 164 } 165 166 #[derive(Debug)] 167 struct AttrHardwareIrq; 168 169 impl Attribute for AttrHardwareIrq { 170 fn name(&self) -> &str { 171 "hwirq" 172 } 173 174 fn mode(&self) -> ModeType { 175 SYSFS_ATTR_MODE_RO 176 } 177 178 fn support(&self) -> SysFSOpsSupport { 179 SysFSOpsSupport::ATTR_SHOW 180 } 181 182 fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> { 183 let irq_desc = kobj 184 .arc_any() 185 .downcast::<IrqDesc>() 186 .map_err(|_| SystemError::EINVAL)?; 187 let hwirq = irq_desc.hardware_irq(); 188 return sysfs_emit_str(buf, &format!("{}\n", hwirq.data())); 189 } 190 } 191 192 #[derive(Debug)] 193 struct AttrType; 194 195 impl Attribute for AttrType { 196 fn name(&self) -> &str { 197 "type" 198 } 199 200 fn mode(&self) -> ModeType { 201 SYSFS_ATTR_MODE_RO 202 } 203 204 fn support(&self) -> SysFSOpsSupport { 205 SysFSOpsSupport::ATTR_SHOW 206 } 207 208 fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> { 209 let irq_desc = kobj 210 .arc_any() 211 .downcast::<IrqDesc>() 212 .map_err(|_| SystemError::EINVAL)?; 213 let irq_type = if irq_desc.irq_data().is_level_type() { 214 "level" 215 } else { 216 "edge" 217 }; 218 219 return sysfs_emit_str(buf, &format!("{}\n", irq_type)); 220 } 221 } 222 223 #[derive(Debug)] 224 struct AttrWakeup; 225 226 impl Attribute for AttrWakeup { 227 fn name(&self) -> &str { 228 "wakeup" 229 } 230 231 fn mode(&self) -> ModeType { 232 SYSFS_ATTR_MODE_RO 233 } 234 235 fn support(&self) -> SysFSOpsSupport { 236 SysFSOpsSupport::ATTR_SHOW 237 } 238 239 fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> { 240 let irq_desc = kobj 241 .arc_any() 242 .downcast::<IrqDesc>() 243 .map_err(|_| SystemError::EINVAL)?; 244 let wakeup = irq_desc.irq_data().is_wakeup_set(); 245 return sysfs_emit_str(buf, &format!("{}\n", wakeup)); 246 } 247 } 248 249 #[derive(Debug)] 250 struct AttrName; 251 252 impl Attribute for AttrName { 253 fn name(&self) -> &str { 254 "name" 255 } 256 257 fn mode(&self) -> ModeType { 258 SYSFS_ATTR_MODE_RO 259 } 260 261 fn support(&self) -> SysFSOpsSupport { 262 SysFSOpsSupport::ATTR_SHOW 263 } 264 265 fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> { 266 let irq_desc = kobj 267 .arc_any() 268 .downcast::<IrqDesc>() 269 .map_err(|_| SystemError::EINVAL)?; 270 271 if let Some(name) = irq_desc.name() { 272 return sysfs_emit_str(buf, &format!("{}\n", name)); 273 } 274 275 return Ok(0); 276 } 277 } 278 279 #[derive(Debug)] 280 struct AttrActions; 281 282 impl Attribute for AttrActions { 283 fn name(&self) -> &str { 284 "actions" 285 } 286 287 fn mode(&self) -> ModeType { 288 SYSFS_ATTR_MODE_RO 289 } 290 291 fn support(&self) -> SysFSOpsSupport { 292 SysFSOpsSupport::ATTR_SHOW 293 } 294 295 fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> { 296 let irq_desc = kobj 297 .arc_any() 298 .downcast::<IrqDesc>() 299 .map_err(|_| SystemError::EINVAL)?; 300 301 let actions = irq_desc.actions(); 302 let mut len = 0; 303 304 for action in actions { 305 if len != 0 { 306 len += sysfs_emit_str(&mut buf[len..], &format!(",{}", action.inner().name())) 307 .unwrap(); 308 } else { 309 len += sysfs_emit_str(&mut buf[len..], &action.inner().name().to_string()).unwrap(); 310 } 311 312 if len >= buf.len() { 313 break; 314 } 315 } 316 317 if len != 0 && len < buf.len() { 318 len += sysfs_emit_str(&mut buf[len..], "\n").unwrap(); 319 } 320 321 return Ok(len); 322 } 323 } 324