diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 462ce49f683a..7801bb30bdba 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -28,6 +28,7 @@ #include <linux/mutex.h> #include <linux/random.h> #include <linux/pm_qos.h> +#include <linux/kobject.h> #include <linux/uaccess.h> #include <asm/byteorder.h> @@ -5147,6 +5148,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) { @@ -5189,6 +5224,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); dev_dbg(&port_dev->dev, "over-current change #%u\n", port_dev->over_current_count); |