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)]
sys_kernel_irq_kset() -> Arc<KSet>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 {
sysfs_ops(&self) -> Option<&dyn SysFSOps>42     fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
43         Some(&KObjectSysFSOps)
44     }
45 
attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>46     fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
47         Some(&[&IrqAttrGroup])
48     }
49 
release(&self, _kobj: Arc<dyn KObject>)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 {
name(&self) -> Option<&str>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
attrs(&self) -> &[&'static dyn Attribute]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 
is_visible( &self, _kobj: Arc<dyn KObject>, attr: &'static dyn Attribute, ) -> Option<ModeType>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)]
irq_sysfs_init() -> Result<(), SystemError>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
irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>)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)]
irq_sysfs_del(desc: &Arc<IrqDesc>)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 {
name(&self) -> &str138     fn name(&self) -> &str {
139         "chip_name"
140     }
141 
mode(&self) -> ModeType142     fn mode(&self) -> ModeType {
143         SYSFS_ATTR_MODE_RO
144     }
145 
support(&self) -> SysFSOpsSupport146     fn support(&self) -> SysFSOpsSupport {
147         SysFSOpsSupport::ATTR_SHOW
148     }
149 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str169     fn name(&self) -> &str {
170         "hwirq"
171     }
172 
mode(&self) -> ModeType173     fn mode(&self) -> ModeType {
174         SYSFS_ATTR_MODE_RO
175     }
176 
support(&self) -> SysFSOpsSupport177     fn support(&self) -> SysFSOpsSupport {
178         SysFSOpsSupport::ATTR_SHOW
179     }
180 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str195     fn name(&self) -> &str {
196         "type"
197     }
198 
mode(&self) -> ModeType199     fn mode(&self) -> ModeType {
200         SYSFS_ATTR_MODE_RO
201     }
202 
support(&self) -> SysFSOpsSupport203     fn support(&self) -> SysFSOpsSupport {
204         SysFSOpsSupport::ATTR_SHOW
205     }
206 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str226     fn name(&self) -> &str {
227         "wakeup"
228     }
229 
mode(&self) -> ModeType230     fn mode(&self) -> ModeType {
231         SYSFS_ATTR_MODE_RO
232     }
233 
support(&self) -> SysFSOpsSupport234     fn support(&self) -> SysFSOpsSupport {
235         SysFSOpsSupport::ATTR_SHOW
236     }
237 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str252     fn name(&self) -> &str {
253         "name"
254     }
255 
mode(&self) -> ModeType256     fn mode(&self) -> ModeType {
257         SYSFS_ATTR_MODE_RO
258     }
259 
support(&self) -> SysFSOpsSupport260     fn support(&self) -> SysFSOpsSupport {
261         SysFSOpsSupport::ATTR_SHOW
262     }
263 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str282     fn name(&self) -> &str {
283         "actions"
284     }
285 
mode(&self) -> ModeType286     fn mode(&self) -> ModeType {
287         SYSFS_ATTR_MODE_RO
288     }
289 
support(&self) -> SysFSOpsSupport290     fn support(&self) -> SysFSOpsSupport {
291         SysFSOpsSupport::ATTR_SHOW
292     }
293 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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