diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 0bd731cbb50cc..c702c78f24d82 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -189,6 +189,16 @@ Description: The file will read "hotplug", "wired" and "not used" if the information is available, and "unknown" otherwise. +What: /sys/bus/usb/devices/.../(hub interface)/portX/over_current_count +Date: February 2018 +Contact: Richard Leitner +Description: + Most hubs are able to detect over-current situations on their + ports and report them to the kernel. This attribute is to expose + the number of over-current situation occurred on a specific port + to user space. This file will contain an unsigned 32 bit value + which wraps to 0 after its maximum is reached. + What: /sys/bus/usb/devices/.../(hub interface)/portX/usb3_lpm_permit Date: November 2015 Contact: Lu Baolu diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ac7bab772a3ae..aaeef03c0d838 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5104,8 +5104,10 @@ 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++; - dev_dbg(&port_dev->dev, "over-current change\n"); + dev_dbg(&port_dev->dev, "over-current change #%u\n", + port_dev->over_current_count); usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_OVER_CURRENT); msleep(100); /* Cool down */ diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 2a700ccc868c9..4dc769ee9c740 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -96,6 +96,7 @@ struct usb_port { enum usb_port_connect_type connect_type; usb_port_location_t location; struct mutex status_lock; + u32 over_current_count; u8 portnum; unsigned int is_superspeed:1; unsigned int usb3_lpm_u1_permit:1; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 1a01e9ad38049..6979bde87d310 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -41,6 +41,15 @@ static ssize_t connect_type_show(struct device *dev, } static DEVICE_ATTR_RO(connect_type); +static ssize_t over_current_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_port *port_dev = to_usb_port(dev); + + return sprintf(buf, "%u\n", port_dev->over_current_count); +} +static DEVICE_ATTR_RO(over_current_count); + static ssize_t usb3_lpm_permit_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -109,6 +118,7 @@ static DEVICE_ATTR_RW(usb3_lpm_permit); static struct attribute *port_dev_attrs[] = { &dev_attr_connect_type.attr, + &dev_attr_over_current_count.attr, NULL, };