diff options
| -rw-r--r-- | drivers/usb/core/hub.c | 46 | ||||
| -rw-r--r-- | drivers/usb/host/isp1760-hcd.c | 8 | ||||
| -rw-r--r-- | drivers/usb/misc/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/usb/misc/isight_firmware.c | 23 |
4 files changed, 65 insertions, 13 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8eb4da332f56..94789be54ca3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub) | |||
| 644 | 644 | ||
| 645 | #ifdef CONFIG_PM | 645 | #ifdef CONFIG_PM |
| 646 | 646 | ||
| 647 | /* Try to identify which devices need USB-PERSIST handling */ | ||
| 648 | static int persistent_device(struct usb_device *udev) | ||
| 649 | { | ||
| 650 | int i; | ||
| 651 | int retval; | ||
| 652 | struct usb_host_config *actconfig; | ||
| 653 | |||
| 654 | /* Explicitly not marked persistent? */ | ||
| 655 | if (!udev->persist_enabled) | ||
| 656 | return 0; | ||
| 657 | |||
| 658 | /* No active config? */ | ||
| 659 | actconfig = udev->actconfig; | ||
| 660 | if (!actconfig) | ||
| 661 | return 0; | ||
| 662 | |||
| 663 | /* FIXME! We should check whether it's open here or not! */ | ||
| 664 | |||
| 665 | /* | ||
| 666 | * Check that all the interface drivers have a | ||
| 667 | * 'reset_resume' entrypoint | ||
| 668 | */ | ||
| 669 | retval = 0; | ||
| 670 | for (i = 0; i < actconfig->desc.bNumInterfaces; i++) { | ||
| 671 | struct usb_interface *intf; | ||
| 672 | struct usb_driver *driver; | ||
| 673 | |||
| 674 | intf = actconfig->interface[i]; | ||
| 675 | if (!intf->dev.driver) | ||
| 676 | continue; | ||
| 677 | driver = to_usb_driver(intf->dev.driver); | ||
| 678 | if (!driver->reset_resume) | ||
| 679 | return 0; | ||
| 680 | /* | ||
| 681 | * We have at least one driver, and that one | ||
| 682 | * has a reset_resume method. | ||
| 683 | */ | ||
| 684 | retval = 1; | ||
| 685 | } | ||
| 686 | return retval; | ||
| 687 | } | ||
| 688 | |||
| 647 | static void hub_restart(struct usb_hub *hub, int type) | 689 | static void hub_restart(struct usb_hub *hub, int type) |
| 648 | { | 690 | { |
| 649 | struct usb_device *hdev = hub->hdev; | 691 | struct usb_device *hdev = hub->hdev; |
| @@ -689,8 +731,8 @@ static void hub_restart(struct usb_hub *hub, int type) | |||
| 689 | * turn off the various status changes to prevent | 731 | * turn off the various status changes to prevent |
| 690 | * khubd from disconnecting it later. | 732 | * khubd from disconnecting it later. |
| 691 | */ | 733 | */ |
| 692 | if (udev->persist_enabled && status == 0 && | 734 | if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) && |
| 693 | !(portstatus & USB_PORT_STAT_ENABLE)) { | 735 | persistent_device(udev)) { |
| 694 | if (portchange & USB_PORT_STAT_C_ENABLE) | 736 | if (portchange & USB_PORT_STAT_C_ENABLE) |
| 695 | clear_port_feature(hub->hdev, port1, | 737 | clear_port_feature(hub->hdev, port1, |
| 696 | USB_PORT_FEAT_C_ENABLE); | 738 | USB_PORT_FEAT_C_ENABLE); |
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9cec8738261..65aa5ecf569a 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
| @@ -2207,14 +2207,14 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, | |||
| 2207 | goto err_put; | 2207 | goto err_put; |
| 2208 | } | 2208 | } |
| 2209 | 2209 | ||
| 2210 | ret = usb_add_hcd(hcd, irq, irqflags); | ||
| 2211 | if (ret) | ||
| 2212 | goto err_unmap; | ||
| 2213 | |||
| 2214 | hcd->irq = irq; | 2210 | hcd->irq = irq; |
| 2215 | hcd->rsrc_start = res_start; | 2211 | hcd->rsrc_start = res_start; |
| 2216 | hcd->rsrc_len = res_len; | 2212 | hcd->rsrc_len = res_len; |
| 2217 | 2213 | ||
| 2214 | ret = usb_add_hcd(hcd, irq, irqflags); | ||
| 2215 | if (ret) | ||
| 2216 | goto err_unmap; | ||
| 2217 | |||
| 2218 | return hcd; | 2218 | return hcd; |
| 2219 | 2219 | ||
| 2220 | err_unmap: | 2220 | err_unmap: |
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index eb6c06979f3b..001789c9a11a 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
| @@ -272,6 +272,7 @@ config USB_TEST | |||
| 272 | config USB_ISIGHTFW | 272 | config USB_ISIGHTFW |
| 273 | tristate "iSight firmware loading support" | 273 | tristate "iSight firmware loading support" |
| 274 | depends on USB | 274 | depends on USB |
| 275 | select FW_LOADER | ||
| 275 | help | 276 | help |
| 276 | This driver loads firmware for USB Apple iSight cameras, allowing | 277 | This driver loads firmware for USB Apple iSight cameras, allowing |
| 277 | them to be driven by the USB video class driver available at | 278 | them to be driven by the USB video class driver available at |
diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index 390e04885536..9f30aa1f8a5d 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c | |||
| @@ -39,9 +39,12 @@ static int isight_firmware_load(struct usb_interface *intf, | |||
| 39 | struct usb_device *dev = interface_to_usbdev(intf); | 39 | struct usb_device *dev = interface_to_usbdev(intf); |
| 40 | int llen, len, req, ret = 0; | 40 | int llen, len, req, ret = 0; |
| 41 | const struct firmware *firmware; | 41 | const struct firmware *firmware; |
| 42 | unsigned char *buf; | 42 | unsigned char *buf = kmalloc(50, GFP_KERNEL); |
| 43 | unsigned char data[4]; | 43 | unsigned char data[4]; |
| 44 | char *ptr; | 44 | u8 *ptr; |
| 45 | |||
| 46 | if (!buf) | ||
| 47 | return -ENOMEM; | ||
| 45 | 48 | ||
| 46 | if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { | 49 | if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { |
| 47 | printk(KERN_ERR "Unable to load isight firmware\n"); | 50 | printk(KERN_ERR "Unable to load isight firmware\n"); |
| @@ -59,7 +62,7 @@ static int isight_firmware_load(struct usb_interface *intf, | |||
| 59 | goto out; | 62 | goto out; |
| 60 | } | 63 | } |
| 61 | 64 | ||
| 62 | while (1) { | 65 | while (ptr+4 <= firmware->data+firmware->size) { |
| 63 | memcpy(data, ptr, 4); | 66 | memcpy(data, ptr, 4); |
| 64 | len = (data[0] << 8 | data[1]); | 67 | len = (data[0] << 8 | data[1]); |
| 65 | req = (data[2] << 8 | data[3]); | 68 | req = (data[2] << 8 | data[3]); |
| @@ -71,10 +74,14 @@ static int isight_firmware_load(struct usb_interface *intf, | |||
| 71 | continue; | 74 | continue; |
| 72 | 75 | ||
| 73 | for (; len > 0; req += 50) { | 76 | for (; len > 0; req += 50) { |
| 74 | llen = len > 50 ? 50 : len; | 77 | llen = min(len, 50); |
| 75 | len -= llen; | 78 | len -= llen; |
| 76 | 79 | if (ptr+llen > firmware->data+firmware->size) { | |
| 77 | buf = kmalloc(llen, GFP_KERNEL); | 80 | printk(KERN_ERR |
| 81 | "Malformed isight firmware"); | ||
| 82 | ret = -ENODEV; | ||
| 83 | goto out; | ||
| 84 | } | ||
| 78 | memcpy(buf, ptr, llen); | 85 | memcpy(buf, ptr, llen); |
| 79 | 86 | ||
| 80 | ptr += llen; | 87 | ptr += llen; |
| @@ -89,16 +96,18 @@ static int isight_firmware_load(struct usb_interface *intf, | |||
| 89 | goto out; | 96 | goto out; |
| 90 | } | 97 | } |
| 91 | 98 | ||
| 92 | kfree(buf); | ||
| 93 | } | 99 | } |
| 94 | } | 100 | } |
| 101 | |||
| 95 | if (usb_control_msg | 102 | if (usb_control_msg |
| 96 | (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, | 103 | (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, |
| 97 | 300) != 1) { | 104 | 300) != 1) { |
| 98 | printk(KERN_ERR "isight firmware loading completion failed\n"); | 105 | printk(KERN_ERR "isight firmware loading completion failed\n"); |
| 99 | ret = -ENODEV; | 106 | ret = -ENODEV; |
| 100 | } | 107 | } |
| 108 | |||
| 101 | out: | 109 | out: |
| 110 | kfree(buf); | ||
| 102 | release_firmware(firmware); | 111 | release_firmware(firmware); |
| 103 | return ret; | 112 | return ret; |
| 104 | } | 113 | } |
