diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-23 08:12:54 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-23 08:12:54 -0700 |
commit | 641e22e04c48af5d813f119c55336e02a22756f5 (patch) | |
tree | 9f7f693e8dd030e1d28585893e6e53bd86b1208c | |
parent | 31f6e1bd3b58c9a67e5ea0c2d372fbf5fc9e326d (diff) | |
parent | fa91d43b914b77637653d984416e17e182f7b807 (diff) | |
download | linux-3.10-641e22e04c48af5d813f119c55336e02a22756f5.tar.gz linux-3.10-641e22e04c48af5d813f119c55336e02a22756f5.tar.bz2 linux-3.10-641e22e04c48af5d813f119c55336e02a22756f5.zip |
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: (29 commits)
USB: Add support for Olimex arm-usb-ocd JTAG interface serial port
USB: Add support for Sierra Wireless Aircard 595U
USB: ldusb bugfix
USB: ftdi_sio: Add USB Product Id for OpenDCC
USB: fix ratelimit call semantics
USB: handle errors in power/level attribute
USB: make the autosuspend workqueue thread freezable
USB: Fix USB OHCI Subvendor for Toshiba Portege 4000
USB: usblp: Use correct DMA address in case of probe error
USB: Fix debug output of ark3116
USB: Onetouch - switch to using input_dev->dev.parent
USB: don't try to kzalloc 0 bytes
USB: remove short initial timeout for device descriptor fetch
USB: Deref URB after usbmon is done with it
USB: Remove duplicate IDs from option card driver
USB: auerswald: fix file release handler
USB: fsl_usb2_udc: Fix UMTI_WIDE support and a compile warning
USB: set the correct Interrupt interval in usb_bulk_msg
USB: New device PID for ftdi_sio driver
USB: remove unneeded WARN_ON
...
30 files changed, 222 insertions, 102 deletions
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl index e7fc9643340..6996d977bf8 100644 --- a/Documentation/DocBook/gadget.tmpl +++ b/Documentation/DocBook/gadget.tmpl @@ -52,7 +52,7 @@ <toc></toc> -<chapter><title>Introduction</title> +<chapter id="intro"><title>Introduction</title> <para>This document presents a Linux-USB "Gadget" kernel mode diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl index a2ebd651b05..af293606fbe 100644 --- a/Documentation/DocBook/usb.tmpl +++ b/Documentation/DocBook/usb.tmpl @@ -185,7 +185,7 @@ </chapter> -<chapter><title>USB-Standard Types</title> +<chapter id="types"><title>USB-Standard Types</title> <para>In <filename><linux/usb/ch9.h></filename> you will find the USB data types defined in chapter 9 of the USB specification. @@ -197,7 +197,7 @@ </chapter> -<chapter><title>Host-Side Data Types and Macros</title> +<chapter id="hostside"><title>Host-Side Data Types and Macros</title> <para>The host side API exposes several layers to drivers, some of which are more necessary than others. @@ -211,7 +211,7 @@ </chapter> - <chapter><title>USB Core APIs</title> + <chapter id="usbcore"><title>USB Core APIs</title> <para>There are two basic I/O models in the USB API. The most elemental one is asynchronous: drivers submit requests @@ -248,7 +248,7 @@ !Edrivers/usb/core/hub.c </chapter> - <chapter><title>Host Controller APIs</title> + <chapter id="hcd"><title>Host Controller APIs</title> <para>These APIs are only for use by host controller drivers, most of which implement standard register interfaces such as @@ -285,7 +285,7 @@ !Idrivers/usb/core/buffer.c </chapter> - <chapter> + <chapter id="usbfs"> <title>The USB Filesystem (usbfs)</title> <para>This chapter presents the Linux <emphasis>usbfs</emphasis>. @@ -317,7 +317,7 @@ not it has a kernel driver. </para> - <sect1> + <sect1 id="usbfs-files"> <title>What files are in "usbfs"?</title> <para>Conventionally mounted at @@ -356,7 +356,7 @@ </sect1> - <sect1> + <sect1 id="usbfs-fstab"> <title>Mounting and Access Control</title> <para>There are a number of mount options for usbfs, which will @@ -439,7 +439,7 @@ </sect1> - <sect1> + <sect1 id="usbfs-devices"> <title>/proc/bus/usb/devices</title> <para>This file is handy for status viewing tools in user @@ -473,7 +473,7 @@ for (;;) { </para> </sect1> - <sect1> + <sect1 id="usbfs-bbbddd"> <title>/proc/bus/usb/BBB/DDD</title> <para>Use these files in one of these basic ways: @@ -510,7 +510,7 @@ for (;;) { </sect1> - <sect1> + <sect1 id="usbfs-lifecycle"> <title>Life Cycle of User Mode Drivers</title> <para>Such a driver first needs to find a device file @@ -565,7 +565,7 @@ for (;;) { </sect1> - <sect1><title>The ioctl() Requests</title> + <sect1 id="usbfs-ioctl"><title>The ioctl() Requests</title> <para>To use these ioctls, you need to include the following headers in your userspace program: @@ -604,7 +604,7 @@ for (;;) { </para> - <sect2> + <sect2 id="usbfs-mgmt"> <title>Management/Status Requests</title> <para>A number of usbfs requests don't deal very directly @@ -736,7 +736,7 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param) </sect2> - <sect2> + <sect2 id="usbfs-sync"> <title>Synchronous I/O Support</title> <para>Synchronous requests involve the kernel blocking @@ -865,7 +865,7 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param) </variablelist> </sect2> - <sect2> + <sect2 id="usbfs-async"> <title>Asynchronous I/O Support</title> <para>As mentioned above, there are situations where it may be diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 5a21f06bf8a..675ac99a79c 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -91,6 +91,22 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) "CDC descriptors on config\n"); } + /* Maybe CDC descriptors are after the endpoint? This bug has + * been seen on some 2Wire Inc RNDIS-ish products. + */ + if (len == 0) { + struct usb_host_endpoint *hep; + + hep = intf->cur_altsetting->endpoint; + if (hep) { + buf = hep->extra; + len = hep->extralen; + } + if (len) + dev_dbg(&intf->dev, + "CDC descriptors on endpoint\n"); + } + /* this assumes that if there's a non-RNDIS vendor variant * of cdc-acm, it'll fail RNDIS requests cleanly. */ diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 980e4aaa97a..cd991a0f75b 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -515,6 +515,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) dev_err(&intf->dev, "dev can't take %u byte packets (max %u)\n", dev->hard_mtu, tmp); + retval = -EINVAL; goto fail_and_release; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f9cd42d058b..5b16d9a1269 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1252,20 +1252,23 @@ EXPORT_SYMBOL_GPL(usbnet_probe); /*-------------------------------------------------------------------------*/ -/* FIXME these suspend/resume methods assume non-CDC style - * devices, with only one interface. +/* + * suspend the whole driver as soon as the first interface is suspended + * resume only when the last interface is resumed */ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); - /* accelerate emptying of the rx and queues, to avoid - * having everything error out. - */ - netif_device_detach (dev->net); - (void) unlink_urbs (dev, &dev->rxq); - (void) unlink_urbs (dev, &dev->txq); + if (!dev->suspend_count++) { + /* accelerate emptying of the rx and queues, to avoid + * having everything error out. + */ + netif_device_detach (dev->net); + (void) unlink_urbs (dev, &dev->rxq); + (void) unlink_urbs (dev, &dev->txq); + } return 0; } EXPORT_SYMBOL_GPL(usbnet_suspend); @@ -1274,8 +1277,10 @@ int usbnet_resume (struct usb_interface *intf) { struct usbnet *dev = usb_get_intfdata(intf); - netif_device_attach (dev->net); - tasklet_schedule (&dev->bh); + if (!--dev->suspend_count) { + netif_device_attach (dev->net); + tasklet_schedule (&dev->bh); + } return 0; } EXPORT_SYMBOL_GPL(usbnet_resume); diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h index 82db5a8e528..a3f8b9e7bc0 100644 --- a/drivers/net/usb/usbnet.h +++ b/drivers/net/usb/usbnet.h @@ -32,6 +32,7 @@ struct usbnet { const char *driver_name; wait_queue_head_t *wait; struct mutex phy_mutex; + unsigned char suspend_count; /* i/o info: pipes etc */ unsigned in, out; diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 15e740e3a5c..7b1edfe46b2 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1003,7 +1003,7 @@ abort: usblp->writebuf, usblp->writeurb->transfer_dma); if (usblp->readbuf) usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, - usblp->readbuf, usblp->writeurb->transfer_dma); + usblp->readbuf, usblp->readurb->transfer_dma); kfree(usblp->statusbuf); kfree(usblp->device_id_string); usb_free_urb(usblp->writeurb); diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index bfb3731d42d..2d4fd530e5e 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -185,10 +185,12 @@ static int usb_parse_interface(struct device *ddev, int cfgno, num_ep = USB_MAXENDPOINTS; } - len = sizeof(struct usb_host_endpoint) * num_ep; - alt->endpoint = kzalloc(len, GFP_KERNEL); - if (!alt->endpoint) - return -ENOMEM; + if (num_ep > 0) { /* Can't allocate 0 bytes */ + len = sizeof(struct usb_host_endpoint) * num_ep; + alt->endpoint = kzalloc(len, GFP_KERNEL); + if (!alt->endpoint) + return -ENOMEM; + } /* Parse all the endpoint descriptors */ n = 0; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index b9f7f90aef8..2619986e530 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -983,7 +983,10 @@ static int autosuspend_check(struct usb_device *udev) #else -#define autosuspend_check(udev) 0 +static inline int autosuspend_check(struct usb_device *udev) +{ + return 0; +} #endif /* CONFIG_USB_SUSPEND */ @@ -1041,7 +1044,6 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (status < 0) goto done; } - cancel_delayed_work(&udev->autosuspend); /* Suspend all the interfaces and then udev itself */ if (udev->actconfig) { @@ -1062,9 +1064,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) usb_resume_interface(intf); } + /* Try another autosuspend when the interfaces aren't busy */ + if (udev->auto_pm) + autosuspend_check(udev); + /* If the suspend succeeded, propagate it up the tree */ - } else if (parent) - usb_autosuspend_device(parent); + } else { + cancel_delayed_work(&udev->autosuspend); + if (parent) + usb_autosuspend_device(parent); + } done: // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); @@ -1475,6 +1484,7 @@ int usb_external_resume_device(struct usb_device *udev) usb_pm_lock(udev); udev->auto_pm = 0; status = usb_resume_both(udev); + udev->last_busy = jiffies; usb_pm_unlock(udev); /* Now that the device is awake, we can start trying to autosuspend diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 40cf882293e..e277258df38 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1018,8 +1018,8 @@ done: atomic_dec (&urb->use_count); if (urb->reject) wake_up (&usb_kill_urb_queue); - usb_put_urb (urb); usbmon_urb_submit_error(&hcd->self, urb, status); + usb_put_urb (urb); } return status; } @@ -1175,10 +1175,6 @@ void usb_hcd_endpoint_disable (struct usb_device *udev, struct urb *urb; hcd = bus_to_hcd(udev->bus); - - WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && - udev->state != USB_STATE_NOTATTACHED); - local_irq_disable (); /* ep is already gone from udev->ep_{in,out}[]; no more submits */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f6b74a678de..caaa46f2dec 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2201,14 +2201,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, continue; } - /* Use a short timeout the first time through, - * so that recalcitrant full-speed devices with - * 8- or 16-byte ep0-maxpackets won't slow things - * down tremendously by NAKing the unexpectedly - * early status stage. Also, retry on all errors; - * some devices are flakey. - * 255 is for WUSB devices, we actually need to use 512. - * WUSB1.0[4.8.1]. + /* Retry on all errors; some devices are flakey. + * 255 is for WUSB devices, we actually need to use + * 512 (WUSB1.0[4.8.1]). */ for (j = 0; j < 3; ++j) { buf->bMaxPacketSize0 = 0; @@ -2216,7 +2211,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_DT_DEVICE << 8, 0, buf, GET_DESCRIPTOR_BUFSIZE, - (i ? USB_CTRL_GET_TIMEOUT : 1000)); + USB_CTRL_GET_TIMEOUT); switch (buf->bMaxPacketSize0) { case 8: case 16: case 32: case 64: case 255: if (buf->bDescriptorType == @@ -2426,10 +2421,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (portchange & USB_PORT_STAT_C_CONNECTION) { status = hub_port_debounce(hub, port1); - if (status < 0 && printk_ratelimit()) { - dev_err (hub_dev, - "connect-debounce failed, port %d disabled\n", - port1); + if (status < 0) { + if (printk_ratelimit()) + dev_err (hub_dev, "connect-debounce failed, " + "port %d disabled\n", port1); goto done; } portstatus = status; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b7434787db5..f9fed34bf7d 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -221,15 +221,10 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { - int interval; - - if (usb_dev->speed == USB_SPEED_HIGH) - interval = 1 << min(15, ep->desc.bInterval - 1); - else - interval = ep->desc.bInterval; pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); usb_fill_int_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, NULL, interval); + usb_api_blocking_completion, NULL, + ep->desc.bInterval); } else usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index e7c98237748..be37c863fdf 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -232,12 +232,15 @@ set_level(struct device *dev, struct device_attribute *attr, int len = count; char *cp; int rc = 0; + int old_autosuspend_disabled, old_autoresume_disabled; cp = memchr(buf, '\n', count); if (cp) len = cp - buf; usb_lock_device(udev); + old_autosuspend_disabled = udev->autosuspend_disabled; + old_autoresume_disabled = udev->autoresume_disabled; /* Setting the flags without calling usb_pm_lock is a subject to * races, but who cares... @@ -263,6 +266,10 @@ set_level(struct device *dev, struct device_attribute *attr, } else rc = -EINVAL; + if (rc) { + udev->autosuspend_disabled = old_autosuspend_disabled; + udev->autoresume_disabled = old_autoresume_disabled; + } usb_unlock_device(udev); return (rc < 0 ? rc : count); } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 18ddc5e67e3..80627b6a2bf 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -205,7 +205,11 @@ struct device_type usb_device_type = { static int ksuspend_usb_init(void) { - ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd"); + /* This workqueue is supposed to be both freezable and + * singlethreaded. Its job doesn't justify running on more + * than one CPU. + */ + ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd"); if (!ksuspend_usb_wq) return -ENOMEM; return 0; diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 157054ea397..3ca2b3159f0 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -228,13 +228,15 @@ static int dr_controller_setup(struct fsl_udc *udc) /* Config PHY interface */ portctrl = fsl_readl(&dr_regs->portsc1); - portctrl &= ~PORTSCX_PHY_TYPE_SEL; + portctrl &= ~(PORTSCX_PHY_TYPE_SEL & PORTSCX_PORT_WIDTH); switch (udc->phy_mode) { case FSL_USB2_PHY_ULPI: portctrl |= PORTSCX_PTS_ULPI; break; - case FSL_USB2_PHY_UTMI: case FSL_USB2_PHY_UTMI_WIDE: + portctrl |= PORTSCX_PTW_16BIT; + /* fall through */ + case FSL_USB2_PHY_UTMI: portctrl |= PORTSCX_PTS_UTMI; break; case FSL_USB2_PHY_SERIAL: @@ -625,7 +627,7 @@ static void fsl_free_buffer(struct usb_ep *_ep, void *buf, struct fsl_ep *ep; if (!_ep) - return NULL; + return; ep = container_of(_ep, struct fsl_ep, ep); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 79705609fd0..ca62cb58322 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -137,7 +137,7 @@ static const struct pci_device_id ohci_pci_quirks[] = { /* Toshiba portege 4000 */ .vendor = PCI_VENDOR_ID_AL, .device = 0x5237, - .subvendor = PCI_VENDOR_ID_TOSHIBA_2, + .subvendor = PCI_VENDOR_ID_TOSHIBA, .subdevice = 0x0004, .driver_data = (unsigned long) broken_suspend, }, diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 20861650905..c225159ca3d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -44,6 +44,7 @@ #define EHCI_USBSTS 4 /* status register */ #define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ #define EHCI_USBINTR 8 /* interrupt register */ +#define EHCI_CONFIGFLAG 0x40 /* configured flag register */ #define EHCI_USBLEGSUP 0 /* legacy support register */ #define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ #define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ @@ -216,6 +217,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) u32 hcc_params, val; u8 offset, cap_length; int count = 256/4; + int tried_handoff = 0; if (!mmio_resource_enabled(pdev, 0)) return; @@ -273,6 +275,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) */ msec = 5000; while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { + tried_handoff = 1; msleep(10); msec -= 10; pci_read_config_dword(pdev, offset, &cap); @@ -292,6 +295,12 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); + + /* If the BIOS ever owned the controller then we + * can't expect any power sessions to remain intact. + */ + if (tried_handoff) + writel(0, op_reg_base + EHCI_CONFIGFLAG); break; case 0: /* illegal reserved capability */ cap = 0; diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index ff0dba01f1c..e98df2ee990 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -57,6 +57,13 @@ #include <asm/system.h> #include <asm/byteorder.h> #include "../core/hcd.h" + + /* FIXME ohci.h is ONLY for internal use by the OHCI driver. + * If you're going to try stuff like this, you need to split + * out shareable stuff (register declarations?) into its own + * file, maybe name <linux/usb/ohci.h> + */ + #include "ohci.h" #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ @@ -173,11 +180,6 @@ struct u132_ring { struct u132_endp *curr_endp; struct delayed_work scheduler; }; -#define OHCI_QUIRK_AMD756 0x01 -#define OHCI_QUIRK_SUPERIO 0x02 -#define OHCI_QUIRK_INITRESET 0x04 -#define OHCI_BIG_ENDIAN 0x08 -#define OHCI_QUIRK_ZFMICRO 0x10 struct u132 { struct kref kref; struct list_head u132_list; diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 88fb56d5db8..cac1500cba6 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -1822,16 +1822,10 @@ static int auerchar_release (struct inode *inode, struct file *file) pauerswald_t cp; dbg("release"); - /* get the mutexes */ - if (down_interruptible (&ccp->mutex)) { - return -ERESTARTSYS; - } + down(&ccp->mutex); cp = ccp->auerdev; if (cp) { - if (down_interruptible (&cp->mutex)) { - up (&ccp->mutex); - return -ERESTARTSYS; - } + down(&cp->mutex); /* remove an open service */ auerswald_removeservice (cp, &ccp->scontext); /* detach from device */ diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index e2172e5cf15..e0f122e131d 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -73,6 +73,13 @@ static struct list_head ftdi_static_list; #include "usb_u132.h" #include <asm/io.h> #include "../core/hcd.h" + + /* FIXME ohci.h is ONLY for internal use by the OHCI driver. + * If you're going to try stuff like this, you need to split + * out shareable stuff (register declarations?) into its own + * file, maybe name <linux/usb/ohci.h> + */ + #include "../host/ohci.h" /* Define these values to match your devices*/ #define USB_FTDI_ELAN_VENDOR_ID 0x0403 @@ -2300,10 +2307,7 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi) offsetof(struct ohci_regs, member), 0, data); #define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \ offsetof(struct ohci_regs, member), 0, data); -#define OHCI_QUIRK_AMD756 0x01 -#define OHCI_QUIRK_SUPERIO 0x02 -#define OHCI_QUIRK_INITRESET 0x04 -#define OHCI_BIG_ENDIAN 0x08 + #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ OHCI_INTR_WDH) diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 11555bde655..7bad4940476 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -165,6 +165,8 @@ struct ld_usb { size_t interrupt_in_endpoint_size; int interrupt_in_running; int interrupt_in_done; + int buffer_overflow; + spinlock_t rbsl; char* interrupt_out_buffer; struct usb_endpoint_descriptor* interrupt_out_endpoint; @@ -230,10 +232,12 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) } else { dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", __FUNCTION__, urb->status); + spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } } + spin_lock(&dev->rbsl); if (urb->actual_length > 0) { next_ring_head = (dev->ring_head+1) % ring_buffer_size; if (next_ring_head != dev->ring_tail) { @@ -244,21 +248,25 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) dev->ring_head = next_ring_head; dbg_info(&dev->intf->dev, "%s: received %d bytes\n", __FUNCTION__, urb->actual_length); - } else + } else { dev_warn(&dev->intf->dev, "Ring buffer overflow, %d bytes dropped\n", urb->actual_length); + dev->buffer_overflow = 1; + } } resubmit: /* resubmit if we're still running */ - if (dev->interrupt_in_running && dev->intf) { + if (dev->interrupt_in_running && !dev->buffer_overflow && dev->intf) { retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); - if (retval) + if (retval) { dev_err(&dev->intf->dev, "usb_submit_urb failed (%d)\n", retval); + dev->buffer_overflow = 1; + } } - + spin_unlock(&dev->rbsl); exit: dev->interrupt_in_done = 1; wake_up_interruptible(&dev->read_wait); @@ -330,6 +338,7 @@ static int ld_usb_open(struct inode *inode, struct file *file) /* initialize in direction */ dev->ring_head = 0; dev->ring_tail = 0; + dev->buffer_overflow = 0; usb_fill_int_urb(dev->interrupt_in_urb, interface_to_usbdev(interface), usb_rcvintpipe(interface_to_usbdev(interface), @@ -439,6 +448,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, size_t *actual_buffer; size_t bytes_to_read; int retval = 0; + int rv; dev = file->private_data; @@ -460,7 +470,10 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, } /* wait for data */ + spin_lock_irq(&dev->rbsl); if (dev->ring_head == dev->ring_tail) { + dev->interrupt_in_done = 0; + spin_unlock_irq(&dev->rbsl); if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; goto unlock_exit; @@ -468,6 +481,8 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); if (retval < 0) goto unlock_exit; + } else { + spin_unlock_irq(&dev->rbsl); } /* actual_buffer contains actual_length + interrupt_in_buffer */ @@ -486,6 +501,17 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, retval = bytes_to_read; + spin_lock_irq(&dev->rbsl); + if (dev->buffer_overflow) { + dev->buffer_overflow = 0; + spin_unlock_irq(&dev->rbsl); + rv = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + if (rv < 0) + dev->buffer_overflow = 1; + } else { + spin_unlock_irq(&dev->rbsl); + } + unlock_exit: /* unlock the device */ up(&dev->sem); @@ -635,6 +661,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * goto exit; } init_MUTEX(&dev->sem); + spin_lock_init(&dev->rbsl); dev->intf = intf; init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->write_wait); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index ea2175bb227..fe437125f14 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -63,7 +63,8 @@ static inline void ARK3116_RCV(struct usb_serial *serial, int seq, request, requesttype, value, index, buf, 0x0000001, 1000); if (result) - dbg("%03d < %d bytes [0x%02X]", seq, result, buf[0]); + dbg("%03d < %d bytes [0x%02X]", seq, result, + ((unsigned char *)buf)[0]); else dbg("%03d < 0 bytes", seq); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 95a1805b064..2353679f601 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -273,12 +273,18 @@ static __u16 product; /* struct ftdi_sio_quirk is used by devices requiring special attention. */ struct ftdi_sio_quirk { + int (*probe)(struct usb_serial *); void (*setup)(struct usb_serial *); /* Special settings during startup. */ }; +static int ftdi_olimex_probe (struct usb_serial *serial); static void ftdi_USB_UIRT_setup (struct usb_serial *serial); static void ftdi_HE_TIRA1_setup (struct usb_serial *serial); +static struct ftdi_sio_quirk ftdi_olimex_quirk = { + .probe = ftdi_olimex_probe, +}; + static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { .setup = ftdi_USB_UIRT_setup, }; @@ -319,6 +325,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, @@ -525,6 +532,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), + .driver_info = (kernel_ulong_t)&ftdi_olimex_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -669,7 +679,7 @@ static struct usb_serial_driver ftdi_sio_device = { /* * *************************************************************************** - * Utlity functions + * Utility functions * *************************************************************************** */ @@ -1171,9 +1181,17 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) /* Probe function to check for special devices */ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id) { + struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info; + + if (quirk && quirk->probe) { + int ret = quirk->probe(serial); + if (ret != 0) + return ret; + } + usb_set_serial_data(serial, (void *)id->driver_info); - return (0); + return 0; } static int ftdi_sio_port_probe(struct usb_serial_port *port) @@ -1268,6 +1286,24 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) priv->force_rtscts = 1; } /* ftdi_HE_TIRA1_setup */ +/* + * First port on Olimex arm-usb-ocd is reserved for JTAG interface + * and can be accessed from userspace using openocd. + */ +static int ftdi_olimex_probe(struct usb_serial *serial) +{ + struct usb_device *udev = serial->dev; + struct usb_interface *interface = serial->interface; + + dbg("%s",__FUNCTION__); + + if (interface == udev->actconfig->interface[0]) { + info("Ignoring reserved serial port on Olimex arm-usb-ocd\n"); + return -ENODEV; + } + + return 0; +} /* ftdi_shutdown is called from usbserial:usb_serial_disconnect * it is called when the usb device is disconnected diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 77ad0a09b38..33aee904724 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -60,6 +60,9 @@ /* DMX4ALL DMX Interfaces */ #define FTDI_DMX4ALL 0xC850 +/* OpenDCC (www.opendcc.de) product id */ +#define FTDI_OPENDCC_PID 0xBFD8 + /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ /* they use the ftdi chipset for the USB interface and the vendor id is the same */ #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ @@ -518,6 +521,15 @@ #define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ #define FTDI_IBS_PROD_PID 0xff3f /* future device */ +/* + * MaxStream devices www.maxstream.net + */ +#define FTDI_MAXSTREAM_PID 0xEE18 /* Xbee PKG-U Module */ + +/* Olimex */ +#define OLIMEX_VID 0x15BA +#define OLIMEX_ARM_USB_OCD_PID 0x0003 + /* 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/mos7840.c b/drivers/usb/serial/mos7840.c index 2366e7b63ec..36620c65107 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -769,11 +769,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) return; } - if (!mos7840_port) { - dbg("%s", "NULL mos7840_port pointer \n"); - return; - } - if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) { dbg("%s", "Port Paranoia failed \n"); return; diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 4adfab988e8..00afc1712c3 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -165,12 +165,10 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; struct usb_serial_port *wport; - struct omninet_data *od = usb_get_serial_port_data(port); int result = 0; dbg("%s - port %d", __FUNCTION__, port->number); - od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL ); wport = serial->port[1]; wport->tty = port->tty; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 8c3f55b080b..89f067d9507 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -165,7 +165,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel XU870 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */ diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 644607de4c1..ac1829c6e8f 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -35,6 +35,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ @@ -60,6 +61,7 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 6d3dad3d1da..d35369392fe 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -84,7 +84,7 @@ resubmit: static int usb_onetouch_open(struct input_dev *dev) { - struct usb_onetouch *onetouch = dev->private; + struct usb_onetouch *onetouch = input_get_drvdata(dev); onetouch->is_open = 1; onetouch->irq->dev = onetouch->udev; @@ -98,7 +98,7 @@ static int usb_onetouch_open(struct input_dev *dev) static void usb_onetouch_close(struct input_dev *dev) { - struct usb_onetouch *onetouch = dev->private; + struct usb_onetouch *onetouch = input_get_drvdata(dev); usb_kill_urb(onetouch->irq); onetouch->is_open = 0; @@ -185,13 +185,14 @@ int onetouch_connect_input(struct us_data *ss) input_dev->name = onetouch->name; input_dev->phys = onetouch->phys; usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &udev->dev; + input_dev->dev.parent = &udev->dev; set_bit(EV_KEY, input_dev->evbit); set_bit(ONETOUCH_BUTTON, input_dev->keybit); clear_bit(0, input_dev->keybit); - input_dev->private = onetouch; + input_set_drvdata(input_dev, onetouch); + input_dev->open = usb_onetouch_open; input_dev->close = usb_onetouch_close; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 8b3145ab775..d230ee72f9c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1179,14 +1179,20 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* This is a virtual windows driver CD, which the zd1211rw driver automatically - * converts into a WLAN device. */ +/* These are virtual windows driver CDs, which the zd1211rw driver automatically + * converts into a WLAN devices. */ UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, "ZyXEL", "G-220F USB-WLAN Install", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), +UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, + "SiteCom", + "WL-117 USB-WLAN Install", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", |