浏览代码

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (48 commits)
  USB: otg: fix module reinsert issue
  USB: handle zero-length usbfs submissions correctly
  USB: EHCI: report actual_length for iso transfers
  USB: option: remove unnecessary and erroneous code
  USB: cypress_m8: remove invalid Clear-Halt
  USB: musb_host: undo incorrect change in musb_advance_schedule()
  USB: fix LANGID=0 regression
  USB: serial: sierra driver id_table additions
  USB serial: Add ID for Turtelizer, an FT2232L-based JTAG/RS-232 adapter.
  USB: fix race leading to a write after kfree in usbfs
  USB: Sierra: fix oops upon device close
  USB: option.c: add A-Link 3GU device id
  USB: Serial: Add support for Arkham Technology adapters
  USB: Fix option_ms regression in 2.6.31-rc2
  USB: gadget audio: select SND_PCM
  USB: ftdi: support NDI devices
  Revert USB: usbfs: deprecate and hide option for !embedded
  USB: usb.h: fix kernel-doc notation
  USB: RNDIS gadget, fix issues talking from PXA
  USB: serial: FTDI with product code FB80 and vendor id 0403
  ...
Linus Torvalds 16 年之前
父节点
当前提交
51feb98d25
共有 48 个文件被更改,包括 578 次插入2383 次删除
  1. 23 8
      drivers/usb/class/cdc-acm.c
  2. 6 4
      drivers/usb/class/usbtmc.c
  3. 1 1
      drivers/usb/core/Kconfig
  4. 6 4
      drivers/usb/core/devices.c
  5. 47 31
      drivers/usb/core/devio.c
  6. 4 0
      drivers/usb/core/hcd.h
  7. 26 14
      drivers/usb/core/hub.c
  8. 4 2
      drivers/usb/core/hub.h
  9. 45 18
      drivers/usb/core/message.c
  10. 22 21
      drivers/usb/gadget/Kconfig
  11. 3 3
      drivers/usb/gadget/audio.c
  12. 6 5
      drivers/usb/gadget/ether.c
  13. 13 11
      drivers/usb/gadget/pxa25x_udc.c
  14. 2 0
      drivers/usb/gadget/rndis.c
  15. 15 14
      drivers/usb/host/Kconfig
  16. 2 0
      drivers/usb/host/ehci-au1xxx.c
  17. 2 0
      drivers/usb/host/ehci-fsl.c
  18. 18 19
      drivers/usb/host/ehci-hcd.c
  19. 2 0
      drivers/usb/host/ehci-ixp4xx.c
  20. 2 0
      drivers/usb/host/ehci-orion.c
  21. 2 0
      drivers/usb/host/ehci-pci.c
  22. 2 0
      drivers/usb/host/ehci-ppc-of.c
  23. 2 0
      drivers/usb/host/ehci-ps3.c
  24. 102 38
      drivers/usb/host/ehci-q.c
  25. 8 4
      drivers/usb/host/ehci-sched.c
  26. 2 0
      drivers/usb/host/ehci.h
  27. 2 6
      drivers/usb/host/fhci-sched.c
  28. 1 1
      drivers/usb/host/isp1760-if.c
  29. 29 3
      drivers/usb/musb/davinci.c
  30. 22 5
      drivers/usb/musb/musb_host.c
  31. 0 14
      drivers/usb/otg/Kconfig
  32. 0 1
      drivers/usb/otg/Makefile
  33. 0 1915
      drivers/usb/otg/langwell_otg.c
  34. 1 0
      drivers/usb/otg/nop-usb-xceiv.c
  35. 7 6
      drivers/usb/serial/console.c
  36. 2 0
      drivers/usb/serial/cp210x.c
  37. 2 2
      drivers/usb/serial/cypress_m8.c
  38. 66 1
      drivers/usb/serial/ftdi_sio.c
  39. 15 3
      drivers/usb/serial/ftdi_sio.h
  40. 18 27
      drivers/usb/serial/option.c
  41. 1 0
      drivers/usb/serial/pl2303.c
  42. 4 0
      drivers/usb/serial/pl2303.h
  43. 31 20
      drivers/usb/serial/sierra.c
  44. 1 2
      drivers/usb/serial/ti_usb_3410_5052.c
  45. 2 1
      drivers/usb/serial/usb-serial.c
  46. 3 0
      drivers/usb/storage/option_ms.c
  47. 4 2
      include/linux/usb.h
  48. 0 177
      include/linux/usb/langwell_otg.h

+ 23 - 8
drivers/usb/class/cdc-acm.c

@@ -387,6 +387,7 @@ static void acm_rx_tasklet(unsigned long _acm)
 	struct acm_ru *rcv;
 	struct acm_ru *rcv;
 	unsigned long flags;
 	unsigned long flags;
 	unsigned char throttled;
 	unsigned char throttled;
+	struct usb_host_endpoint *ep;
 
 
 	dbg("Entering acm_rx_tasklet");
 	dbg("Entering acm_rx_tasklet");
 
 
@@ -462,11 +463,20 @@ urbs:
 
 
 		rcv->buffer = buf;
 		rcv->buffer = buf;
 
 
-		usb_fill_bulk_urb(rcv->urb, acm->dev,
-				  acm->rx_endpoint,
-				  buf->base,
-				  acm->readsize,
-				  acm_read_bulk, rcv);
+		ep = (usb_pipein(acm->rx_endpoint) ? acm->dev->ep_in : acm->dev->ep_out)
+				[usb_pipeendpoint(acm->rx_endpoint)];
+		if (usb_endpoint_xfer_int(&ep->desc))
+			usb_fill_int_urb(rcv->urb, acm->dev,
+					 acm->rx_endpoint,
+					 buf->base,
+					 acm->readsize,
+					 acm_read_bulk, rcv, ep->desc.bInterval);
+		else
+			usb_fill_bulk_urb(rcv->urb, acm->dev,
+					  acm->rx_endpoint,
+					  buf->base,
+					  acm->readsize,
+					  acm_read_bulk, rcv);
 		rcv->urb->transfer_dma = buf->dma;
 		rcv->urb->transfer_dma = buf->dma;
 		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 
@@ -1227,9 +1237,14 @@ made_compressed_probe:
 			goto alloc_fail7;
 			goto alloc_fail7;
 		}
 		}
 
 
-		usb_fill_bulk_urb(snd->urb, usb_dev,
-			usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
-			NULL, acm->writesize, acm_write_bulk, snd);
+		if (usb_endpoint_xfer_int(epwrite))
+			usb_fill_int_urb(snd->urb, usb_dev,
+				usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+				NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
+		else
+			usb_fill_bulk_urb(snd->urb, usb_dev,
+				usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+				NULL, acm->writesize, acm_write_bulk, snd);
 		snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		snd->instance = acm;
 		snd->instance = acm;
 	}
 	}

+ 6 - 4
drivers/usb/class/usbtmc.c

@@ -751,7 +751,7 @@ static int get_capabilities(struct usbtmc_device_data *data)
 {
 {
 	struct device *dev = &data->usb_dev->dev;
 	struct device *dev = &data->usb_dev->dev;
 	char *buffer;
 	char *buffer;
-	int rv;
+	int rv = 0;
 
 
 	buffer = kmalloc(0x18, GFP_KERNEL);
 	buffer = kmalloc(0x18, GFP_KERNEL);
 	if (!buffer)
 	if (!buffer)
@@ -763,7 +763,7 @@ static int get_capabilities(struct usbtmc_device_data *data)
 			     0, 0, buffer, 0x18, USBTMC_TIMEOUT);
 			     0, 0, buffer, 0x18, USBTMC_TIMEOUT);
 	if (rv < 0) {
 	if (rv < 0) {
 		dev_err(dev, "usb_control_msg returned %d\n", rv);
 		dev_err(dev, "usb_control_msg returned %d\n", rv);
-		return rv;
+		goto err_out;
 	}
 	}
 
 
 	dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
 	dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
@@ -773,7 +773,8 @@ static int get_capabilities(struct usbtmc_device_data *data)
 	dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]);
 	dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]);
 	if (buffer[0] != USBTMC_STATUS_SUCCESS) {
 	if (buffer[0] != USBTMC_STATUS_SUCCESS) {
 		dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
 		dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
-		return -EPERM;
+		rv = -EPERM;
+		goto err_out;
 	}
 	}
 
 
 	data->capabilities.interface_capabilities = buffer[4];
 	data->capabilities.interface_capabilities = buffer[4];
@@ -781,8 +782,9 @@ static int get_capabilities(struct usbtmc_device_data *data)
 	data->capabilities.usb488_interface_capabilities = buffer[14];
 	data->capabilities.usb488_interface_capabilities = buffer[14];
 	data->capabilities.usb488_device_capabilities = buffer[15];
 	data->capabilities.usb488_device_capabilities = buffer[15];
 
 
+err_out:
 	kfree(buffer);
 	kfree(buffer);
-	return 0;
+	return rv;
 }
 }
 
 
 #define capability_attribute(name)					\
 #define capability_attribute(name)					\

+ 1 - 1
drivers/usb/core/Kconfig

@@ -28,7 +28,7 @@ comment "Miscellaneous USB options"
 	depends on USB
 	depends on USB
 
 
 config USB_DEVICEFS
 config USB_DEVICEFS
-	bool "USB device filesystem (DEPRECATED)" if EMBEDDED
+	bool "USB device filesystem (DEPRECATED)"
 	depends on USB
 	depends on USB
 	---help---
 	---help---
 	  If you say Y here (and to "/proc file system support" in the "File
 	  If you say Y here (and to "/proc file system support" in the "File

+ 6 - 4
drivers/usb/core/devices.c

@@ -136,17 +136,19 @@ static const struct class_info clas_info[] =
 	{USB_CLASS_AUDIO,		"audio"},
 	{USB_CLASS_AUDIO,		"audio"},
 	{USB_CLASS_COMM,		"comm."},
 	{USB_CLASS_COMM,		"comm."},
 	{USB_CLASS_HID,			"HID"},
 	{USB_CLASS_HID,			"HID"},
-	{USB_CLASS_HUB,			"hub"},
 	{USB_CLASS_PHYSICAL,		"PID"},
 	{USB_CLASS_PHYSICAL,		"PID"},
+	{USB_CLASS_STILL_IMAGE,		"still"},
 	{USB_CLASS_PRINTER,		"print"},
 	{USB_CLASS_PRINTER,		"print"},
 	{USB_CLASS_MASS_STORAGE,	"stor."},
 	{USB_CLASS_MASS_STORAGE,	"stor."},
+	{USB_CLASS_HUB,			"hub"},
 	{USB_CLASS_CDC_DATA,		"data"},
 	{USB_CLASS_CDC_DATA,		"data"},
-	{USB_CLASS_APP_SPEC,		"app."},
-	{USB_CLASS_VENDOR_SPEC,		"vend."},
-	{USB_CLASS_STILL_IMAGE,		"still"},
 	{USB_CLASS_CSCID,		"scard"},
 	{USB_CLASS_CSCID,		"scard"},
 	{USB_CLASS_CONTENT_SEC,		"c-sec"},
 	{USB_CLASS_CONTENT_SEC,		"c-sec"},
 	{USB_CLASS_VIDEO,		"video"},
 	{USB_CLASS_VIDEO,		"video"},
+	{USB_CLASS_WIRELESS_CONTROLLER,	"wlcon"},
+	{USB_CLASS_MISC,		"misc"},
+	{USB_CLASS_APP_SPEC,		"app."},
+	{USB_CLASS_VENDOR_SPEC,		"vend."},
 	{-1,				"unk."}		/* leave as last */
 	{-1,				"unk."}		/* leave as last */
 };
 };
 
 

+ 47 - 31
drivers/usb/core/devio.c

@@ -325,21 +325,34 @@ static void async_completed(struct urb *urb)
 	struct async *as = urb->context;
 	struct async *as = urb->context;
 	struct dev_state *ps = as->ps;
 	struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 	struct siginfo sinfo;
+	struct pid *pid = NULL;
+	uid_t uid = 0;
+	uid_t euid = 0;
+	u32 secid = 0;
+	int signr;
 
 
 	spin_lock(&ps->lock);
 	spin_lock(&ps->lock);
 	list_move_tail(&as->asynclist, &ps->async_completed);
 	list_move_tail(&as->asynclist, &ps->async_completed);
-	spin_unlock(&ps->lock);
 	as->status = urb->status;
 	as->status = urb->status;
-	if (as->signr) {
+	signr = as->signr;
+	if (signr) {
 		sinfo.si_signo = as->signr;
 		sinfo.si_signo = as->signr;
 		sinfo.si_errno = as->status;
 		sinfo.si_errno = as->status;
 		sinfo.si_code = SI_ASYNCIO;
 		sinfo.si_code = SI_ASYNCIO;
 		sinfo.si_addr = as->userurb;
 		sinfo.si_addr = as->userurb;
-		kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
-				      as->euid, as->secid);
+		pid = as->pid;
+		uid = as->uid;
+		euid = as->euid;
+		secid = as->secid;
 	}
 	}
 	snoop(&urb->dev->dev, "urb complete\n");
 	snoop(&urb->dev->dev, "urb complete\n");
 	snoop_urb(urb, as->userurb);
 	snoop_urb(urb, as->userurb);
+	spin_unlock(&ps->lock);
+
+	if (signr)
+		kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid,
+				      euid, secid);
+
 	wake_up(&ps->wait);
 	wake_up(&ps->wait);
 }
 }
 
 
@@ -982,7 +995,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 				USBDEVFS_URB_ZERO_PACKET |
 				USBDEVFS_URB_ZERO_PACKET |
 				USBDEVFS_URB_NO_INTERRUPT))
 				USBDEVFS_URB_NO_INTERRUPT))
 		return -EINVAL;
 		return -EINVAL;
-	if (!uurb->buffer)
+	if (uurb->buffer_length > 0 && !uurb->buffer)
 		return -EINVAL;
 		return -EINVAL;
 	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
 	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
 	    (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
 	    (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
@@ -1038,11 +1051,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 			is_in = 0;
 			is_in = 0;
 			uurb->endpoint &= ~USB_DIR_IN;
 			uurb->endpoint &= ~USB_DIR_IN;
 		}
 		}
-		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
-				uurb->buffer, uurb->buffer_length)) {
-			kfree(dr);
-			return -EFAULT;
-		}
 		snoop(&ps->dev->dev, "control urb: bRequest=%02x "
 		snoop(&ps->dev->dev, "control urb: bRequest=%02x "
 			"bRrequestType=%02x wValue=%04x "
 			"bRrequestType=%02x wValue=%04x "
 			"wIndex=%04x wLength=%04x\n",
 			"wIndex=%04x wLength=%04x\n",
@@ -1062,9 +1070,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		uurb->number_of_packets = 0;
 		uurb->number_of_packets = 0;
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 			return -EINVAL;
-		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
-				uurb->buffer, uurb->buffer_length))
-			return -EFAULT;
 		snoop(&ps->dev->dev, "bulk urb\n");
 		snoop(&ps->dev->dev, "bulk urb\n");
 		break;
 		break;
 
 
@@ -1106,28 +1111,35 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 			return -EINVAL;
 			return -EINVAL;
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 			return -EINVAL;
-		if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
-				uurb->buffer, uurb->buffer_length))
-			return -EFAULT;
 		snoop(&ps->dev->dev, "interrupt urb\n");
 		snoop(&ps->dev->dev, "interrupt urb\n");
 		break;
 		break;
 
 
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	as = alloc_async(uurb->number_of_packets);
-	if (!as) {
+	if (uurb->buffer_length > 0 &&
+			!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+				uurb->buffer, uurb->buffer_length)) {
 		kfree(isopkt);
 		kfree(isopkt);
 		kfree(dr);
 		kfree(dr);
-		return -ENOMEM;
+		return -EFAULT;
 	}
 	}
-	as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL);
-	if (!as->urb->transfer_buffer) {
+	as = alloc_async(uurb->number_of_packets);
+	if (!as) {
 		kfree(isopkt);
 		kfree(isopkt);
 		kfree(dr);
 		kfree(dr);
-		free_async(as);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
+	if (uurb->buffer_length > 0) {
+		as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
+				GFP_KERNEL);
+		if (!as->urb->transfer_buffer) {
+			kfree(isopkt);
+			kfree(dr);
+			free_async(as);
+			return -ENOMEM;
+		}
+	}
 	as->urb->dev = ps->dev;
 	as->urb->dev = ps->dev;
 	as->urb->pipe = (uurb->type << 30) |
 	as->urb->pipe = (uurb->type << 30) |
 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
@@ -1169,7 +1181,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	kfree(isopkt);
 	kfree(isopkt);
 	as->ps = ps;
 	as->ps = ps;
 	as->userurb = arg;
 	as->userurb = arg;
-	if (uurb->endpoint & USB_DIR_IN)
+	if (is_in && uurb->buffer_length > 0)
 		as->userbuffer = uurb->buffer;
 		as->userbuffer = uurb->buffer;
 	else
 	else
 		as->userbuffer = NULL;
 		as->userbuffer = NULL;
@@ -1179,9 +1191,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	as->uid = cred->uid;
 	as->uid = cred->uid;
 	as->euid = cred->euid;
 	as->euid = cred->euid;
 	security_task_getsecid(current, &as->secid);
 	security_task_getsecid(current, &as->secid);
-	if (!is_in) {
+	if (!is_in && uurb->buffer_length > 0) {
 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
-				as->urb->transfer_buffer_length)) {
+				uurb->buffer_length)) {
 			free_async(as);
 			free_async(as);
 			return -EFAULT;
 			return -EFAULT;
 		}
 		}
@@ -1231,22 +1243,22 @@ static int processcompl(struct async *as, void __user * __user *arg)
 	if (as->userbuffer)
 	if (as->userbuffer)
 		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
 		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
 				 urb->transfer_buffer_length))
 				 urb->transfer_buffer_length))
-			return -EFAULT;
+			goto err_out;
 	if (put_user(as->status, &userurb->status))
 	if (put_user(as->status, &userurb->status))
-		return -EFAULT;
+		goto err_out;
 	if (put_user(urb->actual_length, &userurb->actual_length))
 	if (put_user(urb->actual_length, &userurb->actual_length))
-		return -EFAULT;
+		goto err_out;
 	if (put_user(urb->error_count, &userurb->error_count))
 	if (put_user(urb->error_count, &userurb->error_count))
-		return -EFAULT;
+		goto err_out;
 
 
 	if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
 	if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
 		for (i = 0; i < urb->number_of_packets; i++) {
 		for (i = 0; i < urb->number_of_packets; i++) {
 			if (put_user(urb->iso_frame_desc[i].actual_length,
 			if (put_user(urb->iso_frame_desc[i].actual_length,
 				     &userurb->iso_frame_desc[i].actual_length))
 				     &userurb->iso_frame_desc[i].actual_length))
-				return -EFAULT;
+				goto err_out;
 			if (put_user(urb->iso_frame_desc[i].status,
 			if (put_user(urb->iso_frame_desc[i].status,
 				     &userurb->iso_frame_desc[i].status))
 				     &userurb->iso_frame_desc[i].status))
-				return -EFAULT;
+				goto err_out;
 		}
 		}
 	}
 	}
 
 
@@ -1255,6 +1267,10 @@ static int processcompl(struct async *as, void __user * __user *arg)
 	if (put_user(addr, (void __user * __user *)arg))
 	if (put_user(addr, (void __user * __user *)arg))
 		return -EFAULT;
 		return -EFAULT;
 	return 0;
 	return 0;
+
+err_out:
+	free_async(as);
+	return -EFAULT;
 }
 }
 
 
 static struct async *reap_as(struct dev_state *ps)
 static struct async *reap_as(struct dev_state *ps)

+ 4 - 0
drivers/usb/core/hcd.h

@@ -227,6 +227,10 @@ struct hc_driver {
 		/* has a port been handed over to a companion? */
 		/* has a port been handed over to a companion? */
 	int	(*port_handed_over)(struct usb_hcd *, int);
 	int	(*port_handed_over)(struct usb_hcd *, int);
 
 
+		/* CLEAR_TT_BUFFER completion callback */
+	void	(*clear_tt_buffer_complete)(struct usb_hcd *,
+				struct usb_host_endpoint *);
+
 	/* xHCI specific functions */
 	/* xHCI specific functions */
 		/* Called by usb_alloc_dev to alloc HC device structures */
 		/* Called by usb_alloc_dev to alloc HC device structures */
 	int	(*alloc_dev)(struct usb_hcd *, struct usb_device *);
 	int	(*alloc_dev)(struct usb_hcd *, struct usb_device *);

+ 26 - 14
drivers/usb/core/hub.c

@@ -450,10 +450,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
  * talking to TTs must queue control transfers (not just bulk and iso), so
  * talking to TTs must queue control transfers (not just bulk and iso), so
  * both can talk to the same hub concurrently.
  * both can talk to the same hub concurrently.
  */
  */
-static void hub_tt_kevent (struct work_struct *work)
+static void hub_tt_work(struct work_struct *work)
 {
 {
 	struct usb_hub		*hub =
 	struct usb_hub		*hub =
-		container_of(work, struct usb_hub, tt.kevent);
+		container_of(work, struct usb_hub, tt.clear_work);
 	unsigned long		flags;
 	unsigned long		flags;
 	int			limit = 100;
 	int			limit = 100;
 
 
@@ -462,6 +462,7 @@ static void hub_tt_kevent (struct work_struct *work)
 		struct list_head	*next;
 		struct list_head	*next;
 		struct usb_tt_clear	*clear;
 		struct usb_tt_clear	*clear;
 		struct usb_device	*hdev = hub->hdev;
 		struct usb_device	*hdev = hub->hdev;
+		const struct hc_driver	*drv;
 		int			status;
 		int			status;
 
 
 		next = hub->tt.clear_list.next;
 		next = hub->tt.clear_list.next;
@@ -471,21 +472,25 @@ static void hub_tt_kevent (struct work_struct *work)
 		/* drop lock so HCD can concurrently report other TT errors */
 		/* drop lock so HCD can concurrently report other TT errors */
 		spin_unlock_irqrestore (&hub->tt.lock, flags);
 		spin_unlock_irqrestore (&hub->tt.lock, flags);
 		status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
 		status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
-		spin_lock_irqsave (&hub->tt.lock, flags);
-
 		if (status)
 		if (status)
 			dev_err (&hdev->dev,
 			dev_err (&hdev->dev,
 				"clear tt %d (%04x) error %d\n",
 				"clear tt %d (%04x) error %d\n",
 				clear->tt, clear->devinfo, status);
 				clear->tt, clear->devinfo, status);
+
+		/* Tell the HCD, even if the operation failed */
+		drv = clear->hcd->driver;
+		if (drv->clear_tt_buffer_complete)
+			(drv->clear_tt_buffer_complete)(clear->hcd, clear->ep);
+
 		kfree(clear);
 		kfree(clear);
+		spin_lock_irqsave(&hub->tt.lock, flags);
 	}
 	}
 	spin_unlock_irqrestore (&hub->tt.lock, flags);
 	spin_unlock_irqrestore (&hub->tt.lock, flags);
 }
 }
 
 
 /**
 /**
- * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub
- * @udev: the device whose split transaction failed
- * @pipe: identifies the endpoint of the failed transaction
+ * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub
+ * @urb: an URB associated with the failed or incomplete split transaction
  *
  *
  * High speed HCDs use this to tell the hub driver that some split control or
  * High speed HCDs use this to tell the hub driver that some split control or
  * bulk transaction failed in a way that requires clearing internal state of
  * bulk transaction failed in a way that requires clearing internal state of
@@ -495,8 +500,10 @@ static void hub_tt_kevent (struct work_struct *work)
  * It may not be possible for that hub to handle additional full (or low)
  * It may not be possible for that hub to handle additional full (or low)
  * speed transactions until that state is fully cleared out.
  * speed transactions until that state is fully cleared out.
  */
  */
-void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
+int usb_hub_clear_tt_buffer(struct urb *urb)
 {
 {
+	struct usb_device	*udev = urb->dev;
+	int			pipe = urb->pipe;
 	struct usb_tt		*tt = udev->tt;
 	struct usb_tt		*tt = udev->tt;
 	unsigned long		flags;
 	unsigned long		flags;
 	struct usb_tt_clear	*clear;
 	struct usb_tt_clear	*clear;
@@ -508,7 +515,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
 	if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
 	if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
 		dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
 		dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
 		/* FIXME recover somehow ... RESET_TT? */
 		/* FIXME recover somehow ... RESET_TT? */
-		return;
+		return -ENOMEM;
 	}
 	}
 
 
 	/* info that CLEAR_TT_BUFFER needs */
 	/* info that CLEAR_TT_BUFFER needs */
@@ -520,14 +527,19 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
 			: (USB_ENDPOINT_XFER_BULK << 11);
 			: (USB_ENDPOINT_XFER_BULK << 11);
 	if (usb_pipein (pipe))
 	if (usb_pipein (pipe))
 		clear->devinfo |= 1 << 15;
 		clear->devinfo |= 1 << 15;
-	
+
+	/* info for completion callback */
+	clear->hcd = bus_to_hcd(udev->bus);
+	clear->ep = urb->ep;
+
 	/* tell keventd to clear state for this TT */
 	/* tell keventd to clear state for this TT */
 	spin_lock_irqsave (&tt->lock, flags);
 	spin_lock_irqsave (&tt->lock, flags);
 	list_add_tail (&clear->clear_list, &tt->clear_list);
 	list_add_tail (&clear->clear_list, &tt->clear_list);
-	schedule_work (&tt->kevent);
+	schedule_work(&tt->clear_work);
 	spin_unlock_irqrestore (&tt->lock, flags);
 	spin_unlock_irqrestore (&tt->lock, flags);
+	return 0;
 }
 }
-EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
+EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
 
 
 /* If do_delay is false, return the number of milliseconds the caller
 /* If do_delay is false, return the number of milliseconds the caller
  * needs to delay.
  * needs to delay.
@@ -818,7 +830,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
 	if (hub->has_indicators)
 	if (hub->has_indicators)
 		cancel_delayed_work_sync(&hub->leds);
 		cancel_delayed_work_sync(&hub->leds);
 	if (hub->tt.hub)
 	if (hub->tt.hub)
-		cancel_work_sync(&hub->tt.kevent);
+		cancel_work_sync(&hub->tt.clear_work);
 }
 }
 
 
 /* caller has locked the hub device */
 /* caller has locked the hub device */
@@ -935,7 +947,7 @@ static int hub_configure(struct usb_hub *hub,
 
 
 	spin_lock_init (&hub->tt.lock);
 	spin_lock_init (&hub->tt.lock);
 	INIT_LIST_HEAD (&hub->tt.clear_list);
 	INIT_LIST_HEAD (&hub->tt.clear_list);
-	INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
+	INIT_WORK(&hub->tt.clear_work, hub_tt_work);
 	switch (hdev->descriptor.bDeviceProtocol) {
 	switch (hdev->descriptor.bDeviceProtocol) {
 		case 0:
 		case 0:
 			break;
 			break;

+ 4 - 2
drivers/usb/core/hub.h

@@ -188,16 +188,18 @@ struct usb_tt {
 	/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
 	/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
 	spinlock_t		lock;
 	spinlock_t		lock;
 	struct list_head	clear_list;	/* of usb_tt_clear */
 	struct list_head	clear_list;	/* of usb_tt_clear */
-	struct work_struct			kevent;
+	struct work_struct	clear_work;
 };
 };
 
 
 struct usb_tt_clear {
 struct usb_tt_clear {
 	struct list_head	clear_list;
 	struct list_head	clear_list;
 	unsigned		tt;
 	unsigned		tt;
 	u16			devinfo;
 	u16			devinfo;
+	struct usb_hcd		*hcd;
+	struct usb_host_endpoint	*ep;
 };
 };
 
 
-extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
+extern int usb_hub_clear_tt_buffer(struct urb *urb);
 extern void usb_ep0_reinit(struct usb_device *);
 extern void usb_ep0_reinit(struct usb_device *);
 
 
 #endif /* __LINUX_HUB_H */
 #endif /* __LINUX_HUB_H */

+ 45 - 18
drivers/usb/core/message.c

@@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
 	return rc;
 	return rc;
 }
 }
 
 
+static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
+{
+	int err;
+
+	if (dev->have_langid)
+		return 0;
+
+	if (dev->string_langid < 0)
+		return -EPIPE;
+
+	err = usb_string_sub(dev, 0, 0, tbuf);
+
+	/* If the string was reported but is malformed, default to english
+	 * (0x0409) */
+	if (err == -ENODATA || (err > 0 && err < 4)) {
+		dev->string_langid = 0x0409;
+		dev->have_langid = 1;
+		dev_err(&dev->dev,
+			"string descriptor 0 malformed (err = %d), "
+			"defaulting to 0x%04x\n",
+				err, dev->string_langid);
+		return 0;
+	}
+
+	/* In case of all other errors, we assume the device is not able to
+	 * deal with strings at all. Set string_langid to -1 in order to
+	 * prevent any string to be retrieved from the device */
+	if (err < 0) {
+		dev_err(&dev->dev, "string descriptor 0 read error: %d\n",
+					err);
+		dev->string_langid = -1;
+		return -EPIPE;
+	}
+
+	/* always use the first langid listed */
+	dev->string_langid = tbuf[2] | (tbuf[3] << 8);
+	dev->have_langid = 1;
+	dev_dbg(&dev->dev, "default language 0x%04x\n",
+				dev->string_langid);
+	return 0;
+}
+
 /**
 /**
  * usb_string - returns UTF-8 version of a string descriptor
  * usb_string - returns UTF-8 version of a string descriptor
  * @dev: the device whose string descriptor is being retrieved
  * @dev: the device whose string descriptor is being retrieved
@@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 	if (!tbuf)
 	if (!tbuf)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	/* get langid for strings if it's not yet known */
-	if (!dev->have_langid) {
-		err = usb_string_sub(dev, 0, 0, tbuf);
-		if (err < 0) {
-			dev_err(&dev->dev,
-				"string descriptor 0 read error: %d\n",
-				err);
-		} else if (err < 4) {
-			dev_err(&dev->dev, "string descriptor 0 too short\n");
-		} else {
-			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
-			/* always use the first langid listed */
-			dev_dbg(&dev->dev, "default language 0x%04x\n",
-				dev->string_langid);
-		}
-
-		dev->have_langid = 1;
-	}
+	err = usb_get_langid(dev, tbuf);
+	if (err < 0)
+		goto errout;
 
 
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
 	if (err < 0)
 	if (err < 0)

+ 22 - 21
drivers/usb/gadget/Kconfig

@@ -286,6 +286,27 @@ config USB_S3C_HSOTG
 	default USB_GADGET
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 	select USB_GADGET_SELECTED
 
 
+config USB_GADGET_IMX
+	boolean "Freescale IMX USB Peripheral Controller"
+	depends on ARCH_MX1
+	help
+	   Freescale's IMX series include an integrated full speed
+	   USB 1.1 device controller.  The controller in the IMX series
+	   is register-compatible.
+
+	   It has Six fixed-function endpoints, as well as endpoint
+	   zero (for control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "imx_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_IMX
+	tristate
+	depends on USB_GADGET_IMX
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
 config USB_GADGET_S3C2410
 config USB_GADGET_S3C2410
 	boolean "S3C2410 USB Device Controller"
 	boolean "S3C2410 USB Device Controller"
 	depends on ARCH_S3C2410
 	depends on ARCH_S3C2410
@@ -321,27 +342,6 @@ config USB_GADGET_MUSB_HDRC
 	  This OTG-capable silicon IP is used in dual designs including
 	  This OTG-capable silicon IP is used in dual designs including
 	  the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
 	  the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
 
 
-config USB_GADGET_IMX
-	boolean "Freescale IMX USB Peripheral Controller"
-	depends on ARCH_MX1
-	help
-	   Freescale's IMX series include an integrated full speed
-	   USB 1.1 device controller.  The controller in the IMX series
-	   is register-compatible.
-
-	   It has Six fixed-function endpoints, as well as endpoint
-	   zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "imx_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_IMX
-	tristate
-	depends on USB_GADGET_IMX
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 config USB_GADGET_M66592
 config USB_GADGET_M66592
 	boolean "Renesas M66592 USB Peripheral Controller"
 	boolean "Renesas M66592 USB Peripheral Controller"
 	select USB_GADGET_DUALSPEED
 	select USB_GADGET_DUALSPEED
@@ -604,6 +604,7 @@ config USB_ZERO_HNPTEST
 config USB_AUDIO
 config USB_AUDIO
 	tristate "Audio Gadget (EXPERIMENTAL)"
 	tristate "Audio Gadget (EXPERIMENTAL)"
 	depends on SND
 	depends on SND
+	select SND_PCM
 	help
 	help
 	  Gadget Audio is compatible with USB Audio Class specification 1.0.
 	  Gadget Audio is compatible with USB Audio Class specification 1.0.
 	  It will include at least one AudioControl interface, zero or more
 	  It will include at least one AudioControl interface, zero or more

+ 3 - 3
drivers/usb/gadget/audio.c

@@ -42,9 +42,9 @@
  * Instead:  allocate your own, using normal USB-IF procedures.
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
  */
 
 
-/* Thanks to NetChip Technologies for donating this product ID. */
-#define AUDIO_VENDOR_NUM		0x0525	/* NetChip */
-#define AUDIO_PRODUCT_NUM		0xa4a1	/* Linux-USB Audio Gadget */
+/* Thanks to Linux Foundation for donating this product ID. */
+#define AUDIO_VENDOR_NUM		0x1d6b	/* Linux Foundation */
+#define AUDIO_PRODUCT_NUM		0x0101	/* Linux-USB Audio Gadget */
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 

+ 6 - 5
drivers/usb/gadget/ether.c

@@ -293,15 +293,16 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 		/* CDC Subset */
 		/* CDC Subset */
 		eth_config_driver.label = "CDC Subset/SAFE";
 		eth_config_driver.label = "CDC Subset/SAFE";
 
 
-		device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM),
-		device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM),
-		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+		device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM);
+		device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM);
+		if (!has_rndis())
+			device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
 	}
 	}
 
 
 	if (has_rndis()) {
 	if (has_rndis()) {
 		/* RNDIS plus ECM-or-Subset */
 		/* RNDIS plus ECM-or-Subset */
-		device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM),
-		device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM),
+		device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM);
+		device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM);
 		device_desc.bNumConfigurations = 2;
 		device_desc.bNumConfigurations = 2;
 	}
 	}
 
 

+ 13 - 11
drivers/usb/gadget/pxa25x_udc.c

@@ -139,7 +139,7 @@ static int is_vbus_present(void)
 {
 {
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 
-	if (mach->gpio_vbus) {
+	if (gpio_is_valid(mach->gpio_vbus)) {
 		int value = gpio_get_value(mach->gpio_vbus);
 		int value = gpio_get_value(mach->gpio_vbus);
 
 
 		if (mach->gpio_vbus_inverted)
 		if (mach->gpio_vbus_inverted)
@@ -158,7 +158,7 @@ static void pullup_off(void)
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 	int off_level = mach->gpio_pullup_inverted;
 	int off_level = mach->gpio_pullup_inverted;
 
 
-	if (mach->gpio_pullup)
+	if (gpio_is_valid(mach->gpio_pullup))
 		gpio_set_value(mach->gpio_pullup, off_level);
 		gpio_set_value(mach->gpio_pullup, off_level);
 	else if (mach->udc_command)
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
@@ -169,7 +169,7 @@ static void pullup_on(void)
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 	int on_level = !mach->gpio_pullup_inverted;
 	int on_level = !mach->gpio_pullup_inverted;
 
 
-	if (mach->gpio_pullup)
+	if (gpio_is_valid(mach->gpio_pullup))
 		gpio_set_value(mach->gpio_pullup, on_level);
 		gpio_set_value(mach->gpio_pullup, on_level);
 	else if (mach->udc_command)
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
@@ -1000,7 +1000,7 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
 	udc = container_of(_gadget, struct pxa25x_udc, gadget);
 	udc = container_of(_gadget, struct pxa25x_udc, gadget);
 
 
 	/* not all boards support pullup control */
 	/* not all boards support pullup control */
-	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
+	if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 
 
 	udc->pullup = (is_active != 0);
 	udc->pullup = (is_active != 0);
@@ -1802,11 +1802,13 @@ pxa25x_udc_irq(int irq, void *_dev)
 					USIR0 |= tmp;
 					USIR0 |= tmp;
 					handled = 1;
 					handled = 1;
 				}
 				}
+#ifndef	CONFIG_USB_PXA25X_SMALL
 				if (usir1 & tmp) {
 				if (usir1 & tmp) {
 					handle_ep(&dev->ep[i+8]);
 					handle_ep(&dev->ep[i+8]);
 					USIR1 |= tmp;
 					USIR1 |= tmp;
 					handled = 1;
 					handled = 1;
 				}
 				}
+#endif
 			}
 			}
 		}
 		}
 
 
@@ -2160,7 +2162,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 	dev->dev = &pdev->dev;
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
 	dev->mach = pdev->dev.platform_data;
 
 
-	if (dev->mach->gpio_vbus) {
+	if (gpio_is_valid(dev->mach->gpio_vbus)) {
 		if ((retval = gpio_request(dev->mach->gpio_vbus,
 		if ((retval = gpio_request(dev->mach->gpio_vbus,
 				"pxa25x_udc GPIO VBUS"))) {
 				"pxa25x_udc GPIO VBUS"))) {
 			dev_dbg(&pdev->dev,
 			dev_dbg(&pdev->dev,
@@ -2173,7 +2175,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 	} else
 	} else
 		vbus_irq = 0;
 		vbus_irq = 0;
 
 
-	if (dev->mach->gpio_pullup) {
+	if (gpio_is_valid(dev->mach->gpio_pullup)) {
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
 				"pca25x_udc GPIO PULLUP"))) {
 				"pca25x_udc GPIO PULLUP"))) {
 			dev_dbg(&pdev->dev,
 			dev_dbg(&pdev->dev,
@@ -2256,10 +2258,10 @@ lubbock_fail0:
 #endif
 #endif
 	free_irq(irq, dev);
 	free_irq(irq, dev);
  err_irq1:
  err_irq1:
-	if (dev->mach->gpio_pullup)
+	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
 		gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
  err_gpio_pullup:
-	if (dev->mach->gpio_vbus)
+	if (gpio_is_valid(dev->mach->gpio_vbus))
 		gpio_free(dev->mach->gpio_vbus);
 		gpio_free(dev->mach->gpio_vbus);
  err_gpio_vbus:
  err_gpio_vbus:
 	clk_put(dev->clk);
 	clk_put(dev->clk);
@@ -2294,11 +2296,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 		free_irq(LUBBOCK_USB_IRQ, dev);
 		free_irq(LUBBOCK_USB_IRQ, dev);
 	}
 	}
 #endif
 #endif
-	if (dev->mach->gpio_vbus) {
+	if (gpio_is_valid(dev->mach->gpio_vbus)) {
 		free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
 		free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
 		gpio_free(dev->mach->gpio_vbus);
 		gpio_free(dev->mach->gpio_vbus);
 	}
 	}
-	if (dev->mach->gpio_pullup)
+	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
 		gpio_free(dev->mach->gpio_pullup);
 
 
 	clk_put(dev->clk);
 	clk_put(dev->clk);
@@ -2329,7 +2331,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
 	struct pxa25x_udc	*udc = platform_get_drvdata(dev);
 	struct pxa25x_udc	*udc = platform_get_drvdata(dev);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
+	if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
 		WARNING("USB host won't detect disconnect!\n");
 		WARNING("USB host won't detect disconnect!\n");
 	udc->suspended = 1;
 	udc->suspended = 1;
 
 

+ 2 - 0
drivers/usb/gadget/rndis.c

@@ -442,6 +442,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 
 	case OID_802_3_MAC_OPTIONS:
 	case OID_802_3_MAC_OPTIONS:
 		pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
 		pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+		*outbuf = cpu_to_le32(0);
+		retval = 0;
 		break;
 		break;
 
 
 	/* ieee802.3 statistics OIDs (table 4-4) */
 	/* ieee802.3 statistics OIDs (table 4-4) */

+ 15 - 14
drivers/usb/host/Kconfig

@@ -181,26 +181,27 @@ config USB_OHCI_HCD_PPC_SOC
 	  Enables support for the USB controller on the MPC52xx or
 	  Enables support for the USB controller on the MPC52xx or
 	  STB03xxx processor chip.  If unsure, say Y.
 	  STB03xxx processor chip.  If unsure, say Y.
 
 
-config USB_OHCI_HCD_PPC_OF
-	bool "OHCI support for PPC USB controller on OF platform bus"
-	depends on USB_OHCI_HCD && PPC_OF
-	default y
-	---help---
-	  Enables support for the USB controller PowerPC present on the
-	  OpenFirmware platform bus.
-
 config USB_OHCI_HCD_PPC_OF_BE
 config USB_OHCI_HCD_PPC_OF_BE
-	bool "Support big endian HC"
-	depends on USB_OHCI_HCD_PPC_OF
-	default y
+	bool "OHCI support for OF platform bus (big endian)"
+	depends on USB_OHCI_HCD && PPC_OF
 	select USB_OHCI_BIG_ENDIAN_DESC
 	select USB_OHCI_BIG_ENDIAN_DESC
 	select USB_OHCI_BIG_ENDIAN_MMIO
 	select USB_OHCI_BIG_ENDIAN_MMIO
+	---help---
+	  Enables support for big-endian USB controllers present on the
+	  OpenFirmware platform bus.
 
 
 config USB_OHCI_HCD_PPC_OF_LE
 config USB_OHCI_HCD_PPC_OF_LE
-	bool "Support little endian HC"
-	depends on USB_OHCI_HCD_PPC_OF
-	default n
+	bool "OHCI support for OF platform bus (little endian)"
+	depends on USB_OHCI_HCD && PPC_OF
 	select USB_OHCI_LITTLE_ENDIAN
 	select USB_OHCI_LITTLE_ENDIAN
+	---help---
+	  Enables support for little-endian USB controllers present on the
+	  OpenFirmware platform bus.
+
+config USB_OHCI_HCD_PPC_OF
+	bool
+	depends on USB_OHCI_HCD && PPC_OF
+	default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
 
 
 config USB_OHCI_HCD_PCI
 config USB_OHCI_HCD_PCI
 	bool "OHCI support for PCI-bus USB controllers"
 	bool "OHCI support for PCI-bus USB controllers"

+ 2 - 0
drivers/usb/host/ehci-au1xxx.c

@@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
 	.bus_resume		= ehci_bus_resume,
 	.bus_resume		= ehci_bus_resume,
 	.relinquish_port	= ehci_relinquish_port,
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
 	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 };
 
 
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)

+ 2 - 0
drivers/usb/host/ehci-fsl.c

@@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = {
 	.bus_resume = ehci_bus_resume,
 	.bus_resume = ehci_bus_resume,
 	.relinquish_port = ehci_relinquish_port,
 	.relinquish_port = ehci_relinquish_port,
 	.port_handed_over = ehci_port_handed_over,
 	.port_handed_over = ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 };
 
 
 static int ehci_fsl_drv_probe(struct platform_device *pdev)
 static int ehci_fsl_drv_probe(struct platform_device *pdev)

+ 18 - 19
drivers/usb/host/ehci-hcd.c

@@ -1003,6 +1003,8 @@ idle_timeout:
 		schedule_timeout_uninterruptible(1);
 		schedule_timeout_uninterruptible(1);
 		goto rescan;
 		goto rescan;
 	case QH_STATE_IDLE:		/* fully unlinked */
 	case QH_STATE_IDLE:		/* fully unlinked */
+		if (qh->clearing_tt)
+			goto idle_timeout;
 		if (list_empty (&qh->qtd_list)) {
 		if (list_empty (&qh->qtd_list)) {
 			qh_put (qh);
 			qh_put (qh);
 			break;
 			break;
@@ -1030,12 +1032,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	struct ehci_qh		*qh;
 	struct ehci_qh		*qh;
 	int			eptype = usb_endpoint_type(&ep->desc);
 	int			eptype = usb_endpoint_type(&ep->desc);
+	int			epnum = usb_endpoint_num(&ep->desc);
+	int			is_out = usb_endpoint_dir_out(&ep->desc);
+	unsigned long		flags;
 
 
 	if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
 	if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
 		return;
 		return;
 
 
- rescan:
-	spin_lock_irq(&ehci->lock);
+	spin_lock_irqsave(&ehci->lock, flags);
 	qh = ep->hcpriv;
 	qh = ep->hcpriv;
 
 
 	/* For Bulk and Interrupt endpoints we maintain the toggle state
 	/* For Bulk and Interrupt endpoints we maintain the toggle state
@@ -1044,29 +1048,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
 	 * the toggle bit in the QH.
 	 * the toggle bit in the QH.
 	 */
 	 */
 	if (qh) {
 	if (qh) {
+		usb_settoggle(qh->dev, epnum, is_out, 0);
 		if (!list_empty(&qh->qtd_list)) {
 		if (!list_empty(&qh->qtd_list)) {
 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
-		} else if (qh->qh_state == QH_STATE_IDLE) {
-			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
-		} else {
-			/* It's not safe to write into the overlay area
-			 * while the QH is active.  Unlink it first and
-			 * wait for the unlink to complete.
+		} else if (qh->qh_state == QH_STATE_LINKED) {
+
+			/* The toggle value in the QH can't be updated
+			 * while the QH is active.  Unlink it now;
+			 * re-linking will call qh_refresh().
 			 */
 			 */
-			if (qh->qh_state == QH_STATE_LINKED) {
-				if (eptype == USB_ENDPOINT_XFER_BULK) {
-					unlink_async(ehci, qh);
-				} else {
-					intr_deschedule(ehci, qh);
-					(void) qh_schedule(ehci, qh);
-				}
+			if (eptype == USB_ENDPOINT_XFER_BULK) {
+				unlink_async(ehci, qh);
+			} else {
+				intr_deschedule(ehci, qh);
+				(void) qh_schedule(ehci, qh);
 			}
 			}
-			spin_unlock_irq(&ehci->lock);
-			schedule_timeout_uninterruptible(1);
-			goto rescan;
 		}
 		}
 	}
 	}
-	spin_unlock_irq(&ehci->lock);
+	spin_unlock_irqrestore(&ehci->lock, flags);
 }
 }
 
 
 static int ehci_get_frame (struct usb_hcd *hcd)
 static int ehci_get_frame (struct usb_hcd *hcd)

+ 2 - 0
drivers/usb/host/ehci-ixp4xx.c

@@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
 #endif
 #endif
 	.relinquish_port	= ehci_relinquish_port,
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
 	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 };
 
 
 static int ixp4xx_ehci_probe(struct platform_device *pdev)
 static int ixp4xx_ehci_probe(struct platform_device *pdev)

+ 2 - 0
drivers/usb/host/ehci-orion.c

@@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
 	.bus_resume = ehci_bus_resume,
 	.bus_resume = ehci_bus_resume,
 	.relinquish_port = ehci_relinquish_port,
 	.relinquish_port = ehci_relinquish_port,
 	.port_handed_over = ehci_port_handed_over,
 	.port_handed_over = ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 };
 
 
 static void __init
 static void __init

+ 2 - 0
drivers/usb/host/ehci-pci.c

@@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
 	.bus_resume =		ehci_bus_resume,
 	.bus_resume =		ehci_bus_resume,
 	.relinquish_port =	ehci_relinquish_port,
 	.relinquish_port =	ehci_relinquish_port,
 	.port_handed_over =	ehci_port_handed_over,
 	.port_handed_over =	ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 2 - 0
drivers/usb/host/ehci-ppc-of.c

@@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
 #endif
 #endif
 	.relinquish_port	= ehci_relinquish_port,
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
 	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 };
 
 
 
 

+ 2 - 0
drivers/usb/host/ehci-ps3.c

@@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = {
 #endif
 #endif
 	.relinquish_port	= ehci_relinquish_port,
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
 	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 };
 
 
 static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
 static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)

+ 102 - 38
drivers/usb/host/ehci-q.c

@@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
 	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
 	qh->hw_alt_next = EHCI_LIST_END(ehci);
 	qh->hw_alt_next = EHCI_LIST_END(ehci);
 
 
+	/* Except for control endpoints, we make hardware maintain data
+	 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
+	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
+	 * ever clear it.
+	 */
+	if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
+		unsigned	is_out, epnum;
+
+		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+		epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
+		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
+			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
+			usb_settoggle (qh->dev, epnum, is_out, 1);
+		}
+	}
+
 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
 	wmb ();
 	wmb ();
 	qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
 	qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
@@ -123,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
+static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+
+static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
+		struct usb_host_endpoint *ep)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	struct ehci_qh		*qh = ep->hcpriv;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+	qh->clearing_tt = 0;
+	if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
+			&& HC_IS_RUNNING(hcd->state))
+		qh_link_async(ehci, qh);
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
+		struct urb *urb, u32 token)
+{
+
+	/* If an async split transaction gets an error or is unlinked,
+	 * the TT buffer may be left in an indeterminate state.  We
+	 * have to clear the TT buffer.
+	 *
+	 * Note: this routine is never called for Isochronous transfers.
+	 */
+	if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
+#ifdef DEBUG
+		struct usb_device *tt = urb->dev->tt->hub;
+		dev_dbg(&tt->dev,
+			"clear tt buffer port %d, a%d ep%d t%08x\n",
+			urb->dev->ttport, urb->dev->devnum,
+			usb_pipeendpoint(urb->pipe), token);
+#endif /* DEBUG */
+		if (!ehci_is_TDI(ehci)
+				|| urb->dev->tt->hub !=
+				   ehci_to_hcd(ehci)->self.root_hub) {
+			if (usb_hub_clear_tt_buffer(urb) == 0)
+				qh->clearing_tt = 1;
+		} else {
+
+			/* REVISIT ARC-derived cores don't clear the root
+			 * hub TT buffer in this way...
+			 */
+		}
+	}
+}
+
 static int qtd_copy_status (
 static int qtd_copy_status (
 	struct ehci_hcd *ehci,
 	struct ehci_hcd *ehci,
 	struct urb *urb,
 	struct urb *urb,
@@ -149,6 +214,14 @@ static int qtd_copy_status (
 		if (token & QTD_STS_BABBLE) {
 		if (token & QTD_STS_BABBLE) {
 			/* FIXME "must" disable babbling device's port too */
 			/* FIXME "must" disable babbling device's port too */
 			status = -EOVERFLOW;
 			status = -EOVERFLOW;
+		/* CERR nonzero + halt --> stall */
+		} else if (QTD_CERR(token)) {
+			status = -EPIPE;
+
+		/* In theory, more than one of the following bits can be set
+		 * since they are sticky and the transaction is retried.
+		 * Which to test first is rather arbitrary.
+		 */
 		} else if (token & QTD_STS_MMF) {
 		} else if (token & QTD_STS_MMF) {
 			/* fs/ls interrupt xfer missed the complete-split */
 			/* fs/ls interrupt xfer missed the complete-split */
 			status = -EPROTO;
 			status = -EPROTO;
@@ -157,21 +230,15 @@ static int qtd_copy_status (
 				? -ENOSR  /* hc couldn't read data */
 				? -ENOSR  /* hc couldn't read data */
 				: -ECOMM; /* hc couldn't write data */
 				: -ECOMM; /* hc couldn't write data */
 		} else if (token & QTD_STS_XACT) {
 		} else if (token & QTD_STS_XACT) {
-			/* timeout, bad crc, wrong PID, etc; retried */
-			if (QTD_CERR (token))
-				status = -EPIPE;
-			else {
-				ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
-					urb->dev->devpath,
-					usb_pipeendpoint (urb->pipe),
-					usb_pipein (urb->pipe) ? "in" : "out");
-				status = -EPROTO;
-			}
-		/* CERR nonzero + no errors + halt --> stall */
-		} else if (QTD_CERR (token))
-			status = -EPIPE;
-		else	/* unknown */
+			/* timeout, bad CRC, wrong PID, etc */
+			ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n",
+				urb->dev->devpath,
+				usb_pipeendpoint(urb->pipe),
+				usb_pipein(urb->pipe) ? "in" : "out");
+			status = -EPROTO;
+		} else {	/* unknown */
 			status = -EPROTO;
 			status = -EPROTO;
+		}
 
 
 		ehci_vdbg (ehci,
 		ehci_vdbg (ehci,
 			"dev%d ep%d%s qtd token %08x --> status %d\n",
 			"dev%d ep%d%s qtd token %08x --> status %d\n",
@@ -179,28 +246,6 @@ static int qtd_copy_status (
 			usb_pipeendpoint (urb->pipe),
 			usb_pipeendpoint (urb->pipe),
 			usb_pipein (urb->pipe) ? "in" : "out",
 			usb_pipein (urb->pipe) ? "in" : "out",
 			token, status);
 			token, status);
-
-		/* if async CSPLIT failed, try cleaning out the TT buffer */
-		if (status != -EPIPE
-				&& urb->dev->tt
-				&& !usb_pipeint(urb->pipe)
-				&& ((token & QTD_STS_MMF) != 0
-					|| QTD_CERR(token) == 0)
-				&& (!ehci_is_TDI(ehci)
-			                || urb->dev->tt->hub !=
-					   ehci_to_hcd(ehci)->self.root_hub)) {
-#ifdef DEBUG
-			struct usb_device *tt = urb->dev->tt->hub;
-			dev_dbg (&tt->dev,
-				"clear tt buffer port %d, a%d ep%d t%08x\n",
-				urb->dev->ttport, urb->dev->devnum,
-				usb_pipeendpoint (urb->pipe), token);
-#endif /* DEBUG */
-			/* REVISIT ARC-derived cores don't clear the root
-			 * hub TT buffer in this way...
-			 */
-			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
-		}
 	}
 	}
 
 
 	return status;
 	return status;
@@ -391,9 +436,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 			/* qh unlinked; token in overlay may be most current */
 			/* qh unlinked; token in overlay may be most current */
 			if (state == QH_STATE_IDLE
 			if (state == QH_STATE_IDLE
 					&& cpu_to_hc32(ehci, qtd->qtd_dma)
 					&& cpu_to_hc32(ehci, qtd->qtd_dma)
-						== qh->hw_current)
+						== qh->hw_current) {
 				token = hc32_to_cpu(ehci, qh->hw_token);
 				token = hc32_to_cpu(ehci, qh->hw_token);
 
 
+				/* An unlink may leave an incomplete
+				 * async transaction in the TT buffer.
+				 * We have to clear it.
+				 */
+				ehci_clear_tt_buffer(ehci, qh, urb, token);
+			}
+
 			/* force halt for unlinked or blocked qh, so we'll
 			/* force halt for unlinked or blocked qh, so we'll
 			 * patch the qh later and so that completions can't
 			 * patch the qh later and so that completions can't
 			 * activate it while we "know" it's stopped.
 			 * activate it while we "know" it's stopped.
@@ -419,6 +471,13 @@ halt:
 					&& (qtd->hw_alt_next
 					&& (qtd->hw_alt_next
 						& EHCI_LIST_END(ehci)))
 						& EHCI_LIST_END(ehci)))
 				last_status = -EINPROGRESS;
 				last_status = -EINPROGRESS;
+
+			/* As part of low/full-speed endpoint-halt processing
+			 * we must clear the TT buffer (11.17.5).
+			 */
+			if (unlikely(last_status != -EINPROGRESS &&
+					last_status != -EREMOTEIO))
+				ehci_clear_tt_buffer(ehci, qh, urb, token);
 		}
 		}
 
 
 		/* if we're removing something not at the queue head,
 		/* if we're removing something not at the queue head,
@@ -834,6 +893,7 @@ done:
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_state = QH_STATE_IDLE;
 	qh->hw_info1 = cpu_to_hc32(ehci, info1);
 	qh->hw_info1 = cpu_to_hc32(ehci, info1);
 	qh->hw_info2 = cpu_to_hc32(ehci, info2);
 	qh->hw_info2 = cpu_to_hc32(ehci, info2);
+	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
 	qh_refresh (ehci, qh);
 	qh_refresh (ehci, qh);
 	return qh;
 	return qh;
 }
 }
@@ -847,6 +907,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	__hc32		dma = QH_NEXT(ehci, qh->qh_dma);
 	__hc32		dma = QH_NEXT(ehci, qh->qh_dma);
 	struct ehci_qh	*head;
 	struct ehci_qh	*head;
 
 
+	/* Don't link a QH if there's a Clear-TT-Buffer pending */
+	if (unlikely(qh->clearing_tt))
+		return;
+
 	/* (re)start the async schedule? */
 	/* (re)start the async schedule? */
 	head = ehci->async;
 	head = ehci->async;
 	timer_action_done (ehci, TIMER_ASYNC_OFF);
 	timer_action_done (ehci, TIMER_ASYNC_OFF);
@@ -864,7 +928,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		}
 		}
 	}
 	}
 
 
-	/* clear halt and maybe recover from silicon quirk */
+	/* clear halt and/or toggle; and maybe recover from silicon quirk */
 	if (qh->qh_state == QH_STATE_IDLE)
 	if (qh->qh_state == QH_STATE_IDLE)
 		qh_refresh (ehci, qh);
 		qh_refresh (ehci, qh);
 
 

+ 8 - 4
drivers/usb/host/ehci-sched.c

@@ -1619,11 +1619,14 @@ itd_complete (
 				desc->status = -EPROTO;
 				desc->status = -EPROTO;
 
 
 			/* HC need not update length with this error */
 			/* HC need not update length with this error */
-			if (!(t & EHCI_ISOC_BABBLE))
-				desc->actual_length = EHCI_ITD_LENGTH (t);
+			if (!(t & EHCI_ISOC_BABBLE)) {
+				desc->actual_length = EHCI_ITD_LENGTH(t);
+				urb->actual_length += desc->actual_length;
+			}
 		} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
 		} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
 			desc->status = 0;
 			desc->status = 0;
-			desc->actual_length = EHCI_ITD_LENGTH (t);
+			desc->actual_length = EHCI_ITD_LENGTH(t);
+			urb->actual_length += desc->actual_length;
 		} else {
 		} else {
 			/* URB was too late */
 			/* URB was too late */
 			desc->status = -EXDEV;
 			desc->status = -EXDEV;
@@ -2014,7 +2017,8 @@ sitd_complete (
 			desc->status = -EPROTO;
 			desc->status = -EPROTO;
 	} else {
 	} else {
 		desc->status = 0;
 		desc->status = 0;
-		desc->actual_length = desc->length - SITD_LENGTH (t);
+		desc->actual_length = desc->length - SITD_LENGTH(t);
+		urb->actual_length += desc->actual_length;
 	}
 	}
 	stream->depth -= stream->interval << 3;
 	stream->depth -= stream->interval << 3;
 
 

+ 2 - 0
drivers/usb/host/ehci.h

@@ -354,7 +354,9 @@ struct ehci_qh {
 	unsigned short		period;		/* polling interval */
 	unsigned short		period;		/* polling interval */
 	unsigned short		start;		/* where polling starts */
 	unsigned short		start;		/* where polling starts */
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
+
 	struct usb_device	*dev;		/* access to TT */
 	struct usb_device	*dev;		/* access to TT */
+	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
 } __attribute__ ((aligned (32)));
 } __attribute__ ((aligned (32)));
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 2 - 6
drivers/usb/host/fhci-sched.c

@@ -576,9 +576,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
 			out_be16(&usb->fhci->regs->usb_event,
 			out_be16(&usb->fhci->regs->usb_event,
 				 usb->saved_msk);
 				 usb->saved_msk);
 		} else if (usb->port_status == FHCI_PORT_DISABLED) {
 		} else if (usb->port_status == FHCI_PORT_DISABLED) {
-			if (fhci_ioports_check_bus_state(fhci) == 1 &&
-					usb->port_status != FHCI_PORT_LOW &&
-					usb->port_status != FHCI_PORT_FULL)
+			if (fhci_ioports_check_bus_state(fhci) == 1)
 				fhci_device_connected_interrupt(fhci);
 				fhci_device_connected_interrupt(fhci);
 		}
 		}
 		usb_er &= ~USB_E_RESET_MASK;
 		usb_er &= ~USB_E_RESET_MASK;
@@ -605,9 +603,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
 	}
 	}
 
 
 	if (usb_er & USB_E_IDLE_MASK) {
 	if (usb_er & USB_E_IDLE_MASK) {
-		if (usb->port_status == FHCI_PORT_DISABLED &&
-				usb->port_status != FHCI_PORT_LOW &&
-				usb->port_status != FHCI_PORT_FULL) {
+		if (usb->port_status == FHCI_PORT_DISABLED) {
 			usb_er &= ~USB_E_RESET_MASK;
 			usb_er &= ~USB_E_RESET_MASK;
 			fhci_device_connected_interrupt(fhci);
 			fhci_device_connected_interrupt(fhci);
 		} else if (usb->port_status ==
 		} else if (usb->port_status ==

+ 1 - 1
drivers/usb/host/isp1760-if.c

@@ -361,7 +361,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
 
 
 static struct platform_driver isp1760_plat_driver = {
 static struct platform_driver isp1760_plat_driver = {
 	.probe	= isp1760_plat_probe,
 	.probe	= isp1760_plat_probe,
-	.remove	= isp1760_plat_remove,
+	.remove	= __devexit_p(isp1760_plat_remove),
 	.driver	= {
 	.driver	= {
 		.name	= "isp1760",
 		.name	= "isp1760",
 	},
 	},

+ 29 - 3
drivers/usb/musb/davinci.c

@@ -35,13 +35,14 @@
 #include <mach/hardware.h>
 #include <mach/hardware.h>
 #include <mach/memory.h>
 #include <mach/memory.h>
 #include <mach/gpio.h>
 #include <mach/gpio.h>
+#include <mach/cputype.h>
 
 
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 
 
 #include "musb_core.h"
 #include "musb_core.h"
 
 
 #ifdef CONFIG_MACH_DAVINCI_EVM
 #ifdef CONFIG_MACH_DAVINCI_EVM
-#define GPIO_nVBUS_DRV		87
+#define GPIO_nVBUS_DRV		144
 #endif
 #endif
 
 
 #include "davinci.h"
 #include "davinci.h"
@@ -329,7 +330,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
 			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
 			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
 			WARNING("VBUS error workaround (delay coming)\n");
 			WARNING("VBUS error workaround (delay coming)\n");
 		} else if (is_host_enabled(musb) && drvvbus) {
 		} else if (is_host_enabled(musb) && drvvbus) {
-			musb->is_active = 1;
 			MUSB_HST_MODE(musb);
 			MUSB_HST_MODE(musb);
 			musb->xceiv->default_a = 1;
 			musb->xceiv->default_a = 1;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
@@ -343,7 +343,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
 			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
 			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
 		}
 		}
 
 
-		/* NOTE:  this must complete poweron within 100 msec */
+		/* NOTE:  this must complete poweron within 100 msec
+		 * (OTG_TIME_A_WAIT_VRISE) but we don't check for that.
+		 */
 		davinci_source_power(musb, drvvbus, 0);
 		davinci_source_power(musb, drvvbus, 0);
 		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
 		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				drvvbus ? "on" : "off",
@@ -411,6 +413,21 @@ int __init musb_platform_init(struct musb *musb)
 		__raw_writel(phy_ctrl, USB_PHY_CTRL);
 		__raw_writel(phy_ctrl, USB_PHY_CTRL);
 	}
 	}
 
 
+	/* On dm355, the default-A state machine needs DRVVBUS control.
+	 * If we won't be a host, there's no need to turn it on.
+	 */
+	if (cpu_is_davinci_dm355()) {
+		u32	deepsleep = __raw_readl(DM355_DEEPSLEEP);
+
+		if (is_host_enabled(musb)) {
+			deepsleep &= ~DRVVBUS_OVERRIDE;
+		} else {
+			deepsleep &= ~DRVVBUS_FORCE;
+			deepsleep |= DRVVBUS_OVERRIDE;
+		}
+		__raw_writel(deepsleep, DM355_DEEPSLEEP);
+	}
+
 	/* reset the controller */
 	/* reset the controller */
 	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
 	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
 
 
@@ -437,6 +454,15 @@ int musb_platform_exit(struct musb *musb)
 	if (is_host_enabled(musb))
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
 		del_timer_sync(&otg_workaround);
 
 
+	/* force VBUS off */
+	if (cpu_is_davinci_dm355()) {
+		u32	deepsleep = __raw_readl(DM355_DEEPSLEEP);
+
+		deepsleep &= ~DRVVBUS_FORCE;
+		deepsleep |= DRVVBUS_OVERRIDE;
+		__raw_writel(deepsleep, DM355_DEEPSLEEP);
+	}
+
 	davinci_source_power(musb, 0 /*off*/, 1);
 	davinci_source_power(musb, 0 /*off*/, 1);
 
 
 	/* delay, to avoid problems with module reload */
 	/* delay, to avoid problems with module reload */

+ 22 - 5
drivers/usb/musb/musb_host.c

@@ -373,7 +373,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
 		musb_save_toggle(qh, is_in, urb);
 		musb_save_toggle(qh, is_in, urb);
 		break;
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
 	case USB_ENDPOINT_XFER_ISOC:
-		if (urb->error_count)
+		if (status == 0 && urb->error_count)
 			status = -EXDEV;
 			status = -EXDEV;
 		break;
 		break;
 	}
 	}
@@ -2235,13 +2235,30 @@ static void musb_h_stop(struct usb_hcd *hcd)
 static int musb_bus_suspend(struct usb_hcd *hcd)
 static int musb_bus_suspend(struct usb_hcd *hcd)
 {
 {
 	struct musb	*musb = hcd_to_musb(hcd);
 	struct musb	*musb = hcd_to_musb(hcd);
+	u8		devctl;
 
 
-	if (musb->xceiv->state == OTG_STATE_A_SUSPEND)
+	if (!is_host_active(musb))
 		return 0;
 		return 0;
 
 
-	if (is_host_active(musb) && musb->is_active) {
-		WARNING("trying to suspend as %s is_active=%i\n",
-			otg_state_string(musb), musb->is_active);
+	switch (musb->xceiv->state) {
+	case OTG_STATE_A_SUSPEND:
+		return 0;
+	case OTG_STATE_A_WAIT_VRISE:
+		/* ID could be grounded even if there's no device
+		 * on the other end of the cable.  NOTE that the
+		 * A_WAIT_VRISE timers are messy with MUSB...
+		 */
+		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+		if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+			musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+		break;
+	default:
+		break;
+	}
+
+	if (musb->is_active) {
+		WARNING("trying to suspend as %s while active\n",
+				otg_state_string(musb));
 		return -EBUSY;
 		return -EBUSY;
 	} else
 	} else
 		return 0;
 		return 0;

+ 0 - 14
drivers/usb/otg/Kconfig

@@ -59,18 +59,4 @@ config NOP_USB_XCEIV
 	 built-in with usb ip or which are autonomous and doesn't require any
 	 built-in with usb ip or which are autonomous and doesn't require any
 	 phy programming such as ISP1x04 etc.
 	 phy programming such as ISP1x04 etc.
 
 
-config USB_LANGWELL_OTG
-	tristate "Intel Langwell USB OTG dual-role support"
-	depends on USB && MRST
-	select USB_OTG
-	select USB_OTG_UTILS
-	help
-	  Say Y here if you want to build Intel Langwell USB OTG
-	  transciever driver in kernel. This driver implements role
-	  switch between EHCI host driver and Langwell USB OTG
-	  client driver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called langwell_otg.
-
 endif # USB || OTG
 endif # USB || OTG

+ 0 - 1
drivers/usb/otg/Makefile

@@ -9,7 +9,6 @@ obj-$(CONFIG_USB_OTG_UTILS)	+= otg.o
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
-obj-$(CONFIG_USB_LANGWELL_OTG)	+= langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 
 
 ccflags-$(CONFIG_USB_DEBUG)	+= -DDEBUG
 ccflags-$(CONFIG_USB_DEBUG)	+= -DDEBUG

+ 0 - 1915
drivers/usb/otg/langwell_otg.c

@@ -1,1915 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/* This driver helps to switch Langwell OTG controller function between host
- * and peripheral. It works with EHCI driver and Langwell client controller
- * driver together.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/notifier.h>
-#include <asm/ipc_defs.h>
-#include <linux/delay.h>
-#include "../core/hcd.h"
-
-#include <linux/usb/langwell_otg.h>
-
-#define	DRIVER_DESC		"Intel Langwell USB OTG transceiver driver"
-#define	DRIVER_VERSION		"3.0.0.32L.0002"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "langwell_otg";
-
-static int langwell_otg_probe(struct pci_dev *pdev,
-			const struct pci_device_id *id);
-static void langwell_otg_remove(struct pci_dev *pdev);
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
-static int langwell_otg_resume(struct pci_dev *pdev);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
-				struct usb_bus *host);
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
-				struct usb_gadget *gadget);
-static int langwell_otg_start_srp(struct otg_transceiver *otg);
-
-static const struct pci_device_id pci_ids[] = {{
-	.class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =   ~0,
-	.vendor =	0x8086,
-	.device =	0x0811,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-static struct pci_driver otg_pci_driver = {
-	.name =		(char *) driver_name,
-	.id_table =	pci_ids,
-
-	.probe =	langwell_otg_probe,
-	.remove =	langwell_otg_remove,
-
-	.suspend =	langwell_otg_suspend,
-	.resume =	langwell_otg_resume,
-};
-
-static const char *state_string(enum usb_otg_state state)
-{
-	switch (state) {
-	case OTG_STATE_A_IDLE:
-		return "a_idle";
-	case OTG_STATE_A_WAIT_VRISE:
-		return "a_wait_vrise";
-	case OTG_STATE_A_WAIT_BCON:
-		return "a_wait_bcon";
-	case OTG_STATE_A_HOST:
-		return "a_host";
-	case OTG_STATE_A_SUSPEND:
-		return "a_suspend";
-	case OTG_STATE_A_PERIPHERAL:
-		return "a_peripheral";
-	case OTG_STATE_A_WAIT_VFALL:
-		return "a_wait_vfall";
-	case OTG_STATE_A_VBUS_ERR:
-		return "a_vbus_err";
-	case OTG_STATE_B_IDLE:
-		return "b_idle";
-	case OTG_STATE_B_SRP_INIT:
-		return "b_srp_init";
-	case OTG_STATE_B_PERIPHERAL:
-		return "b_peripheral";
-	case OTG_STATE_B_WAIT_ACON:
-		return "b_wait_acon";
-	case OTG_STATE_B_HOST:
-		return "b_host";
-	default:
-		return "UNDEFINED";
-	}
-}
-
-/* HSM timers */
-static inline struct langwell_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
-	struct langwell_otg_timer *timer;
-	timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
-	timer->function = function;
-	timer->expires = expires;
-	timer->data = data;
-	return timer;
-}
-
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr,
-	*a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_res_tmr,
-	*b_bus_suspend_tmr;
-
-static struct list_head active_timers;
-
-static struct langwell_otg *the_transceiver;
-
-/* host/client notify transceiver when event affects HNP state */
-void langwell_update_transceiver()
-{
-	otg_dbg("transceiver driver is notified\n");
-	queue_work(the_transceiver->qwork, &the_transceiver->work);
-}
-EXPORT_SYMBOL(langwell_update_transceiver);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
-					struct usb_bus *host)
-{
-	otg->host = host;
-
-	return 0;
-}
-
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
-					struct usb_gadget *gadget)
-{
-	otg->gadget = gadget;
-
-	return 0;
-}
-
-static int langwell_otg_set_power(struct otg_transceiver *otg,
-				unsigned mA)
-{
-	return 0;
-}
-
-/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/
-static void langwell_otg_drv_vbus(int on)
-{
-	struct ipc_pmic_reg_data	pmic_data = {0};
-	struct ipc_pmic_reg_data	battery_data;
-
-	/* Check if battery is attached or not */
-	battery_data.pmic_reg_data[0].register_address = 0xd2;
-	battery_data.ioc = 0;
-	battery_data.num_entries = 1;
-	if (ipc_pmic_register_read(&battery_data)) {
-		otg_dbg("Failed to read PMIC register 0xd2.\n");
-		return;
-	}
-
-	if ((battery_data.pmic_reg_data[0].value & 0x20) == 0) {
-		otg_dbg("no battery attached\n");
-		return;
-	}
-
-	/* Workaround for battery attachment issue */
-	if (battery_data.pmic_reg_data[0].value == 0x34) {
-		otg_dbg("battery \n");
-		return;
-	}
-
-	otg_dbg("battery attached\n");
-
-	pmic_data.ioc = 0;
-	pmic_data.pmic_reg_data[0].register_address = 0xD4;
-	pmic_data.num_entries = 1;
-	if (on)
-		pmic_data.pmic_reg_data[0].value = 0x20;
-	else
-		pmic_data.pmic_reg_data[0].value = 0xc0;
-
-	if (ipc_pmic_register_write(&pmic_data, TRUE))
-		otg_dbg("Failed to write PMIC.\n");
-
-}
-
-/* charge vbus or discharge vbus through a resistor to ground */
-static void langwell_otg_chrg_vbus(int on)
-{
-
-	u32	val;
-
-	val = readl(the_transceiver->regs + CI_OTGSC);
-
-	if (on)
-		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
-				the_transceiver->regs + CI_OTGSC);
-	else
-		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
-				the_transceiver->regs + CI_OTGSC);
-
-}
-
-/* Start SRP */
-static int langwell_otg_start_srp(struct otg_transceiver *otg)
-{
-	u32	val;
-
-	otg_dbg("Start SRP ->\n");
-
-	val = readl(the_transceiver->regs + CI_OTGSC);
-
-	writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
-		the_transceiver->regs + CI_OTGSC);
-
-	/* Check if the data plus is finished or not */
-	msleep(8);
-	val = readl(the_transceiver->regs + CI_OTGSC);
-	if (val & (OTGSC_HADP | OTGSC_DP))
-		otg_dbg("DataLine SRP Error\n");
-
-	/* FIXME: VBus SRP */
-
-	return 0;
-}
-
-
-/* stop SOF via bus_suspend */
-static void langwell_otg_loc_sof(int on)
-{
-	struct usb_hcd	*hcd;
-	int		err;
-
-	otg_dbg("loc_sof -> %d\n", on);
-
-	hcd = bus_to_hcd(the_transceiver->otg.host);
-	if (on)
-		err = hcd->driver->bus_resume(hcd);
-	else
-		err = hcd->driver->bus_suspend(hcd);
-
-	if (err)
-		otg_dbg("Failed to resume/suspend bus - %d\n", err);
-}
-
-static void langwell_otg_phy_low_power(int on)
-{
-	u32	val;
-
-	otg_dbg("phy low power mode-> %d\n", on);
-
-	val = readl(the_transceiver->regs + CI_HOSTPC1);
-	if (on)
-		writel(val | HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1);
-	else
-		writel(val & ~HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1);
-}
-
-/* Enable/Disable OTG interrupt */
-static void langwell_otg_intr(int on)
-{
-	u32 val;
-
-	otg_dbg("interrupt -> %d\n", on);
-
-	val = readl(the_transceiver->regs + CI_OTGSC);
-	if (on) {
-		val = val | (OTGSC_INTEN_MASK | OTGSC_IDPU);
-		writel(val, the_transceiver->regs + CI_OTGSC);
-	} else {
-		val = val & ~(OTGSC_INTEN_MASK | OTGSC_IDPU);
-		writel(val, the_transceiver->regs + CI_OTGSC);
-	}
-}
-
-/* set HAAR: Hardware Assist Auto-Reset */
-static void langwell_otg_HAAR(int on)
-{
-	u32	val;
-
-	otg_dbg("HAAR -> %d\n", on);
-
-	val = readl(the_transceiver->regs + CI_OTGSC);
-	if (on)
-		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
-				the_transceiver->regs + CI_OTGSC);
-	else
-		writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
-				the_transceiver->regs + CI_OTGSC);
-}
-
-/* set HABA: Hardware Assist B-Disconnect to A-Connect */
-static void langwell_otg_HABA(int on)
-{
-	u32	val;
-
-	otg_dbg("HABA -> %d\n", on);
-
-	val = readl(the_transceiver->regs + CI_OTGSC);
-	if (on)
-		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
-				the_transceiver->regs + CI_OTGSC);
-	else
-		writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
-				the_transceiver->regs + CI_OTGSC);
-}
-
-static int langwell_otg_check_se0_srp(int on)
-{
-	u32 val;
-
-	int delay_time = TB_SE0_SRP * 10; /* step is 100us */
-
-	otg_dbg("check_se0_srp -> \n");
-
-	do {
-		udelay(100);
-		if (!delay_time--)
-			break;
-		val = readl(the_transceiver->regs + CI_PORTSC1);
-		val &= PORTSC_LS;
-	} while (!val);
-
-	otg_dbg("check_se0_srp <- \n");
-	return val;
-}
-
-/* The timeout callback function to set time out bit */
-static void set_tmout(unsigned long indicator)
-{
-	*(int *)indicator = 1;
-}
-
-void langwell_otg_nsf_msg(unsigned long indicator)
-{
-	switch (indicator) {
-	case 2:
-	case 4:
-	case 6:
-	case 7:
-		printk(KERN_ERR "OTG:NSF-%lu - deivce not responding\n",
-				indicator);
-		break;
-	case 3:
-		printk(KERN_ERR "OTG:NSF-%lu - deivce not supported\n",
-				indicator);
-		break;
-	default:
-		printk(KERN_ERR "Do not have this kind of NSF\n");
-		break;
-	}
-}
-
-/* Initialize timers */
-static void langwell_otg_init_timers(struct otg_hsm *hsm)
-{
-	/* HSM used timers */
-	a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
-				(unsigned long)&hsm->a_wait_vrise_tmout);
-	a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON,
-				(unsigned long)&hsm->a_wait_bcon_tmout);
-	a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
-				(unsigned long)&hsm->a_aidl_bdis_tmout);
-	b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST,
-				(unsigned long)&hsm->b_ase0_brst_tmout);
-	b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
-				(unsigned long)&hsm->b_se0_srp);
-	b_srp_res_tmr = otg_timer_initializer(&set_tmout, TB_SRP_RES,
-				(unsigned long)&hsm->b_srp_res_tmout);
-	b_bus_suspend_tmr = otg_timer_initializer(&set_tmout, TB_BUS_SUSPEND,
-				(unsigned long)&hsm->b_bus_suspend_tmout);
-}
-
-/* Free timers */
-static void langwell_otg_free_timers(void)
-{
-	kfree(a_wait_vrise_tmr);
-	kfree(a_wait_bcon_tmr);
-	kfree(a_aidl_bdis_tmr);
-	kfree(b_ase0_brst_tmr);
-	kfree(b_se0_srp_tmr);
-	kfree(b_srp_res_tmr);
-	kfree(b_bus_suspend_tmr);
-}
-
-/* Add timer to timer list */
-static void langwell_otg_add_timer(void *gtimer)
-{
-	struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
-	struct langwell_otg_timer *tmp_timer;
-	u32	val32;
-
-	/* Check if the timer is already in the active list,
-	 * if so update timer count
-	 */
-	list_for_each_entry(tmp_timer, &active_timers, list)
-		if (tmp_timer == timer) {
-			timer->count = timer->expires;
-			return;
-		}
-	timer->count = timer->expires;
-
-	if (list_empty(&active_timers)) {
-		val32 = readl(the_transceiver->regs + CI_OTGSC);
-		writel(val32 | OTGSC_1MSE, the_transceiver->regs + CI_OTGSC);
-	}
-
-	list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-static void langwell_otg_del_timer(void *gtimer)
-{
-	struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
-	struct langwell_otg_timer *tmp_timer, *del_tmp;
-	u32 val32;
-
-	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
-		if (tmp_timer == timer)
-			list_del(&timer->list);
-
-	if (list_empty(&active_timers)) {
-		val32 = readl(the_transceiver->regs + CI_OTGSC);
-		writel(val32 & ~OTGSC_1MSE, the_transceiver->regs + CI_OTGSC);
-	}
-}
-
-/* Reduce timer count by 1, and find timeout conditions.*/
-static int langwell_otg_tick_timer(u32 *int_sts)
-{
-	struct langwell_otg_timer *tmp_timer, *del_tmp;
-	int expired = 0;
-
-	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
-		tmp_timer->count--;
-		/* check if timer expires */
-		if (!tmp_timer->count) {
-			list_del(&tmp_timer->list);
-			tmp_timer->function(tmp_timer->data);
-			expired = 1;
-		}
-	}
-
-	if (list_empty(&active_timers)) {
-		otg_dbg("tick timer: disable 1ms int\n");
-		*int_sts = *int_sts & ~OTGSC_1MSE;
-	}
-	return expired;
-}
-
-static void reset_otg(void)
-{
-	u32	val;
-	int	delay_time = 1000;
-
-	otg_dbg("reseting OTG controller ...\n");
-	val = readl(the_transceiver->regs + CI_USBCMD);
-	writel(val | USBCMD_RST, the_transceiver->regs + CI_USBCMD);
-	do {
-		udelay(100);
-		if (!delay_time--)
-			otg_dbg("reset timeout\n");
-		val = readl(the_transceiver->regs + CI_USBCMD);
-		val &= USBCMD_RST;
-	} while (val != 0);
-	otg_dbg("reset done.\n");
-}
-
-static void set_host_mode(void)
-{
-	u32 	val;
-
-	reset_otg();
-	val = readl(the_transceiver->regs + CI_USBMODE);
-	val = (val & (~USBMODE_CM)) | USBMODE_HOST;
-	writel(val, the_transceiver->regs + CI_USBMODE);
-}
-
-static void set_client_mode(void)
-{
-	u32 	val;
-
-	reset_otg();
-	val = readl(the_transceiver->regs + CI_USBMODE);
-	val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
-	writel(val, the_transceiver->regs + CI_USBMODE);
-}
-
-static void init_hsm(void)
-{
-	struct langwell_otg	*langwell = the_transceiver;
-	u32			val32;
-
-	/* read OTGSC after reset */
-	val32 = readl(langwell->regs + CI_OTGSC);
-	otg_dbg("%s: OTGSC init value = 0x%x\n", __func__, val32);
-
-	/* set init state */
-	if (val32 & OTGSC_ID) {
-		langwell->hsm.id = 1;
-		langwell->otg.default_a = 0;
-		set_client_mode();
-		langwell->otg.state = OTG_STATE_B_IDLE;
-		langwell_otg_drv_vbus(0);
-	} else {
-		langwell->hsm.id = 0;
-		langwell->otg.default_a = 1;
-		set_host_mode();
-		langwell->otg.state = OTG_STATE_A_IDLE;
-	}
-
-	/* set session indicator */
-	if (val32 & OTGSC_BSE)
-		langwell->hsm.b_sess_end = 1;
-	if (val32 & OTGSC_BSV)
-		langwell->hsm.b_sess_vld = 1;
-	if (val32 & OTGSC_ASV)
-		langwell->hsm.a_sess_vld = 1;
-	if (val32 & OTGSC_AVV)
-		langwell->hsm.a_vbus_vld = 1;
-
-	/* defautly power the bus */
-	langwell->hsm.a_bus_req = 1;
-	langwell->hsm.a_bus_drop = 0;
-	/* defautly don't request bus as B device */
-	langwell->hsm.b_bus_req = 0;
-	/* no system error */
-	langwell->hsm.a_clr_err = 0;
-}
-
-static irqreturn_t otg_dummy_irq(int irq, void *_dev)
-{
-	void __iomem	*reg_base = _dev;
-	u32	val;
-	u32	int_mask = 0;
-
-	val = readl(reg_base + CI_USBMODE);
-	if ((val & USBMODE_CM) != USBMODE_DEVICE)
-		return IRQ_NONE;
-
-	val = readl(reg_base + CI_USBSTS);
-	int_mask = val & INTR_DUMMY_MASK;
-
-	if (int_mask == 0)
-		return IRQ_NONE;
-
-	/* clear hsm.b_conn here since host driver can't detect it
-	*  otg_dummy_irq called means B-disconnect happened.
-	*/
-	if (the_transceiver->hsm.b_conn) {
-		the_transceiver->hsm.b_conn = 0;
-		if (spin_trylock(&the_transceiver->wq_lock)) {
-			queue_work(the_transceiver->qwork,
-				&the_transceiver->work);
-			spin_unlock(&the_transceiver->wq_lock);
-		}
-	}
-	/* Clear interrupts */
-	writel(int_mask, reg_base + CI_USBSTS);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t otg_irq(int irq, void *_dev)
-{
-	struct	langwell_otg *langwell = _dev;
-	u32	int_sts, int_en;
-	u32	int_mask = 0;
-	int	flag = 0;
-
-	int_sts = readl(langwell->regs + CI_OTGSC);
-	int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
-	int_mask = int_sts & int_en;
-	if (int_mask == 0)
-		return IRQ_NONE;
-
-	if (int_mask & OTGSC_IDIS) {
-		otg_dbg("%s: id change int\n", __func__);
-		langwell->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
-		flag = 1;
-	}
-	if (int_mask & OTGSC_DPIS) {
-		otg_dbg("%s: data pulse int\n", __func__);
-		langwell->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
-		flag = 1;
-	}
-	if (int_mask & OTGSC_BSEIS) {
-		otg_dbg("%s: b session end int\n", __func__);
-		langwell->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
-		flag = 1;
-	}
-	if (int_mask & OTGSC_BSVIS) {
-		otg_dbg("%s: b session valid int\n", __func__);
-		langwell->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
-		flag = 1;
-	}
-	if (int_mask & OTGSC_ASVIS) {
-		otg_dbg("%s: a session valid int\n", __func__);
-		langwell->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
-		flag = 1;
-	}
-	if (int_mask & OTGSC_AVVIS) {
-		otg_dbg("%s: a vbus valid int\n", __func__);
-		langwell->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
-		flag = 1;
-	}
-
-	if (int_mask & OTGSC_1MSS) {
-		/* need to schedule otg_work if any timer is expired */
-		if (langwell_otg_tick_timer(&int_sts))
-			flag = 1;
-	}
-
-	writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
-			langwell->regs + CI_OTGSC);
-	if (flag)
-		queue_work(langwell->qwork, &langwell->work);
-
-	return IRQ_HANDLED;
-}
-
-static void langwell_otg_work(struct work_struct *work)
-{
-	struct langwell_otg *langwell = container_of(work,
-					struct langwell_otg, work);
-	int	retval;
-
-	otg_dbg("%s: old state = %s\n", __func__,
-			state_string(langwell->otg.state));
-
-	switch (langwell->otg.state) {
-	case OTG_STATE_UNDEFINED:
-	case OTG_STATE_B_IDLE:
-		if (!langwell->hsm.id) {
-			langwell_otg_del_timer(b_srp_res_tmr);
-			langwell->otg.default_a = 1;
-			langwell->hsm.a_srp_det = 0;
-
-			langwell_otg_chrg_vbus(0);
-			langwell_otg_drv_vbus(0);
-
-			set_host_mode();
-			langwell->otg.state = OTG_STATE_A_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.b_srp_res_tmout) {
-			langwell->hsm.b_srp_res_tmout = 0;
-			langwell->hsm.b_bus_req = 0;
-			langwell_otg_nsf_msg(6);
-		} else if (langwell->hsm.b_sess_vld) {
-			langwell_otg_del_timer(b_srp_res_tmr);
-			langwell->hsm.b_sess_end = 0;
-			langwell->hsm.a_bus_suspend = 0;
-
-			langwell_otg_chrg_vbus(0);
-			if (langwell->client_ops) {
-				langwell->client_ops->resume(langwell->pdev);
-				langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-			} else
-				otg_dbg("client driver not loaded.\n");
-
-		} else if (langwell->hsm.b_bus_req &&
-				(langwell->hsm.b_sess_end)) {
-			/* workaround for b_se0_srp detection */
-			retval = langwell_otg_check_se0_srp(0);
-			if (retval) {
-				langwell->hsm.b_bus_req = 0;
-				otg_dbg("LS is not SE0, try again later\n");
-			} else {
-				/* Start SRP */
-				langwell_otg_start_srp(&langwell->otg);
-				langwell_otg_add_timer(b_srp_res_tmr);
-			}
-		}
-		break;
-	case OTG_STATE_B_SRP_INIT:
-		if (!langwell->hsm.id) {
-			langwell->otg.default_a = 1;
-			langwell->hsm.a_srp_det = 0;
-
-			langwell_otg_drv_vbus(0);
-			langwell_otg_chrg_vbus(0);
-
-			langwell->otg.state = OTG_STATE_A_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.b_sess_vld) {
-			langwell_otg_chrg_vbus(0);
-			if (langwell->client_ops) {
-				langwell->client_ops->resume(langwell->pdev);
-				langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-			} else
-				otg_dbg("client driver not loaded.\n");
-		}
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		if (!langwell->hsm.id) {
-			langwell->otg.default_a = 1;
-			langwell->hsm.a_srp_det = 0;
-
-			langwell_otg_drv_vbus(0);
-			langwell_otg_chrg_vbus(0);
-			set_host_mode();
-
-			if (langwell->client_ops) {
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			} else
-				otg_dbg("client driver has been removed.\n");
-
-			langwell->otg.state = OTG_STATE_A_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (!langwell->hsm.b_sess_vld) {
-			langwell->hsm.b_hnp_enable = 0;
-
-			if (langwell->client_ops) {
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			} else
-				otg_dbg("client driver has been removed.\n");
-
-			langwell->otg.state = OTG_STATE_B_IDLE;
-		} else if (langwell->hsm.b_bus_req && langwell->hsm.b_hnp_enable
-			&& langwell->hsm.a_bus_suspend) {
-
-			if (langwell->client_ops) {
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			} else
-				otg_dbg("client driver has been removed.\n");
-
-			langwell_otg_HAAR(1);
-			langwell->hsm.a_conn = 0;
-
-			if (langwell->host_ops) {
-				langwell->host_ops->probe(langwell->pdev,
-					langwell->host_ops->id_table);
-				langwell->otg.state = OTG_STATE_B_WAIT_ACON;
-			} else
-				otg_dbg("host driver not loaded.\n");
-
-			langwell->hsm.a_bus_resume = 0;
-			langwell->hsm.b_ase0_brst_tmout = 0;
-			langwell_otg_add_timer(b_ase0_brst_tmr);
-		}
-		break;
-
-	case OTG_STATE_B_WAIT_ACON:
-		if (!langwell->hsm.id) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
-			langwell->otg.default_a = 1;
-			langwell->hsm.a_srp_det = 0;
-
-			langwell_otg_drv_vbus(0);
-			langwell_otg_chrg_vbus(0);
-			set_host_mode();
-
-			langwell_otg_HAAR(0);
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell->otg.state = OTG_STATE_A_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (!langwell->hsm.b_sess_vld) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
-			langwell->hsm.b_hnp_enable = 0;
-			langwell->hsm.b_bus_req = 0;
-			langwell_otg_chrg_vbus(0);
-			langwell_otg_HAAR(0);
-
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell->otg.state = OTG_STATE_B_IDLE;
-		} else if (langwell->hsm.a_conn) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
-			langwell_otg_HAAR(0);
-			langwell->otg.state = OTG_STATE_B_HOST;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.a_bus_resume ||
-				langwell->hsm.b_ase0_brst_tmout) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
-			langwell_otg_HAAR(0);
-			langwell_otg_nsf_msg(7);
-
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-
-			langwell->hsm.a_bus_suspend = 0;
-			langwell->hsm.b_bus_req = 0;
-
-			if (langwell->client_ops)
-				langwell->client_ops->resume(langwell->pdev);
-			else
-				otg_dbg("client driver not loaded.\n");
-
-			langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-		}
-		break;
-
-	case OTG_STATE_B_HOST:
-		if (!langwell->hsm.id) {
-			langwell->otg.default_a = 1;
-			langwell->hsm.a_srp_det = 0;
-
-			langwell_otg_drv_vbus(0);
-			langwell_otg_chrg_vbus(0);
-			set_host_mode();
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell->otg.state = OTG_STATE_A_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (!langwell->hsm.b_sess_vld) {
-			langwell->hsm.b_hnp_enable = 0;
-			langwell->hsm.b_bus_req = 0;
-			langwell_otg_chrg_vbus(0);
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell->otg.state = OTG_STATE_B_IDLE;
-		} else if ((!langwell->hsm.b_bus_req) ||
-				(!langwell->hsm.a_conn)) {
-			langwell->hsm.b_bus_req = 0;
-			langwell_otg_loc_sof(0);
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-
-			langwell->hsm.a_bus_suspend = 0;
-
-			if (langwell->client_ops)
-				langwell->client_ops->resume(langwell->pdev);
-			else
-				otg_dbg("client driver not loaded.\n");
-
-			langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-		}
-		break;
-
-	case OTG_STATE_A_IDLE:
-		langwell->otg.default_a = 1;
-		if (langwell->hsm.id) {
-			langwell->otg.default_a = 0;
-			langwell->hsm.b_bus_req = 0;
-			langwell_otg_drv_vbus(0);
-			langwell_otg_chrg_vbus(0);
-
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.a_sess_vld) {
-			langwell_otg_drv_vbus(1);
-			langwell->hsm.a_srp_det = 1;
-			langwell->hsm.a_wait_vrise_tmout = 0;
-			langwell_otg_add_timer(a_wait_vrise_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_VRISE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (!langwell->hsm.a_bus_drop &&
-			(langwell->hsm.a_srp_det || langwell->hsm.a_bus_req)) {
-			langwell_otg_drv_vbus(1);
-			langwell->hsm.a_wait_vrise_tmout = 0;
-			langwell_otg_add_timer(a_wait_vrise_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_VRISE;
-			queue_work(langwell->qwork, &langwell->work);
-		}
-		break;
-	case OTG_STATE_A_WAIT_VRISE:
-		if (langwell->hsm.id) {
-			langwell_otg_del_timer(a_wait_vrise_tmr);
-			langwell->hsm.b_bus_req = 0;
-			langwell->otg.default_a = 0;
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_B_IDLE;
-		} else if (langwell->hsm.a_vbus_vld) {
-			langwell_otg_del_timer(a_wait_vrise_tmr);
-			if (langwell->host_ops)
-				langwell->host_ops->probe(langwell->pdev,
-						langwell->host_ops->id_table);
-			else
-				otg_dbg("host driver not loaded.\n");
-			langwell->hsm.b_conn = 0;
-			langwell->hsm.a_set_b_hnp_en = 0;
-			langwell->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-		} else if (langwell->hsm.a_wait_vrise_tmout) {
-			if (langwell->hsm.a_vbus_vld) {
-				if (langwell->host_ops)
-					langwell->host_ops->probe(
-						langwell->pdev,
-						langwell->host_ops->id_table);
-				else
-					otg_dbg("host driver not loaded.\n");
-				langwell->hsm.b_conn = 0;
-				langwell->hsm.a_set_b_hnp_en = 0;
-				langwell->hsm.a_wait_bcon_tmout = 0;
-				langwell_otg_add_timer(a_wait_bcon_tmr);
-				langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-			} else {
-				langwell_otg_drv_vbus(0);
-				langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-			}
-		}
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		if (langwell->hsm.id) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
-
-			langwell->otg.default_a = 0;
-			langwell->hsm.b_bus_req = 0;
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (!langwell->hsm.a_vbus_vld) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
-
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-		} else if (langwell->hsm.a_bus_drop ||
-				(langwell->hsm.a_wait_bcon_tmout &&
-				!langwell->hsm.a_bus_req)) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
-
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-		} else if (langwell->hsm.b_conn) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
-
-			langwell->hsm.a_suspend_req = 0;
-			langwell->otg.state = OTG_STATE_A_HOST;
-			if (!langwell->hsm.a_bus_req &&
-				langwell->hsm.a_set_b_hnp_en) {
-				/* It is not safe enough to do a fast
-				 * transistion from A_WAIT_BCON to
-				 * A_SUSPEND */
-				msleep(10000);
-				if (langwell->hsm.a_bus_req)
-					break;
-
-				if (request_irq(langwell->pdev->irq,
-					otg_dummy_irq, IRQF_SHARED,
-					driver_name, langwell->regs) != 0) {
-					otg_dbg("request interrupt %d fail\n",
-					langwell->pdev->irq);
-				}
-
-				langwell_otg_HABA(1);
-				langwell->hsm.b_bus_resume = 0;
-				langwell->hsm.a_aidl_bdis_tmout = 0;
-				langwell_otg_add_timer(a_aidl_bdis_tmr);
-
-				langwell_otg_loc_sof(0);
-				langwell->otg.state = OTG_STATE_A_SUSPEND;
-			} else if (!langwell->hsm.a_bus_req &&
-				!langwell->hsm.a_set_b_hnp_en) {
-				struct pci_dev *pdev = langwell->pdev;
-				if (langwell->host_ops)
-					langwell->host_ops->remove(pdev);
-				else
-					otg_dbg("host driver removed.\n");
-				langwell_otg_drv_vbus(0);
-				langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-			}
-		}
-		break;
-	case OTG_STATE_A_HOST:
-		if (langwell->hsm.id) {
-			langwell->otg.default_a = 0;
-			langwell->hsm.b_bus_req = 0;
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.a_bus_drop ||
-		(!langwell->hsm.a_set_b_hnp_en && !langwell->hsm.a_bus_req)) {
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-		} else if (!langwell->hsm.a_vbus_vld) {
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-		} else if (langwell->hsm.a_set_b_hnp_en
-				&& !langwell->hsm.a_bus_req) {
-			/* Set HABA to enable hardware assistance to signal
-			 *  A-connect after receiver B-disconnect. Hardware
-			 *  will then set client mode and enable URE, SLE and
-			 *  PCE after the assistance. otg_dummy_irq is used to
-			 *  clean these ints when client driver is not resumed.
-			 */
-			if (request_irq(langwell->pdev->irq,
-				otg_dummy_irq, IRQF_SHARED, driver_name,
-				langwell->regs) != 0) {
-				otg_dbg("request interrupt %d failed\n",
-						langwell->pdev->irq);
-			}
-
-			/* set HABA */
-			langwell_otg_HABA(1);
-			langwell->hsm.b_bus_resume = 0;
-			langwell->hsm.a_aidl_bdis_tmout = 0;
-			langwell_otg_add_timer(a_aidl_bdis_tmr);
-			langwell_otg_loc_sof(0);
-			langwell->otg.state = OTG_STATE_A_SUSPEND;
-		} else if (!langwell->hsm.b_conn || !langwell->hsm.a_bus_req) {
-			langwell->hsm.a_wait_bcon_tmout = 0;
-			langwell->hsm.a_set_b_hnp_en = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-		}
-		break;
-	case OTG_STATE_A_SUSPEND:
-		if (langwell->hsm.id) {
-			langwell_otg_del_timer(a_aidl_bdis_tmr);
-			langwell_otg_HABA(0);
-			free_irq(langwell->pdev->irq, langwell->regs);
-			langwell->otg.default_a = 0;
-			langwell->hsm.b_bus_req = 0;
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.a_bus_req ||
-				langwell->hsm.b_bus_resume) {
-			langwell_otg_del_timer(a_aidl_bdis_tmr);
-			langwell_otg_HABA(0);
-			free_irq(langwell->pdev->irq, langwell->regs);
-			langwell->hsm.a_suspend_req = 0;
-			langwell_otg_loc_sof(1);
-			langwell->otg.state = OTG_STATE_A_HOST;
-		} else if (langwell->hsm.a_aidl_bdis_tmout ||
-				langwell->hsm.a_bus_drop) {
-			langwell_otg_del_timer(a_aidl_bdis_tmr);
-			langwell_otg_HABA(0);
-			free_irq(langwell->pdev->irq, langwell->regs);
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-		} else if (!langwell->hsm.b_conn &&
-				langwell->hsm.a_set_b_hnp_en) {
-			langwell_otg_del_timer(a_aidl_bdis_tmr);
-			langwell_otg_HABA(0);
-			free_irq(langwell->pdev->irq, langwell->regs);
-
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-
-			langwell->hsm.b_bus_suspend = 0;
-			langwell->hsm.b_bus_suspend_vld = 0;
-			langwell->hsm.b_bus_suspend_tmout = 0;
-
-			/* msleep(200); */
-			if (langwell->client_ops)
-				langwell->client_ops->resume(langwell->pdev);
-			else
-				otg_dbg("client driver not loaded.\n");
-
-			langwell_otg_add_timer(b_bus_suspend_tmr);
-			langwell->otg.state = OTG_STATE_A_PERIPHERAL;
-			break;
-		} else if (!langwell->hsm.a_vbus_vld) {
-			langwell_otg_del_timer(a_aidl_bdis_tmr);
-			langwell_otg_HABA(0);
-			free_irq(langwell->pdev->irq, langwell->regs);
-			if (langwell->host_ops)
-				langwell->host_ops->remove(langwell->pdev);
-			else
-				otg_dbg("host driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-		}
-		break;
-	case OTG_STATE_A_PERIPHERAL:
-		if (langwell->hsm.id) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
-			langwell->otg.default_a = 0;
-			langwell->hsm.b_bus_req = 0;
-			if (langwell->client_ops)
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			else
-				otg_dbg("client driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (!langwell->hsm.a_vbus_vld) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
-			if (langwell->client_ops)
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			else
-				otg_dbg("client driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-		} else if (langwell->hsm.a_bus_drop) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
-			if (langwell->client_ops)
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			else
-				otg_dbg("client driver has been removed.\n");
-			langwell_otg_drv_vbus(0);
-			langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-		} else if (langwell->hsm.b_bus_suspend) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
-			if (langwell->client_ops)
-				langwell->client_ops->suspend(langwell->pdev,
-					PMSG_FREEZE);
-			else
-				otg_dbg("client driver has been removed.\n");
-
-			if (langwell->host_ops)
-				langwell->host_ops->probe(langwell->pdev,
-						langwell->host_ops->id_table);
-			else
-				otg_dbg("host driver not loaded.\n");
-			langwell->hsm.a_set_b_hnp_en = 0;
-			langwell->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-		} else if (langwell->hsm.b_bus_suspend_tmout) {
-			u32	val;
-			val = readl(langwell->regs + CI_PORTSC1);
-			if (!(val & PORTSC_SUSP))
-				break;
-			if (langwell->client_ops)
-				langwell->client_ops->suspend(langwell->pdev,
-						PMSG_FREEZE);
-			else
-				otg_dbg("client driver has been removed.\n");
-			if (langwell->host_ops)
-				langwell->host_ops->probe(langwell->pdev,
-						langwell->host_ops->id_table);
-			else
-				otg_dbg("host driver not loaded.\n");
-			langwell->hsm.a_set_b_hnp_en = 0;
-			langwell->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-		}
-		break;
-	case OTG_STATE_A_VBUS_ERR:
-		if (langwell->hsm.id) {
-			langwell->otg.default_a = 0;
-			langwell->hsm.a_clr_err = 0;
-			langwell->hsm.a_srp_det = 0;
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.a_clr_err) {
-			langwell->hsm.a_clr_err = 0;
-			langwell->hsm.a_srp_det = 0;
-			reset_otg();
-			init_hsm();
-			if (langwell->otg.state == OTG_STATE_A_IDLE)
-				queue_work(langwell->qwork, &langwell->work);
-		}
-		break;
-	case OTG_STATE_A_WAIT_VFALL:
-		if (langwell->hsm.id) {
-			langwell->otg.default_a = 0;
-			langwell->otg.state = OTG_STATE_B_IDLE;
-			queue_work(langwell->qwork, &langwell->work);
-		} else if (langwell->hsm.a_bus_req) {
-			langwell_otg_drv_vbus(1);
-			langwell->hsm.a_wait_vrise_tmout = 0;
-			langwell_otg_add_timer(a_wait_vrise_tmr);
-			langwell->otg.state = OTG_STATE_A_WAIT_VRISE;
-		} else if (!langwell->hsm.a_sess_vld) {
-			langwell->hsm.a_srp_det = 0;
-			langwell_otg_drv_vbus(0);
-			set_host_mode();
-			langwell->otg.state = OTG_STATE_A_IDLE;
-		}
-		break;
-	default:
-		;
-	}
-
-	otg_dbg("%s: new state = %s\n", __func__,
-			state_string(langwell->otg.state));
-}
-
-	static ssize_t
-show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-	struct langwell_otg *langwell;
-	char *next;
-	unsigned size;
-	unsigned t;
-
-	langwell = the_transceiver;
-	next = buf;
-	size = PAGE_SIZE;
-
-	t = scnprintf(next, size,
-		"\n"
-		"USBCMD = 0x%08x \n"
-		"USBSTS = 0x%08x \n"
-		"USBINTR = 0x%08x \n"
-		"ASYNCLISTADDR = 0x%08x \n"
-		"PORTSC1 = 0x%08x \n"
-		"HOSTPC1 = 0x%08x \n"
-		"OTGSC = 0x%08x \n"
-		"USBMODE = 0x%08x \n",
-		readl(langwell->regs + 0x30),
-		readl(langwell->regs + 0x34),
-		readl(langwell->regs + 0x38),
-		readl(langwell->regs + 0x48),
-		readl(langwell->regs + 0x74),
-		readl(langwell->regs + 0xb4),
-		readl(langwell->regs + 0xf4),
-		readl(langwell->regs + 0xf8)
-		);
-	size -= t;
-	next += t;
-
-	return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-	struct langwell_otg *langwell;
-	char *next;
-	unsigned size;
-	unsigned t;
-
-	langwell = the_transceiver;
-	next = buf;
-	size = PAGE_SIZE;
-
-	t = scnprintf(next, size,
-		"\n"
-		"current state = %s\n"
-		"a_bus_resume = \t%d\n"
-		"a_bus_suspend = \t%d\n"
-		"a_conn = \t%d\n"
-		"a_sess_vld = \t%d\n"
-		"a_srp_det = \t%d\n"
-		"a_vbus_vld = \t%d\n"
-		"b_bus_resume = \t%d\n"
-		"b_bus_suspend = \t%d\n"
-		"b_conn = \t%d\n"
-		"b_se0_srp = \t%d\n"
-		"b_sess_end = \t%d\n"
-		"b_sess_vld = \t%d\n"
-		"id = \t%d\n"
-		"a_set_b_hnp_en = \t%d\n"
-		"b_srp_done = \t%d\n"
-		"b_hnp_enable = \t%d\n"
-		"a_wait_vrise_tmout = \t%d\n"
-		"a_wait_bcon_tmout = \t%d\n"
-		"a_aidl_bdis_tmout = \t%d\n"
-		"b_ase0_brst_tmout = \t%d\n"
-		"a_bus_drop = \t%d\n"
-		"a_bus_req = \t%d\n"
-		"a_clr_err = \t%d\n"
-		"a_suspend_req = \t%d\n"
-		"b_bus_req = \t%d\n"
-		"b_bus_suspend_tmout = \t%d\n"
-		"b_bus_suspend_vld = \t%d\n",
-		state_string(langwell->otg.state),
-		langwell->hsm.a_bus_resume,
-		langwell->hsm.a_bus_suspend,
-		langwell->hsm.a_conn,
-		langwell->hsm.a_sess_vld,
-		langwell->hsm.a_srp_det,
-		langwell->hsm.a_vbus_vld,
-		langwell->hsm.b_bus_resume,
-		langwell->hsm.b_bus_suspend,
-		langwell->hsm.b_conn,
-		langwell->hsm.b_se0_srp,
-		langwell->hsm.b_sess_end,
-		langwell->hsm.b_sess_vld,
-		langwell->hsm.id,
-		langwell->hsm.a_set_b_hnp_en,
-		langwell->hsm.b_srp_done,
-		langwell->hsm.b_hnp_enable,
-		langwell->hsm.a_wait_vrise_tmout,
-		langwell->hsm.a_wait_bcon_tmout,
-		langwell->hsm.a_aidl_bdis_tmout,
-		langwell->hsm.b_ase0_brst_tmout,
-		langwell->hsm.a_bus_drop,
-		langwell->hsm.a_bus_req,
-		langwell->hsm.a_clr_err,
-		langwell->hsm.a_suspend_req,
-		langwell->hsm.b_bus_req,
-		langwell->hsm.b_bus_suspend_tmout,
-		langwell->hsm.b_bus_suspend_vld
-		);
-	size -= t;
-	next += t;
-
-	return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct langwell_otg *langwell;
-	char *next;
-	unsigned size;
-	unsigned t;
-
-	langwell =  the_transceiver;
-	next = buf;
-	size = PAGE_SIZE;
-
-	t = scnprintf(next, size, "%d", langwell->hsm.a_bus_req);
-	size -= t;
-	next += t;
-
-	return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct langwell_otg *langwell;
-	langwell = the_transceiver;
-	if (!langwell->otg.default_a)
-		return -1;
-	if (count > 2)
-		return -1;
-
-	if (buf[0] == '0') {
-		langwell->hsm.a_bus_req = 0;
-		otg_dbg("a_bus_req = 0\n");
-	} else if (buf[0] == '1') {
-		/* If a_bus_drop is TRUE, a_bus_req can't be set */
-		if (langwell->hsm.a_bus_drop)
-			return -1;
-		langwell->hsm.a_bus_req = 1;
-		otg_dbg("a_bus_req = 1\n");
-	}
-	if (spin_trylock(&langwell->wq_lock)) {
-		queue_work(langwell->qwork, &langwell->work);
-		spin_unlock(&langwell->wq_lock);
-	}
-	return count;
-}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct langwell_otg *langwell;
-	char *next;
-	unsigned size;
-	unsigned t;
-
-	langwell =  the_transceiver;
-	next = buf;
-	size = PAGE_SIZE;
-
-	t = scnprintf(next, size, "%d", langwell->hsm.a_bus_drop);
-	size -= t;
-	next += t;
-
-	return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct langwell_otg *langwell;
-	langwell = the_transceiver;
-	if (!langwell->otg.default_a)
-		return -1;
-	if (count > 2)
-		return -1;
-
-	if (buf[0] == '0') {
-		langwell->hsm.a_bus_drop = 0;
-		otg_dbg("a_bus_drop = 0\n");
-	} else if (buf[0] == '1') {
-		langwell->hsm.a_bus_drop = 1;
-		langwell->hsm.a_bus_req = 0;
-		otg_dbg("a_bus_drop = 1, then a_bus_req = 0\n");
-	}
-	if (spin_trylock(&langwell->wq_lock)) {
-		queue_work(langwell->qwork, &langwell->work);
-		spin_unlock(&langwell->wq_lock);
-	}
-	return count;
-}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
-	get_a_bus_drop, set_a_bus_drop);
-
-static ssize_t
-get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct langwell_otg *langwell;
-	char *next;
-	unsigned size;
-	unsigned t;
-
-	langwell =  the_transceiver;
-	next = buf;
-	size = PAGE_SIZE;
-
-	t = scnprintf(next, size, "%d", langwell->hsm.b_bus_req);
-	size -= t;
-	next += t;
-
-	return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_b_bus_req(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct langwell_otg *langwell;
-	langwell = the_transceiver;
-
-	if (langwell->otg.default_a)
-		return -1;
-
-	if (count > 2)
-		return -1;
-
-	if (buf[0] == '0') {
-		langwell->hsm.b_bus_req = 0;
-		otg_dbg("b_bus_req = 0\n");
-	} else if (buf[0] == '1') {
-		langwell->hsm.b_bus_req = 1;
-		otg_dbg("b_bus_req = 1\n");
-	}
-	if (spin_trylock(&langwell->wq_lock)) {
-		queue_work(langwell->qwork, &langwell->work);
-		spin_unlock(&langwell->wq_lock);
-	}
-	return count;
-}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct langwell_otg *langwell;
-	langwell = the_transceiver;
-
-	if (!langwell->otg.default_a)
-		return -1;
-	if (count > 2)
-		return -1;
-
-	if (buf[0] == '1') {
-		langwell->hsm.a_clr_err = 1;
-		otg_dbg("a_clr_err = 1\n");
-	}
-	if (spin_trylock(&langwell->wq_lock)) {
-		queue_work(langwell->qwork, &langwell->work);
-		spin_unlock(&langwell->wq_lock);
-	}
-	return count;
-}
-static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
-
-static struct attribute *inputs_attrs[] = {
-	&dev_attr_a_bus_req.attr,
-	&dev_attr_a_bus_drop.attr,
-	&dev_attr_b_bus_req.attr,
-	&dev_attr_a_clr_err.attr,
-	NULL,
-};
-
-static struct attribute_group debug_dev_attr_group = {
-	.name = "inputs",
-	.attrs = inputs_attrs,
-};
-
-int langwell_register_host(struct pci_driver *host_driver)
-{
-	int	ret = 0;
-
-	the_transceiver->host_ops = host_driver;
-	queue_work(the_transceiver->qwork, &the_transceiver->work);
-	otg_dbg("host controller driver is registered\n");
-
-	return ret;
-}
-EXPORT_SYMBOL(langwell_register_host);
-
-void langwell_unregister_host(struct pci_driver *host_driver)
-{
-	if (the_transceiver->host_ops)
-		the_transceiver->host_ops->remove(the_transceiver->pdev);
-	the_transceiver->host_ops = NULL;
-	the_transceiver->hsm.a_bus_drop = 1;
-	queue_work(the_transceiver->qwork, &the_transceiver->work);
-	otg_dbg("host controller driver is unregistered\n");
-}
-EXPORT_SYMBOL(langwell_unregister_host);
-
-int langwell_register_peripheral(struct pci_driver *client_driver)
-{
-	int	ret = 0;
-
-	if (client_driver)
-		ret = client_driver->probe(the_transceiver->pdev,
-				client_driver->id_table);
-	if (!ret) {
-		the_transceiver->client_ops = client_driver;
-		queue_work(the_transceiver->qwork, &the_transceiver->work);
-		otg_dbg("client controller driver is registered\n");
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(langwell_register_peripheral);
-
-void langwell_unregister_peripheral(struct pci_driver *client_driver)
-{
-	if (the_transceiver->client_ops)
-		the_transceiver->client_ops->remove(the_transceiver->pdev);
-	the_transceiver->client_ops = NULL;
-	the_transceiver->hsm.b_bus_req = 0;
-	queue_work(the_transceiver->qwork, &the_transceiver->work);
-	otg_dbg("client controller driver is unregistered\n");
-}
-EXPORT_SYMBOL(langwell_unregister_peripheral);
-
-static int langwell_otg_probe(struct pci_dev *pdev,
-		const struct pci_device_id *id)
-{
-	unsigned long		resource, len;
-	void __iomem 		*base = NULL;
-	int			retval;
-	u32			val32;
-	struct langwell_otg	*langwell;
-	char			qname[] = "langwell_otg_queue";
-
-	retval = 0;
-	otg_dbg("\notg controller is detected.\n");
-	if (pci_enable_device(pdev) < 0) {
-		retval = -ENODEV;
-		goto done;
-	}
-
-	langwell = kzalloc(sizeof *langwell, GFP_KERNEL);
-	if (langwell == NULL) {
-		retval = -ENOMEM;
-		goto done;
-	}
-	the_transceiver = langwell;
-
-	/* control register: BAR 0 */
-	resource = pci_resource_start(pdev, 0);
-	len = pci_resource_len(pdev, 0);
-	if (!request_mem_region(resource, len, driver_name)) {
-		retval = -EBUSY;
-		goto err;
-	}
-	langwell->region = 1;
-
-	base = ioremap_nocache(resource, len);
-	if (base == NULL) {
-		retval = -EFAULT;
-		goto err;
-	}
-	langwell->regs = base;
-
-	if (!pdev->irq) {
-		otg_dbg("No IRQ.\n");
-		retval = -ENODEV;
-		goto err;
-	}
-
-	langwell->qwork = create_workqueue(qname);
-	if (!langwell->qwork) {
-		otg_dbg("cannot create workqueue %s\n", qname);
-		retval = -ENOMEM;
-		goto err;
-	}
-	INIT_WORK(&langwell->work, langwell_otg_work);
-
-	/* OTG common part */
-	langwell->pdev = pdev;
-	langwell->otg.dev = &pdev->dev;
-	langwell->otg.label = driver_name;
-	langwell->otg.set_host = langwell_otg_set_host;
-	langwell->otg.set_peripheral = langwell_otg_set_peripheral;
-	langwell->otg.set_power = langwell_otg_set_power;
-	langwell->otg.start_srp = langwell_otg_start_srp;
-	langwell->otg.state = OTG_STATE_UNDEFINED;
-	if (otg_set_transceiver(&langwell->otg)) {
-		otg_dbg("can't set transceiver\n");
-		retval = -EBUSY;
-		goto err;
-	}
-
-	reset_otg();
-	init_hsm();
-
-	spin_lock_init(&langwell->lock);
-	spin_lock_init(&langwell->wq_lock);
-	INIT_LIST_HEAD(&active_timers);
-	langwell_otg_init_timers(&langwell->hsm);
-
-	if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
-				driver_name, langwell) != 0) {
-		otg_dbg("request interrupt %d failed\n", pdev->irq);
-		retval = -EBUSY;
-		goto err;
-	}
-
-	/* enable OTGSC int */
-	val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
-		OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
-	writel(val32, langwell->regs + CI_OTGSC);
-
-	retval = device_create_file(&pdev->dev, &dev_attr_registers);
-	if (retval < 0) {
-		otg_dbg("Can't register sysfs attribute: %d\n", retval);
-		goto err;
-	}
-
-	retval = device_create_file(&pdev->dev, &dev_attr_hsm);
-	if (retval < 0) {
-		otg_dbg("Can't hsm sysfs attribute: %d\n", retval);
-		goto err;
-	}
-
-	retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
-	if (retval < 0) {
-		otg_dbg("Can't register sysfs attr group: %d\n", retval);
-		goto err;
-	}
-
-	if (langwell->otg.state == OTG_STATE_A_IDLE)
-		queue_work(langwell->qwork, &langwell->work);
-
-	return 0;
-
-err:
-	if (the_transceiver)
-		langwell_otg_remove(pdev);
-done:
-	return retval;
-}
-
-static void langwell_otg_remove(struct pci_dev *pdev)
-{
-	struct langwell_otg *langwell;
-
-	langwell = the_transceiver;
-
-	if (langwell->qwork) {
-		flush_workqueue(langwell->qwork);
-		destroy_workqueue(langwell->qwork);
-	}
-	langwell_otg_free_timers();
-
-	/* disable OTGSC interrupt as OTGSC doesn't change in reset */
-	writel(0, langwell->regs + CI_OTGSC);
-
-	if (pdev->irq)
-		free_irq(pdev->irq, langwell);
-	if (langwell->regs)
-		iounmap(langwell->regs);
-	if (langwell->region)
-		release_mem_region(pci_resource_start(pdev, 0),
-				pci_resource_len(pdev, 0));
-
-	otg_set_transceiver(NULL);
-	pci_disable_device(pdev);
-	sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
-	device_remove_file(&pdev->dev, &dev_attr_hsm);
-	device_remove_file(&pdev->dev, &dev_attr_registers);
-	kfree(langwell);
-	langwell = NULL;
-}
-
-static void transceiver_suspend(struct pci_dev *pdev)
-{
-	pci_save_state(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-	langwell_otg_phy_low_power(1);
-}
-
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
-{
-	int 	ret = 0;
-	struct langwell_otg *langwell;
-
-	langwell = the_transceiver;
-
-	/* Disbale OTG interrupts */
-	langwell_otg_intr(0);
-
-	if (pdev->irq)
-		free_irq(pdev->irq, langwell);
-
-	/* Prevent more otg_work */
-	flush_workqueue(langwell->qwork);
-	spin_lock(&langwell->wq_lock);
-
-	/* start actions */
-	switch (langwell->otg.state) {
-	case OTG_STATE_A_IDLE:
-	case OTG_STATE_B_IDLE:
-	case OTG_STATE_A_WAIT_VFALL:
-	case OTG_STATE_A_VBUS_ERR:
-		transceiver_suspend(pdev);
-		break;
-	case OTG_STATE_A_WAIT_VRISE:
-		langwell_otg_del_timer(a_wait_vrise_tmr);
-		langwell->hsm.a_srp_det = 0;
-		langwell_otg_drv_vbus(0);
-		langwell->otg.state = OTG_STATE_A_IDLE;
-		transceiver_suspend(pdev);
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		langwell_otg_del_timer(a_wait_bcon_tmr);
-		if (langwell->host_ops)
-			ret = langwell->host_ops->suspend(pdev, message);
-		langwell_otg_drv_vbus(0);
-		break;
-	case OTG_STATE_A_HOST:
-		if (langwell->host_ops)
-			ret = langwell->host_ops->suspend(pdev, message);
-		langwell_otg_drv_vbus(0);
-		langwell_otg_phy_low_power(1);
-		break;
-	case OTG_STATE_A_SUSPEND:
-		langwell_otg_del_timer(a_aidl_bdis_tmr);
-		langwell_otg_HABA(0);
-		if (langwell->host_ops)
-			langwell->host_ops->remove(pdev);
-		else
-			otg_dbg("host driver has been removed.\n");
-		langwell_otg_drv_vbus(0);
-		transceiver_suspend(pdev);
-		langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-		break;
-	case OTG_STATE_A_PERIPHERAL:
-		if (langwell->client_ops)
-			ret = langwell->client_ops->suspend(pdev, message);
-		else
-			otg_dbg("client driver has been removed.\n");
-		langwell_otg_drv_vbus(0);
-		transceiver_suspend(pdev);
-		langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-		break;
-	case OTG_STATE_B_HOST:
-		if (langwell->host_ops)
-			langwell->host_ops->remove(pdev);
-		else
-			otg_dbg("host driver has been removed.\n");
-		langwell->hsm.b_bus_req = 0;
-		transceiver_suspend(pdev);
-		langwell->otg.state = OTG_STATE_B_IDLE;
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		if (langwell->client_ops)
-			ret = langwell->client_ops->suspend(pdev, message);
-		else
-			otg_dbg("client driver has been removed.\n");
-		break;
-	case OTG_STATE_B_WAIT_ACON:
-		langwell_otg_del_timer(b_ase0_brst_tmr);
-		langwell_otg_HAAR(0);
-		if (langwell->host_ops)
-			langwell->host_ops->remove(pdev);
-		else
-			otg_dbg("host driver has been removed.\n");
-		langwell->hsm.b_bus_req = 0;
-		langwell->otg.state = OTG_STATE_B_IDLE;
-		transceiver_suspend(pdev);
-		break;
-	default:
-		otg_dbg("error state before suspend\n ");
-		break;
-	}
-	spin_unlock(&langwell->wq_lock);
-
-	return ret;
-}
-
-static void transceiver_resume(struct pci_dev *pdev)
-{
-	pci_restore_state(pdev);
-	pci_set_power_state(pdev, PCI_D0);
-	langwell_otg_phy_low_power(0);
-}
-
-static int langwell_otg_resume(struct pci_dev *pdev)
-{
-	int 	ret = 0;
-	struct langwell_otg *langwell;
-
-	langwell = the_transceiver;
-
-	spin_lock(&langwell->wq_lock);
-
-	switch (langwell->otg.state) {
-	case OTG_STATE_A_IDLE:
-	case OTG_STATE_B_IDLE:
-	case OTG_STATE_A_WAIT_VFALL:
-	case OTG_STATE_A_VBUS_ERR:
-		transceiver_resume(pdev);
-		break;
-	case OTG_STATE_A_WAIT_BCON:
-		langwell_otg_add_timer(a_wait_bcon_tmr);
-		langwell_otg_drv_vbus(1);
-		if (langwell->host_ops)
-			ret = langwell->host_ops->resume(pdev);
-		break;
-	case OTG_STATE_A_HOST:
-		langwell_otg_drv_vbus(1);
-		langwell_otg_phy_low_power(0);
-		if (langwell->host_ops)
-			ret = langwell->host_ops->resume(pdev);
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		if (langwell->client_ops)
-			ret = langwell->client_ops->resume(pdev);
-		else
-			otg_dbg("client driver not loaded.\n");
-		break;
-	default:
-		otg_dbg("error state before suspend\n ");
-		break;
-	}
-
-	if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
-				driver_name, the_transceiver) != 0) {
-		otg_dbg("request interrupt %d failed\n", pdev->irq);
-		ret = -EBUSY;
-	}
-
-	/* enable OTG interrupts */
-	langwell_otg_intr(1);
-
-	spin_unlock(&langwell->wq_lock);
-
-	queue_work(langwell->qwork, &langwell->work);
-
-
-	return ret;
-}
-
-static int __init langwell_otg_init(void)
-{
-	return pci_register_driver(&otg_pci_driver);
-}
-module_init(langwell_otg_init);
-
-static void __exit langwell_otg_cleanup(void)
-{
-	pci_unregister_driver(&otg_pci_driver);
-}
-module_exit(langwell_otg_cleanup);

+ 1 - 0
drivers/usb/otg/nop-usb-xceiv.c

@@ -53,6 +53,7 @@ EXPORT_SYMBOL(usb_nop_xceiv_register);
 void usb_nop_xceiv_unregister(void)
 void usb_nop_xceiv_unregister(void)
 {
 {
 	platform_device_unregister(pd);
 	platform_device_unregister(pd);
+	pd = NULL;
 }
 }
 EXPORT_SYMBOL(usb_nop_xceiv_unregister);
 EXPORT_SYMBOL(usb_nop_xceiv_unregister);
 
 

+ 7 - 6
drivers/usb/serial/console.c

@@ -169,9 +169,11 @@ static int usb_console_setup(struct console *co, char *options)
 			kfree(tty);
 			kfree(tty);
 		}
 		}
 	}
 	}
-	/* So we know not to kill the hardware on a hangup on this
-	   port. We have also bumped the use count by one so it won't go
-	   idle */
+	/* Now that any required fake tty operations are completed restore
+	 * the tty port count */
+	--port->port.count;
+	/* The console is special in terms of closing the device so
+	 * indicate this port is now acting as a system console. */
 	port->console = 1;
 	port->console = 1;
 	retval = 0;
 	retval = 0;
 
 
@@ -204,7 +206,7 @@ static void usb_console_write(struct console *co,
 
 
 	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
 
-	if (!port->port.count) {
+	if (!port->console) {
 		dbg("%s - port not opened", __func__);
 		dbg("%s - port not opened", __func__);
 		return;
 		return;
 	}
 	}
@@ -300,8 +302,7 @@ void usb_serial_console_exit(void)
 {
 {
 	if (usbcons_info.port) {
 	if (usbcons_info.port) {
 		unregister_console(&usbcons);
 		unregister_console(&usbcons);
-		if (usbcons_info.port->port.count)
-			usbcons_info.port->port.count--;
+		usbcons_info.port->console = 0;
 		usbcons_info.port = NULL;
 		usbcons_info.port = NULL;
 	}
 	}
 }
 }

+ 2 - 0
drivers/usb/serial/cp210x.c

@@ -67,6 +67,8 @@ static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
 	{ USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */
 	{ USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */
+	{ USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */
+	{ USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
 	{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
 	{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */

+ 2 - 2
drivers/usb/serial/cypress_m8.c

@@ -1228,8 +1228,8 @@ static void cypress_read_int_callback(struct urb *urb)
 		/* precursor to disconnect so just go away */
 		/* precursor to disconnect so just go away */
 		return;
 		return;
 	case -EPIPE:
 	case -EPIPE:
-		usb_clear_halt(port->serial->dev, 0x81);
-		break;
+		/* Can't call usb_clear_halt while in_interrupt */
+		/* FALLS THROUGH */
 	default:
 	default:
 		/* something ugly is going on... */
 		/* something ugly is going on... */
 		dev_err(&urb->dev->dev,
 		dev_err(&urb->dev->dev,

+ 66 - 1
drivers/usb/serial/ftdi_sio.c

@@ -108,6 +108,7 @@ struct ftdi_sio_quirk {
 
 
 static int   ftdi_jtag_probe(struct usb_serial *serial);
 static int   ftdi_jtag_probe(struct usb_serial *serial);
 static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
 static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
+static int   ftdi_NDI_device_setup(struct usb_serial *serial);
 static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
 static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
 static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
 static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
 
 
@@ -119,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
 	.probe  = ftdi_mtxorb_hack_setup,
 	.probe  = ftdi_mtxorb_hack_setup,
 };
 };
 
 
+static struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
+	.probe	= ftdi_NDI_device_setup,
+};
+
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
 	.port_probe = ftdi_USB_UIRT_setup,
 	.port_probe = ftdi_USB_UIRT_setup,
 };
 };
@@ -192,6 +197,7 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
@@ -580,6 +586,9 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) },
 	{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
 	{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
 	{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
 	{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
 	{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
 	{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
@@ -645,6 +654,16 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
 	{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
 	{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
 	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
 	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
@@ -661,6 +680,8 @@ static struct usb_device_id id_table_combined [] = {
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
 	{ USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
 	{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
@@ -668,7 +689,6 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
 	{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
 	{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
 	{ USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) },
 	{ USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) },
-	{ USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) },
 	{ USB_DEVICE(ATMEL_VID, STK541_PID) },
 	{ USB_DEVICE(ATMEL_VID, STK541_PID) },
 	{ USB_DEVICE(DE_VID, STB_PID) },
 	{ USB_DEVICE(DE_VID, STB_PID) },
 	{ USB_DEVICE(DE_VID, WHT_PID) },
 	{ USB_DEVICE(DE_VID, WHT_PID) },
@@ -1024,6 +1044,16 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
 	case FT2232C: /* FT2232C chip */
 	case FT2232C: /* FT2232C chip */
 	case FT232RL:
 	case FT232RL:
 		if (baud <= 3000000) {
 		if (baud <= 3000000) {
+			__u16 product_id = le16_to_cpu(
+				port->serial->dev->descriptor.idProduct);
+			if (((FTDI_NDI_HUC_PID == product_id) ||
+			     (FTDI_NDI_SPECTRA_SCU_PID == product_id) ||
+			     (FTDI_NDI_FUTURE_2_PID == product_id) ||
+			     (FTDI_NDI_FUTURE_3_PID == product_id) ||
+			     (FTDI_NDI_AURORA_SCU_PID == product_id)) &&
+			    (baud == 19200)) {
+				baud = 1200000;
+			}
 			div_value = ftdi_232bm_baud_to_divisor(baud);
 			div_value = ftdi_232bm_baud_to_divisor(baud);
 		} else {
 		} else {
 			dbg("%s - Baud rate too high!", __func__);
 			dbg("%s - Baud rate too high!", __func__);
@@ -1554,6 +1584,39 @@ static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
 	priv->force_rtscts = 1;
 	priv->force_rtscts = 1;
 } /* ftdi_HE_TIRA1_setup */
 } /* ftdi_HE_TIRA1_setup */
 
 
+/*
+ * Module parameter to control latency timer for NDI FTDI-based USB devices.
+ * If this value is not set in modprobe.conf.local its value will be set to 1ms.
+ */
+static int ndi_latency_timer = 1;
+
+/* Setup for the NDI FTDI-based USB devices, which requires hardwired
+ * baudrate (19200 gets mapped to 1200000).
+ *
+ * Called from usbserial:serial_probe.
+ */
+static int ftdi_NDI_device_setup(struct usb_serial *serial)
+{
+	struct usb_device *udev = serial->dev;
+	int latency = ndi_latency_timer;
+	int rv = 0;
+	char buf[1];
+
+	if (latency == 0)
+		latency = 1;
+	if (latency > 99)
+		latency = 99;
+
+	dbg("%s setting NDI device latency to %d", __func__, latency);
+	dev_info(&udev->dev, "NDI device with a latency value of %d", latency);
+
+	rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
+				FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
+				latency, 0, buf, 0, WDR_TIMEOUT);
+	return 0;
+}
+
 /*
 /*
  * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
  * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
  * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
  * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
@@ -2623,3 +2686,5 @@ MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
 module_param(product, ushort, 0);
 module_param(product, ushort, 0);
 MODULE_PARM_DESC(product, "User specified product ID");
 MODULE_PARM_DESC(product, "User specified product ID");
 
 
+module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");

+ 15 - 3
drivers/usb/serial/ftdi_sio.h

@@ -506,6 +506,7 @@
  *
  *
  * Armin Laeuger originally sent the PID for the UM 100 module.
  * Armin Laeuger originally sent the PID for the UM 100 module.
  */
  */
+#define FTDI_R2000KU_TRUE_RNG	0xFB80  /* R2000KU TRUE RNG */
 #define FTDI_ELV_UR100_PID	0xFB58	/* USB-RS232-Umsetzer (UR 100) */
 #define FTDI_ELV_UR100_PID	0xFB58	/* USB-RS232-Umsetzer (UR 100) */
 #define FTDI_ELV_UM100_PID	0xFB5A	/* USB-Modul UM 100 */
 #define FTDI_ELV_UM100_PID	0xFB5A	/* USB-Modul UM 100 */
 #define FTDI_ELV_UO100_PID	0xFB5B	/* USB-Modul UO 100 */
 #define FTDI_ELV_UO100_PID	0xFB5B	/* USB-Modul UO 100 */
@@ -614,6 +615,9 @@
 #define FTDI_CCSICDU20_0_PID    0xF9D0
 #define FTDI_CCSICDU20_0_PID    0xF9D0
 #define FTDI_CCSICDU40_1_PID    0xF9D1
 #define FTDI_CCSICDU40_1_PID    0xF9D1
 #define FTDI_CCSMACHX_2_PID     0xF9D2
 #define FTDI_CCSMACHX_2_PID     0xF9D2
+#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
+#define FTDI_CCSICDU64_4_PID    0xF9D4
+#define FTDI_CCSPRIME8_5_PID    0xF9D5
 
 
 /* Inside Accesso contactless reader (http://www.insidefr.com) */
 /* Inside Accesso contactless reader (http://www.insidefr.com) */
 #define INSIDE_ACCESSO		0xFAD0
 #define INSIDE_ACCESSO		0xFAD0
@@ -735,6 +739,15 @@
 /* Pyramid Computer GmbH */
 /* Pyramid Computer GmbH */
 #define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
 #define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
 
 
+/*
+ * NDI (www.ndigital.com) product ids
+ */
+#define FTDI_NDI_HUC_PID		0xDA70	/* NDI Host USB Converter */
+#define FTDI_NDI_SPECTRA_SCU_PID	0xDA71	/* NDI Spectra SCU */
+#define FTDI_NDI_FUTURE_2_PID		0xDA72	/* NDI future device #2 */
+#define FTDI_NDI_FUTURE_3_PID		0xDA73	/* NDI future device #3 */
+#define FTDI_NDI_AURORA_SCU_PID		0xDA74	/* NDI Aurora SCU */
+
 /*
 /*
  * Posiflex inc retail equipment (http://www.posiflex.com.tw)
  * Posiflex inc retail equipment (http://www.posiflex.com.tw)
  */
  */
@@ -848,9 +861,6 @@
 #define TML_VID			0x1B91	/* Vendor ID */
 #define TML_VID			0x1B91	/* Vendor ID */
 #define TML_USB_SERIAL_PID	0x0064	/* USB - Serial Converter */
 #define TML_USB_SERIAL_PID	0x0064	/* USB - Serial Converter */
 
 
-/* NDI Polaris System */
-#define FTDI_NDI_HUC_PID        0xDA70
-
 /* Propox devices */
 /* Propox devices */
 #define FTDI_PROPOX_JTAGCABLEII_PID	0xD738
 #define FTDI_PROPOX_JTAGCABLEII_PID	0xD738
 
 
@@ -934,6 +944,8 @@
 #define MARVELL_VID		0x9e88
 #define MARVELL_VID		0x9e88
 #define MARVELL_SHEEVAPLUG_PID	0x9e8f
 #define MARVELL_SHEEVAPLUG_PID	0x9e8f
 
 
+#define FTDI_TURTELIZER_PID	0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
+
 /*
 /*
  *   BmRequestType:  1100 0000b
  *   BmRequestType:  1100 0000b
  *   bRequest:       FTDI_E2_READ
  *   bRequest:       FTDI_E2_READ

+ 18 - 27
drivers/usb/serial/option.c

@@ -206,6 +206,7 @@ static int  option_resume(struct usb_serial *serial);
 #define NOVATELWIRELESS_PRODUCT_MC950D		0x4400
 #define NOVATELWIRELESS_PRODUCT_MC950D		0x4400
 #define NOVATELWIRELESS_PRODUCT_U727		0x5010
 #define NOVATELWIRELESS_PRODUCT_U727		0x5010
 #define NOVATELWIRELESS_PRODUCT_MC760		0x6000
 #define NOVATELWIRELESS_PRODUCT_MC760		0x6000
+#define NOVATELWIRELESS_PRODUCT_OVMC760		0x6002
 
 
 /* FUTURE NOVATEL PRODUCTS */
 /* FUTURE NOVATEL PRODUCTS */
 #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED	0X6001
 #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED	0X6001
@@ -307,11 +308,20 @@ static int  option_resume(struct usb_serial *serial);
 #define DLINK_VENDOR_ID				0x1186
 #define DLINK_VENDOR_ID				0x1186
 #define DLINK_PRODUCT_DWM_652			0x3e04
 #define DLINK_PRODUCT_DWM_652			0x3e04
 
 
+#define QISDA_VENDOR_ID				0x1da5
+#define QISDA_PRODUCT_H21_4512			0x4512
+#define QISDA_PRODUCT_H21_4523			0x4523
+#define QISDA_PRODUCT_H20_4515			0x4515
+#define QISDA_PRODUCT_H20_4519			0x4519
+
 
 
 /* TOSHIBA PRODUCTS */
 /* TOSHIBA PRODUCTS */
 #define TOSHIBA_VENDOR_ID			0x0930
 #define TOSHIBA_VENDOR_ID			0x0930
 #define TOSHIBA_PRODUCT_HSDPA_MINICARD		0x1302
 #define TOSHIBA_PRODUCT_HSDPA_MINICARD		0x1302
 
 
+#define ALINK_VENDOR_ID				0x1e0e
+#define ALINK_PRODUCT_3GU			0x9200
+
 static struct usb_device_id option_ids[] = {
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -430,6 +440,7 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
@@ -529,8 +540,13 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
 	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
 	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
 	{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
 	{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
-	{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
+	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
+	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
+	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
+	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
+	{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
 	{ } /* Terminating entry */
 	{ } /* Terminating entry */
 };
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -732,7 +748,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
 		memcpy(this_urb->transfer_buffer, buf, todo);
 		memcpy(this_urb->transfer_buffer, buf, todo);
 		this_urb->transfer_buffer_length = todo;
 		this_urb->transfer_buffer_length = todo;
 
 
-		this_urb->dev = port->serial->dev;
 		err = usb_submit_urb(this_urb, GFP_ATOMIC);
 		err = usb_submit_urb(this_urb, GFP_ATOMIC);
 		if (err) {
 		if (err) {
 			dbg("usb_submit_urb %p (write bulk) failed "
 			dbg("usb_submit_urb %p (write bulk) failed "
@@ -860,7 +875,6 @@ static void option_instat_callback(struct urb *urb)
 
 
 	/* Resubmit urb so we continue receiving IRQ data */
 	/* Resubmit urb so we continue receiving IRQ data */
 	if (status != -ESHUTDOWN && status != -ENOENT) {
 	if (status != -ESHUTDOWN && status != -ENOENT) {
-		urb->dev = serial->dev;
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		if (err)
 		if (err)
 			dbg("%s: resubmit intr urb failed. (%d)",
 			dbg("%s: resubmit intr urb failed. (%d)",
@@ -921,23 +935,11 @@ static int option_open(struct tty_struct *tty,
 
 
 	dbg("%s", __func__);
 	dbg("%s", __func__);
 
 
-	/* Reset low level data toggle and start reading from endpoints */
+	/* Start reading from the IN endpoint */
 	for (i = 0; i < N_IN_URB; i++) {
 	for (i = 0; i < N_IN_URB; i++) {
 		urb = portdata->in_urbs[i];
 		urb = portdata->in_urbs[i];
 		if (!urb)
 		if (!urb)
 			continue;
 			continue;
-		if (urb->dev != serial->dev) {
-			dbg("%s: dev %p != %p", __func__,
-				urb->dev, serial->dev);
-			continue;
-		}
-
-		/*
-		 * make sure endpoint data toggle is synchronized with the
-		 * device
-		 */
-		usb_clear_halt(urb->dev, urb->pipe);
-
 		err = usb_submit_urb(urb, GFP_KERNEL);
 		err = usb_submit_urb(urb, GFP_KERNEL);
 		if (err) {
 		if (err) {
 			dbg("%s: submit urb %d failed (%d) %d",
 			dbg("%s: submit urb %d failed (%d) %d",
@@ -946,16 +948,6 @@ static int option_open(struct tty_struct *tty,
 		}
 		}
 	}
 	}
 
 
-	/* Reset low level data toggle on out endpoints */
-	for (i = 0; i < N_OUT_URB; i++) {
-		urb = portdata->out_urbs[i];
-		if (!urb)
-			continue;
-		urb->dev = serial->dev;
-		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-				usb_pipeout(urb->pipe), 0); */
-	}
-
 	option_send_setup(port);
 	option_send_setup(port);
 
 
 	return 0;
 	return 0;
@@ -1218,7 +1210,6 @@ static int option_resume(struct usb_serial *serial)
 			dbg("%s: No interrupt URB for port %d\n", __func__, i);
 			dbg("%s: No interrupt URB for port %d\n", __func__, i);
 			continue;
 			continue;
 		}
 		}
-		port->interrupt_in_urb->dev = serial->dev;
 		err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
 		err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
 		dbg("Submitted interrupt URB for port %d (result %d)", i, err);
 		dbg("Submitted interrupt URB for port %d (result %d)", i, err);
 		if (err < 0) {
 		if (err < 0) {

+ 1 - 0
drivers/usb/serial/pl2303.c

@@ -94,6 +94,7 @@ static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
 	{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
 	{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
 	{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
 	{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
 	{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
+	{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 	{ }					/* Terminating entry */
 };
 };
 
 

+ 4 - 0
drivers/usb/serial/pl2303.h

@@ -122,3 +122,7 @@
 /* Hewlett-Packard LD220-HP POS Pole Display */
 /* Hewlett-Packard LD220-HP POS Pole Display */
 #define HP_VENDOR_ID		0x03f0
 #define HP_VENDOR_ID		0x03f0
 #define HP_LD220_PRODUCT_ID	0x3524
 #define HP_LD220_PRODUCT_ID	0x3524
+
+/* Cressi Edy (diving computer) PC interface */
+#define CRESSI_VENDOR_ID	0x04b8
+#define CRESSI_EDY_PRODUCT_ID	0x0521

+ 31 - 20
drivers/usb/serial/sierra.c

@@ -181,35 +181,50 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = {
 };
 };
 
 
 static struct usb_device_id id_table [] = {
 static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
+	{ USB_DEVICE(0x03F0, 0x1B1D) },	/* HP ev2200 a.k.a MC5720 */
+	{ USB_DEVICE(0x03F0, 0x1E1D) },	/* HP hs2300 a.k.a MC8775 */
+
 	{ USB_DEVICE(0x1199, 0x0017) },	/* Sierra Wireless EM5625 */
 	{ USB_DEVICE(0x1199, 0x0017) },	/* Sierra Wireless EM5625 */
 	{ USB_DEVICE(0x1199, 0x0018) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0018) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */
 	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
 	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
-	{ USB_DEVICE(0x1199, 0x0024) },	/* Sierra Wireless MC5727 */
 	{ USB_DEVICE(0x1199, 0x0220) },	/* Sierra Wireless MC5725 */
 	{ USB_DEVICE(0x1199, 0x0220) },	/* Sierra Wireless MC5725 */
+	{ USB_DEVICE(0x1199, 0x0022) },	/* Sierra Wireless EM5725 */
+	{ USB_DEVICE(0x1199, 0x0024) },	/* Sierra Wireless MC5727 */
+	{ USB_DEVICE(0x1199, 0x0224) },	/* Sierra Wireless MC5727 */
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
+	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
 	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */
 	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */
-	 /* Sierra Wireless C597 */
+	/* Sierra Wireless C597 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
-	 /* Sierra Wireless Device */
+	/* Sierra Wireless T598 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
-	{ USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */
-	{ USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */
-	{ USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */
+	{ USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */
+	{ USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */
+	{ USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */
+	{ USB_DEVICE(0x1199, 0x0029) }, /* Sierra Wireless Device */
 
 
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
-	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6803) },	/* Sierra Wireless MC8765 */
 	{ USB_DEVICE(0x1199, 0x6803) },	/* Sierra Wireless MC8765 */
+	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
+	{ USB_DEVICE(0x1199, 0x6805) },	/* Sierra Wireless MC8765 */
+	{ USB_DEVICE(0x1199, 0x6808) },	/* Sierra Wireless MC8755 */
+	{ USB_DEVICE(0x1199, 0x6809) },	/* Sierra Wireless MC8765 */
 	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 & AC 875U */
 	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 & AC 875U */
-	{ USB_DEVICE(0x1199, 0x6813) },	/* Sierra Wireless MC8775 (Lenovo) */
+	{ USB_DEVICE(0x1199, 0x6813) },	/* Sierra Wireless MC8775 */
 	{ USB_DEVICE(0x1199, 0x6815) },	/* Sierra Wireless MC8775 */
 	{ USB_DEVICE(0x1199, 0x6815) },	/* Sierra Wireless MC8775 */
-	{ USB_DEVICE(0x03f0, 0x1e1d) },	/* HP hs2300 a.k.a MC8775 */
+	{ USB_DEVICE(0x1199, 0x6816) },	/* Sierra Wireless MC8775 */
 	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
 	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
 	{ USB_DEVICE(0x1199, 0x6821) },	/* Sierra Wireless AirCard 875U */
 	{ USB_DEVICE(0x1199, 0x6821) },	/* Sierra Wireless AirCard 875U */
+	{ USB_DEVICE(0x1199, 0x6822) },	/* Sierra Wireless AirCard 875E */
 	{ USB_DEVICE(0x1199, 0x6832) },	/* Sierra Wireless MC8780 */
 	{ USB_DEVICE(0x1199, 0x6832) },	/* Sierra Wireless MC8780 */
 	{ USB_DEVICE(0x1199, 0x6833) },	/* Sierra Wireless MC8781 */
 	{ USB_DEVICE(0x1199, 0x6833) },	/* Sierra Wireless MC8781 */
+	{ USB_DEVICE(0x1199, 0x6834) },	/* Sierra Wireless MC8780 */
+	{ USB_DEVICE(0x1199, 0x6835) },	/* Sierra Wireless MC8781 */
+	{ USB_DEVICE(0x1199, 0x6838) },	/* Sierra Wireless MC8780 */
+	{ USB_DEVICE(0x1199, 0x6839) },	/* Sierra Wireless MC8781 */
 	{ USB_DEVICE(0x1199, 0x683A) },	/* Sierra Wireless MC8785 */
 	{ USB_DEVICE(0x1199, 0x683A) },	/* Sierra Wireless MC8785 */
 	{ USB_DEVICE(0x1199, 0x683B) },	/* Sierra Wireless MC8785 Composite */
 	{ USB_DEVICE(0x1199, 0x683B) },	/* Sierra Wireless MC8785 Composite */
 	/* Sierra Wireless MC8790, MC8791, MC8792 Composite */
 	/* Sierra Wireless MC8790, MC8791, MC8792 Composite */
@@ -227,16 +242,13 @@ static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x1199, 0x685A) },	/* Sierra Wireless AirCard 885 E */
 	{ USB_DEVICE(0x1199, 0x685A) },	/* Sierra Wireless AirCard 885 E */
 	/* Sierra Wireless C885 */
 	/* Sierra Wireless C885 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
-	/* Sierra Wireless Device */
+	/* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
-	/* Sierra Wireless Device */
+	/* Sierra Wireless C22/C33 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)},
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)},
-	/* Sierra Wireless Device */
+	/* Sierra Wireless HSPA Non-Composite Device */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
-
-	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
-	{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
-
+	{ USB_DEVICE(0x1199, 0x6893) },	/* Sierra Wireless Device */
 	{ USB_DEVICE(0x1199, 0x68A3), 	/* Sierra Wireless Direct IP modems */
 	{ USB_DEVICE(0x1199, 0x68A3), 	/* Sierra Wireless Direct IP modems */
 	  .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
 	  .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
 	},
 	},
@@ -814,7 +826,7 @@ static int sierra_startup(struct usb_serial *serial)
 	return 0;
 	return 0;
 }
 }
 
 
-static void sierra_disconnect(struct usb_serial *serial)
+static void sierra_release(struct usb_serial *serial)
 {
 {
 	int i;
 	int i;
 	struct usb_serial_port *port;
 	struct usb_serial_port *port;
@@ -830,7 +842,6 @@ static void sierra_disconnect(struct usb_serial *serial)
 		if (!portdata)
 		if (!portdata)
 			continue;
 			continue;
 		kfree(portdata);
 		kfree(portdata);
-		usb_set_serial_port_data(port, NULL);
 	}
 	}
 }
 }
 
 
@@ -853,7 +864,7 @@ static struct usb_serial_driver sierra_device = {
 	.tiocmget          = sierra_tiocmget,
 	.tiocmget          = sierra_tiocmget,
 	.tiocmset          = sierra_tiocmset,
 	.tiocmset          = sierra_tiocmset,
 	.attach            = sierra_startup,
 	.attach            = sierra_startup,
-	.disconnect        = sierra_disconnect,
+	.release           = sierra_release,
 	.read_int_callback = sierra_instat_callback,
 	.read_int_callback = sierra_instat_callback,
 };
 };
 
 

+ 1 - 2
drivers/usb/serial/ti_usb_3410_5052.c

@@ -191,7 +191,6 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
-	{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
 };
 };
 
 
 static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = {
 static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = {
@@ -1658,7 +1657,7 @@ static int ti_do_download(struct usb_device *dev, int pipe,
 	u8 cs = 0;
 	u8 cs = 0;
 	int done;
 	int done;
 	struct ti_firmware_header *header;
 	struct ti_firmware_header *header;
-	int status;
+	int status = 0;
 	int len;
 	int len;
 
 
 	for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)
 	for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)

+ 2 - 1
drivers/usb/serial/usb-serial.c

@@ -221,7 +221,8 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
 	tty->driver_data = port;
 	tty->driver_data = port;
 	tty_port_tty_set(&port->port, tty);
 	tty_port_tty_set(&port->port, tty);
 
 
-	if (port->port.count == 1) {
+	/* If the console is attached, the device is already open */
+	if (port->port.count == 1 && !port->console) {
 
 
 		/* lock this module before we call it
 		/* lock this module before we call it
 		 * this may fail, which means we must bail out,
 		 * this may fail, which means we must bail out,

+ 3 - 0
drivers/usb/storage/option_ms.c

@@ -118,6 +118,9 @@ static int option_inquiry(struct us_data *us)
 
 
 	result = memcmp(buffer+8, "Option", 6);
 	result = memcmp(buffer+8, "Option", 6);
 
 
+	if (result != 0)
+		result = memcmp(buffer+8, "ZCOPTION", 8);
+
 	/* Read the CSW */
 	/* Read the CSW */
 	usb_stor_bulk_transfer_buf(us,
 	usb_stor_bulk_transfer_buf(us,
 			us->recv_bulk_pipe,
 			us->recv_bulk_pipe,

+ 4 - 2
include/linux/usb.h

@@ -888,8 +888,6 @@ struct usb_driver {
  * struct usb_device_driver - identifies USB device driver to usbcore
  * struct usb_device_driver - identifies USB device driver to usbcore
  * @name: The driver name should be unique among USB drivers,
  * @name: The driver name should be unique among USB drivers,
  *	and should normally be the same as the module name.
  *	and should normally be the same as the module name.
- * @nodename: Callback to provide a naming hint for a possible
- *	device node to create.
  * @probe: Called to see if the driver is willing to manage a particular
  * @probe: Called to see if the driver is willing to manage a particular
  *	device.  If it is, probe returns zero and uses dev_set_drvdata()
  *	device.  If it is, probe returns zero and uses dev_set_drvdata()
  *	to associate driver-specific data with the device.  If unwilling
  *	to associate driver-specific data with the device.  If unwilling
@@ -924,6 +922,8 @@ extern struct bus_type usb_bus_type;
 /**
 /**
  * struct usb_class_driver - identifies a USB driver that wants to use the USB major number
  * struct usb_class_driver - identifies a USB driver that wants to use the USB major number
  * @name: the usb class device name for this driver.  Will show up in sysfs.
  * @name: the usb class device name for this driver.  Will show up in sysfs.
+ * @nodename: Callback to provide a naming hint for a possible
+ *	device node to create.
  * @fops: pointer to the struct file_operations of this driver.
  * @fops: pointer to the struct file_operations of this driver.
  * @minor_base: the start of the minor range for this driver.
  * @minor_base: the start of the minor range for this driver.
  *
  *
@@ -1046,6 +1046,8 @@ typedef void (*usb_complete_t)(struct urb *);
  *	the device driver is saying that it provided this DMA address,
  *	the device driver is saying that it provided this DMA address,
  *	which the host controller driver should use in preference to the
  *	which the host controller driver should use in preference to the
  *	transfer_buffer.
  *	transfer_buffer.
+ * @sg: scatter gather buffer list
+ * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
  *	be broken up into chunks according to the current maximum packet
  *	be broken up into chunks according to the current maximum packet
  *	size for the endpoint, which is a function of the configuration
  *	size for the endpoint, which is a function of the configuration

+ 0 - 177
include/linux/usb/langwell_otg.h

@@ -1,177 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __LANGWELL_OTG_H__
-#define __LANGWELL_OTG_H__
-
-/* notify transceiver driver about OTG events */
-extern void langwell_update_transceiver(void);
-/* HCD register bus driver */
-extern int langwell_register_host(struct pci_driver *host_driver);
-/* HCD unregister bus driver */
-extern void langwell_unregister_host(struct pci_driver *host_driver);
-/* DCD register bus driver */
-extern int langwell_register_peripheral(struct pci_driver *client_driver);
-/* DCD unregister bus driver */
-extern void langwell_unregister_peripheral(struct pci_driver *client_driver);
-/* No silent failure, output warning message */
-extern void langwell_otg_nsf_msg(unsigned long message);
-
-#define CI_USBCMD		0x30
-#	define USBCMD_RST		BIT(1)
-#	define USBCMD_RS		BIT(0)
-#define CI_USBSTS		0x34
-#	define USBSTS_SLI		BIT(8)
-#	define USBSTS_URI		BIT(6)
-#	define USBSTS_PCI		BIT(2)
-#define CI_PORTSC1		0x74
-#	define PORTSC_PP		BIT(12)
-#	define PORTSC_LS		(BIT(11) | BIT(10))
-#	define PORTSC_SUSP		BIT(7)
-#	define PORTSC_CCS		BIT(0)
-#define CI_HOSTPC1		0xb4
-#	define HOSTPC1_PHCD		BIT(22)
-#define CI_OTGSC		0xf4
-#	define OTGSC_DPIE		BIT(30)
-#	define OTGSC_1MSE		BIT(29)
-#	define OTGSC_BSEIE		BIT(28)
-#	define OTGSC_BSVIE		BIT(27)
-#	define OTGSC_ASVIE		BIT(26)
-#	define OTGSC_AVVIE		BIT(25)
-#	define OTGSC_IDIE		BIT(24)
-#	define OTGSC_DPIS		BIT(22)
-#	define OTGSC_1MSS		BIT(21)
-#	define OTGSC_BSEIS		BIT(20)
-#	define OTGSC_BSVIS		BIT(19)
-#	define OTGSC_ASVIS		BIT(18)
-#	define OTGSC_AVVIS		BIT(17)
-#	define OTGSC_IDIS		BIT(16)
-#	define OTGSC_DPS		BIT(14)
-#	define OTGSC_1MST		BIT(13)
-#	define OTGSC_BSE		BIT(12)
-#	define OTGSC_BSV		BIT(11)
-#	define OTGSC_ASV		BIT(10)
-#	define OTGSC_AVV		BIT(9)
-#	define OTGSC_ID			BIT(8)
-#	define OTGSC_HABA		BIT(7)
-#	define OTGSC_HADP		BIT(6)
-#	define OTGSC_IDPU		BIT(5)
-#	define OTGSC_DP			BIT(4)
-#	define OTGSC_OT			BIT(3)
-#	define OTGSC_HAAR		BIT(2)
-#	define OTGSC_VC			BIT(1)
-#	define OTGSC_VD			BIT(0)
-#	define OTGSC_INTEN_MASK		(0x7f << 24)
-#	define OTGSC_INTSTS_MASK	(0x7f << 16)
-#define CI_USBMODE		0xf8
-#	define USBMODE_CM		(BIT(1) | BIT(0))
-#	define USBMODE_IDLE		0
-#	define USBMODE_DEVICE		0x2
-#	define USBMODE_HOST		0x3
-
-#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
-
-struct otg_hsm {
-	/* Input */
-	int a_bus_resume;
-	int a_bus_suspend;
-	int a_conn;
-	int a_sess_vld;
-	int a_srp_det;
-	int a_vbus_vld;
-	int b_bus_resume;
-	int b_bus_suspend;
-	int b_conn;
-	int b_se0_srp;
-	int b_sess_end;
-	int b_sess_vld;
-	int id;
-
-	/* Internal variables */
-	int a_set_b_hnp_en;
-	int b_srp_done;
-	int b_hnp_enable;
-
-	/* Timeout indicator for timers */
-	int a_wait_vrise_tmout;
-	int a_wait_bcon_tmout;
-	int a_aidl_bdis_tmout;
-	int b_ase0_brst_tmout;
-	int b_bus_suspend_tmout;
-	int b_srp_res_tmout;
-
-	/* Informative variables */
-	int a_bus_drop;
-	int a_bus_req;
-	int a_clr_err;
-	int a_suspend_req;
-	int b_bus_req;
-
-	/* Output */
-	int drv_vbus;
-	int loc_conn;
-	int loc_sof;
-
-	/* Others */
-	int b_bus_suspend_vld;
-};
-
-#define TA_WAIT_VRISE	100
-#define TA_WAIT_BCON	30000
-#define TA_AIDL_BDIS	15000
-#define TB_ASE0_BRST	5000
-#define TB_SE0_SRP	2
-#define TB_SRP_RES	100
-#define TB_BUS_SUSPEND	500
-
-struct langwell_otg_timer {
-	unsigned long expires;	/* Number of count increase to timeout */
-	unsigned long count;	/* Tick counter */
-	void (*function)(unsigned long);	/* Timeout function */
-	unsigned long data;	/* Data passed to function */
-	struct list_head list;
-};
-
-struct langwell_otg {
-	struct otg_transceiver 	otg;
-	struct otg_hsm 		hsm;
-	void __iomem 		*regs;
-	unsigned 		region;
-	struct pci_driver	*host_ops;
-	struct pci_driver	*client_ops;
-	struct pci_dev		*pdev;
-	struct work_struct 	work;
-	struct workqueue_struct	*qwork;
-	spinlock_t 		lock;
-	spinlock_t 		wq_lock;
-};
-
-static inline struct langwell_otg *otg_to_langwell(struct otg_transceiver *otg)
-{
-	return container_of(otg, struct langwell_otg, otg);
-}
-
-#ifdef DEBUG
-#define otg_dbg(fmt, args...) \
-	printk(KERN_DEBUG fmt , ## args)
-#else
-#define otg_dbg(fmt, args...) \
-	do { } while (0)
-#endif /* DEBUG */
-#endif /* __LANGWELL_OTG_H__ */