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