diff options
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/devio.c | 20 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 2 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 117 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.h | 1 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 6 | ||||
| -rw-r--r-- | drivers/usb/core/inode.c | 1 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 40 | ||||
| -rw-r--r-- | drivers/usb/core/usb.h | 6 |
8 files changed, 70 insertions, 123 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 26fece124e0e..7513bb083c15 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -1700,7 +1700,7 @@ const struct file_operations usbdev_file_operations = { | |||
| 1700 | .release = usbdev_release, | 1700 | .release = usbdev_release, |
| 1701 | }; | 1701 | }; |
| 1702 | 1702 | ||
| 1703 | void usb_fs_classdev_common_remove(struct usb_device *udev) | 1703 | static void usbdev_remove(struct usb_device *udev) |
| 1704 | { | 1704 | { |
| 1705 | struct dev_state *ps; | 1705 | struct dev_state *ps; |
| 1706 | struct siginfo sinfo; | 1706 | struct siginfo sinfo; |
| @@ -1742,10 +1742,15 @@ static void usb_classdev_remove(struct usb_device *dev) | |||
| 1742 | { | 1742 | { |
| 1743 | if (dev->usb_classdev) | 1743 | if (dev->usb_classdev) |
| 1744 | device_unregister(dev->usb_classdev); | 1744 | device_unregister(dev->usb_classdev); |
| 1745 | usb_fs_classdev_common_remove(dev); | ||
| 1746 | } | 1745 | } |
| 1747 | 1746 | ||
| 1748 | static int usb_classdev_notify(struct notifier_block *self, | 1747 | #else |
| 1748 | #define usb_classdev_add(dev) 0 | ||
| 1749 | #define usb_classdev_remove(dev) do {} while (0) | ||
| 1750 | |||
| 1751 | #endif | ||
| 1752 | |||
| 1753 | static int usbdev_notify(struct notifier_block *self, | ||
| 1749 | unsigned long action, void *dev) | 1754 | unsigned long action, void *dev) |
| 1750 | { | 1755 | { |
| 1751 | switch (action) { | 1756 | switch (action) { |
| @@ -1755,15 +1760,15 @@ static int usb_classdev_notify(struct notifier_block *self, | |||
| 1755 | break; | 1760 | break; |
| 1756 | case USB_DEVICE_REMOVE: | 1761 | case USB_DEVICE_REMOVE: |
| 1757 | usb_classdev_remove(dev); | 1762 | usb_classdev_remove(dev); |
| 1763 | usbdev_remove(dev); | ||
| 1758 | break; | 1764 | break; |
| 1759 | } | 1765 | } |
| 1760 | return NOTIFY_OK; | 1766 | return NOTIFY_OK; |
| 1761 | } | 1767 | } |
| 1762 | 1768 | ||
| 1763 | static struct notifier_block usbdev_nb = { | 1769 | static struct notifier_block usbdev_nb = { |
| 1764 | .notifier_call = usb_classdev_notify, | 1770 | .notifier_call = usbdev_notify, |
| 1765 | }; | 1771 | }; |
| 1766 | #endif | ||
| 1767 | 1772 | ||
| 1768 | static struct cdev usb_device_cdev; | 1773 | static struct cdev usb_device_cdev; |
| 1769 | 1774 | ||
| @@ -1798,9 +1803,8 @@ int __init usb_devio_init(void) | |||
| 1798 | * to /sys/dev | 1803 | * to /sys/dev |
| 1799 | */ | 1804 | */ |
| 1800 | usb_classdev_class->dev_kobj = NULL; | 1805 | usb_classdev_class->dev_kobj = NULL; |
| 1801 | |||
| 1802 | usb_register_notify(&usbdev_nb); | ||
| 1803 | #endif | 1806 | #endif |
| 1807 | usb_register_notify(&usbdev_nb); | ||
| 1804 | out: | 1808 | out: |
| 1805 | return retval; | 1809 | return retval; |
| 1806 | 1810 | ||
| @@ -1811,8 +1815,8 @@ error_cdev: | |||
| 1811 | 1815 | ||
| 1812 | void usb_devio_cleanup(void) | 1816 | void usb_devio_cleanup(void) |
| 1813 | { | 1817 | { |
| 1814 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
| 1815 | usb_unregister_notify(&usbdev_nb); | 1818 | usb_unregister_notify(&usbdev_nb); |
| 1819 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
| 1816 | class_destroy(usb_classdev_class); | 1820 | class_destroy(usb_classdev_class); |
| 1817 | #endif | 1821 | #endif |
| 1818 | cdev_del(&usb_device_cdev); | 1822 | cdev_del(&usb_device_cdev); |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 98760553bc95..d0a21a5f8201 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
| @@ -284,7 +284,7 @@ static int usb_unbind_interface(struct device *dev) | |||
| 284 | * supports "soft" unbinding. | 284 | * supports "soft" unbinding. |
| 285 | */ | 285 | */ |
| 286 | if (!driver->soft_unbind) | 286 | if (!driver->soft_unbind) |
| 287 | usb_disable_interface(udev, intf); | 287 | usb_disable_interface(udev, intf, false); |
| 288 | 288 | ||
| 289 | driver->disconnect(intf); | 289 | driver->disconnect(intf); |
| 290 | usb_cancel_queued_reset(intf); | 290 | usb_cancel_queued_reset(intf); |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 507741ed4482..c54fc40458b1 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
| @@ -128,7 +128,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | pci_set_master(dev); | 130 | pci_set_master(dev); |
| 131 | device_set_wakeup_enable(&dev->dev, 1); | ||
| 132 | 131 | ||
| 133 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | 132 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); |
| 134 | if (retval != 0) | 133 | if (retval != 0) |
| @@ -201,6 +200,7 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
| 201 | struct usb_hcd *hcd = pci_get_drvdata(dev); | 200 | struct usb_hcd *hcd = pci_get_drvdata(dev); |
| 202 | int retval = 0; | 201 | int retval = 0; |
| 203 | int wake, w; | 202 | int wake, w; |
| 203 | int has_pci_pm; | ||
| 204 | 204 | ||
| 205 | /* Root hub suspend should have stopped all downstream traffic, | 205 | /* Root hub suspend should have stopped all downstream traffic, |
| 206 | * and all bus master traffic. And done so for both the interface | 206 | * and all bus master traffic. And done so for both the interface |
| @@ -230,6 +230,15 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
| 230 | 230 | ||
| 231 | synchronize_irq(dev->irq); | 231 | synchronize_irq(dev->irq); |
| 232 | 232 | ||
| 233 | /* Downstream ports from this root hub should already be quiesced, so | ||
| 234 | * there will be no DMA activity. Now we can shut down the upstream | ||
| 235 | * link (except maybe for PME# resume signaling) and enter some PCI | ||
| 236 | * low power state, if the hardware allows. | ||
| 237 | */ | ||
| 238 | pci_disable_device(dev); | ||
| 239 | |||
| 240 | pci_save_state(dev); | ||
| 241 | |||
| 233 | /* Don't fail on error to enable wakeup. We rely on pci code | 242 | /* Don't fail on error to enable wakeup. We rely on pci code |
| 234 | * to reject requests the hardware can't implement, rather | 243 | * to reject requests the hardware can't implement, rather |
| 235 | * than coding the same thing. | 244 | * than coding the same thing. |
| @@ -241,35 +250,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
| 241 | wake = w; | 250 | wake = w; |
| 242 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); | 251 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); |
| 243 | 252 | ||
| 244 | /* Downstream ports from this root hub should already be quiesced, so | ||
| 245 | * there will be no DMA activity. Now we can shut down the upstream | ||
| 246 | * link (except maybe for PME# resume signaling) and enter some PCI | ||
| 247 | * low power state, if the hardware allows. | ||
| 248 | */ | ||
| 249 | pci_disable_device(dev); | ||
| 250 | done: | ||
| 251 | return retval; | ||
| 252 | } | ||
| 253 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); | ||
| 254 | |||
| 255 | /** | ||
| 256 | * usb_hcd_pci_suspend_late - suspend a PCI-based HCD after IRQs are disabled | ||
| 257 | * @dev: USB Host Controller being suspended | ||
| 258 | * @message: Power Management message describing this state transition | ||
| 259 | * | ||
| 260 | * Store this function in the HCD's struct pci_driver as .suspend_late. | ||
| 261 | */ | ||
| 262 | int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | ||
| 263 | { | ||
| 264 | int retval = 0; | ||
| 265 | int has_pci_pm; | ||
| 266 | |||
| 267 | /* We might already be suspended (runtime PM -- not yet written) */ | ||
| 268 | if (dev->current_state != PCI_D0) | ||
| 269 | goto done; | ||
| 270 | |||
| 271 | pci_save_state(dev); | ||
| 272 | |||
| 273 | /* Don't change state if we don't need to */ | 253 | /* Don't change state if we don't need to */ |
| 274 | if (message.event == PM_EVENT_FREEZE || | 254 | if (message.event == PM_EVENT_FREEZE || |
| 275 | message.event == PM_EVENT_PRETHAW) { | 255 | message.event == PM_EVENT_PRETHAW) { |
| @@ -315,7 +295,7 @@ int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | |||
| 315 | done: | 295 | done: |
| 316 | return retval; | 296 | return retval; |
| 317 | } | 297 | } |
| 318 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); | 298 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); |
| 319 | 299 | ||
| 320 | /** | 300 | /** |
| 321 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled | 301 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled |
| @@ -325,65 +305,8 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); | |||
| 325 | */ | 305 | */ |
| 326 | int usb_hcd_pci_resume_early(struct pci_dev *dev) | 306 | int usb_hcd_pci_resume_early(struct pci_dev *dev) |
| 327 | { | 307 | { |
| 328 | int retval = 0; | 308 | pci_restore_state(dev); |
| 329 | pci_power_t state = dev->current_state; | 309 | return 0; |
| 330 | |||
| 331 | #ifdef CONFIG_PPC_PMAC | ||
| 332 | /* Reenable ASIC clocks for USB */ | ||
| 333 | if (machine_is(powermac)) { | ||
| 334 | struct device_node *of_node; | ||
| 335 | |||
| 336 | of_node = pci_device_to_OF_node(dev); | ||
| 337 | if (of_node) | ||
| 338 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
| 339 | of_node, 0, 1); | ||
| 340 | } | ||
| 341 | #endif | ||
| 342 | |||
| 343 | /* NOTE: chip docs cover clean "real suspend" cases (what Linux | ||
| 344 | * calls "standby", "suspend to RAM", and so on). There are also | ||
| 345 | * dirty cases when swsusp fakes a suspend in "shutdown" mode. | ||
| 346 | */ | ||
| 347 | if (state != PCI_D0) { | ||
| 348 | #ifdef DEBUG | ||
| 349 | int pci_pm; | ||
| 350 | u16 pmcr; | ||
| 351 | |||
| 352 | pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
| 353 | pci_read_config_word(dev, pci_pm + PCI_PM_CTRL, &pmcr); | ||
| 354 | pmcr &= PCI_PM_CTRL_STATE_MASK; | ||
| 355 | if (pmcr) { | ||
| 356 | /* Clean case: power to USB and to HC registers was | ||
| 357 | * maintained; remote wakeup is easy. | ||
| 358 | */ | ||
| 359 | dev_dbg(&dev->dev, "resume from PCI D%d\n", pmcr); | ||
| 360 | } else { | ||
| 361 | /* Clean: HC lost Vcc power, D0 uninitialized | ||
| 362 | * + Vaux may have preserved port and transceiver | ||
| 363 | * state ... for remote wakeup from D3cold | ||
| 364 | * + or not; HCD must reinit + re-enumerate | ||
| 365 | * | ||
| 366 | * Dirty: D0 semi-initialized cases with swsusp | ||
| 367 | * + after BIOS init | ||
| 368 | * + after Linux init (HCD statically linked) | ||
| 369 | */ | ||
| 370 | dev_dbg(&dev->dev, "resume from previous PCI D%d\n", | ||
| 371 | state); | ||
| 372 | } | ||
| 373 | #endif | ||
| 374 | |||
| 375 | retval = pci_set_power_state(dev, PCI_D0); | ||
| 376 | } else { | ||
| 377 | /* Same basic cases: clean (powered/not), dirty */ | ||
| 378 | dev_dbg(&dev->dev, "PCI legacy resume\n"); | ||
| 379 | } | ||
| 380 | |||
| 381 | if (retval < 0) | ||
| 382 | dev_err(&dev->dev, "can't resume: %d\n", retval); | ||
| 383 | else | ||
| 384 | pci_restore_state(dev); | ||
| 385 | |||
| 386 | return retval; | ||
| 387 | } | 310 | } |
| 388 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); | 311 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); |
| 389 | 312 | ||
| @@ -398,6 +321,18 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
| 398 | struct usb_hcd *hcd; | 321 | struct usb_hcd *hcd; |
| 399 | int retval; | 322 | int retval; |
| 400 | 323 | ||
| 324 | #ifdef CONFIG_PPC_PMAC | ||
| 325 | /* Reenable ASIC clocks for USB */ | ||
| 326 | if (machine_is(powermac)) { | ||
| 327 | struct device_node *of_node; | ||
| 328 | |||
| 329 | of_node = pci_device_to_OF_node(dev); | ||
| 330 | if (of_node) | ||
| 331 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
| 332 | of_node, 0, 1); | ||
| 333 | } | ||
| 334 | #endif | ||
| 335 | |||
| 401 | hcd = pci_get_drvdata(dev); | 336 | hcd = pci_get_drvdata(dev); |
| 402 | if (hcd->state != HC_STATE_SUSPENDED) { | 337 | if (hcd->state != HC_STATE_SUSPENDED) { |
| 403 | dev_dbg(hcd->self.controller, | 338 | dev_dbg(hcd->self.controller, |
| @@ -405,6 +340,8 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
| 405 | return 0; | 340 | return 0; |
| 406 | } | 341 | } |
| 407 | 342 | ||
| 343 | pci_enable_wake(dev, PCI_D0, false); | ||
| 344 | |||
| 408 | retval = pci_enable_device(dev); | 345 | retval = pci_enable_device(dev); |
| 409 | if (retval < 0) { | 346 | if (retval < 0) { |
| 410 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", | 347 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 572d2cf46e8d..5b94a56bec23 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -257,7 +257,6 @@ extern void usb_hcd_pci_remove(struct pci_dev *dev); | |||
| 257 | 257 | ||
| 258 | #ifdef CONFIG_PM | 258 | #ifdef CONFIG_PM |
| 259 | extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg); | 259 | extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg); |
| 260 | extern int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t msg); | ||
| 261 | extern int usb_hcd_pci_resume_early(struct pci_dev *dev); | 260 | extern int usb_hcd_pci_resume_early(struct pci_dev *dev); |
| 262 | extern int usb_hcd_pci_resume(struct pci_dev *dev); | 261 | extern int usb_hcd_pci_resume(struct pci_dev *dev); |
| 263 | #endif /* CONFIG_PM */ | 262 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d5d0e40b1e2d..cd50d86029e7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -1554,7 +1554,7 @@ static int usb_configure_device_otg(struct usb_device *udev) | |||
| 1554 | * (Includes HNP test device.) | 1554 | * (Includes HNP test device.) |
| 1555 | */ | 1555 | */ |
| 1556 | if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { | 1556 | if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { |
| 1557 | err = usb_port_suspend(udev); | 1557 | err = usb_port_suspend(udev, PMSG_SUSPEND); |
| 1558 | if (err < 0) | 1558 | if (err < 0) |
| 1559 | dev_dbg(&udev->dev, "HNP fail, %d\n", err); | 1559 | dev_dbg(&udev->dev, "HNP fail, %d\n", err); |
| 1560 | } | 1560 | } |
| @@ -2382,8 +2382,8 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) | |||
| 2382 | 2382 | ||
| 2383 | void usb_ep0_reinit(struct usb_device *udev) | 2383 | void usb_ep0_reinit(struct usb_device *udev) |
| 2384 | { | 2384 | { |
| 2385 | usb_disable_endpoint(udev, 0 + USB_DIR_IN); | 2385 | usb_disable_endpoint(udev, 0 + USB_DIR_IN, true); |
| 2386 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT); | 2386 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT, true); |
| 2387 | usb_enable_endpoint(udev, &udev->ep0, true); | 2387 | usb_enable_endpoint(udev, &udev->ep0, true); |
| 2388 | } | 2388 | } |
| 2389 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); | 2389 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 2a129cb7bb56..dff5760a37f6 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
| @@ -717,7 +717,6 @@ static void usbfs_remove_device(struct usb_device *dev) | |||
| 717 | fs_remove_file (dev->usbfs_dentry); | 717 | fs_remove_file (dev->usbfs_dentry); |
| 718 | dev->usbfs_dentry = NULL; | 718 | dev->usbfs_dentry = NULL; |
| 719 | } | 719 | } |
| 720 | usb_fs_classdev_common_remove(dev); | ||
| 721 | } | 720 | } |
| 722 | 721 | ||
| 723 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) | 722 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index de51667dd64d..31fb204f44c6 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -1039,14 +1039,15 @@ static void remove_intf_ep_devs(struct usb_interface *intf) | |||
| 1039 | * @dev: the device whose endpoint is being disabled | 1039 | * @dev: the device whose endpoint is being disabled |
| 1040 | * @epaddr: the endpoint's address. Endpoint number for output, | 1040 | * @epaddr: the endpoint's address. Endpoint number for output, |
| 1041 | * endpoint number + USB_DIR_IN for input | 1041 | * endpoint number + USB_DIR_IN for input |
| 1042 | * @reset_hardware: flag to erase any endpoint state stored in the | ||
| 1043 | * controller hardware | ||
| 1042 | * | 1044 | * |
| 1043 | * Deallocates hcd/hardware state for this endpoint ... and nukes all | 1045 | * Disables the endpoint for URB submission and nukes all pending URBs. |
| 1044 | * pending urbs. | 1046 | * If @reset_hardware is set then also deallocates hcd/hardware state |
| 1045 | * | 1047 | * for the endpoint. |
| 1046 | * If the HCD hasn't registered a disable() function, this sets the | ||
| 1047 | * endpoint's maxpacket size to 0 to prevent further submissions. | ||
| 1048 | */ | 1048 | */ |
| 1049 | void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | 1049 | void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, |
| 1050 | bool reset_hardware) | ||
| 1050 | { | 1051 | { |
| 1051 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; | 1052 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; |
| 1052 | struct usb_host_endpoint *ep; | 1053 | struct usb_host_endpoint *ep; |
| @@ -1056,15 +1057,18 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
| 1056 | 1057 | ||
| 1057 | if (usb_endpoint_out(epaddr)) { | 1058 | if (usb_endpoint_out(epaddr)) { |
| 1058 | ep = dev->ep_out[epnum]; | 1059 | ep = dev->ep_out[epnum]; |
| 1059 | dev->ep_out[epnum] = NULL; | 1060 | if (reset_hardware) |
| 1061 | dev->ep_out[epnum] = NULL; | ||
| 1060 | } else { | 1062 | } else { |
| 1061 | ep = dev->ep_in[epnum]; | 1063 | ep = dev->ep_in[epnum]; |
| 1062 | dev->ep_in[epnum] = NULL; | 1064 | if (reset_hardware) |
| 1065 | dev->ep_in[epnum] = NULL; | ||
| 1063 | } | 1066 | } |
| 1064 | if (ep) { | 1067 | if (ep) { |
| 1065 | ep->enabled = 0; | 1068 | ep->enabled = 0; |
| 1066 | usb_hcd_flush_endpoint(dev, ep); | 1069 | usb_hcd_flush_endpoint(dev, ep); |
| 1067 | usb_hcd_disable_endpoint(dev, ep); | 1070 | if (reset_hardware) |
| 1071 | usb_hcd_disable_endpoint(dev, ep); | ||
| 1068 | } | 1072 | } |
| 1069 | } | 1073 | } |
| 1070 | 1074 | ||
| @@ -1072,17 +1076,21 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
| 1072 | * usb_disable_interface -- Disable all endpoints for an interface | 1076 | * usb_disable_interface -- Disable all endpoints for an interface |
| 1073 | * @dev: the device whose interface is being disabled | 1077 | * @dev: the device whose interface is being disabled |
| 1074 | * @intf: pointer to the interface descriptor | 1078 | * @intf: pointer to the interface descriptor |
| 1079 | * @reset_hardware: flag to erase any endpoint state stored in the | ||
| 1080 | * controller hardware | ||
| 1075 | * | 1081 | * |
| 1076 | * Disables all the endpoints for the interface's current altsetting. | 1082 | * Disables all the endpoints for the interface's current altsetting. |
| 1077 | */ | 1083 | */ |
| 1078 | void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf) | 1084 | void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, |
| 1085 | bool reset_hardware) | ||
| 1079 | { | 1086 | { |
| 1080 | struct usb_host_interface *alt = intf->cur_altsetting; | 1087 | struct usb_host_interface *alt = intf->cur_altsetting; |
| 1081 | int i; | 1088 | int i; |
| 1082 | 1089 | ||
| 1083 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { | 1090 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { |
| 1084 | usb_disable_endpoint(dev, | 1091 | usb_disable_endpoint(dev, |
| 1085 | alt->endpoint[i].desc.bEndpointAddress); | 1092 | alt->endpoint[i].desc.bEndpointAddress, |
| 1093 | reset_hardware); | ||
| 1086 | } | 1094 | } |
| 1087 | } | 1095 | } |
| 1088 | 1096 | ||
| @@ -1103,8 +1111,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
| 1103 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, | 1111 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, |
| 1104 | skip_ep0 ? "non-ep0" : "all"); | 1112 | skip_ep0 ? "non-ep0" : "all"); |
| 1105 | for (i = skip_ep0; i < 16; ++i) { | 1113 | for (i = skip_ep0; i < 16; ++i) { |
| 1106 | usb_disable_endpoint(dev, i); | 1114 | usb_disable_endpoint(dev, i, true); |
| 1107 | usb_disable_endpoint(dev, i + USB_DIR_IN); | 1115 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
| 1108 | } | 1116 | } |
| 1109 | dev->toggle[0] = dev->toggle[1] = 0; | 1117 | dev->toggle[0] = dev->toggle[1] = 0; |
| 1110 | 1118 | ||
| @@ -1274,7 +1282,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
| 1274 | remove_intf_ep_devs(iface); | 1282 | remove_intf_ep_devs(iface); |
| 1275 | usb_remove_sysfs_intf_files(iface); | 1283 | usb_remove_sysfs_intf_files(iface); |
| 1276 | } | 1284 | } |
| 1277 | usb_disable_interface(dev, iface); | 1285 | usb_disable_interface(dev, iface, true); |
| 1278 | 1286 | ||
| 1279 | iface->cur_altsetting = alt; | 1287 | iface->cur_altsetting = alt; |
| 1280 | 1288 | ||
| @@ -1353,8 +1361,8 @@ int usb_reset_configuration(struct usb_device *dev) | |||
| 1353 | */ | 1361 | */ |
| 1354 | 1362 | ||
| 1355 | for (i = 1; i < 16; ++i) { | 1363 | for (i = 1; i < 16; ++i) { |
| 1356 | usb_disable_endpoint(dev, i); | 1364 | usb_disable_endpoint(dev, i, true); |
| 1357 | usb_disable_endpoint(dev, i + USB_DIR_IN); | 1365 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
| 1358 | } | 1366 | } |
| 1359 | 1367 | ||
| 1360 | config = dev->actconfig; | 1368 | config = dev->actconfig; |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 386177867a8a..79d8a9ea559b 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
| @@ -15,9 +15,10 @@ extern void usb_enable_endpoint(struct usb_device *dev, | |||
| 15 | struct usb_host_endpoint *ep, bool reset_toggle); | 15 | struct usb_host_endpoint *ep, bool reset_toggle); |
| 16 | extern void usb_enable_interface(struct usb_device *dev, | 16 | extern void usb_enable_interface(struct usb_device *dev, |
| 17 | struct usb_interface *intf, bool reset_toggles); | 17 | struct usb_interface *intf, bool reset_toggles); |
| 18 | extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr); | 18 | extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, |
| 19 | bool reset_hardware); | ||
| 19 | extern void usb_disable_interface(struct usb_device *dev, | 20 | extern void usb_disable_interface(struct usb_device *dev, |
| 20 | struct usb_interface *intf); | 21 | struct usb_interface *intf, bool reset_hardware); |
| 21 | extern void usb_release_interface_cache(struct kref *ref); | 22 | extern void usb_release_interface_cache(struct kref *ref); |
| 22 | extern void usb_disable_device(struct usb_device *dev, int skip_ep0); | 23 | extern void usb_disable_device(struct usb_device *dev, int skip_ep0); |
| 23 | extern int usb_deauthorize_device(struct usb_device *); | 24 | extern int usb_deauthorize_device(struct usb_device *); |
| @@ -151,7 +152,6 @@ extern struct usb_driver usbfs_driver; | |||
| 151 | extern const struct file_operations usbfs_devices_fops; | 152 | extern const struct file_operations usbfs_devices_fops; |
| 152 | extern const struct file_operations usbdev_file_operations; | 153 | extern const struct file_operations usbdev_file_operations; |
| 153 | extern void usbfs_conn_disc_event(void); | 154 | extern void usbfs_conn_disc_event(void); |
| 154 | extern void usb_fs_classdev_common_remove(struct usb_device *udev); | ||
| 155 | 155 | ||
| 156 | extern int usb_devio_init(void); | 156 | extern int usb_devio_init(void); |
| 157 | extern void usb_devio_cleanup(void); | 157 | extern void usb_devio_cleanup(void); |
