diff options
author | Dan Williams <dan.j.williams@intel.com> | 2014-05-20 21:08:52 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-27 19:38:53 -0400 |
commit | d5c3834e4af3acc4d7fc52faba2711c666655632 (patch) | |
tree | 78f1249a5347f81e8250fd8f26261f98fd024ccc /drivers/usb | |
parent | b7e38eac88265c4cb779edc72a5906116fc6c000 (diff) |
usb: make usb_port flags atomic, rename did_runtime_put to child_usage
We want to manipulate ->did_runtime_put in usb_port_runtime_resume(),
but we don't want that to collide with other updates. Move usb_port
flags to new port-bitmap fields in usb_hub. "did_runtime_put" is renamed
"child_usage_bits" to reflect that it is strictly standing in for the
fact that usb_devices are not the device_model children of their parent
port.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 39 | ||||
-rw-r--r-- | drivers/usb/core/hub.h | 7 | ||||
-rw-r--r-- | drivers/usb/core/port.c | 4 |
3 files changed, 25 insertions, 25 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5a909ba6fb67..31a492a4a881 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -751,16 +751,20 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, | |||
751 | int port1, bool set) | 751 | int port1, bool set) |
752 | { | 752 | { |
753 | int ret; | 753 | int ret; |
754 | struct usb_port *port_dev = hub->ports[port1 - 1]; | ||
755 | 754 | ||
756 | if (set) | 755 | if (set) |
757 | ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); | 756 | ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); |
758 | else | 757 | else |
759 | ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); | 758 | ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); |
760 | 759 | ||
761 | if (!ret) | 760 | if (ret) |
762 | port_dev->power_is_on = set; | 761 | return ret; |
763 | return ret; | 762 | |
763 | if (set) | ||
764 | set_bit(port1, hub->power_bits); | ||
765 | else | ||
766 | clear_bit(port1, hub->power_bits); | ||
767 | return 0; | ||
764 | } | 768 | } |
765 | 769 | ||
766 | /** | 770 | /** |
@@ -839,7 +843,7 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) | |||
839 | dev_dbg(hub->intfdev, "trying to enable port power on " | 843 | dev_dbg(hub->intfdev, "trying to enable port power on " |
840 | "non-switchable hub\n"); | 844 | "non-switchable hub\n"); |
841 | for (port1 = 1; port1 <= hub->hdev->maxchild; port1++) | 845 | for (port1 = 1; port1 <= hub->hdev->maxchild; port1++) |
842 | if (hub->ports[port1 - 1]->power_is_on) | 846 | if (test_bit(port1, hub->power_bits)) |
843 | set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); | 847 | set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); |
844 | else | 848 | else |
845 | usb_clear_port_feature(hub->hdev, port1, | 849 | usb_clear_port_feature(hub->hdev, port1, |
@@ -1180,15 +1184,13 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1180 | set_bit(port1, hub->change_bits); | 1184 | set_bit(port1, hub->change_bits); |
1181 | 1185 | ||
1182 | } else if (udev->persist_enabled) { | 1186 | } else if (udev->persist_enabled) { |
1183 | struct usb_port *port_dev = hub->ports[port1 - 1]; | ||
1184 | |||
1185 | #ifdef CONFIG_PM | 1187 | #ifdef CONFIG_PM |
1186 | udev->reset_resume = 1; | 1188 | udev->reset_resume = 1; |
1187 | #endif | 1189 | #endif |
1188 | /* Don't set the change_bits when the device | 1190 | /* Don't set the change_bits when the device |
1189 | * was powered off. | 1191 | * was powered off. |
1190 | */ | 1192 | */ |
1191 | if (port_dev->power_is_on) | 1193 | if (test_bit(port1, hub->power_bits)) |
1192 | set_bit(port1, hub->change_bits); | 1194 | set_bit(port1, hub->change_bits); |
1193 | 1195 | ||
1194 | } else { | 1196 | } else { |
@@ -2096,16 +2098,15 @@ void usb_disconnect(struct usb_device **pdev) | |||
2096 | usb_hcd_synchronize_unlinks(udev); | 2098 | usb_hcd_synchronize_unlinks(udev); |
2097 | 2099 | ||
2098 | if (udev->parent) { | 2100 | if (udev->parent) { |
2101 | int port1 = udev->portnum; | ||
2099 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); | 2102 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); |
2100 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; | 2103 | struct usb_port *port_dev = hub->ports[port1 - 1]; |
2101 | 2104 | ||
2102 | sysfs_remove_link(&udev->dev.kobj, "port"); | 2105 | sysfs_remove_link(&udev->dev.kobj, "port"); |
2103 | sysfs_remove_link(&port_dev->dev.kobj, "device"); | 2106 | sysfs_remove_link(&port_dev->dev.kobj, "device"); |
2104 | 2107 | ||
2105 | if (!port_dev->did_runtime_put) | 2108 | if (test_and_clear_bit(port1, hub->child_usage_bits)) |
2106 | pm_runtime_put(&port_dev->dev); | 2109 | pm_runtime_put(&port_dev->dev); |
2107 | else | ||
2108 | port_dev->did_runtime_put = false; | ||
2109 | } | 2110 | } |
2110 | 2111 | ||
2111 | usb_remove_ep_devs(&udev->ep0); | 2112 | usb_remove_ep_devs(&udev->ep0); |
@@ -2416,7 +2417,8 @@ int usb_new_device(struct usb_device *udev) | |||
2416 | /* Create link files between child device and usb port device. */ | 2417 | /* Create link files between child device and usb port device. */ |
2417 | if (udev->parent) { | 2418 | if (udev->parent) { |
2418 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); | 2419 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); |
2419 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; | 2420 | int port1 = udev->portnum; |
2421 | struct usb_port *port_dev = hub->ports[port1 - 1]; | ||
2420 | 2422 | ||
2421 | err = sysfs_create_link(&udev->dev.kobj, | 2423 | err = sysfs_create_link(&udev->dev.kobj, |
2422 | &port_dev->dev.kobj, "port"); | 2424 | &port_dev->dev.kobj, "port"); |
@@ -2430,7 +2432,8 @@ int usb_new_device(struct usb_device *udev) | |||
2430 | goto fail; | 2432 | goto fail; |
2431 | } | 2433 | } |
2432 | 2434 | ||
2433 | pm_runtime_get_sync(&port_dev->dev); | 2435 | if (!test_and_set_bit(port1, hub->child_usage_bits)) |
2436 | pm_runtime_get_sync(&port_dev->dev); | ||
2434 | } | 2437 | } |
2435 | 2438 | ||
2436 | (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); | 2439 | (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); |
@@ -3100,10 +3103,9 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
3100 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | 3103 | usb_set_device_state(udev, USB_STATE_SUSPENDED); |
3101 | } | 3104 | } |
3102 | 3105 | ||
3103 | if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) { | 3106 | if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled |
3107 | && test_and_clear_bit(port1, hub->child_usage_bits)) | ||
3104 | pm_runtime_put_sync(&port_dev->dev); | 3108 | pm_runtime_put_sync(&port_dev->dev); |
3105 | port_dev->did_runtime_put = true; | ||
3106 | } | ||
3107 | 3109 | ||
3108 | usb_mark_last_busy(hub->hdev); | 3110 | usb_mark_last_busy(hub->hdev); |
3109 | return status; | 3111 | return status; |
@@ -3245,9 +3247,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
3245 | int status; | 3247 | int status; |
3246 | u16 portchange, portstatus; | 3248 | u16 portchange, portstatus; |
3247 | 3249 | ||
3248 | if (port_dev->did_runtime_put) { | 3250 | if (!test_and_set_bit(port1, hub->child_usage_bits)) { |
3249 | status = pm_runtime_get_sync(&port_dev->dev); | 3251 | status = pm_runtime_get_sync(&port_dev->dev); |
3250 | port_dev->did_runtime_put = false; | ||
3251 | if (status < 0) { | 3252 | if (status < 0) { |
3252 | dev_dbg(&udev->dev, "can't resume usb port, status %d\n", | 3253 | dev_dbg(&udev->dev, "can't resume usb port, status %d\n", |
3253 | status); | 3254 | status); |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 048c797f394c..3ef1c2e435cc 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -51,6 +51,9 @@ struct usb_hub { | |||
51 | device present */ | 51 | device present */ |
52 | unsigned long wakeup_bits[1]; /* ports that have signaled | 52 | unsigned long wakeup_bits[1]; /* ports that have signaled |
53 | remote wakeup */ | 53 | remote wakeup */ |
54 | unsigned long power_bits[1]; /* ports that are powered */ | ||
55 | unsigned long child_usage_bits[1]; /* ports powered on for | ||
56 | children */ | ||
54 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ | 57 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ |
55 | #error event_bits[] is too short! | 58 | #error event_bits[] is too short! |
56 | #endif | 59 | #endif |
@@ -86,8 +89,6 @@ struct usb_hub { | |||
86 | * @connect_type: port's connect type | 89 | * @connect_type: port's connect type |
87 | * @location: opaque representation of platform connector location | 90 | * @location: opaque representation of platform connector location |
88 | * @portnum: port index num based one | 91 | * @portnum: port index num based one |
89 | * @power_is_on: port's power state | ||
90 | * @did_runtime_put: port has done pm_runtime_put(). | ||
91 | */ | 92 | */ |
92 | struct usb_port { | 93 | struct usb_port { |
93 | struct usb_device *child; | 94 | struct usb_device *child; |
@@ -97,8 +98,6 @@ struct usb_port { | |||
97 | enum usb_port_connect_type connect_type; | 98 | enum usb_port_connect_type connect_type; |
98 | usb_port_location_t location; | 99 | usb_port_location_t location; |
99 | u8 portnum; | 100 | u8 portnum; |
100 | unsigned power_is_on:1; | ||
101 | unsigned did_runtime_put:1; | ||
102 | }; | 101 | }; |
103 | 102 | ||
104 | #define to_usb_port(_dev) \ | 103 | #define to_usb_port(_dev) \ |
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 40c3ac173e9e..795778c71e31 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
@@ -82,7 +82,7 @@ static int usb_port_runtime_resume(struct device *dev) | |||
82 | if (!hub) | 82 | if (!hub) |
83 | return -EINVAL; | 83 | return -EINVAL; |
84 | if (hub->in_reset) { | 84 | if (hub->in_reset) { |
85 | port_dev->power_is_on = 1; | 85 | set_bit(port1, hub->power_bits); |
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
@@ -320,7 +320,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) | |||
320 | 320 | ||
321 | hub->ports[port1 - 1] = port_dev; | 321 | hub->ports[port1 - 1] = port_dev; |
322 | port_dev->portnum = port1; | 322 | port_dev->portnum = port1; |
323 | port_dev->power_is_on = true; | 323 | set_bit(port1, hub->power_bits); |
324 | port_dev->dev.parent = hub->intfdev; | 324 | port_dev->dev.parent = hub->intfdev; |
325 | port_dev->dev.groups = port_dev_group; | 325 | port_dev->dev.groups = port_dev_group; |
326 | port_dev->dev.type = &usb_port_device_type; | 326 | port_dev->dev.type = &usb_port_device_type; |