diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-09-09 18:41:01 +0200 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-09-17 16:20:10 +0200 |
| commit | c0675673d84615135d7a15e21699a4390db7ba59 (patch) | |
| tree | 571ba43c3c3e79fe5a9a77ed893995baa19cb5c0 | |
| parent | f8113f311cf8be566d809598e967bf5ceb35b567 (diff) | |
| download | linux-next-c0675673d84615135d7a15e21699a4390db7ba59.tar.gz linux-next-c0675673d84615135d7a15e21699a4390db7ba59.zip | |
driver core/ACPI: Introduce companion_bus_register()
The ACPI bus type does not allow drivers to be registered, so the sysfs
attributes related to drivers created for it and its devices are
useless, and its drivers/ directory is always empty. All of that is
confusing and wasteful.
To allow skipping the creation of those sysfs attributes, introduce a
"companion" bus type concept and add a special registration function for
registering "companion" bus types, companion_bus_register().
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://patch.msgid.link/6329043.lOV4Wx5bFT@rafael.j.wysocki
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
| -rw-r--r-- | drivers/acpi/bus.c | 8 | ||||
| -rw-r--r-- | drivers/base/bus.c | 72 | ||||
| -rw-r--r-- | include/linux/device/bus.h | 1 |
3 files changed, 57 insertions, 24 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 808c6746be14..48f0b4809f94 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1120,11 +1120,6 @@ EXPORT_SYMBOL_GPL(acpi_driver_match_device); ACPI Bus operations -------------------------------------------------------------------------- */ -static int acpi_bus_match(struct device *dev, const struct device_driver *drv) -{ - return 0; -} - static int acpi_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { return __acpi_device_uevent_modalias(to_acpi_device(dev), env); @@ -1132,7 +1127,6 @@ static int acpi_device_uevent(const struct device *dev, struct kobj_uevent_env * const struct bus_type acpi_bus_type = { .name = "acpi", - .match = acpi_bus_match, .uevent = acpi_device_uevent, }; @@ -1451,7 +1445,7 @@ static int __init acpi_bus_init(void) */ acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); - result = bus_register(&acpi_bus_type); + result = companion_bus_register(&acpi_bus_type); if (!result) return 0; diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d17bd91490ee..92f2b450a3eb 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -738,6 +738,11 @@ int bus_add_driver(struct device_driver *drv) if (!sp) return -EINVAL; + if (!sp->drivers_kset) { + error = -ENXIO; + goto out_put_bus; + } + /* * Reference in sp is now incremented and will be dropped when * the driver is removed from the bus @@ -930,15 +935,7 @@ static ssize_t bus_uevent_store(const struct bus_type *bus, static struct bus_attribute bus_attr_uevent = __ATTR(uevent, 0200, NULL, bus_uevent_store); -/** - * bus_register - register a driver-core subsystem - * @bus: bus to register - * - * Once we have that, we register the bus with the kobject - * infrastructure, then register the children subsystems it has: - * the devices and drivers that belong to the subsystem. - */ -int bus_register(const struct bus_type *bus) +static int bus_register_internal(const struct bus_type *bus, bool use_drivers) { int retval; struct subsys_private *priv; @@ -960,7 +957,7 @@ int bus_register(const struct bus_type *bus) bus_kobj->kset = bus_kset; bus_kobj->ktype = &bus_ktype; - priv->drivers_autoprobe = 1; + priv->drivers_autoprobe = use_drivers; retval = kset_register(&priv->subsys); if (retval) @@ -976,10 +973,12 @@ int bus_register(const struct bus_type *bus) goto bus_devices_fail; } - priv->drivers_kset = kset_create_and_add("drivers", NULL, bus_kobj); - if (!priv->drivers_kset) { - retval = -ENOMEM; - goto bus_drivers_fail; + if (use_drivers) { + priv->drivers_kset = kset_create_and_add("drivers", NULL, bus_kobj); + if (!priv->drivers_kset) { + retval = -ENOMEM; + goto bus_drivers_fail; + } } INIT_LIST_HEAD(&priv->interfaces); @@ -989,9 +988,11 @@ int bus_register(const struct bus_type *bus) klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); klist_init(&priv->klist_drivers, NULL, NULL); - retval = add_probe_files(bus); - if (retval) - goto bus_probe_files_fail; + if (use_drivers) { + retval = add_probe_files(bus); + if (retval) + goto bus_probe_files_fail; + } retval = sysfs_create_groups(bus_kobj, bus->bus_groups); if (retval) @@ -1016,9 +1017,41 @@ out: kfree(priv); return retval; } + +/** + * bus_register - register a driver-core subsystem + * @bus: bus to register + * + * Once we have that, we register the bus with the kobject + * infrastructure, then register the children subsystems it has: + * the devices and drivers that belong to the subsystem. + */ +int bus_register(const struct bus_type *bus) +{ + return bus_register_internal(bus, true); +} EXPORT_SYMBOL_GPL(bus_register); /** + * companion_bus_register - register a companion bus type + * @bus: companion bus to register + * + * A companion bus is a bus without drivers. Devices that belong to it can be + * bound to other devices as their "companions" and represent interfaces that + * can be used by the drivers of those other devices. They may also be used for + * the enumeration of those other devices. + * + * The ACPI bus is a specific example of a companion bus. + * + * Registering a companion bus is like registering a regular bus except that it + * skips the creation of sysfs interfaces related to drivers for @bus. + */ +int companion_bus_register(const struct bus_type *bus) +{ + return bus_register_internal(bus, false); +} + +/** * bus_unregister - remove a bus from the system * @bus: bus. * @@ -1415,6 +1448,11 @@ struct device_driver *driver_find(const char *name, const struct bus_type *bus) if (!sp) return NULL; + if (!sp->drivers_kset) { + subsys_put(sp); + return NULL; + } + k = kset_find_obj(sp->drivers_kset, name); subsys_put(sp); if (!k) diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index a38f7229b8f4..89e156b9acb5 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -113,6 +113,7 @@ struct bus_type { bool need_parent_lock; }; +int __must_check companion_bus_register(const struct bus_type *bus); int __must_check bus_register(const struct bus_type *bus); void bus_unregister(const struct bus_type *bus); |
