bus: mhi: host: Only expose controller sysfs attributes on the controller device
Subsystems (3)
PATCH 1/1 bus: mhi: host: Only expose controller sysfs attributes on the controller device
The serial_number, oem_pk_hash and soc_reset attributes are registered through mhi_bus_type.dev_groups, so the driver core creates them for every device on the MHI bus. MHI client devices (the per-channel devices such as mhi0_DUN or mhi0_MBIM) are also MHI bus devices, so each of them ends up with its own copies of these files even though they all operate on the same mhi_controller:
$ ls /sys/bus/mhi/devices/mhi0_DUN/ driver oem_pk_hash power serial_number soc_reset subsystem uevent
This is wrong for several reasons:
- The attributes describe the controller, not the channel. Their callbacks all dereference mhi_dev->mhi_cntrl and read BHI registers or issue a controller-wide SoC reset, so writing soc_reset through mhi0_DUN resets the whole device while looking like a per-channel operation.
- oem_pk_hash reports failures with dev_err(dev, ...), so a single failing controller produces one log line per registered channel device instead of one.
- Userspace has no way to tell which copy is authoritative.
Move the attributes off the bus and attach them to the controller device only. mhi_register_controller() now installs the group via mhi_dev->dev.groups before device_add(), while the channel devices created by mhi_create_devices() are left untouched. No functional change for the controller device; the files stay at the paths listed in Documentation/ABI/stable/sysfs-bus-mhi.
Note that trigger_edl was already handled this way, through an explicit sysfs_create_file() on the controller kobject, which is why it never appeared on the channel devices.
--- drivers/bus/mhi/host/init.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/bus/mhi/host/init.c +12 -3
@@ -150,13 +150,21 @@ static ssize_t trigger_edl_store(struct device *dev, }static DEVICE_ATTR_WO (trigger_edl); -static struct attribute *mhi_dev_attrs[] = { +static struct attribute *mhi_cntrl_dev_attrs[] = { &dev_attr_serial_number.attr, &dev_attr_oem_pk_hash.attr, &dev_attr_soc_reset.attr,NULL , }; -ATTRIBUTE_GROUPS (mhi_dev); + +static const struct attribute_group mhi_cntrl_dev_group = { + .attrs = mhi_cntrl_dev_attrs, +}; + +static const struct attribute_group *mhi_cntrl_dev_groups[] = { + &mhi_cntrl_dev_group, +NULL , +};/* MHI protocol requires the transfer ring to be aligned with ring length */ static int mhi_alloc_aligned_ring(struct mhi_controller *mhi_cntrl,
@@ -1019,6 +1027,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,dev_set_name (&mhi_dev->dev,"mhi%d" , mhi_cntrl->index); mhi_dev->name =dev_name (&mhi_dev->dev); + mhi_dev->dev.groups = mhi_cntrl_dev_groups; +/* Init wakeup source */ device_init_wakeup (&mhi_dev->dev, true);
@@ -1455,7 +1465,6 @@ const struct bus_type mhi_bus_type = { .uevent = mhi_uevent, .probe = mhi_probe, .remove = mhi_remove, - .dev_groups = mhi_dev_groups, };static int __init mhi_init (void )
Signature · 1 line
2.53.0