[PATCH v6 1/3] driver core: add device_enumeration_failure_notify() helper
Akshay Gujar <[email protected]> Sun, 2 Aug 2026 23:31:06 +0000
| Newsgroups | org.kernel.vger.linux-usb,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Hotpluggable buses may detect that a device is physically present, but enumeration can fail early due to protocol-level errors. Such failures are currently only visible via kernel log messages, with no structured notification to userspace. Introduce device_enumeration_failure_notify(), a helper in the driver core that emits a KOBJ_CHANGE uevent with DEVICE_ENUMERATION_FAILURE=<failed_id> The emitting device and the identifier are separate arguments because the device being enumerated usually does not exist yet. The event is emitted from a device the bus driver has already registered, and the identifier names the port or slot that failed. Signed-off-by: Akshay Gujar <[email protected]> --- drivers/base/core.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/device.h | 2 ++ 2 files changed, 37 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 4d026682944f2..af6901799df58 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3830,6 +3830,41 @@ int device_add(struct device *dev) } EXPORT_SYMBOL_GPL(device_add); +/** + * device_enumeration_failure_notify - notify userspace of enumeration failure + * @dev: device to emit the uevent from + * @failed_id: bus-specific identifier of the port or slot that failed to + * enumerate, e.g. the port device name for USB + * + * Emit a KOBJ_CHANGE uevent from @dev carrying + * DEVICE_ENUMERATION_FAILURE=@failed_id. + * + * Return: 0 on success, a negative error code otherwise. + * + * See Documentation/ABI/testing/sysfs-uevent for more details. + */ +int device_enumeration_failure_notify(struct device *dev, + const char *failed_id) +{ + char *envp[2] = { NULL, NULL }; + int ret; + + if (!failed_id || !*failed_id) + return -EINVAL; + + envp[0] = kasprintf(GFP_KERNEL, "DEVICE_ENUMERATION_FAILURE=%s", + failed_id); + + if (!envp[0]) + return -ENOMEM; + + ret = kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); + kfree(envp[0]); + + return ret; +} +EXPORT_SYMBOL_GPL(device_enumeration_failure_notify); + /** * device_register - register a device with the system. * @dev: pointer to the device structure diff --git a/include/linux/device.h b/include/linux/device.h index 7b2baffdd2f55..7dc9b2316ea24 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1394,4 +1394,6 @@ static inline bool device_link_test(const struct device_link *link, u32 flags) #define MODULE_ALIAS_CHARDEV_MAJOR(major) \ MODULE_ALIAS("char-major-" __stringify(major) "-*") +int device_enumeration_failure_notify(struct device *dev, const char *failed_id); + #endif /* _DEVICE_H_ */ -- 2.19.0