diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-23 21:35:04 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-23 21:35:04 -0700 |
commit | 9e1a3e31cbfd5f5822e633c4bdf3304079cb10c2 (patch) | |
tree | 88653393c17c0ac5c0b30a244d6e6dc97b314e1f | |
parent | de80af4cc9c30318224b8520dc76a7d097e64cbd (diff) | |
parent | d65cc1b45e7d3a24c25fd3d730042e407d6d64ce (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (35 commits)
usb: add PRODUCT, TYPE to usb-interface events
USB: resubmission unusual_devs modification for Nikon D80
usb quirks: Add Canon EOS 5D (PC Connection mode) to the autosuspend blacklist
USB: make EHCI initialize properly on PPC SOCs
UEAGLE: Remove sysfs files on error case
USB: fsl_usb2_udc: fix bug in processing setup requests
USB: g_file_storage: fix bug in DMA buffer handling
USB: update last_busy field correctly
USB: fix DoS in pwc USB video driver
USB: allow retry on descriptor fetch errors
USB: unkill cxacru atm driver
USB: Adding support for HTC Smartphones to ipaq
USB: another quirky device
USB: quirky mass storage device
USB: ohci, fix oddball gcc warning
usb-storage: fix bugs in the disconnect pathway
usb: typo in usb R8A66597 HCD config
USB: accept 1-byte Device Status replies, fixing some b0rken devices
USB: blacklist Samsung ML-2010 printer
usb-serial: fix oti6858.c segfault in termios handling
...
35 files changed, 255 insertions, 172 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 2c7b158ce7e..40307f3f6fe 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1772,6 +1772,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, if (dev->alt_max_pkt_size == NULL) { em28xx_errdev("out of memory!\n"); em28xx_devused&=~(1<<nr); + kfree(dev); return -ENOMEM; } diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9c0e8d18c2f..3d81966d8c4 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file) return 0; } + +static void pwc_cleanup(struct pwc_device *pdev) +{ + pwc_remove_sysfs_files(pdev->vdev); + video_unregister_device(pdev->vdev); +} + /* Note that all cleanup is done in the reverse order as in _open */ static int pwc_video_close(struct inode *inode, struct file *file) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; - int i; + int i, hint; PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); @@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file) pwc_isoc_cleanup(pdev); pwc_free_buffers(pdev); + lock_kernel(); /* Turn off LEDS and power down camera, but only when not unplugged */ - if (pdev->error_status != EPIPE) { + if (!pdev->unplugged) { /* Turn LEDs off */ if (pwc_set_leds(pdev, 0, 0) < 0) PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); @@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file) if (i < 0) PWC_ERROR("Failed to power down camera (%d)\n", i); } + pdev->vopen--; + PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i); + } else { + pwc_cleanup(pdev); + /* Free memory (don't set pdev to 0 just yet) */ + kfree(pdev); + /* search device_hint[] table if we occupy a slot, by any chance */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) + if (device_hint[hint].pdev == pdev) + device_hint[hint].pdev = NULL; } - pdev->vopen--; - PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); + unlock_kernel(); + return 0; } @@ -1791,21 +1809,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf) /* Alert waiting processes */ wake_up_interruptible(&pdev->frameq); /* Wait until device is closed */ - while (pdev->vopen) - schedule(); - /* Device is now closed, so we can safely unregister it */ - PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); - pwc_remove_sysfs_files(pdev->vdev); - video_unregister_device(pdev->vdev); - - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); + if(pdev->vopen) { + pdev->unplugged = 1; + } else { + /* Device is closed, so we can safely unregister it */ + PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); + pwc_cleanup(pdev); + /* Free memory (don't set pdev to 0 just yet) */ + kfree(pdev); disconnect_out: - /* search device_hint[] table if we occupy a slot, by any chance */ - for (hint = 0; hint < MAX_DEV_HINTS; hint++) - if (device_hint[hint].pdev == pdev) - device_hint[hint].pdev = NULL; + /* search device_hint[] table if we occupy a slot, by any chance */ + for (hint = 0; hint < MAX_DEV_HINTS; hint++) + if (device_hint[hint].pdev == pdev) + device_hint[hint].pdev = NULL; + } unlock_kernel(); } diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 910a04f5392..8e8e5b27e77 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -193,6 +193,7 @@ struct pwc_device char vsnapshot; /* snapshot mode */ char vsync; /* used by isoc handler */ char vmirror; /* for ToUCaM series */ + char unplugged; int cmd_len; unsigned char cmd_buf[13]; diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 63436892688..7580aa5da0f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -21,6 +21,7 @@ config USB_ARCH_HAS_HCD default y if USB_ARCH_HAS_EHCI default y if PCMCIA && !M32R # sl811_cs default y if ARM # SL-811 + default y if SUPERH # r8a66597-hcd default PCI # many non-PCI SOC chips embed OHCI diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 02c52f8d5db..a73e714288e 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -456,7 +456,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, int* actual_length) { struct timer_list timer; - int status = urb->status; init_timer(&timer); timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT); @@ -468,7 +467,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, if (actual_length) *actual_length = urb->actual_length; - return status; + return urb->status; /* must read status after completion */ } static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index a1a1c9d467e..29807d048b0 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1721,9 +1721,12 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, ret = uea_boot(sc); if (ret < 0) - goto error; + goto error_rm_grp; return 0; + +error_rm_grp: + sysfs_remove_group(&intf->dev.kobj, &attr_grp); error: kfree(sc); return ret; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fe940e0536e..f51e22490ed 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -921,6 +921,10 @@ skip_normal_probe: return -EINVAL; } } + + /* Accept probe requests only for the control interface */ + if (intf != control_interface) + return -ENODEV; if (usb_interface_claimed(data_interface)) { /* valid in this context */ dev_dbg(&intf->dev,"The data interface isn't available"); @@ -1109,10 +1113,12 @@ static void acm_disconnect(struct usb_interface *intf) return; } if (acm->country_codes){ - device_remove_file(&intf->dev, &dev_attr_wCountryCodes); - device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate); + device_remove_file(&acm->control->dev, + &dev_attr_wCountryCodes); + device_remove_file(&acm->control->dev, + &dev_attr_iCountryCodeRelDate); } - device_remove_file(&intf->dev, &dev_attr_bmCapabilities); + device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); acm->dev = NULL; usb_set_intfdata(acm->control, NULL); usb_set_intfdata(acm->data, NULL); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 654857493a8..a1ad11d0c47 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1224,6 +1224,8 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) udev->auto_pm = 1; udev->pm_usage_cnt += inc_usage_cnt; WARN_ON(udev->pm_usage_cnt < 0); + if (inc_usage_cnt) + udev->last_busy = jiffies; if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { if (udev->state == USB_STATE_SUSPENDED) status = usb_resume_both(udev); @@ -1232,8 +1234,6 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) else if (inc_usage_cnt) udev->last_busy = jiffies; } else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { - if (inc_usage_cnt) - udev->last_busy = jiffies; status = usb_suspend_both(udev, PMSG_SUSPEND); } usb_pm_unlock(udev); @@ -1342,16 +1342,15 @@ static int usb_autopm_do_interface(struct usb_interface *intf, else { udev->auto_pm = 1; intf->pm_usage_cnt += inc_usage_cnt; + udev->last_busy = jiffies; if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { if (udev->state == USB_STATE_SUSPENDED) status = usb_resume_both(udev); if (status != 0) intf->pm_usage_cnt -= inc_usage_cnt; - else if (inc_usage_cnt) + else udev->last_busy = jiffies; } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { - if (inc_usage_cnt) - udev->last_busy = jiffies; status = usb_suspend_both(udev, PMSG_SUSPEND); } } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index e341a1da517..f7b337feb3e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1644,9 +1644,10 @@ static int finish_port_resume(struct usb_device *udev) * and device drivers will know about any resume quirks. */ if (status == 0) { + devstatus = 0; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); if (status >= 0) - status = (status == 2 ? 0 : -ENODEV); + status = (status > 0 ? 0 : -ENODEV); } if (status) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b6bd05e3d43..d8f7b089a8f 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -637,12 +637,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char memset(buf,0,size); // Make sure we parse really received data for (i = 0; i < 3; ++i) { - /* retry on length 0 or stall; some devices are flakey */ + /* retry on length 0 or error; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (type << 8) + index, 0, buf, size, USB_CTRL_GET_TIMEOUT); - if (result == 0 || result == -EPIPE) + if (result <= 0 && result != -ETIMEDOUT) continue; if (result > 1 && ((u8 *)buf)[1] != type) { result = -EPROTO; @@ -1358,6 +1358,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, usb_dev = interface_to_usbdev(intf); alt = intf->cur_altsetting; +#ifdef CONFIG_USB_DEVICEFS + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "DEVICE=/proc/bus/usb/%03d/%03d", + usb_dev->bus->busnum, usb_dev->devnum)) + return -ENOMEM; +#endif + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PRODUCT=%x/%x/%x", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + le16_to_cpu(usb_dev->descriptor.bcdDevice))) + return -ENOMEM; + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "TYPE=%d/%d/%d", + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol)) + return -ENOMEM; + if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "INTERFACE=%d/%d/%d", diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index b7917c5a3c6..9e467118dc9 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -30,6 +30,8 @@ static const struct usb_device_id usb_quirk_list[] = { /* HP 5300/5370C scanner */ { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, + /* Hewlett-Packard PhotoSmart 720 / PhotoSmart 935 (storage) */ + { USB_DEVICE(0x03f0, 0x4002), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */ { USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Benq S2W 3300U */ @@ -56,6 +58,8 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Seiko Epson Corp.*/ { USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Samsung ML-2010 printer */ + { USB_DEVICE(0x04e8, 0x326c), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Samsung ML-2510 Series printer */ { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Elsa MicroLink 56k (V.250) */ @@ -64,12 +68,20 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Agfa Snapscan1212u */ { USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Seagate RSS LLC */ + { USB_DEVICE(0x0bc2, 0x3000), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Umax [hex] Astra 3400U */ { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Philips PSC805 audio device */ { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Alcor multi-card reader */ + { USB_DEVICE(0x058f, 0x6366), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + + /* Canon EOS 5D in PC Connection mode */ + { USB_DEVICE(0x04a9, 0x3101), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* RIM Blackberry */ { USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index f2fbdc7fe37..d008d1360a7 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -34,8 +34,6 @@ * bypassing some hardware (and driver) issues. UML could help too. */ -#define DEBUG - #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index be7a1bd2823..965ad7bec7b 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -599,7 +599,6 @@ enum fsg_buffer_state { struct fsg_buffhd { void *buf; - dma_addr_t dma; enum fsg_buffer_state state; struct fsg_buffhd *next; @@ -1295,6 +1294,7 @@ static int class_setup_req(struct fsg_dev *fsg, struct usb_request *req = fsg->ep0req; int value = -EOPNOTSUPP; u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); if (!fsg->config) @@ -1308,7 +1308,7 @@ static int class_setup_req(struct fsg_dev *fsg, if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; - if (w_index != 0) { + if (w_index != 0 || w_value != 0) { value = -EDOM; break; } @@ -1324,7 +1324,7 @@ static int class_setup_req(struct fsg_dev *fsg, if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; - if (w_index != 0) { + if (w_index != 0 || w_value != 0) { value = -EDOM; break; } @@ -1343,7 +1343,7 @@ static int class_setup_req(struct fsg_dev *fsg, if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; - if (w_index != 0) { + if (w_index != 0 || w_value != 0) { value = -EDOM; break; } @@ -2611,7 +2611,6 @@ static int send_status(struct fsg_dev *fsg) fsg->intr_buffhd = bh; // Point to the right buffhd fsg->intreq->buf = bh->inreq->buf; - fsg->intreq->dma = bh->inreq->dma; fsg->intreq->context = bh; start_transfer(fsg, fsg->intr_in, fsg->intreq, &fsg->intreq_busy, &bh->state); @@ -3200,7 +3199,6 @@ reset: if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) goto reset; bh->inreq->buf = bh->outreq->buf = bh->buf; - bh->inreq->dma = bh->outreq->dma = bh->dma; bh->inreq->context = bh->outreq->context = bh; bh->inreq->complete = bulk_in_complete; bh->outreq->complete = bulk_out_complete; diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 10b2b33b869..d57bcfbc08a 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1277,31 +1277,32 @@ static void setup_received_irq(struct fsl_udc *udc, udc_reset_ep_queue(udc, 0); + /* We process some stardard setup requests here */ switch (setup->bRequest) { - /* Request that need Data+Status phase from udc */ case USB_REQ_GET_STATUS: - if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_STANDARD)) + /* Data+Status phase from udc */ + if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK)) != (USB_DIR_IN | USB_TYPE_STANDARD)) break; ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength); - break; + return; - /* Requests that need Status phase from udc */ case USB_REQ_SET_ADDRESS: + /* Status phase from udc */ if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE)) break; ch9setaddress(udc, wValue, wIndex, wLength); - break; + return; - /* Handled by udc, no data, status by udc */ case USB_REQ_CLEAR_FEATURE: case USB_REQ_SET_FEATURE: - { /* status transaction */ + /* Status phase from udc */ + { int rc = -EOPNOTSUPP; - if ((setup->bRequestType & USB_RECIP_MASK) - == USB_RECIP_ENDPOINT) { + if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) + == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { int pipe = get_pipe_by_windex(wIndex); struct fsl_ep *ep; @@ -1315,8 +1316,9 @@ static void setup_received_irq(struct fsl_udc *udc, ? 1 : 0); spin_lock(&udc->lock); - } else if ((setup->bRequestType & USB_RECIP_MASK) - == USB_RECIP_DEVICE) { + } else if ((setup->bRequestType & (USB_RECIP_MASK + | USB_TYPE_MASK)) == (USB_RECIP_DEVICE + | USB_TYPE_STANDARD)) { /* Note: The driver has not include OTG support yet. * This will be set when OTG support is added */ if (!udc->gadget.is_otg) @@ -1329,39 +1331,42 @@ static void setup_received_irq(struct fsl_udc *udc, USB_DEVICE_A_ALT_HNP_SUPPORT) udc->gadget.a_alt_hnp_support = 1; rc = 0; - } + } else + break; + if (rc == 0) { if (ep0_prime_status(udc, EP_DIR_IN)) ep0stall(udc); } - break; + return; } - /* Requests handled by gadget */ - default: - if (wLength) { - /* Data phase from gadget, status phase from udc */ - udc->ep0_dir = (setup->bRequestType & USB_DIR_IN) - ? USB_DIR_IN : USB_DIR_OUT; - spin_unlock(&udc->lock); - if (udc->driver->setup(&udc->gadget, - &udc->local_setup_buff) < 0) - ep0stall(udc); - spin_lock(&udc->lock); - udc->ep0_state = (setup->bRequestType & USB_DIR_IN) - ? DATA_STATE_XMIT : DATA_STATE_RECV; - } else { - /* No data phase, IN status from gadget */ - udc->ep0_dir = USB_DIR_IN; - spin_unlock(&udc->lock); - if (udc->driver->setup(&udc->gadget, - &udc->local_setup_buff) < 0) - ep0stall(udc); - spin_lock(&udc->lock); - udc->ep0_state = WAIT_FOR_OUT_STATUS; - } + default: break; } + + /* Requests handled by gadget */ + if (wLength) { + /* Data phase from gadget, status phase from udc */ + udc->ep0_dir = (setup->bRequestType & USB_DIR_IN) + ? USB_DIR_IN : USB_DIR_OUT; + spin_unlock(&udc->lock); + if (udc->driver->setup(&udc->gadget, + &udc->local_setup_buff) < 0) + ep0stall(udc); + spin_lock(&udc->lock); + udc->ep0_state = (setup->bRequestType & USB_DIR_IN) + ? DATA_STATE_XMIT : DATA_STATE_RECV; + } else { + /* No data phase, IN status from gadget */ + udc->ep0_dir = USB_DIR_IN; + spin_unlock(&udc->lock); + if (udc->driver->setup(&udc->gadget, + &udc->local_setup_buff) < 0) + ep0stall(udc); + spin_lock(&udc->lock); + udc->ep0_state = WAIT_FOR_OUT_STATUS; + } } /* Process request for Data or Status phase of ep0 diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 72b4ebbf132..1407ad1c812 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -967,7 +967,7 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) udc = container_of(_gadget, struct pxa2xx_udc, gadget); /* not all boards support pullup control */ - if (!udc->mach->udc_command) + if (!udc->mach->gpio_pullup && !udc->mach->udc_command) return -EOPNOTSUPP; is_active = (is_active != 0); @@ -2309,7 +2309,7 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) { struct pxa2xx_udc *udc = platform_get_drvdata(dev); - if (!udc->mach->udc_command) + if (!udc->mach->gpio_pullup && !udc->mach->udc_command) WARN("USB host won't detect disconnect!\n"); pullup(udc, 0); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2f529828c74..565d6ef4c4c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -237,7 +237,7 @@ config USB_SL811_CS module will be called "sl811_cs". config USB_R8A66597_HCD - tristate "R8A66597 HCD suppoort" + tristate "R8A66597 HCD support" depends on USB help The R8A66597 is a USB 2.0 host and peripheral controller. diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 5d1b12aad77..b1d19268cb2 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -1,8 +1,6 @@ /* * EHCI HCD (Host Controller Driver) for USB. * - * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> - * * Bus Glue for AMD Alchemy Au1xxx * * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org> @@ -196,6 +194,9 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { /* * basic lifecycle operations + * + * FIXME -- ehci_init() doesn't do enough here. + * See ehci-ppc-soc for a complete implementation. */ .reset = ehci_init, .start = ehci_run, diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c index c2cedb09ed8..4f99b0eb27b 100644 --- a/drivers/usb/host/ehci-ppc-soc.c +++ b/drivers/usb/host/ehci-ppc-soc.c @@ -6,7 +6,7 @@ * Bus Glue for PPC On-Chip EHCI driver * Tested on AMCC 440EPx * - * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net> + * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com> * * This file is licenced under the GPL. */ @@ -15,6 +15,24 @@ extern int usb_disabled(void); +/* called during probe() after chip reset completes */ +static int ehci_ppc_soc_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + + retval = ehci_halt(ehci); + if (retval) + return retval; + + retval = ehci_init(hcd); + if (retval) + return retval; + + ehci->sbrn = 0x20; + return ehci_reset(ehci); +} + /** * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs * Context: !in_interrupt() @@ -120,7 +138,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_init, + .reset = ehci_ppc_soc_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 6f9e43e9a6c..f61c6cdd06f 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -74,7 +74,7 @@ urb_print (struct urb * urb, char * str, int small) #define ohci_dbg_sw(ohci, next, size, format, arg...) \ do { \ - if (next) { \ + if (next != NULL) { \ unsigned s_len; \ s_len = scnprintf (*next, *size, format, ## arg ); \ *size -= s_len; *next += s_len; \ diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index d60f1985320..40a1de4c256 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2208,8 +2208,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) clean_up: if (reg) iounmap(reg); - if (res) - release_mem_region(res->start, 1); return ret; } diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 7f765ec038c..b88eb3c62c0 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -1520,12 +1520,15 @@ static void u132_hcd_endp_work_scheduler(struct work_struct *work) } } } +#ifdef CONFIG_PM static void port_power(struct u132 *u132, int pn, int is_on) { u132->port[pn].power = is_on; } +#endif + static void u132_power(struct u132 *u132, int is_on) { struct usb_hcd *hcd = u132_to_hcd(u132) |