aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2014-05-20 21:08:52 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 19:38:53 -0400
commitd5c3834e4af3acc4d7fc52faba2711c666655632 (patch)
tree78f1249a5347f81e8250fd8f26261f98fd024ccc
parentb7e38eac88265c4cb779edc72a5906116fc6c000 (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>
-rw-r--r--drivers/usb/core/hub.c39
-rw-r--r--drivers/usb/core/hub.h7
-rw-r--r--drivers/usb/core/port.c4
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 */
92struct usb_port { 93struct 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;