diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-08-30 15:47:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:57 -0400 |
commit | 01d883d44a1ca8dc77486635d428cba63e7fdadf (patch) | |
tree | 447a4293b2ec4dfa1b3d03a46a3a33498809f0e8 /drivers | |
parent | 645daaab0b6adc35c1838df2a82f9d729fdb1767 (diff) |
usbcore: non-hub-specific uses of autosuspend
This patch (as741) makes the non-hub parts of usbcore actually use the
autosuspend facilities added by an earlier patch.
Devices opened through usbfs are autoresumed and then
autosuspended upon close.
Likewise for usb-skeleton.
Devices are autoresumed for usb_set_configuration.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/devio.c | 11 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 7 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 10 | ||||
-rw-r--r-- | drivers/usb/usb-skeleton.c | 11 |
4 files changed, 28 insertions, 11 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 43c08724a2d8..fd345ad810f8 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -558,10 +558,12 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
558 | dev = usbdev_lookup_minor(iminor(inode)); | 558 | dev = usbdev_lookup_minor(iminor(inode)); |
559 | if (!dev) | 559 | if (!dev) |
560 | dev = inode->i_private; | 560 | dev = inode->i_private; |
561 | if (!dev) { | 561 | if (!dev) |
562 | kfree(ps); | ||
563 | goto out; | 562 | goto out; |
564 | } | 563 | ret = usb_autoresume_device(dev, 1); |
564 | if (ret) | ||
565 | goto out; | ||
566 | |||
565 | usb_get_dev(dev); | 567 | usb_get_dev(dev); |
566 | ret = 0; | 568 | ret = 0; |
567 | ps->dev = dev; | 569 | ps->dev = dev; |
@@ -581,6 +583,8 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
581 | list_add_tail(&ps->list, &dev->filelist); | 583 | list_add_tail(&ps->list, &dev->filelist); |
582 | file->private_data = ps; | 584 | file->private_data = ps; |
583 | out: | 585 | out: |
586 | if (ret) | ||
587 | kfree(ps); | ||
584 | mutex_unlock(&usbfs_mutex); | 588 | mutex_unlock(&usbfs_mutex); |
585 | return ret; | 589 | return ret; |
586 | } | 590 | } |
@@ -604,6 +608,7 @@ static int usbdev_release(struct inode *inode, struct file *file) | |||
604 | releaseintf(ps, ifnum); | 608 | releaseintf(ps, ifnum); |
605 | } | 609 | } |
606 | destroy_all_async(ps); | 610 | destroy_all_async(ps); |
611 | usb_autosuspend_device(dev, 1); | ||
607 | usb_unlock_device(dev); | 612 | usb_unlock_device(dev); |
608 | usb_put_dev(dev); | 613 | usb_put_dev(dev); |
609 | kfree(ps); | 614 | kfree(ps); |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 5358e656477c..16332cc57946 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -172,14 +172,10 @@ static void generic_disconnect(struct usb_device *udev) | |||
172 | 172 | ||
173 | /* if this is only an unbind, not a physical disconnect, then | 173 | /* if this is only an unbind, not a physical disconnect, then |
174 | * unconfigure the device */ | 174 | * unconfigure the device */ |
175 | if (udev->state == USB_STATE_CONFIGURED) | 175 | if (udev->actconfig) |
176 | usb_set_configuration(udev, 0); | 176 | usb_set_configuration(udev, 0); |
177 | 177 | ||
178 | usb_remove_sysfs_dev_files(udev); | 178 | usb_remove_sysfs_dev_files(udev); |
179 | |||
180 | /* in case the call failed or the device was suspended */ | ||
181 | if (udev->state >= USB_STATE_CONFIGURED) | ||
182 | usb_disable_device(udev, 0); | ||
183 | } | 179 | } |
184 | 180 | ||
185 | #ifdef CONFIG_PM | 181 | #ifdef CONFIG_PM |
@@ -208,4 +204,5 @@ struct usb_device_driver usb_generic_driver = { | |||
208 | .suspend = generic_suspend, | 204 | .suspend = generic_suspend, |
209 | .resume = generic_resume, | 205 | .resume = generic_resume, |
210 | #endif | 206 | #endif |
207 | .supports_autosuspend = 1, | ||
211 | }; | 208 | }; |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 1580c81a0db7..28c6cf225780 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -1366,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) | |||
1366 | if (cp && configuration == 0) | 1366 | if (cp && configuration == 0) |
1367 | dev_warn(&dev->dev, "config 0 descriptor??\n"); | 1367 | dev_warn(&dev->dev, "config 0 descriptor??\n"); |
1368 | 1368 | ||
1369 | if (dev->state == USB_STATE_SUSPENDED) | ||
1370 | return -EHOSTUNREACH; | ||
1371 | |||
1372 | /* Allocate memory for new interfaces before doing anything else, | 1369 | /* Allocate memory for new interfaces before doing anything else, |
1373 | * so that if we run out then nothing will have changed. */ | 1370 | * so that if we run out then nothing will have changed. */ |
1374 | n = nintf = 0; | 1371 | n = nintf = 0; |
@@ -1403,6 +1400,11 @@ free_interfaces: | |||
1403 | configuration, -i); | 1400 | configuration, -i); |
1404 | } | 1401 | } |
1405 | 1402 | ||
1403 | /* Wake up the device so we can send it the Set-Config request */ | ||
1404 | ret = usb_autoresume_device(dev, 1); | ||
1405 | if (ret) | ||
1406 | goto free_interfaces; | ||
1407 | |||
1406 | /* if it's already configured, clear out old state first. | 1408 | /* if it's already configured, clear out old state first. |
1407 | * getting rid of old interfaces means unbinding their drivers. | 1409 | * getting rid of old interfaces means unbinding their drivers. |
1408 | */ | 1410 | */ |
@@ -1422,6 +1424,7 @@ free_interfaces: | |||
1422 | dev->actconfig = cp; | 1424 | dev->actconfig = cp; |
1423 | if (!cp) { | 1425 | if (!cp) { |
1424 | usb_set_device_state(dev, USB_STATE_ADDRESS); | 1426 | usb_set_device_state(dev, USB_STATE_ADDRESS); |
1427 | usb_autosuspend_device(dev, 1); | ||
1425 | goto free_interfaces; | 1428 | goto free_interfaces; |
1426 | } | 1429 | } |
1427 | usb_set_device_state(dev, USB_STATE_CONFIGURED); | 1430 | usb_set_device_state(dev, USB_STATE_CONFIGURED); |
@@ -1490,6 +1493,7 @@ free_interfaces: | |||
1490 | usb_create_sysfs_intf_files (intf); | 1493 | usb_create_sysfs_intf_files (intf); |
1491 | } | 1494 | } |
1492 | 1495 | ||
1496 | usb_autosuspend_device(dev, 1); | ||
1493 | return 0; | 1497 | return 0; |
1494 | } | 1498 | } |
1495 | 1499 | ||
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 9b542a6ba978..1b51d3187a95 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -90,6 +90,11 @@ static int skel_open(struct inode *inode, struct file *file) | |||
90 | goto exit; | 90 | goto exit; |
91 | } | 91 | } |
92 | 92 | ||
93 | /* prevent the device from being autosuspended */ | ||
94 | retval = usb_autopm_get_interface(interface); | ||
95 | if (retval) | ||
96 | goto exit; | ||
97 | |||
93 | /* increment our usage count for the device */ | 98 | /* increment our usage count for the device */ |
94 | kref_get(&dev->kref); | 99 | kref_get(&dev->kref); |
95 | 100 | ||
@@ -108,6 +113,12 @@ static int skel_release(struct inode *inode, struct file *file) | |||
108 | if (dev == NULL) | 113 | if (dev == NULL) |
109 | return -ENODEV; | 114 | return -ENODEV; |
110 | 115 | ||
116 | /* allow the device to be autosuspended */ | ||
117 | mutex_lock(&dev->io_mutex); | ||
118 | if (dev->interface) | ||
119 | usb_autopm_put_interface(dev->interface); | ||
120 | mutex_unlock(&dev->io_mutex); | ||
121 | |||
111 | /* decrement the count on our device */ | 122 | /* decrement the count on our device */ |
112 | kref_put(&dev->kref, skel_delete); | 123 | kref_put(&dev->kref, skel_delete); |
113 | return 0; | 124 | return 0; |