|
@@ -1,16 +1,37 @@
|
|
|
-use alloc::sync::Arc;
|
|
|
+use alloc::{string::ToString, sync::Arc};
|
|
|
use system_error::SystemError;
|
|
|
use unified_init::macros::unified_init;
|
|
|
|
|
|
use crate::{
|
|
|
- driver::base::kobject::{KObjType, KObject, KObjectSysFSOps},
|
|
|
+ driver::base::{
|
|
|
+ kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps},
|
|
|
+ kset::KSet,
|
|
|
+ },
|
|
|
filesystem::{
|
|
|
- sysfs::{Attribute, AttributeGroup, SysFSOps},
|
|
|
+ sysfs::{
|
|
|
+ file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport,
|
|
|
+ SYSFS_ATTR_MODE_RO,
|
|
|
+ },
|
|
|
vfs::syscall::ModeType,
|
|
|
},
|
|
|
init::initcall::INITCALL_POSTCORE,
|
|
|
+ misc::ksysfs::sys_kernel_kset,
|
|
|
+};
|
|
|
+
|
|
|
+use super::{
|
|
|
+ irqdesc::{irq_desc_manager, IrqDesc},
|
|
|
+ IrqNumber,
|
|
|
};
|
|
|
|
|
|
+/// `/sys/kernel/irq`的kset
|
|
|
+static mut SYS_KERNEL_IRQ_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
|
|
+
|
|
|
+#[inline(always)]
|
|
|
+#[allow(dead_code)]
|
|
|
+pub fn sys_kernel_irq_kset() -> Arc<KSet> {
|
|
|
+ unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.clone().unwrap() }
|
|
|
+}
|
|
|
+
|
|
|
/// 中断描述符的kobjtype
|
|
|
///
|
|
|
/// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#280
|
|
@@ -40,9 +61,20 @@ impl AttributeGroup for IrqAttrGroup {
|
|
|
None
|
|
|
}
|
|
|
|
|
|
+ /// 所有的属性
|
|
|
+ ///
|
|
|
+ /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268
|
|
|
fn attrs(&self) -> &[&'static dyn Attribute] {
|
|
|
- todo!("irq_attr_group.attrs")
|
|
|
- // todo: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268
|
|
|
+ // 每个irq的属性
|
|
|
+ // todo: 添加per_cpu_count属性
|
|
|
+ &[
|
|
|
+ &AttrChipName,
|
|
|
+ &AttrHardwareIrq,
|
|
|
+ &AttrType,
|
|
|
+ &AttrWakeup,
|
|
|
+ &AttrName,
|
|
|
+ &AttrActions,
|
|
|
+ ]
|
|
|
}
|
|
|
|
|
|
fn is_visible(
|
|
@@ -60,6 +92,229 @@ impl AttributeGroup for IrqAttrGroup {
|
|
|
#[unified_init(INITCALL_POSTCORE)]
|
|
|
fn irq_sysfs_init() -> Result<(), SystemError> {
|
|
|
// todo!("irq_sysfs_init");
|
|
|
- kwarn!("Unimplemented: irq_sysfs_init");
|
|
|
- Ok(())
|
|
|
+
|
|
|
+ let irq_kset = KSet::new("irq".to_string());
|
|
|
+ irq_kset
|
|
|
+ .register(Some(sys_kernel_kset()))
|
|
|
+ .expect("register irq kset failed");
|
|
|
+ unsafe {
|
|
|
+ SYS_KERNEL_IRQ_KSET_INSTANCE = Some(irq_kset);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 把所有的irq都注册到/sys/kernel/irq下
|
|
|
+ for (irq, desc) in irq_desc_manager().iter_descs() {
|
|
|
+ irq_sysfs_add(irq, desc);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Ok(());
|
|
|
+}
|
|
|
+
|
|
|
+/// 把irqdesc添加到sysfs
|
|
|
+fn irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>) {
|
|
|
+ if unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.is_none() } {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let kset = sys_kernel_irq_kset();
|
|
|
+ KObjectManager::add_kobj(desc.clone() as Arc<dyn KObject>, Some(kset)).unwrap_or_else(|e| {
|
|
|
+ kwarn!("Failed to add irq({irq:?}) kobject to sysfs: {:?}", e);
|
|
|
+ });
|
|
|
+
|
|
|
+ desc.mark_in_sysfs();
|
|
|
+}
|
|
|
+
|
|
|
+/// 从sysfs中删除irqdesc
|
|
|
+#[allow(dead_code)]
|
|
|
+pub(super) fn irq_sysfs_del(desc: &Arc<IrqDesc>) {
|
|
|
+ if desc.in_sysfs() {
|
|
|
+ KObjectManager::remove_kobj(desc.clone() as Arc<dyn KObject>);
|
|
|
+ desc.mark_not_in_sysfs();
|
|
|
+ }
|
|
|
+}
|
|
|
+#[derive(Debug)]
|
|
|
+struct AttrChipName;
|
|
|
+
|
|
|
+impl Attribute for AttrChipName {
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ "chip_name"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ SYSFS_ATTR_MODE_RO
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ SysFSOpsSupport::ATTR_SHOW
|
|
|
+ }
|
|
|
+
|
|
|
+ fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ let irq_desc = kobj
|
|
|
+ .arc_any()
|
|
|
+ .downcast::<IrqDesc>()
|
|
|
+ .map_err(|_| SystemError::EINVAL)?;
|
|
|
+ let chip = irq_desc.irq_data().chip();
|
|
|
+ let name = chip.name();
|
|
|
+ let len = core::cmp::min(name.len() + 1, buf.len());
|
|
|
+ let name = format!("{}\n", name);
|
|
|
+ buf[..len].copy_from_slice(name.as_bytes());
|
|
|
+ return Ok(len);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+struct AttrHardwareIrq;
|
|
|
+
|
|
|
+impl Attribute for AttrHardwareIrq {
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ "hwirq"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ SYSFS_ATTR_MODE_RO
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ SysFSOpsSupport::ATTR_SHOW
|
|
|
+ }
|
|
|
+
|
|
|
+ fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ let irq_desc = kobj
|
|
|
+ .arc_any()
|
|
|
+ .downcast::<IrqDesc>()
|
|
|
+ .map_err(|_| SystemError::EINVAL)?;
|
|
|
+ let hwirq = irq_desc.hardware_irq();
|
|
|
+ return sysfs_emit_str(buf, &format!("{}\n", hwirq.data()));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+struct AttrType;
|
|
|
+
|
|
|
+impl Attribute for AttrType {
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ "type"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ SYSFS_ATTR_MODE_RO
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ SysFSOpsSupport::ATTR_SHOW
|
|
|
+ }
|
|
|
+
|
|
|
+ fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ let irq_desc = kobj
|
|
|
+ .arc_any()
|
|
|
+ .downcast::<IrqDesc>()
|
|
|
+ .map_err(|_| SystemError::EINVAL)?;
|
|
|
+ let irq_type = if irq_desc.irq_data().is_level_type() {
|
|
|
+ "level"
|
|
|
+ } else {
|
|
|
+ "edge"
|
|
|
+ };
|
|
|
+
|
|
|
+ return sysfs_emit_str(buf, &format!("{}\n", irq_type));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+struct AttrWakeup;
|
|
|
+
|
|
|
+impl Attribute for AttrWakeup {
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ "wakeup"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ SYSFS_ATTR_MODE_RO
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ SysFSOpsSupport::ATTR_SHOW
|
|
|
+ }
|
|
|
+
|
|
|
+ fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ let irq_desc = kobj
|
|
|
+ .arc_any()
|
|
|
+ .downcast::<IrqDesc>()
|
|
|
+ .map_err(|_| SystemError::EINVAL)?;
|
|
|
+ let wakeup = irq_desc.irq_data().is_wakeup_set();
|
|
|
+ return sysfs_emit_str(buf, &format!("{}\n", wakeup));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+struct AttrName;
|
|
|
+
|
|
|
+impl Attribute for AttrName {
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ "name"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ SYSFS_ATTR_MODE_RO
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ SysFSOpsSupport::ATTR_SHOW
|
|
|
+ }
|
|
|
+
|
|
|
+ fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ let irq_desc = kobj
|
|
|
+ .arc_any()
|
|
|
+ .downcast::<IrqDesc>()
|
|
|
+ .map_err(|_| SystemError::EINVAL)?;
|
|
|
+
|
|
|
+ if let Some(name) = irq_desc.name() {
|
|
|
+ return sysfs_emit_str(buf, &format!("{}\n", name));
|
|
|
+ }
|
|
|
+
|
|
|
+ return Ok(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+struct AttrActions;
|
|
|
+
|
|
|
+impl Attribute for AttrActions {
|
|
|
+ fn name(&self) -> &str {
|
|
|
+ "actions"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn mode(&self) -> ModeType {
|
|
|
+ SYSFS_ATTR_MODE_RO
|
|
|
+ }
|
|
|
+
|
|
|
+ fn support(&self) -> SysFSOpsSupport {
|
|
|
+ SysFSOpsSupport::ATTR_SHOW
|
|
|
+ }
|
|
|
+
|
|
|
+ fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
|
|
+ let irq_desc = kobj
|
|
|
+ .arc_any()
|
|
|
+ .downcast::<IrqDesc>()
|
|
|
+ .map_err(|_| SystemError::EINVAL)?;
|
|
|
+
|
|
|
+ let actions = irq_desc.actions();
|
|
|
+ let mut len = 0;
|
|
|
+
|
|
|
+ for action in actions {
|
|
|
+ if len != 0 {
|
|
|
+ len += sysfs_emit_str(&mut buf[len..], &format!(",{}", action.name())).unwrap();
|
|
|
+ } else {
|
|
|
+ len += sysfs_emit_str(&mut buf[len..], &format!("{}", action.name())).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ if len >= buf.len() {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if len != 0 && len < buf.len() {
|
|
|
+ len += sysfs_emit_str(&mut buf[len..], "\n").unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ return Ok(len);
|
|
|
+ }
|
|
|
}
|