diff options
Diffstat (limited to 'drivers/usb')
36 files changed, 316 insertions, 207 deletions
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..63b1243a913 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -60,7 +60,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; spin_lock(&dynids->lock); - list_add_tail(&dynids->list, &dynid->node); + list_add_tail(&dynid->node, &dynids->list); spin_unlock(&dynids->lock); if (get_driver(driver)) { @@ -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..ebf3dc20110 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -28,8 +28,16 @@ * devices is broken... */ static const struct usb_device_id usb_quirk_list[] = { + /* CBM - Flash disk */ + { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME }, /* 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 }, + + /* SGS Thomson Microelectronics 4in1 card reader */ + { USB_DEVICE(0x0483, 0x0321), .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,25 +64,54 @@ 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) */ { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Ultima Electronics Corp.*/ { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + + /* Genesys USB-to-IDE */ + { USB_DEVICE(0x0503, 0x0702), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + + /* USB Graphical LCD - EEH Datalink GmbH */ + { USB_DEVICE(0x060c, 0x04eb), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + + /* INTEL VALUE SSD */ + { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* M-Systems Flash Disk Pioneers */ + { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + /* 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 }, { USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Apple iPhone */ + { USB_DEVICE(0x05ac, 0x1290), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + + /* SKYMEDI USB_DRIVE */ + { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, + { } /* terminating entry must be last */ }; @@ -115,4 +152,10 @@ void usb_detect_quirks(struct usb_device *udev) /* do any special quirk handling here if needed */ if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND) usb_autosuspend_quirk(udev); + + /* By default, disable autosuspend for all non-hubs */ +#ifdef CONFIG_USB_SUSPEND + if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) + udev->autosuspend_delay = -1; +#endif } 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/gadget/serial.c b/drivers/usb/gadget/serial.c index 9cd98e73dc1..ce4d2e09633 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -1691,14 +1691,12 @@ static int gs_setup_class(struct usb_gadget *gadget, switch (ctrl->bRequest) { case USB_CDC_REQ_SET_LINE_CODING: - ret = min(wLength, - (u16)sizeof(struct usb_cdc_line_coding)); - if (port) { - spin_lock(&port->port_lock); - memcpy(&port->port_line_coding, req->buf, ret); - spin_unlock(&port->port_lock); - } - ret = 0; + /* FIXME Submit req to read the data; have its completion + * handler copy that data to port->port_line_coding (iff + * it's valid) and maybe pass it on. Until then, fail. + */ + printk(KERN_WARNING "gs_setup: set_line_coding " + "unuspported\n"); break; case USB_CDC_REQ_GET_LINE_CODING: @@ -1713,11 +1711,18 @@ static int gs_setup_class(struct usb_gadget *gadget, break; case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - ret = 0; + /* FIXME Submit req to read the data; have its completion + * handler use that to set the state (iff it's valid) and + * maybe pass it on. Until then, fail. + */ + printk(KERN_WARNING "gs_setup: set_control_line_state " + "unuspported\n"); break; default: - printk(KERN_ERR "gs_setup: unknown class request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n", + printk(KERN_ERR "gs_setup: unknown class request, " + "type=%02x, request=%02x, value=%04x, " + "index=%04x, length=%d\n", ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength); break; 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) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 9f37ba44c13..b64ca91d9b0 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3404,6 +3404,7 @@ static void sisusb_disconnect(struct usb_interface *intf) } static struct usb_device_id sisusb_table [] = { + { USB_DEVICE(0x0711, 0x0550) }, { USB_DEVICE(0x0711, 0x0900) }, { USB_DEVICE(0x0711, 0x0901) }, { USB_DEVICE(0x0711, 0x0902) }, diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index cff6fd190a2..77bb893bf2e 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -18,7 +18,6 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ - { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index e67ce25f751..86724e88570 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -383,6 +383,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios } baud = tty_get_baud_rate(port->tty); + if (baud == 0) { + dbg("%s - tty_get_baud_rate says 0 baud", __FUNCTION__); + return; + } urb_value = BELKIN_SA_BAUD(baud); /* Clip to maximum speed */ if (urb_value == 0) diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index c08a38402b9..a47a24f8820 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -138,7 +138,7 @@ static void free_dynids(struct usb_serial_driver *drv) static struct driver_attribute drv_attrs[] = { __ATTR_NULL, }; -static inline void free_dynids(struct usb_driver *drv) +static inline void free_dynids(struct usb_serial_driver *drv) { } #endif diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7b1673a4407..2d045857b18 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -538,6 +538,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, @@ -566,6 +568,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, + { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), .driver_info = (kernel_ulong_t)&ftdi_olimex_quirk }, { }, /* Optional parameter entry */ diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index d9e49716db1..b57b90ae9f9 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -430,6 +430,9 @@ */ #define EVOLUTION_VID 0xDEEE /* Vendor ID */ #define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ +#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ +#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ +#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ /* Pyramid Computer GmbH */ #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ @@ -531,6 +534,14 @@ #define OLIMEX_VID 0x15BA #define OLIMEX_ARM_USB_OCD_PID 0x0003 + +/* + * The Mobility Lab (TML) + * Submitted by Pierre Castella + */ +#define TML_VID 0x1B91 /* Vendor ID */ +#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 04bd3b7a298..f1c90cfe725 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1,7 +1,7 @@ /* * Garmin GPS driver * - * Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net + * Copyright (C) 2006,2007 Hermann Kneissel herkne@users.sourceforge.net * * The latest version of the driver can be found at * http://sourceforge.net/projects/garmin-gps/ @@ -34,6 +34,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <asm/uaccess.h> +#include <asm/atomic.h> #include <linux/usb.h> #include <linux/usb/serial.h> @@ -52,7 +53,7 @@ static int debug = 0; */ #define VERSION_MAJOR 0 -#define VERSION_MINOR 28 +#define VERSION_MINOR 31 #define _STR(s) #s #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) @@ -141,6 +142,8 @@ struct garmin_data { __u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */ __u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */ __u8 privpkt[4*6]; + atomic_t req_count; + atomic_t resp_count; spinlock_t lock; struct list_head pktlist; }; @@ -171,8 +174,6 @@ struct garmin_data { #define CLEAR_HALT_REQUIRED 0x0001 #define FLAGS_QUEUING 0x0100 -#define FLAGS_APP_RESP_SEEN 0x0200 -#define FLAGS_APP_REQ_SEEN 0x0400 #define FLAGS_DROP_DATA 0x0800 #define FLAGS_GSP_SKIP 0x1000 @@ -186,7 +187,8 @@ struct garmin_data { /* function prototypes */ static void gsp_next_packet(struct garmin_data * garmin_data_p); static int garmin_write_bulk(struct usb_serial_port *port, - const unsigned char *buf, int count); + const unsigned char *buf, int count, + int dismiss_ack); /* some special packets to be send or received */ static unsigned char const GARMIN_START_SESSION_REQ[] @@ -233,9 +235,7 @@ static struct usb_driver garmin_driver = { static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p) { - return ((garmin_data_p->flags - & (FLAGS_APP_REQ_SEEN|FLAGS_APP_RESP_SEEN)) - == FLAGS_APP_REQ_SEEN); + return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count); } @@ -463,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) usbdata[2] = __cpu_to_le32(size); garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer, - GARMIN_PKTHDR_LENGTH+size); + GARMIN_PKTHDR_LENGTH+size, 0); /* if this was an abort-transfer command, flush all queued data. */ @@ -818,7 +818,7 @@ static int nat_receive(struct garmin_data * garmin_data_p, if (garmin_data_p->insize >= len) { garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer, - len); + len, 0); garmin_data_p->insize = 0; /* if this was an abort-transfer command, @@ -893,10 +893,11 @@ static int garmin_clear(struct garmin_data * garmin_data_p) struct usb_serial_port *port = garmin_data_p->port; - if (port != NULL && garmin_data_p->flags & FLAGS_APP_RESP_SEEN) { + if (port != NULL && atomic_read(&garmin_data_p->resp_count)) { /* send a terminate command */ status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ, - sizeof(GARMIN_STOP_TRANSFER_REQ)); + sizeof(GARMIN_STOP_TRANSFER_REQ), + 1); } /* flush all queued data */ @@ -939,7 +940,8 @@ static int garmin_init_session(struct usb_serial_port *port) dbg("%s - starting session ...", __FUNCTION__); garmin_data_p->state = STATE_ACTIVE; status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ, - sizeof(GARMIN_START_SESSION_REQ)); + sizeof(GARMIN_START_SESSION_REQ), + 0); if (status >= 0) { @@ -950,7 +952,8 @@ static int garmin_init_session(struct usb_serial_port *port) /* not needed, but the win32 driver does it too ... */ status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ2, - sizeof(GARMIN_START_SESSION_REQ2)); + sizeof(GARMIN_START_SESSION_REQ2), + 0); if (status >= 0) { status = 0; spin_lock_irqsave(&garmin_data_p->lock, flags); @@ -987,6 +990,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp) garmin_data_p->mode = initial_mode; garmin_data_p->count = 0; garmin_data_p->flags = 0; + atomic_set(&garmin_data_p->req_count, 0); + atomic_set(&garmin_data_p->resp_count, 0); spin_unlock_irqrestore(&garmin_data_p->lock, flags); /* shutdown any bulk reads that might be going on */ @@ -1035,28 +1040,39 @@ static void garmin_write_bulk_callback (struct urb *urb) { unsigned long flags; struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); int status = urb->status; - /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree (urb->transfer_buffer); + if (port) { + struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); - dbg("%s - port %d", __FUNCTION__, port->number); + dbg("%s - port %d", __FUNCTION__, port->number); - if (status) { - dbg("%s - nonzero write bulk status received: %d", - __FUNCTION__, status); - spin_lock_irqsave(&garmin_data_p->lock, flags); - garmin_data_p->flags |= CLEAR_HALT_REQUIRED; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer) + && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) { + gsp_send_ack(garmin_data_p, ((__u8 *)urb->transfer_buffer)[4]); + } + + if (status) { + dbg("%s - nonzero write bulk status received: %d", + __FUNCTION__, urb->status); + spin_lock_irqsave(&garmin_data_p->lock, flags); + garmin_data_p->flags |= CLEAR_HALT_REQUIRED; + spin_unlock_irqrestore(&garmin_data_p->lock, flags); + } + + usb_serial_port_softint(port); } - usb_serial_port_softint(port); + /* Ignore errors that resulted from garmin_write_bulk with dismiss_ack=1 */ + + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree (urb->transfer_buffer); } static int garmin_write_bulk (struct usb_serial_port *port, - const unsigned char *buf, int count) + const unsigned char *buf, int count, + int dismiss_ack) { unsigned long flags; struct usb_serial *serial = port->serial; @@ -1093,13 +1109,12 @@ static int garmin_write_bulk (struct usb_serial_port *port, usb_sndbulkpipe (serial->dev, port->bulk_out_endpointAddress), buffer, count, - garmin_write_bulk_callback, port); + garmin_write_bulk_callback, + dismiss_ack ? NULL : port); urb->transfer_flags |= URB_ZERO_PACKET; if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { - spin_lock_irqsave(&garmin_data_p->lock, flags); - garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + atomic_inc(&garmin_data_p->req_count); if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { pkt_clear(garmin_data_p); garmin_data_p->state = STATE_GSP_WAIT_DATA; @@ -1114,13 +1129,6 @@ static int garmin_write_bulk (struct usb_serial_port *port, "failed with status = %d\n", __FUNCTION__, status); count = status; - } else { - - if (GARMIN_LAYERID_APPL == getLayerId(buffer) - && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) { - - gsp_send_ack(garmin_data_p, buffer[4]); - } } /* we are done with this urb, so let the host driver @@ -1135,7 +1143,6 @@ static int garmin_write_bulk (struct usb_serial_port *port, static int garmin_write (struct usb_serial_port *port, const unsigned char *buf, int count) { - unsigned long flags; int pktid, pktsiz, len; struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; @@ -1186,9 +1193,7 @@ static int garmin_write (struct usb_serial_port *port, break; case PRIV_PKTID_RESET_REQ: - spin_lock_irqsave(&garmin_data_p->lock, flags); - garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + atomic_inc(&garmin_data_p->req_count); break; case PRIV_PKTID_SET_DEF_MODE: @@ -1241,8 +1246,6 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port) static void garmin_read_process(struct garmin_data * garmin_data_p, unsigned char *data, unsigned data_length) { - unsigned long flags; - if (garmin_data_p->flags & FLAGS_DROP_DATA) { /* abort-transfer cmd is actice */ dbg("%s - pkt dropped", __FUNCTION__); @@ -1254,9 +1257,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, the device */ if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, sizeof(GARMIN_APP_LAYER_REPLY))) { - spin_lock_irqsave(&garmin_data_p->lock, flags); - garmin_data_p->flags |= FLAGS_APP_RESP_SEEN; - spin_unlock_irqrestore(&garmin_data_p->lock, flags); + atomic_inc(&garmin_data_p->resp_count); } /* if throttling is active or postprecessing is required diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 0455c1552ae..6a3a704b584 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -545,6 +545,7 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ + { USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 84c12b5f127..a18659e0700 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -108,8 +108,10 @@ static int option_send_setup(struct usb_serial_port *port); #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E600 0x1001 #define HUAWEI_PRODUCT_E220 0x1003 +#define HUAWEI_PRODUCT_E220BIS 0x1004 #define NOVATELWIRELESS_VENDOR_ID 0x1410 +#define DELL_VENDOR_ID 0x413C #define ANYDATA_VENDOR_ID 0x16d5 #define ANYDATA_PRODUCT_ADU_E100A 0x6501 @@ -119,8 +121,6 @@ static int option_send_setup(struct usb_serial_port *port); #define BANDRICH_PRODUCT_C100_1 0x1002 #define BANDRICH_PRODUCT_C100_2 0x1003 -#define DELL_VENDOR_ID 0x413C - static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -159,6 +159,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, + { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */ @@ -171,11 +172,17 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8117) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8128) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, - { USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index d7db71eca52..64f3f66a7a3 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -817,23 +817,6 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, __FUNCTION__, port->number, cmd, arg); switch (cmd) { - case TCGETS: - if (copy_to_user(user_arg, port->tty->termios, - sizeof(struct ktermios))) { - return -EFAULT; - } - return 0; - - case TCSETS: - case TCSETSW: /* FIXME: this is not the same! */ - case TCSETSF: /* FIXME: this is not the same! */ - if (copy_from_user(port->tty->termios, user_arg, - sizeof(struct ktermios))) { - return -EFAULT; - } - oti6858_set_termios(port, NULL); - return 0; - case TCFLSH: /* FIXME */ return 0; diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 86899d55d8d..51669b7622b 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -74,13 +74,13 @@ #include <linux/usb/serial.h> -#ifndef CONFIG_USB_SAFE_PADDED -#define CONFIG_USB_SAFE_PADDED 0 +#ifndef CONFIG_USB_SERIAL_SAFE_PADDED +#define CONFIG_USB_SERIAL_SAFE_PADDED 0 #endif static int debug; static int safe = 1; -static int padded = CONFIG_USB_SAFE_PADDED; +static int padded = CONFIG_USB_SERIAL_SAFE_PADDED; #define DRIVER_VERSION "v0.0b" #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com" diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 7d84a7647e8..30e08c0bcdc 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -104,6 +104,8 @@ static struct usb_device_id id_table [] = { .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h index 4ce6f62a6f3..57229cf6647 100644 --- a/drivers/usb/serial/visor.h +++ b/drivers/usb/serial/visor.h @@ -48,6 +48,9 @@ #define SONY_CLIE_UX50_ID 0x0144 #define SONY_CLIE_TJ25_ID 0x0169 +#define ACER_VENDOR_ID 0x0502 +#define ACER_S10_ID 0x0001 + #define SAMSUNG_VENDOR_ID 0x04E8 #define SAMSUNG_SCH_I330_ID 0x8001 #define SAMSUNG_SPH_I500_ID 0x6601 diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 47e56079925..1ba19eaa197 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -285,15 +285,10 @@ static int device_reset(struct scsi_cmnd *srb) US_DEBUGP("%s called\n", __FUNCTION__); - result = usb_autopm_get_interface(us->pusb_intf); - if (result == 0) { - - /* lock the device pointers and do the reset */ - mutex_lock(&(us->dev_mutex)); - result = us->transport_reset(us); - mutex_unlock(&us->dev_mutex); - usb_autopm_put_interface(us->pusb_intf); - } + /* lock the device pointers and do the reset */ + mutex_lock(&(us->dev_mutex)); + result = us->transport_reset(us); + mutex_unlock(&us->dev_mutex); return result < 0 ? FAILED : SUCCESS; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d8d008d4294..c6b78ba815e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -342,12 +342,19 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, US_FL_FIX_CAPACITY), /* Reported by Emil Larsson <emil@swip.net> */ -UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100, +UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, "NIKON", "NIKON DSC D80", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Ortwin Glueck <odi@odi.ch> */ +UNUSUAL_DEV( 0x04b0, 0x0413, 0x0110, 0x0110, + "NIKON", + "NIKON DSC D40", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* BENQ DC5330 * Reported by Manuel Fombuena <mfombuena@ya.com> and * Frank Copeland <fjc@thingy.apana.org.au> */ @@ -897,6 +904,22 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com> + * This USB MP3/AVI player device fails and disconnects if more than 128 + * sectors (64kB) are read/written in a single command, and may be present + * at least in the following products: + * "Magnex Digital Video Panel DVP 1800" + * "MP4 AIGO 4GB SLOT SD" + * "Teclast TL-C260 MP3" + * "i.Meizu PMP MP3/MP4" + * "Speed MV8 MP4 Audio Player" + */ +UNUSUAL_DEV( 0x071b, 0x3203, 0x0100, 0x0100, + "RockChip", + "ROCK MP3", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* Reported by Olivier Blondeau <zeitoun@gmail.com> */ UNUSUAL_DEV( 0x0727, 0x0306, 0x0100, 0x0100, "ATMEL", @@ -1393,6 +1416,13 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), +/* Reported by Ricardo Barberis <ricardo@dattatec.com> */ +UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, + "Sony Ericsson", + "P1i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, "Sony Ericsson", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 28842d208bb..59181667066 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); -/* These are used to make sure the module doesn't unload before all the - * threads have exited. - */ -static atomic_t total_threads = ATOMIC_INIT(0); -static DECLARE_COMPLETION(threads_gone); - - /* * The entries in this table correspond, line for line, * with the entries of us_unusual_dev_list[]. @@ -191,14 +184,16 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) { struct us_data *us = usb_get_intfdata(iface); - US_DEBUGP("%s\n", __FUNCTION__); - /* Wait until no command is running */ mutex_lock(&us->dev_mutex); + US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_SUSPEND); + /* When runtime PM is working, we'll set a flag to indicate + * whether we should autoresume when a SCSI request arrives. */ + mutex_unlock(&us->dev_mutex); return 0; } @@ -207,11 +202,13 @@ static int storage_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); - US_DEBUGP("%s\n", __FUNCTION__); + mutex_lock(&us->dev_mutex); + US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_RESUME); + mutex_unlock(&us->dev_mutex); return 0; } @@ -309,7 +306,6 @@ static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); - int autopm_rc; for(;;) { US_DEBUGP("*** thread sleeping.\n"); @@ -318,9 +314,6 @@ static int usb_stor_control_thread(void * __us) US_DEBUGP("*** thread awakened.\n"); - /* Autoresume the device */ - autopm_rc = usb_autopm_get_interface(us->pusb_intf); - /* lock the device pointers */ mutex_lock(&(us->dev_mutex)); @@ -379,12 +372,6 @@ static int usb_stor_control_thread(void * __us) us->srb->result = SAM_STAT_GOOD; } - /* Did the autoresume fail? */ - else if (autopm_rc < 0) { - US_DEBUGP("Could not wake device\n"); - us->srb->result = DID_ERROR << 16; - } - /* we've got a command, let's do it! */ else { US_DEBUG(usb_stor_show_command(us->srb)); @@ -427,10 +414,6 @@ SkipForAbort: /* unlock the device pointers */ mutex_unlock(&us->dev_mutex); - - /* Start an autosuspend */ - if (autopm_rc == 0) - usb_autopm_put_interface(us->pusb_intf); } /* for (;;) */ /* Wait until we are told to stop */ @@ -879,9 +862,6 @@ static void quiesce_and_remove_host(struct us_data *us) usb_stor_stop_transport(us); wake_up(&us->delay_wait); - /* It doesn't matter if the SCSI-scanning thread is still running. - * The thread will exit when it sees the DISCONNECTING flag. */ - /* queuecommand won't accept any new commands and the control * thread won't execute a previously-queued command. If there * is such a command pending, complete it with an error. */ @@ -891,12 +871,16 @@ static void quiesce_and_remove_host(struct us_data *us) scsi_lock(host); us->srb->scsi_done(us->srb); us->srb = NULL; + complete(&us->notify); /* in case of an abort */ scsi_unlock(host); } mutex_unlock(&us->dev_mutex); /* Now we own no commands so it's safe to remove the SCSI host */ scsi_remove_host(host); + + /* Wait for the SCSI-scanning thread to stop */ + wait_for_completion(&us->scanning_done); } /* Second stage of disconnect processing: deallocate all resources */ @@ -947,9 +931,7 @@ retry: /* Should we unbind if no devices were detected? */ } - scsi_host_put(us_to_host(us)); - usb_autopm_put_interface(us->pusb_intf); - complete_and_exit(&threads_gone, 0); + complete_and_exit(&us->scanning_done, 0); } @@ -984,6 +966,7 @@ static int storage_probe(struct usb_interface *intf, init_MUTEX_LOCKED(&(us->sema)); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); + init_completion(&us->scanning_done); /* Associate the us_data structure with the USB device */ result = associate_dev(us, intf); @@ -1033,12 +1016,6 @@ static int storage_probe(struct usb_interface *intf, goto BadDevice; } - /* Take a reference to the host for the scanning thread and - * count it among all the threads we have launched. Then - * start it up. */ - scsi_host_get(us_to_host(us)); - atomic_inc(&total_threads); - usb_autopm_get_interface(intf); /* dropped in the scanning thread */ wake_up_process(th); return 0; @@ -1076,7 +1053,6 @@ static struct usb_driver usb_storage_driver = { .pre_reset = storage_pre_reset, .post_reset = storage_post_reset, .id_table = storage_usb_ids, - .supports_autosuspend = 1, }; static int __init usb_stor_init(void) @@ -1104,16 +1080,6 @@ static void __exit usb_stor_exit(void) US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; - /* Don't return until all of our control and scanning threads - * have exited. Since each thread signals threads_gone as its - * last act, we have to call wait_for_completion the right number - * of times. - */ - while (atomic_read(&total_threads) > 0) { - wait_for_completion(&threads_gone); - atomic_dec(&total_threads); - } - usb_usual_clear_present(USB_US_TYPE_STOR); } diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 6445665b157..8d87503e256 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -150,6 +150,7 @@ struct us_data { struct semaphore sema; /* to sleep thread on */ struct completion notify; /* thread begin/end */ wait_queue_head_t delay_wait; /* wait during scan, reset */ + struct completion scanning_done; /* wait for scan thread */ /* subdriver information */ void *extra; /* Any extra data */ |