[RFC PATCH V2 1/2] usb: usb port power off mechanism add "auto" option

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

 



This patch is to add "auto" option to attribute portX/control.
When echo "auto", the port's feature PORT_POWER would be clear
if the port's connect type was mark not-used(connectability and
visibility are both cleared) and with no device attached.

Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx>
---
This patchset is based on the following patchset
http://marc.info/?l=linux-usb&m=134517695007182&w=2
      usb: make usb port a real device
      usb: move children to struct usb_port
      usb/acpi: Bind ACPI node to USB port, not usb_device.
      usb/acpi: Store info on device removability.
      xhci: Handle clear PORT_POWER feature.
      usb/acpi: Use ACPI methods to power off ports.
      usb: Fail a get config when the port is powered off.
      usb : Add sysfs files to control port power.

v2: add "auto" option process in the hub_power_on()
---
 drivers/usb/core/hub.c |   35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3def91e..07c62dd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -42,6 +42,7 @@
 enum port_power_policy {
 	USB_PORT_POWER_ON = 0,
 	USB_PORT_POWER_OFF,
+	USB_PORT_POWER_AUTO,
 };
 
 struct usb_port {
@@ -101,6 +102,7 @@ struct usb_hub {
 
 static const char on_string[] = "on";
 static const char off_string[] = "off";
+static const char auto_string[] = "auto";
 static const struct attribute_group *port_dev_group[];
 
 static inline int hub_is_superspeed(struct usb_device *hdev)
@@ -842,6 +844,7 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
 	unsigned delay;
 	u16 wHubCharacteristics =
 			le16_to_cpu(hub->descriptor->wHubCharacteristics);
+	struct usb_port *pport;
 
 	/* Enable power on each port.  Some hubs have reserved values
 	 * of LPSM (> 2) in their descriptors, even though they are
@@ -854,13 +857,18 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
 	else
 		dev_dbg(hub->intfdev, "trying to enable port power on "
 				"non-switchable hub\n");
-	for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
-		if (hub->ports[port1 - 1]->port_power_policy
-				== USB_PORT_POWER_ON)
-			set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
-		else
+	for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) {
+		pport = hub->ports[port1 - 1];
+
+		if (pport->port_power_policy == USB_PORT_POWER_OFF ||
+				(pport->port_power_policy == USB_PORT_POWER_AUTO
+				 && pport->connect_type == USB_PORT_NOT_USED
+				 && !pport->child))
 			clear_port_feature(hub->hdev, port1,
-					USB_PORT_FEAT_POWER);
+				USB_PORT_FEAT_POWER);
+		else
+			set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
+	}
 
 	/* Wait at least 100 msec for power to become stable */
 	delay = max(pgood_delay, (unsigned) 100);
@@ -4703,6 +4711,9 @@ static ssize_t show_port_power_control(struct device *dev,
 	case USB_PORT_POWER_OFF:
 		result = off_string;
 		break;
+	case USB_PORT_POWER_AUTO:
+		result = auto_string;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -4741,6 +4752,18 @@ static ssize_t store_port_power_control(struct device *dev,
 		usb_autopm_put_interface(intf);
 		if (ret < 0)
 			return -EIO;
+	} else if (len == sizeof(auto_string) - 1
+			&& strncmp(buf, auto_string, len) == 0) {
+		hub_port->port_power_policy = USB_PORT_POWER_AUTO;
+		if (hub_port->connect_type
+				== USB_PORT_NOT_USED && !hub_port->child) {
+			usb_autopm_get_interface(intf);
+			ret = clear_port_feature(hdev, port1,
+				USB_PORT_FEAT_POWER);
+			usb_autopm_put_interface(intf);
+			if (ret < 0)
+				return -EIO;
+		}
 	} else
 		return -EINVAL;
 
-- 
1.7.9.5

--
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