mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
feat: 支持 sysfs下 block, char, Net, rtc, tty 等类型设备的 uevent 文件读操作 (#973)
* 新增CommonAttrGroup,基本支持sysfs下各种类型设备的uevent属性文件的读测试 * 修改net设备的uevent内容,使之与Linux语义一致 * 删除无用注释
This commit is contained in:
parent
4e4ce68e03
commit
38d161ccfe
@ -133,7 +133,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
|
||||
show &= false;
|
||||
}
|
||||
}
|
||||
|
||||
show = false;
|
||||
if show {
|
||||
debug!("[SYS] [Pid: {:?}] [Call: {:?}]", pid, to_print);
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
/// 引入Module
|
||||
use crate::driver::{
|
||||
use crate::{driver::{
|
||||
base::{
|
||||
device::{
|
||||
device_number::{DeviceNumber, Major},
|
||||
Device, DeviceError, IdTable, BLOCKDEVS,
|
||||
device_number::{DeviceNumber, Major}, Device, DeviceError, IdTable, BLOCKDEVS
|
||||
},
|
||||
map::{
|
||||
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
||||
@ -11,7 +10,7 @@ use crate::driver::{
|
||||
},
|
||||
},
|
||||
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
|
||||
};
|
||||
}, filesystem::sysfs::AttributeGroup};
|
||||
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Display, ops::Deref};
|
||||
|
@ -43,6 +43,7 @@ use super::{
|
||||
},
|
||||
kset::KSet,
|
||||
swnode::software_node_notify,
|
||||
uevent::UeventAttr,
|
||||
};
|
||||
|
||||
pub mod bus;
|
||||
@ -1025,6 +1026,25 @@ impl Eq for DeviceId {}
|
||||
|
||||
impl IrqHandlerData for DeviceId {}
|
||||
|
||||
/// sysfs下设备的通用属性组
|
||||
#[derive(Debug)]
|
||||
pub struct CommonAttrGroup;
|
||||
impl AttributeGroup for CommonAttrGroup {
|
||||
fn name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
fn attrs(&self) -> &[&'static dyn Attribute] {
|
||||
&[&UeventAttr]
|
||||
}
|
||||
fn is_visible(
|
||||
&self,
|
||||
_kobj: alloc::sync::Arc<dyn KObject>,
|
||||
attr: &'static dyn Attribute,
|
||||
) -> Option<crate::filesystem::vfs::syscall::ModeType> {
|
||||
Some(attr.mode())
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// class_dir列表,通过parent kobject的name和class_dir的name来索引class_dir实例
|
||||
static ref CLASS_DIR_KSET_INSTANCE: RwLock<BTreeMap<String, Arc<ClassDir>>> = RwLock::new(BTreeMap::new());
|
||||
|
@ -22,7 +22,7 @@ use crate::{
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{kset::KSet, uevent::kobject_uevent};
|
||||
use super::{device::CommonAttrGroup, kset::KSet, uevent::kobject_uevent};
|
||||
|
||||
pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any;
|
||||
|
@ -11,12 +11,12 @@ use crate::{
|
||||
bus::{Bus, BusState},
|
||||
device_manager,
|
||||
driver::Driver,
|
||||
Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable,
|
||||
CommonAttrGroup, Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
@ -329,4 +329,8 @@ impl Device for PlatformBusDevice {
|
||||
fn set_dev_parent(&self, dev_parent: Option<Weak<dyn Device>>) {
|
||||
self.inner().device_common.parent = dev_parent;
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&CommonAttrGroup])
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ use alloc::string::{String, ToString};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use intertrait::cast::CastArc;
|
||||
use log::warn;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::block::block_device::{BlockDevice, BlockDeviceOps};
|
||||
@ -128,46 +129,60 @@ impl Attribute for UeventAttr {
|
||||
|
||||
/// 用户空间读取 uevent 文件,返回 uevent 信息
|
||||
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let device: Arc<dyn KObject> = _kobj
|
||||
.parent()
|
||||
.and_then(|x| x.upgrade())
|
||||
.ok_or(SystemError::ENODEV)?;
|
||||
let device = kobj2device(device).ok_or(SystemError::EINVAL)?;
|
||||
let device = _kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
|
||||
warn!("device:{:?} is not a device!", e);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
log::info!("show uevent");
|
||||
let device_type = device.dev_type();
|
||||
let mut uevent_content = String::new();
|
||||
log::info!("device_type: {:?}", device_type);
|
||||
match device_type {
|
||||
DeviceType::Block => {
|
||||
let block_device = device
|
||||
.cast::<dyn BlockDevice>()
|
||||
.ok()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
let major = block_device.id_table().device_number().major().data();
|
||||
let minor = block_device.id_table().device_number().minor();
|
||||
let device_name = block_device.id_table().name();
|
||||
let major = device.id_table().device_number().major().data();
|
||||
let minor = device.id_table().device_number().minor();
|
||||
let device_name = device.id_table().name();
|
||||
writeln!(&mut uevent_content, "MAJOR={:?}", major).unwrap();
|
||||
writeln!(&mut uevent_content, "MINOR={:?}", minor).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVTYPE=disk").unwrap();
|
||||
}
|
||||
DeviceType::Char => {
|
||||
let char_device = device
|
||||
.cast::<dyn CharDevice>()
|
||||
.ok()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
let major = char_device.id_table().device_number().major().data();
|
||||
let minor = char_device.id_table().device_number().minor();
|
||||
let device_name = char_device.id_table().name();
|
||||
let major = device.id_table().device_number().major().data();
|
||||
let minor = device.id_table().device_number().minor();
|
||||
let device_name = device.id_table().name();
|
||||
writeln!(&mut uevent_content, "MAJOR={}", major).unwrap();
|
||||
writeln!(&mut uevent_content, "MINOR={}", minor).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVTYPE=char").unwrap();
|
||||
}
|
||||
DeviceType::Net => {
|
||||
let net_device = device.cast::<dyn Iface>().ok().ok_or(SystemError::EINVAL)?;
|
||||
// let ifindex = net_device.ifindex().expect("Find ifindex error.\n");
|
||||
let device_name = net_device.iface_name();
|
||||
let net_device = device.clone().cast::<dyn Iface>().map_err(|e: Arc<dyn Device>| {
|
||||
warn!("device:{:?} is not a net device!", e);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let iface_id = net_device.nic_id();
|
||||
let device_name = device.name();
|
||||
writeln!(&mut uevent_content, "INTERFACE={}", device_name).unwrap();
|
||||
// writeln!(&mut uevent_content, "IFINDEX={}", ifindex).unwrap();
|
||||
writeln!(&mut uevent_content, "IFINDEX={}", iface_id).unwrap();
|
||||
}
|
||||
DeviceType::Bus => {
|
||||
// 处理总线设备类型
|
||||
let device_name = device.name();
|
||||
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVTYPE=bus").unwrap();
|
||||
}
|
||||
DeviceType::Rtc => {
|
||||
// 处理RTC设备类型
|
||||
let device_name = device.name();
|
||||
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVTYPE=rtc").unwrap();
|
||||
}
|
||||
DeviceType::Pci => {
|
||||
// 处理PCI设备类型
|
||||
let device_name = device.name();
|
||||
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
|
||||
writeln!(&mut uevent_content, "DEVTYPE=pci").unwrap();
|
||||
}
|
||||
_ => {
|
||||
// 处理其他设备类型
|
||||
@ -180,17 +195,15 @@ impl Attribute for UeventAttr {
|
||||
}
|
||||
/// 捕获来自用户空间对 uevent 文件的写操作,触发uevent事件
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
log::info!("store uevent");
|
||||
return kobject_synth_uevent(_buf, _kobj);
|
||||
}
|
||||
}
|
||||
|
||||
/// 将 kobject 转换为 device
|
||||
fn kobj2device(kobj: Arc<dyn KObject>) -> Option<Arc<dyn Device>> {
|
||||
kobj.cast::<dyn Device>().ok()
|
||||
}
|
||||
|
||||
/// 将设备的基本信息写入 uevent 文件
|
||||
fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result<usize, SystemError> {
|
||||
log::info!("sysfs_emit_str");
|
||||
let bytes = content.as_bytes();
|
||||
if buf.len() < bytes.len() {
|
||||
return Err(SystemError::ENOMEM);
|
||||
@ -211,7 +224,10 @@ fn kobject_synth_uevent(buf: &[u8], kobj: Arc<dyn KObject>) -> Result<usize, Sys
|
||||
};
|
||||
|
||||
if let Err(e) = result {
|
||||
let device = kobj2device(kobj).ok_or(SystemError::EINVAL)?;
|
||||
let device = kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
|
||||
warn!("device:{:?} is not a device!", e);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let devname = device.name();
|
||||
log::error!("synth uevent: {}: {:?}", devname, e);
|
||||
return Err(SystemError::EINVAL);
|
||||
|
@ -24,7 +24,7 @@ use crate::{
|
||||
device::{
|
||||
bus::Bus,
|
||||
driver::{Driver, DriverCommonData},
|
||||
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -38,7 +38,7 @@ use crate::{
|
||||
},
|
||||
},
|
||||
exception::{irqdesc::IrqReturn, IrqNumber},
|
||||
filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable},
|
||||
filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable, sysfs::AttributeGroup},
|
||||
init::initcall::INITCALL_POSTCORE,
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
@ -342,7 +342,7 @@ impl VirtIODevice for VirtIOBlkDevice {
|
||||
|
||||
impl Device for VirtIOBlkDevice {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
DeviceType::Net
|
||||
DeviceType::Block
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
@ -407,6 +407,10 @@ impl Device for VirtIOBlkDevice {
|
||||
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
|
||||
self.inner().device_common.parent = parent;
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&CommonAttrGroup])
|
||||
}
|
||||
}
|
||||
|
||||
impl KObject for VirtIOBlkDevice {
|
||||
@ -472,7 +476,7 @@ fn virtio_blk_driver_init() -> Result<(), SystemError> {
|
||||
let driver = VirtIOBlkDriver::new();
|
||||
virtio_driver_manager()
|
||||
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
||||
.expect("Add virtio net driver failed");
|
||||
.expect("Add virtio block driver failed");
|
||||
unsafe {
|
||||
VIRTIO_BLK_DRIVER = Some(driver);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
driver::base::{
|
||||
class::{class_manager, Class},
|
||||
device::sys_dev_char_kset,
|
||||
device::{sys_dev_char_kset, CommonAttrGroup},
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
@ -78,6 +78,6 @@ impl Class for NetClass {
|
||||
}
|
||||
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
return &[&NetAttrGroup];
|
||||
return &[&NetAttrGroup, &CommonAttrGroup];
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use crate::{
|
||||
device::{
|
||||
bus::Bus,
|
||||
driver::{Driver, DriverCommonData},
|
||||
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -41,7 +41,7 @@ use crate::{
|
||||
},
|
||||
},
|
||||
exception::{irqdesc::IrqReturn, IrqNumber},
|
||||
filesystem::kernfs::KernFSInode,
|
||||
filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
|
||||
init::initcall::INITCALL_POSTCORE,
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
@ -249,6 +249,10 @@ impl Device for VirtIONetDevice {
|
||||
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
|
||||
self.inner().device_common.parent = parent;
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&CommonAttrGroup])
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtIODevice for VirtIONetDevice {
|
||||
|
@ -8,7 +8,10 @@ use alloc::{
|
||||
use crate::{
|
||||
driver::base::{
|
||||
class::Class,
|
||||
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable},
|
||||
device::{
|
||||
bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType,
|
||||
IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
},
|
||||
@ -84,7 +87,7 @@ impl PciDevice for PciGeneralDevice {
|
||||
|
||||
impl Device for PciGeneralDevice {
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&BasicPciReadOnlyAttrs])
|
||||
Some(&[&BasicPciReadOnlyAttrs, &CommonAttrGroup])
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
|
@ -10,7 +10,10 @@ use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
class::Class,
|
||||
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable},
|
||||
device::{
|
||||
bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType,
|
||||
IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
},
|
||||
@ -74,7 +77,7 @@ impl PciDevice for TestDevice {
|
||||
|
||||
impl Device for TestDevice {
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&HelloAttr])
|
||||
Some(&[&HelloAttr, &CommonAttrGroup])
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
|
@ -9,10 +9,11 @@ use unified_init::macros::unified_init;
|
||||
use crate::{
|
||||
driver::base::{
|
||||
class::{class_manager, Class},
|
||||
device::{device_manager, sys_dev_char_kset},
|
||||
device::{device_manager, sys_dev_char_kset, CommonAttrGroup},
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
filesystem::sysfs::AttributeGroup,
|
||||
init::initcall::INITCALL_SUBSYS,
|
||||
time::{timekeeping::do_settimeofday64, PosixTimeSpec},
|
||||
};
|
||||
@ -78,6 +79,9 @@ impl Class for RtcClass {
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.subsystem;
|
||||
}
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
return &[&CommonAttrGroup];
|
||||
}
|
||||
}
|
||||
|
||||
/// 注册rtc通用设备
|
||||
|
@ -9,7 +9,8 @@ use crate::{
|
||||
driver::base::{
|
||||
class::Class,
|
||||
device::{
|
||||
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable,
|
||||
bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device, DeviceCommonData,
|
||||
DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -172,7 +173,7 @@ impl Device for RtcGeneralDevice {
|
||||
true
|
||||
}
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&RtcAttrGroup])
|
||||
Some(&[&RtcAttrGroup, &CommonAttrGroup])
|
||||
}
|
||||
|
||||
fn dev_parent(&self) -> Option<Weak<dyn Device>> {
|
||||
|
@ -8,10 +8,11 @@ use unified_init::macros::unified_init;
|
||||
use crate::{
|
||||
driver::base::{
|
||||
class::{class_manager, Class},
|
||||
device::sys_dev_char_kset,
|
||||
device::{sys_dev_char_kset, CommonAttrGroup},
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
filesystem::sysfs::AttributeGroup,
|
||||
init::initcall::INITCALL_SUBSYS,
|
||||
};
|
||||
|
||||
@ -61,6 +62,10 @@ impl Class for TtyClass {
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.subsystem;
|
||||
}
|
||||
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
return &[&CommonAttrGroup];
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化帧缓冲区子系统
|
||||
|
@ -11,8 +11,8 @@ use crate::{
|
||||
base::{
|
||||
class::Class,
|
||||
device::{
|
||||
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType,
|
||||
IdTable,
|
||||
bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device,
|
||||
DeviceCommonData, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -235,7 +235,7 @@ impl Device for FbConsoleDevice {
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
return Some(&[&AnonymousAttributeGroup]);
|
||||
return Some(&[&AnonymousAttributeGroup, &CommonAttrGroup]);
|
||||
}
|
||||
|
||||
fn dev_parent(&self) -> Option<Weak<dyn Device>> {
|
||||
|
@ -18,7 +18,7 @@ use crate::{
|
||||
device_manager,
|
||||
device_number::{DeviceNumber, Major},
|
||||
driver::Driver,
|
||||
sys_dev_char_kset, Device, DeviceCommonData, DeviceType, IdTable,
|
||||
sys_dev_char_kset, CommonAttrGroup, Device, DeviceCommonData, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -112,6 +112,10 @@ impl Class for GraphicsClass {
|
||||
fn subsystem(&self) -> &SubSysPrivate {
|
||||
return &self.subsystem;
|
||||
}
|
||||
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
return &[&CommonAttrGroup];
|
||||
}
|
||||
}
|
||||
|
||||
/// 帧缓冲区管理器
|
||||
@ -373,7 +377,7 @@ impl Device for FbDevice {
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&FbDeviceAttrGroup])
|
||||
Some(&[&FbDeviceAttrGroup, &CommonAttrGroup])
|
||||
}
|
||||
|
||||
fn dev_parent(&self) -> Option<Weak<dyn Device>> {
|
||||
|
@ -5,6 +5,7 @@ use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
driver::base::{
|
||||
device::CommonAttrGroup,
|
||||
kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps},
|
||||
kset::KSet,
|
||||
},
|
||||
@ -45,7 +46,7 @@ impl KObjType for IrqKObjType {
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&IrqAttrGroup])
|
||||
Some(&[&IrqAttrGroup, &CommonAttrGroup])
|
||||
}
|
||||
|
||||
fn release(&self, _kobj: Arc<dyn KObject>) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user