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.williams@xxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html