Before we add another 2 bitfields to the port state, convert it to an
unsigned long and use bitops helpers to manipulate it.  This later
enables setting bits to request action without worrying about colliding
updates.  In particular, a flag to request that the child device be
woken up when the port restores power is added in a later patch.

Signed-off-by: Dan Williams <dan.j.willi...@intel.com>
---
 drivers/usb/core/hub.c  |   26 +++++++++++++++-----------
 drivers/usb/core/hub.h  |    8 ++++----
 drivers/usb/core/port.c |    2 +-
 3 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 783acfca6c51..5ab8ce870f5b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -758,9 +758,14 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct 
usb_hub *hub,
        else
                ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
 
-       if (!ret)
-               port_dev->power_is_on = set;
-       return ret;
+       if (ret)
+               return ret;
+
+       if (set)
+               set_bit(USB_PORTDEV_POWER, &port_dev->flags);
+       else
+               clear_bit(USB_PORTDEV_POWER, &port_dev->flags);
+       return 0;
 }
 
 /**
@@ -839,7 +844,7 @@ static unsigned hub_power_on(struct usb_hub *hub, bool 
do_delay)
                dev_dbg(hub->intfdev, "trying to enable port power on "
                                "non-switchable hub\n");
        for (port1 = 1; port1 <= hub->hdev->maxchild; port1++)
-               if (hub->ports[port1 - 1]->power_is_on)
+               if (test_bit(USB_PORTDEV_POWER, &hub->ports[port1 - 1]->flags))
                        set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
                else
                        usb_clear_port_feature(hub->hdev, port1,
@@ -1188,7 +1193,7 @@ static void hub_activate(struct usb_hub *hub, enum 
hub_activation_type type)
                        /* Don't set the change_bits when the device
                         * was powered off.
                         */
-                       if (port_dev->power_is_on)
+                       if (test_bit(USB_PORTDEV_POWER, &port_dev->flags))
                                set_bit(port1, hub->change_bits);
 
                } else {
@@ -2090,10 +2095,10 @@ void usb_disconnect(struct usb_device **pdev)
                sysfs_remove_link(&udev->dev.kobj, "port");
                sysfs_remove_link(&port_dev->dev.kobj, "device");
 
-               if (!port_dev->did_runtime_put)
+               /* if we didn't do it at "runtime" we need to do it now */
+               if (!test_and_clear_bit(USB_PORTDEV_DID_RUNTIME_PUT,
+                                       &port_dev->flags))
                        pm_runtime_put(&port_dev->dev);
-               else
-                       port_dev->did_runtime_put = false;
        }
 
        usb_remove_ep_devs(&udev->ep0);
@@ -3090,7 +3095,7 @@ int usb_port_suspend(struct usb_device *udev, 
pm_message_t msg)
 
        if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
                pm_runtime_put_sync(&port_dev->dev);
-               port_dev->did_runtime_put = true;
+               set_bit(USB_PORTDEV_DID_RUNTIME_PUT, &port_dev->flags);
        }
 
        usb_mark_last_busy(hub->hdev);
@@ -3233,9 +3238,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t 
msg)
        int             status;
        u16             portchange, portstatus;
 
-       if (port_dev->did_runtime_put) {
+       if (test_and_clear_bit(USB_PORTDEV_DID_RUNTIME_PUT, &port_dev->flags)) {
                status = pm_runtime_get_sync(&port_dev->dev);
-               port_dev->did_runtime_put = false;
                if (status < 0) {
                        dev_dbg(&udev->dev, "can't resume usb port, status 
%d\n",
                                        status);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 0d8c5b0cdf09..fabf05ea3de6 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -85,8 +85,7 @@ struct usb_hub {
  * @connect_type: port's connect type
  * @location: opaque representation of platform connector location
  * @portnum: port index num based one
- * @power_is_on: port's power state
- * @did_runtime_put: port has done pm_runtime_put().
+ * @flags: operational state, and requests
  */
 struct usb_port {
        struct usb_device *child;
@@ -96,8 +95,9 @@ struct usb_port {
        enum usb_port_connect_type connect_type;
        usb_port_location_t location;
        u8 portnum;
-       unsigned power_is_on:1;
-       unsigned did_runtime_put:1;
+       #define USB_PORTDEV_POWER 0
+       #define USB_PORTDEV_DID_RUNTIME_PUT 1
+       unsigned long flags;
 };
 
 #define to_usb_port(_dev) \
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index b7f5225cee2b..99de5acb1240 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -314,7 +314,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int 
port1)
 
        hub->ports[port1 - 1] = port_dev;
        port_dev->portnum = port1;
-       port_dev->power_is_on = true;
+       set_bit(USB_PORTDEV_POWER, &port_dev->flags);
        port_dev->dev.parent = hub->intfdev;
        port_dev->dev.groups = port_dev_group;
        port_dev->dev.type = &usb_port_device_type;

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

Reply via email to