[PATCH v2 11/14] USB: add connect_type == hotplug as a port poweroff constraint

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Now that userspace can discover the constraints keeping a port powered, require
it to explicitly disable hotplug capability before powering off a port.  This
makes the 'connect_type' attribute writable, and must be set to 'hardwired'
before a port is a candidate for poweroff.

Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---
 Documentation/ABI/testing/sysfs-bus-usb |    2 ++
 drivers/usb/core/port.c                 |   36 ++++++++++++++++++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 91bfcfcfbfe3..65db3a686de9 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -160,6 +160,8 @@ Description:
 			  port
 		'pm_qos_no_power_off': child inactive, pm qos flag keeps
 				       power enabled
+		'hotplug': child inactive, remaining powered to detect
+			   hotplug events
 		'wakeup enabled': child inactive, port kept powered to
 				  handle remote wakeup events
 		'persist disabled': child inactive, but child device
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index f7d1cd8a97d3..977e5b137b79 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -46,7 +46,38 @@ static ssize_t connect_type_show(struct device *dev,
 
 	return sprintf(buf, "%s\n", result);
 }
-static DEVICE_ATTR_RO(connect_type);
+
+static ssize_t connect_type_store(struct device *dev, struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+	ssize_t sz = len;
+	int i;
+	struct action { const char *str; enum usb_port_connect_type type; };
+	static const struct action action[] = {
+		{ .str = "hotplug", .type = USB_PORT_CONNECT_TYPE_HOT_PLUG, },
+		{ .str = "hardwired", .type = USB_PORT_CONNECT_TYPE_HARD_WIRED },
+	};
+
+	if (buf[len-1] == '\n' || buf[len-1] == '\0')
+		sz--;
+
+	for (i = 0; i < ARRAY_SIZE(action); i++) {
+		const struct action *act = &action[i];
+
+		if (sz == strlen(act->str)
+		    && strncmp(buf, act->str, sz) == 0) {
+			pm_runtime_get_sync(&port_dev->dev);
+			port_dev->connect_type = act->type;
+			pm_runtime_put_sync(&port_dev->dev);
+			return len;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static DEVICE_ATTR_RW(connect_type);
 
 static struct attribute *port_dev_attrs[] = {
 	&dev_attr_connect_type.attr,
@@ -103,6 +134,9 @@ static const char *power_on_reason(struct usb_port *port_dev)
 	if (dev_pm_qos_flags(&port_dev->dev, flag) == PM_QOS_FLAGS_ALL)
 		return "pm_qos_no_power_off";
 
+	if (port_dev->connect_type < USB_PORT_CONNECT_TYPE_HARD_WIRED)
+		return "hotplug";
+
 	udev = usb_port_get_child(port_dev);
 	if (udev && udev->do_remote_wakeup)
 		reason = "wakeup enabled";

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux