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)]
sys_kernel_irq_kset() -> Arc<KSet>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 {
sysfs_ops(&self) -> Option<&dyn SysFSOps>43 fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
44 Some(&KObjectSysFSOps)
45 }
46
attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>47 fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
48 Some(&[&IrqAttrGroup])
49 }
50
release(&self, _kobj: Arc<dyn KObject>)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 {
name(&self) -> Option<&str>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
attrs(&self) -> &[&'static dyn Attribute]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
is_visible( &self, _kobj: Arc<dyn KObject>, attr: &'static dyn Attribute, ) -> Option<ModeType>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)]
irq_sysfs_init() -> Result<(), SystemError>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
irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>)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)]
irq_sysfs_del(desc: &Arc<IrqDesc>)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 {
name(&self) -> &str139 fn name(&self) -> &str {
140 "chip_name"
141 }
142
mode(&self) -> ModeType143 fn mode(&self) -> ModeType {
144 SYSFS_ATTR_MODE_RO
145 }
146
support(&self) -> SysFSOpsSupport147 fn support(&self) -> SysFSOpsSupport {
148 SysFSOpsSupport::ATTR_SHOW
149 }
150
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str170 fn name(&self) -> &str {
171 "hwirq"
172 }
173
mode(&self) -> ModeType174 fn mode(&self) -> ModeType {
175 SYSFS_ATTR_MODE_RO
176 }
177
support(&self) -> SysFSOpsSupport178 fn support(&self) -> SysFSOpsSupport {
179 SysFSOpsSupport::ATTR_SHOW
180 }
181
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str196 fn name(&self) -> &str {
197 "type"
198 }
199
mode(&self) -> ModeType200 fn mode(&self) -> ModeType {
201 SYSFS_ATTR_MODE_RO
202 }
203
support(&self) -> SysFSOpsSupport204 fn support(&self) -> SysFSOpsSupport {
205 SysFSOpsSupport::ATTR_SHOW
206 }
207
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str227 fn name(&self) -> &str {
228 "wakeup"
229 }
230
mode(&self) -> ModeType231 fn mode(&self) -> ModeType {
232 SYSFS_ATTR_MODE_RO
233 }
234
support(&self) -> SysFSOpsSupport235 fn support(&self) -> SysFSOpsSupport {
236 SysFSOpsSupport::ATTR_SHOW
237 }
238
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str253 fn name(&self) -> &str {
254 "name"
255 }
256
mode(&self) -> ModeType257 fn mode(&self) -> ModeType {
258 SYSFS_ATTR_MODE_RO
259 }
260
support(&self) -> SysFSOpsSupport261 fn support(&self) -> SysFSOpsSupport {
262 SysFSOpsSupport::ATTR_SHOW
263 }
264
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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 {
name(&self) -> &str283 fn name(&self) -> &str {
284 "actions"
285 }
286
mode(&self) -> ModeType287 fn mode(&self) -> ModeType {
288 SYSFS_ATTR_MODE_RO
289 }
290
support(&self) -> SysFSOpsSupport291 fn support(&self) -> SysFSOpsSupport {
292 SysFSOpsSupport::ATTR_SHOW
293 }
294
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>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