usb: core: added uevent for over-current
Greg Kroah-Hartman
maintainerQuoted 70 lines · Jon Flatley
After commit
1cbd53c8cd85("usb: core: introduce per-port over-current counters") usb ports expose a sysfs value 'over_current_count' to user space. This value on its own is not very useful as it requires manual polling.As a solution, fire a udev event from the usb hub device that specifies the values '
OVER_CURRENT_PORT' and 'OVER_CURRENT_COUNT' that indicate the path of the usb port where the over-current event occurred and the value of 'over_current_count' in sysfs. Additionally, callsysfs_notify()so the sysfs value supportspoll().Signed-off-by Jon Flatley <[email protected]>--- drivers/usb/core/hub.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)drivers/usb/core/hub.c +35
-0@@ -27,6 +27,7 @@#include <linux/random.h> #include <linux/pm_qos.h> #include <linux/pm_dark_resume.h> +#include <linux/kobject.h> #include <asm/uaccess.h> #include <asm/byteorder.h> @@ -5096,6 +5097,40 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,usb_lock_port (port_dev); } +/* Handle notifying userspace about hub over-current events */ +static void port_over_current_notify (struct usb_port *port_dev) +{ +static char *envp[] = {NULL ,NULL ,NULL }; +struct device *hub_dev; +char *port_dev_path; + +sysfs_notify (&port_dev->dev.kobj,NULL ,"over_current_count" ); + + hub_dev = port_dev->dev.parent; + +if (!hub_dev) +return ; + + port_dev_path =kobject_get_path (&port_dev->dev.kobj,GFP_KERNEL ); +if (!port_dev_path) +return ; + + envp[0 ] =kasprintf (GFP_KERNEL ,"OVER_CURRENT_PORT=%s" , port_dev_path); +if (!envp[0 ]) +return ; + + envp[1 ] =kasprintf (GFP_KERNEL ,"OVER_CURRENT_COUNT=%u" , + port_dev->over_current_count); +if (!envp[1 ]) + goto exit; + +kobject_uevent_env (&hub_dev->kobj,KOBJ_CHANGE , envp); + +kfree (envp[1 ]); +exit: +kfree (envp[0 ]); +} +static void port_event (struct usb_hub *hub,int port1) __must_hold(&port_dev->status_lock) {
drivers/usb/core/hub.c static void port_event(struct usb_hub *hub, int port1) · line 5176
Quoted 4 lines
drivers/usb/core/hub.c +1
-0@@ -5138,6 +5173,7 @@ static void port_event(struct usb_hub *hub, int port1)if (portchange &USB_PORT_STAT_C_OVERCURRENT ) {u16 status =0 , unused; port_dev->over_current_count++; +port_over_current_notify (port_dev);
When an overcurrent "event" happens, does it just stay overloaded for long periods of time? Would this flood the system with lots of kobject messages, or is this rate-limited somehow?
Also, as this is a new user/kernel abi you are creating, it needs to be documented somewhere. Perhaps in the sysfs file information for this attribute?
thanks,
greg k-h