aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/devio.c11
-rw-r--r--drivers/usb/core/generic.c7
-rw-r--r--drivers/usb/core/message.c10
-rw-r--r--drivers/usb/usb-skeleton.c11
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;