Browse Source

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:
  USB: sisusbvga: add USB ID for 0711:0918 Magic Control Technology Corp.
  USB: automatically enable RHSC interrupts
  USB: Don't rebind before "complete" callback
  USB: Add new PM callback methods for USB
  USB: Defer Set-Interface for suspended devices
  USB: Add udev argument to interface suspend/resume functions
  USB: cdc-acm: don't unlock acm->mutex on error path
  MUSB: Fix index register corruption seen with g_ether and Windows host
  usb: musb: get rid of MUSB_LOGLEVEL and use parameter
  usb: musb: get rid of procfs entry
  USB: Fix pxa27x_udc usb speed handling.
  USB: cdc-acm: quirk for Conexant CX93010 USB modem
  USB: fix bug in usb_unlink_anchored_urbs()
  usb-serial: option support HSDPA modem A2502
  USB: ISP1760: fixed trivial math in comment
Linus Torvalds 17 years ago
parent
commit
691a55998c

+ 4 - 1
drivers/usb/class/cdc-acm.c

@@ -589,8 +589,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 	tasklet_schedule(&acm->urb_task);
 
 done:
-err_out:
 	mutex_unlock(&acm->mutex);
+err_out:
 	mutex_unlock(&open_mutex);
 	return rv;
 
@@ -1362,6 +1362,9 @@ static struct usb_device_id acm_ids[] = {
 	{ USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
+	{ USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */
+	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+	},
 
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,

+ 49 - 47
drivers/usb/core/driver.c

@@ -230,6 +230,13 @@ static int usb_probe_interface(struct device *dev)
 		 */
 		intf->pm_usage_cnt = !(driver->supports_autosuspend);
 
+		/* Carry out a deferred switch to altsetting 0 */
+		if (intf->needs_altsetting0) {
+			usb_set_interface(udev, intf->altsetting[0].
+					desc.bInterfaceNumber, 0);
+			intf->needs_altsetting0 = 0;
+		}
+
 		error = driver->probe(intf, id);
 		if (error) {
 			mark_quiesced(intf);
@@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev)
 
 	driver->disconnect(intf);
 
-	/* reset other interface state */
-	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
+	/* Reset other interface state.
+	 * We cannot do a Set-Interface if the device is suspended or
+	 * if it is prepared for a system sleep (since installing a new
+	 * altsetting means creating new endpoint device entries).
+	 * When either of these happens, defer the Set-Interface.
+	 */
+	if (!error && intf->dev.power.status == DPM_ON)
+		usb_set_interface(udev, intf->altsetting[0].
+				desc.bInterfaceNumber, 0);
+	else
+		intf->needs_altsetting0 = 1;
 	usb_set_intfdata(intf, NULL);
 
 	intf->condition = USB_INTERFACE_UNBOUND;
@@ -798,7 +814,8 @@ void usb_forced_unbind_intf(struct usb_interface *intf)
  * The caller must hold @intf's device's lock, but not its pm_mutex
  * and not @intf->dev.sem.
  *
- * FIXME: The caller must block system sleep transitions.
+ * Note: Rebinds will be skipped if a system sleep transition is in
+ * progress and the PM "complete" callback hasn't occurred yet.
  */
 void usb_rebind_intf(struct usb_interface *intf)
 {
@@ -814,10 +831,12 @@ void usb_rebind_intf(struct usb_interface *intf)
 	}
 
 	/* Try to rebind the interface */
-	intf->needs_binding = 0;
-	rc = device_attach(&intf->dev);
-	if (rc < 0)
-		dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+	if (intf->dev.power.status == DPM_ON) {
+		intf->needs_binding = 0;
+		rc = device_attach(&intf->dev);
+		if (rc < 0)
+			dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+	}
 }
 
 #ifdef CONFIG_PM
@@ -829,7 +848,6 @@ void usb_rebind_intf(struct usb_interface *intf)
  * or rebind interfaces that have been unbound, according to @action.
  *
  * The caller must hold @udev's device lock.
- * FIXME: For rebinds, the caller must block system sleep transitions.
  */
 static void do_unbind_rebind(struct usb_device *udev, int action)
 {
@@ -851,22 +869,8 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
 				}
 				break;
 			case DO_REBIND:
-				if (intf->needs_binding) {
-
-	/* FIXME: The next line is needed because we are going to probe
-	 * the interface, but as far as the PM core is concerned the
-	 * interface is still suspended.  The problem wouldn't exist
-	 * if we could rebind the interface during the interface's own
-	 * resume() call, but at the time the usb_device isn't locked!
-	 *
-	 * The real solution will be to carry this out during the device's
-	 * complete() callback.  Until that is implemented, we have to
-	 * use this hack.
-	 */
-//					intf->dev.power.sleeping = 0;
-
+				if (intf->needs_binding)
 					usb_rebind_intf(intf);
-				}
 				break;
 			}
 		}
@@ -926,14 +930,14 @@ static int usb_resume_device(struct usb_device *udev)
 }
 
 /* Caller has locked intf's usb_device's pm mutex */
-static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+static int usb_suspend_interface(struct usb_device *udev,
+		struct usb_interface *intf, pm_message_t msg)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
 
 	/* with no hardware, USB interfaces only use FREEZE and ON states */
-	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
-			!is_active(intf))
+	if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
 		goto done;
 
 	if (intf->condition == USB_INTERFACE_UNBOUND)	/* This can't happen */
@@ -944,7 +948,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
 		status = driver->suspend(intf, msg);
 		if (status == 0)
 			mark_quiesced(intf);
-		else if (!interface_to_usbdev(intf)->auto_pm)
+		else if (!udev->auto_pm)
 			dev_err(&intf->dev, "%s error %d\n",
 					"suspend", status);
 	} else {
@@ -961,13 +965,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
 }
 
 /* Caller has locked intf's usb_device's pm_mutex */
-static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+static int usb_resume_interface(struct usb_device *udev,
+		struct usb_interface *intf, int reset_resume)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
 
-	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
-			is_active(intf))
+	if (udev->state == USB_STATE_NOTATTACHED || is_active(intf))
 		goto done;
 
 	/* Don't let autoresume interfere with unbinding */
@@ -975,8 +979,17 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
 		goto done;
 
 	/* Can't resume it if it doesn't have a driver. */
-	if (intf->condition == USB_INTERFACE_UNBOUND)
+	if (intf->condition == USB_INTERFACE_UNBOUND) {
+
+		/* Carry out a deferred switch to altsetting 0 */
+		if (intf->needs_altsetting0 &&
+				intf->dev.power.status == DPM_ON) {
+			usb_set_interface(udev, intf->altsetting[0].
+					desc.bInterfaceNumber, 0);
+			intf->needs_altsetting0 = 0;
+		}
 		goto done;
+	}
 
 	/* Don't resume if the interface is marked for rebinding */
 	if (intf->needs_binding)
@@ -1151,7 +1164,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 	if (udev->actconfig) {
 		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
-			status = usb_suspend_interface(intf, msg);
+			status = usb_suspend_interface(udev, intf, msg);
 			if (status != 0)
 				break;
 		}
@@ -1163,7 +1176,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 	if (status != 0) {
 		while (--i >= 0) {
 			intf = udev->actconfig->interface[i];
-			usb_resume_interface(intf, 0);
+			usb_resume_interface(udev, intf, 0);
 		}
 
 		/* Try another autosuspend when the interfaces aren't busy */
@@ -1276,7 +1289,7 @@ static int usb_resume_both(struct usb_device *udev)
 	if (status == 0 && udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
-			usb_resume_interface(intf, udev->reset_resume);
+			usb_resume_interface(udev, intf, udev->reset_resume);
 		}
 	}
 
@@ -1605,12 +1618,10 @@ int usb_external_resume_device(struct usb_device *udev)
 	return status;
 }
 
-static int usb_suspend(struct device *dev, pm_message_t message)
+int usb_suspend(struct device *dev, pm_message_t message)
 {
 	struct usb_device	*udev;
 
-	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
-		return 0;
 	udev = to_usb_device(dev);
 
 	/* If udev is already suspended, we can skip this suspend and
@@ -1629,12 +1640,10 @@ static int usb_suspend(struct device *dev, pm_message_t message)
 	return usb_external_suspend_device(udev, message);
 }
 
-static int usb_resume(struct device *dev)
+int usb_resume(struct device *dev)
 {
 	struct usb_device	*udev;
 
-	if (!is_usb_device(dev))	/* Ignore PM for interfaces */
-		return 0;
 	udev = to_usb_device(dev);
 
 	/* If udev->skip_sys_resume is set then udev was already suspended
@@ -1646,17 +1655,10 @@ static int usb_resume(struct device *dev)
 	return usb_external_resume_device(udev);
 }
 
-#else
-
-#define usb_suspend	NULL
-#define usb_resume	NULL
-
 #endif /* CONFIG_PM */
 
 struct bus_type usb_bus_type = {
 	.name =		"usb",
 	.match =	usb_device_match,
 	.uevent =	usb_uevent,
-	.suspend =	usb_suspend,
-	.resume =	usb_resume,
 };

+ 0 - 9
drivers/usb/core/hcd.c

@@ -924,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
 	return retval;
 }
 
-void usb_enable_root_hub_irq (struct usb_bus *bus)
-{
-	struct usb_hcd *hcd;
-
-	hcd = container_of (bus, struct usb_hcd, self);
-	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
-		hcd->driver->hub_irq_enable (hcd);
-}
-
 
 /*-------------------------------------------------------------------------*/
 

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

@@ -212,8 +212,6 @@ struct hc_driver {
 	int	(*bus_suspend)(struct usb_hcd *);
 	int	(*bus_resume)(struct usb_hcd *);
 	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
-	void	(*hub_irq_enable)(struct usb_hcd *);
-		/* Needed only if port-change IRQs are level-triggered */
 
 		/* force handover of high-speed port to full-speed companion */
 	void	(*relinquish_port)(struct usb_hcd *, int);
@@ -379,8 +377,6 @@ extern struct list_head usb_bus_list;
 extern struct mutex usb_bus_list_lock;
 extern wait_queue_head_t usb_kill_urb_queue;
 
-extern void usb_enable_root_hub_irq(struct usb_bus *bus);
-
 extern int usb_find_interface_driver(struct usb_device *dev,
 	struct usb_interface *interface);
 

+ 0 - 9
drivers/usb/core/hub.c

@@ -2102,8 +2102,6 @@ int usb_port_resume(struct usb_device *udev)
 	}
 
 	clear_bit(port1, hub->busy_bits);
-	if (!hub->hdev->parent && !hub->busy_bits[0])
-		usb_enable_root_hub_irq(hub->hdev->bus);
 
 	status = check_port_resume_type(udev,
 			hub, port1, status, portchange, portstatus);
@@ -3081,11 +3079,6 @@ static void hub_events(void)
 			}
 		}
 
-		/* If this is a root hub, tell the HCD it's okay to
-		 * re-enable port-change interrupts now. */
-		if (!hdev->parent && !hub->busy_bits[0])
-			usb_enable_root_hub_irq(hdev->bus);
-
 loop_autopm:
 		/* Allow autosuspend if we're not going to run again */
 		if (list_empty(&hub->event_list))
@@ -3311,8 +3304,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
 			break;
 	}
 	clear_bit(port1, parent_hub->busy_bits);
-	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
-		usb_enable_root_hub_irq(parent_hdev->bus);
 
 	if (ret < 0)
 		goto re_enumerate;

+ 7 - 2
drivers/usb/core/urb.c

@@ -601,15 +601,20 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
 void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
 {
 	struct urb *victim;
+	unsigned long flags;
 
-	spin_lock_irq(&anchor->lock);
+	spin_lock_irqsave(&anchor->lock, flags);
 	while (!list_empty(&anchor->urb_list)) {
 		victim = list_entry(anchor->urb_list.prev, struct urb,
 				    anchor_list);
+		usb_get_urb(victim);
+		spin_unlock_irqrestore(&anchor->lock, flags);
 		/* this will unanchor the URB */
 		usb_unlink_urb(victim);
+		usb_put_urb(victim);
+		spin_lock_irqsave(&anchor->lock, flags);
 	}
-	spin_unlock_irq(&anchor->lock);
+	spin_unlock_irqrestore(&anchor->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
 

+ 67 - 6
drivers/usb/core/usb.c

@@ -219,12 +219,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 }
 #endif	/* CONFIG_HOTPLUG */
 
-struct device_type usb_device_type = {
-	.name =		"usb_device",
-	.release =	usb_release_dev,
-	.uevent =	usb_dev_uevent,
-};
-
 #ifdef	CONFIG_PM
 
 static int ksuspend_usb_init(void)
@@ -244,13 +238,80 @@ static void ksuspend_usb_cleanup(void)
 	destroy_workqueue(ksuspend_usb_wq);
 }
 
+/* USB device Power-Management thunks.
+ * There's no need to distinguish here between quiescing a USB device
+ * and powering it down; the generic_suspend() routine takes care of
+ * it by skipping the usb_port_suspend() call for a quiesce.  And for
+ * USB interfaces there's no difference at all.
+ */
+
+static int usb_dev_prepare(struct device *dev)
+{
+	return 0;		/* Implement eventually? */
+}
+
+static void usb_dev_complete(struct device *dev)
+{
+	/* Currently used only for rebinding interfaces */
+	usb_resume(dev);	/* Implement eventually? */
+}
+
+static int usb_dev_suspend(struct device *dev)
+{
+	return usb_suspend(dev, PMSG_SUSPEND);
+}
+
+static int usb_dev_resume(struct device *dev)
+{
+	return usb_resume(dev);
+}
+
+static int usb_dev_freeze(struct device *dev)
+{
+	return usb_suspend(dev, PMSG_FREEZE);
+}
+
+static int usb_dev_thaw(struct device *dev)
+{
+	return usb_resume(dev);
+}
+
+static int usb_dev_poweroff(struct device *dev)
+{
+	return usb_suspend(dev, PMSG_HIBERNATE);
+}
+
+static int usb_dev_restore(struct device *dev)
+{
+	return usb_resume(dev);
+}
+
+static struct pm_ops usb_device_pm_ops = {
+	.prepare =	usb_dev_prepare,
+	.complete =	usb_dev_complete,
+	.suspend =	usb_dev_suspend,
+	.resume =	usb_dev_resume,
+	.freeze =	usb_dev_freeze,
+	.thaw =		usb_dev_thaw,
+	.poweroff =	usb_dev_poweroff,
+	.restore =	usb_dev_restore,
+};
+
 #else
 
 #define ksuspend_usb_init()	0
 #define ksuspend_usb_cleanup()	do {} while (0)
+#define usb_device_pm_ops	(*(struct pm_ops *)0)
 
 #endif	/* CONFIG_PM */
 
+struct device_type usb_device_type = {
+	.name =		"usb_device",
+	.release =	usb_release_dev,
+	.uevent =	usb_dev_uevent,
+	.pm =		&usb_device_pm_ops,
+};
+
 
 /* Returns 1 if @usb_bus is WUSB, 0 otherwise */
 static unsigned usb_bus_is_wusb(struct usb_bus *bus)

+ 3 - 0
drivers/usb/core/usb.h

@@ -41,6 +41,9 @@ extern void usb_host_cleanup(void);
 
 #ifdef	CONFIG_PM
 
+extern int usb_suspend(struct device *dev, pm_message_t msg);
+extern int usb_resume(struct device *dev);
+
 extern void usb_autosuspend_work(struct work_struct *work);
 extern int usb_port_suspend(struct usb_device *dev);
 extern int usb_port_resume(struct usb_device *dev);

+ 1 - 1
drivers/usb/gadget/pxa27x_udc.c

@@ -1622,7 +1622,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 	struct pxa_udc *udc = the_controller;
 	int retval;
 
-	if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind
+	if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind
 			|| !driver->disconnect || !driver->setup)
 		return -EINVAL;
 	if (!udc)

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

@@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 		/*
 		 * write bank1 address twice to ensure the 90ns delay (time
 		 * between BANK0 write and the priv_read_copy() call is at
-		 * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns)
+		 * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns)
 		 */
 		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
 				HC_MEMORY_REG);

+ 0 - 1
drivers/usb/host/ohci-at91.c

@@ -260,7 +260,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-au1xxx.c

@@ -163,7 +163,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-ep93xx.c

@@ -134,7 +134,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
 	.get_frame_number	= ohci_get_frame,
 	.hub_status_data	= ohci_hub_status_data,
 	.hub_control		= ohci_hub_control,
-	.hub_irq_enable		= ohci_rhsc_enable,
 #ifdef CONFIG_PM
 	.bus_suspend		= ohci_bus_suspend,
 	.bus_resume		= ohci_bus_resume,

+ 31 - 22
drivers/usb/host/ohci-hub.c

@@ -36,18 +36,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* hcd->hub_irq_enable() */
-static void ohci_rhsc_enable (struct usb_hcd *hcd)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-
-	spin_lock_irq(&ohci->lock);
-	if (!ohci->autostop)
-		del_timer(&hcd->rh_timer);	/* Prevent next poll */
-	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
-	spin_unlock_irq(&ohci->lock);
-}
-
 #define OHCI_SCHED_ENABLES \
 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
@@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
 		int any_connected)
 {
 	int	poll_rh = 1;
+	int	rhsc;
 
+	rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
 
 	case OHCI_USB_OPER:
-		/* keep on polling until we know a device is connected
-		 * and RHSC is enabled */
+		/* If no status changes are pending, enable status-change
+		 * interrupts.
+		 */
+		if (!rhsc && !changed) {
+			rhsc = OHCI_INTR_RHSC;
+			ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
+		}
+
+		/* Keep on polling until we know a device is connected
+		 * and RHSC is enabled, or until we autostop.
+		 */
 		if (!ohci->autostop) {
 			if (any_connected ||
 					!device_may_wakeup(&ohci_to_hcd(ohci)
 						->self.root_hub->dev)) {
-				if (ohci_readl(ohci, &ohci->regs->intrenable) &
-						OHCI_INTR_RHSC)
+				if (rhsc)
 					poll_rh = 0;
 			} else {
 				ohci->autostop = 1;
@@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
 				ohci->autostop = 0;
 				ohci->next_statechange = jiffies +
 						STATECHANGE_DELAY;
-			} else if (time_after_eq(jiffies,
+			} else if (rhsc && time_after_eq(jiffies,
 						ohci->next_statechange)
 					&& !ohci->ed_rm_list
 					&& !(ohci->hc_control &
 						OHCI_SCHED_ENABLES)) {
 				ohci_rh_suspend(ohci, 1);
+				poll_rh = 0;
 			}
 		}
 		break;
@@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
 			else
 				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
 		} else {
+			if (!rhsc && (ohci->autostop ||
+					ohci_to_hcd(ohci)->self.root_hub->
+						do_remote_wakeup))
+				ohci_writel(ohci, OHCI_INTR_RHSC,
+						&ohci->regs->intrenable);
+
 			/* everything is idle, no need for polling */
 			poll_rh = 0;
 		}
@@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
 		int any_connected)
 {
-	int	poll_rh = 1;
-
-	/* keep on polling until RHSC is enabled */
+	/* If RHSC is enabled, don't poll */
 	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
-		poll_rh = 0;
-	return poll_rh;
+		return 0;
+
+	/* If no status changes are pending, enable status-change interrupts */
+	if (!changed) {
+		ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+		return 0;
+	}
+	return 1;
 }
 
 #endif	/* CONFIG_PM */

+ 0 - 1
drivers/usb/host/ohci-lh7a404.c

@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-omap.c

@@ -470,7 +470,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-pci.c

@@ -459,7 +459,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-pnx4008.c

@@ -277,7 +277,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
 	 */
 	.hub_status_data = ohci_hub_status_data,
 	.hub_control = ohci_hub_control,
-	.hub_irq_enable = ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend = ohci_bus_suspend,
 	.bus_resume = ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-pnx8550.c

@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-ppc-of.c

@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-ppc-soc.c

@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-ps3.c

@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
 	.get_frame_number	= ohci_get_frame,
 	.hub_status_data	= ohci_hub_status_data,
 	.hub_control		= ohci_hub_control,
-	.hub_irq_enable		= ohci_rhsc_enable,
 	.start_port_reset	= ohci_start_port_reset,
 #if defined(CONFIG_PM)
 	.bus_suspend 		= ohci_bus_suspend,

+ 0 - 1
drivers/usb/host/ohci-pxa27x.c

@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef  CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-s3c2410.c

@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
 	 */
 	.hub_status_data =	ohci_s3c2410_hub_status_data,
 	.hub_control =		ohci_s3c2410_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-sa1111.c

@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-sh.c

@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-sm501.c

@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,

+ 0 - 1
drivers/usb/host/ohci-ssb.c

@@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
 
 	.hub_status_data	= ohci_hub_status_data,
 	.hub_control		= ohci_hub_control,
-	.hub_irq_enable		= ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend		= ohci_bus_suspend,
 	.bus_resume		= ohci_bus_resume,

+ 0 - 11
drivers/usb/host/u132-hcd.c

@@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
 		return 0;
 }
 
-static void u132_hub_irq_enable(struct usb_hcd *hcd)
-{
-	struct u132 *u132 = hcd_to_u132(hcd);
-	if (u132->going > 1) {
-		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
-			, u132->going);
-	} else if (u132->going > 0)
-		dev_err(&u132->platform_dev->dev, "device is being removed\n");
-}
-
 
 #ifdef CONFIG_PM
 static int u132_bus_suspend(struct usb_hcd *hcd)
@@ -2995,7 +2985,6 @@ static struct hc_driver u132_hc_driver = {
 	.bus_suspend = u132_bus_suspend,
 	.bus_resume = u132_bus_resume,
 	.start_port_reset = u132_start_port_reset,
-	.hub_irq_enable = u132_hub_irq_enable,
 };
 
 /*

+ 1 - 0
drivers/usb/misc/sisusbvga/sisusb.c

@@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = {
 	{ USB_DEVICE(0x0711, 0x0900) },
 	{ USB_DEVICE(0x0711, 0x0901) },
 	{ USB_DEVICE(0x0711, 0x0902) },
+	{ USB_DEVICE(0x0711, 0x0918) },
 	{ USB_DEVICE(0x182d, 0x021c) },
 	{ USB_DEVICE(0x182d, 0x0269) },
 	{ }

+ 6 - 7
drivers/usb/musb/Kconfig

@@ -165,12 +165,11 @@ config USB_TUSB_OMAP_DMA
 	help
 	  Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
 
-config	USB_MUSB_LOGLEVEL
+config	USB_MUSB_DEBUG
 	depends on USB_MUSB_HDRC
-	int  'Logging Level (0 - none / 3 - annoying / ... )'
-	default 0
+	bool "Enable debugging messages"
+	default n
 	help
-	  Set the logging level. 0 disables the debugging altogether,
-	  although when USB_DEBUG is set the value is at least 1.
-	  Starting at level 3, per-transfer (urb, usb_request, packet,
-	  or dma transfer) tracing may kick in.
+	  This enables musb debugging. To set the logging level use the debug
+	  module parameter. Starting at level 3, per-transfer (urb, usb_request,
+	  packet, or dma transfer) tracing may kick in.

+ 2 - 19
drivers/usb/musb/Makefile

@@ -64,23 +64,6 @@ endif
 
 # Debugging
 
-MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL)
-
-ifeq ("$(strip $(MUSB_DEBUG))","")
-    ifdef CONFIG_USB_DEBUG
-	MUSB_DEBUG:=1
-    else
-	MUSB_DEBUG:=0
-    endif
+ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
+	EXTRA_CFLAGS += -DDEBUG
 endif
-
-ifneq ($(MUSB_DEBUG),0)
-    EXTRA_CFLAGS += -DDEBUG
-
-    ifeq ($(CONFIG_PROC_FS),y)
-	musb_hdrc-objs		+= musb_procfs.o
-    endif
-
-endif
-
-EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG)

+ 15 - 23
drivers/usb/musb/musb_core.c

@@ -114,23 +114,14 @@
 
 
 
-#if MUSB_DEBUG > 0
-unsigned debug = MUSB_DEBUG;
-module_param(debug, uint, 0);
-MODULE_PARM_DESC(debug, "initial debug message level");
-
-#define MUSB_VERSION_SUFFIX	"/dbg"
-#endif
+unsigned debug;
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 
 #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
 #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
 
-#define MUSB_VERSION_BASE "6.0"
-
-#ifndef MUSB_VERSION_SUFFIX
-#define MUSB_VERSION_SUFFIX	""
-#endif
-#define MUSB_VERSION	MUSB_VERSION_BASE MUSB_VERSION_SUFFIX
+#define MUSB_VERSION "6.0"
 
 #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
 
@@ -2037,6 +2028,8 @@ bad_config:
 		musb->xceiv.state = OTG_STATE_A_IDLE;
 
 		status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+		if (status)
+			goto fail;
 
 		DBG(1, "%s mode, status %d, devctl %02x %c\n",
 			"HOST", status,
@@ -2051,6 +2044,8 @@ bad_config:
 		musb->xceiv.state = OTG_STATE_B_IDLE;
 
 		status = musb_gadget_setup(musb);
+		if (status)
+			goto fail;
 
 		DBG(1, "%s mode, status %d, dev%02x\n",
 			is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
@@ -2059,16 +2054,14 @@ bad_config:
 
 	}
 
-	if (status == 0)
-		musb_debug_create("driver/musb_hdrc", musb);
-	else {
+	return 0;
+
 fail:
-		if (musb->clock)
-			clk_put(musb->clock);
-		device_init_wakeup(dev, 0);
-		musb_free(musb);
-		return status;
-	}
+	if (musb->clock)
+		clk_put(musb->clock);
+	device_init_wakeup(dev, 0);
+	musb_free(musb);
+	return status;
 
 #ifdef CONFIG_SYSFS
 	status = device_create_file(dev, &dev_attr_mode);
@@ -2131,7 +2124,6 @@ static int __devexit musb_remove(struct platform_device *pdev)
 	 *  - OTG mode: both roles are deactivated (or never-activated)
 	 */
 	musb_shutdown(pdev);
-	musb_debug_delete("driver/musb_hdrc", musb);
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 	if (musb->board_mode == MUSB_HOST)
 		usb_remove_hcd(musb_to_hcd(musb));

+ 0 - 19
drivers/usb/musb/musb_core.h

@@ -485,23 +485,4 @@ extern int musb_platform_get_vbus_status(struct musb *musb);
 extern int __init musb_platform_init(struct musb *musb);
 extern int musb_platform_exit(struct musb *musb);
 
-/*-------------------------- ProcFS definitions ---------------------*/
-
-struct proc_dir_entry;
-
-#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS)
-extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
-extern void musb_debug_delete(char *name, struct musb *data);
-
-#else
-static inline struct proc_dir_entry *
-musb_debug_create(char *name, struct musb *data)
-{
-	return NULL;
-}
-static inline void musb_debug_delete(char *name, struct musb *data)
-{
-}
-#endif
-
 #endif	/* __MUSB_CORE_H__ */

+ 0 - 4
drivers/usb/musb/musb_debug.h

@@ -48,11 +48,7 @@
 				__func__, __LINE__ , ## args); \
 	} } while (0)
 
-#if MUSB_DEBUG > 0
 extern unsigned debug;
-#else
-#define debug	0
-#endif
 
 static inline int _dbg_level(unsigned l)
 {

+ 2 - 0
drivers/usb/musb/musb_gadget_ep0.c

@@ -476,6 +476,7 @@ static void ep0_rxstate(struct musb *musb)
 			return;
 		musb->ackpend = 0;
 	}
+	musb_ep_select(musb->mregs, 0);
 	musb_writew(regs, MUSB_CSR0, tmp);
 }
 
@@ -528,6 +529,7 @@ static void ep0_txstate(struct musb *musb)
 	}
 
 	/* send it out, triggering a "txpktrdy cleared" irq */
+	musb_ep_select(musb->mregs, 0);
 	musb_writew(regs, MUSB_CSR0, csr);
 }
 

+ 0 - 830
drivers/usb/musb/musb_procfs.c

@@ -1,830 +0,0 @@
-/*
- * MUSB OTG driver debug support
- *
- * Copyright 2005 Mentor Graphics Corporation
- * Copyright (C) 2005-2006 by Texas Instruments
- * Copyright (C) 2006-2007 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>	/* FIXME remove procfs writes */
-#include <asm/arch/hardware.h>
-
-#include "musb_core.h"
-
-#include "davinci.h"
-
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-
-static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
-{
-	int				count;
-	int				tmp;
-	struct usb_host_endpoint	*hep = qh->hep;
-	struct urb			*urb;
-
-	count = snprintf(buf, max, "    qh %p dev%d ep%d%s max%d\n",
-			qh, qh->dev->devnum, qh->epnum,
-			({ char *s; switch (qh->type) {
-			case USB_ENDPOINT_XFER_BULK:
-				s = "-bulk"; break;
-			case USB_ENDPOINT_XFER_INT:
-				s = "-int"; break;
-			case USB_ENDPOINT_XFER_CONTROL:
-				s = ""; break;
-			default:
-				s = "iso"; break;
-			}; s; }),
-			qh->maxpacket);
-	if (count <= 0)
-		return 0;
-	buf += count;
-	max -= count;
-
-	list_for_each_entry(urb, &hep->urb_list, urb_list) {
-		tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
-				usb_pipein(urb->pipe) ? "in" : "out",
-				urb, urb->actual_length,
-				urb->transfer_buffer_length);
-		if (tmp <= 0)
-			break;
-		tmp = min(tmp, (int)max);
-		count += tmp;
-		buf += tmp;
-		max -= tmp;
-	}
-	return count;
-}
-
-static int
-dump_queue(struct list_head *q, char *buf, unsigned max)
-{
-	int		count = 0;
-	struct musb_qh	*qh;
-
-	list_for_each_entry(qh, q, ring) {
-		int	tmp;
-
-		tmp = dump_qh(qh, buf, max);
-		if (tmp <= 0)
-			break;
-		tmp = min(tmp, (int)max);
-		count += tmp;
-		buf += tmp;
-		max -= tmp;
-	}
-	return count;
-}
-
-#endif	/* HCD */
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
-{
-	char		*buf = buffer;
-	int		code = 0;
-	void __iomem	*regs = ep->hw_ep->regs;
-	char		*mode = "1buf";
-
-	if (ep->is_in) {
-		if (ep->hw_ep->tx_double_buffered)
-			mode = "2buf";
-	} else {
-		if (ep->hw_ep->rx_double_buffered)
-			mode = "2buf";
-	}
-
-	do {
-		struct usb_request	*req;
-
-		code = snprintf(buf, max,
-				"\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
-				ep->name, ep->current_epnum,
-				mode, ep->dma ? " dma" : "",
-				musb_readw(regs,
-					(ep->is_in || !ep->current_epnum)
-						? MUSB_TXCSR
-						: MUSB_RXCSR),
-				musb_readw(regs, ep->is_in
-						? MUSB_TXMAXP
-						: MUSB_RXMAXP)
-				);
-		if (code <= 0)
-			break;
-		code = min(code, (int) max);
-		buf += code;
-		max -= code;
-
-		if (is_cppi_enabled() && ep->current_epnum) {
-			unsigned	cppi = ep->current_epnum - 1;
-			void __iomem	*base = ep->musb->ctrl_base;
-			unsigned	off1 = cppi << 2;
-			void __iomem	*ram = base;
-			char		tmp[16];
-
-			if (ep->is_in) {
-				ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
-				tmp[0] = 0;
-			} else {
-				ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
-				snprintf(tmp, sizeof tmp, "%d left, ",
-					musb_readl(base,
-					DAVINCI_RXCPPI_BUFCNT0_REG + off1));
-			}
-
-			code = snprintf(buf, max, "%cX DMA%d: %s"
-					"%08x %08x, %08x %08x; "
-					"%08x %08x %08x .. %08x\n",
-				ep->is_in ? 'T' : 'R',
-				ep->current_epnum - 1, tmp,
-				musb_readl(ram, 0 * 4),
-				musb_readl(ram, 1 * 4),
-				musb_readl(ram, 2 * 4),
-				musb_readl(ram, 3 * 4),
-				musb_readl(ram, 4 * 4),
-				musb_readl(ram, 5 * 4),
-				musb_readl(ram, 6 * 4),
-				musb_readl(ram, 7 * 4));
-			if (code <= 0)
-				break;
-			code = min(code, (int) max);
-			buf += code;
-			max -= code;
-		}
-
-		if (list_empty(&ep->req_list)) {
-			code = snprintf(buf, max, "\t(queue empty)\n");
-			if (code <= 0)
-				break;
-			code = min(code, (int) max);
-			buf += code;
-			max -= code;
-			break;
-		}
-		list_for_each_entry(req, &ep->req_list, list) {
-			code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
-					req,
-					req->zero ? "zero, " : "",
-					req->short_not_ok ? "!short, " : "",
-					req->actual, req->length);
-			if (code <= 0)
-				break;
-			code = min(code, (int) max);
-			buf += code;
-			max -= code;
-		}
-	} while (0);
-	return buf - buffer;
-}
-#endif
-
-static int
-dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
-{
-	int			code = 0;
-	char			*buf = aBuffer;
-	struct musb_hw_ep	*hw_ep = &musb->endpoints[epnum];
-
-	do {
-		musb_ep_select(musb->mregs, epnum);
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-		if (is_host_active(musb)) {
-			int		dump_rx, dump_tx;
-			void __iomem	*regs = hw_ep->regs;
-
-			/* TEMPORARY (!) until we have a real periodic
-			 * schedule tree ...
-			 */
-			if (!epnum) {
-				/* control is shared, uses RX queue
-				 * but (mostly) shadowed tx registers
-				 */
-				dump_tx = !list_empty(&musb->control);
-				dump_rx = 0;
-			} else if (hw_ep == musb->bulk_ep) {
-				dump_tx = !list_empty(&musb->out_bulk);
-				dump_rx = !list_empty(&musb->in_bulk);
-			} else if (musb->periodic[epnum]) {
-				struct usb_host_endpoint	*hep;
-
-				hep = musb->periodic[epnum]->hep;
-				dump_rx = hep->desc.bEndpointAddress
-						& USB_ENDPOINT_DIR_MASK;
-				dump_tx = !dump_rx;
-			} else
-				break;
-			/* END TEMPORARY */
-
-
-			if (dump_rx) {
-				code = snprintf(buf, max,
-					"\nRX%d: %s rxcsr %04x interval %02x "
-					"max %04x type %02x; "
-					"dev %d hub %d port %d"
-					"\n",
-					epnum,
-					hw_ep->rx_double_buffered
-						? "2buf" : "1buf",
-					musb_readw(regs, MUSB_RXCSR),
-					musb_readb(regs, MUSB_RXINTERVAL),
-					musb_readw(regs, MUSB_RXMAXP),
-					musb_readb(regs, MUSB_RXTYPE),
-					/* FIXME:  assumes multipoint */
-					musb_readb(musb->mregs,
-						MUSB_BUSCTL_OFFSET(epnum,
-						MUSB_RXFUNCADDR)),
-					musb_readb(musb->mregs,
-						MUSB_BUSCTL_OFFSET(epnum,
-						MUSB_RXHUBADDR)),
-					musb_readb(musb->mregs,
-						MUSB_BUSCTL_OFFSET(epnum,
-						MUSB_RXHUBPORT))
-					);
-				if (code <= 0)
-					break;
-				code = min(code, (int) max);
-				buf += code;
-				max -= code;
-
-				if (is_cppi_enabled()
-						&& epnum
-						&& hw_ep->rx_channel) {
-					unsigned	cppi = epnum - 1;
-					unsigned	off1 = cppi << 2;
-					void __iomem	*base;
-					void __iomem	*ram;
-					char		tmp[16];
-
-					base = musb->ctrl_base;
-					ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
-							cppi) + base;
-					snprintf(tmp, sizeof tmp, "%d left, ",
-						musb_readl(base,
-						DAVINCI_RXCPPI_BUFCNT0_REG
-								+ off1));
-
-					code = snprintf(buf, max,
-						"    rx dma%d: %s"
-						"%08x %08x, %08x %08x; "
-						"%08x %08x %08x .. %08x\n",
-						cppi, tmp,
-						musb_readl(ram, 0 * 4),
-						musb_readl(ram, 1 * 4),
-						musb_readl(ram, 2 * 4),
-						musb_readl(ram, 3 * 4),
-						musb_readl(ram, 4 * 4),
-						musb_readl(ram, 5 * 4),
-						musb_readl(ram, 6 * 4),
-						musb_readl(ram, 7 * 4));
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				}
-
-				if (hw_ep == musb->bulk_ep
-						&& !list_empty(
-							&musb->in_bulk)) {
-					code = dump_queue(&musb->in_bulk,
-							buf, max);
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				} else if (musb->periodic[epnum]) {
-					code = dump_qh(musb->periodic[epnum],
-							buf, max);
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				}
-			}
-
-			if (dump_tx) {
-				code = snprintf(buf, max,
-					"\nTX%d: %s txcsr %04x interval %02x "
-					"max %04x type %02x; "
-					"dev %d hub %d port %d"
-					"\n",
-					epnum,
-					hw_ep->tx_double_buffered
-						? "2buf" : "1buf",
-					musb_readw(regs, MUSB_TXCSR),
-					musb_readb(regs, MUSB_TXINTERVAL),
-					musb_readw(regs, MUSB_TXMAXP),
-					musb_readb(regs, MUSB_TXTYPE),
-					/* FIXME:  assumes multipoint */
-					musb_readb(musb->mregs,
-						MUSB_BUSCTL_OFFSET(epnum,
-						MUSB_TXFUNCADDR)),
-					musb_readb(musb->mregs,
-						MUSB_BUSCTL_OFFSET(epnum,
-						MUSB_TXHUBADDR)),
-					musb_readb(musb->mregs,
-						MUSB_BUSCTL_OFFSET(epnum,
-						MUSB_TXHUBPORT))
-					);
-				if (code <= 0)
-					break;
-				code = min(code, (int) max);
-				buf += code;
-				max -= code;
-
-				if (is_cppi_enabled()
-						&& epnum
-						&& hw_ep->tx_channel) {
-					unsigned	cppi = epnum - 1;
-					void __iomem	*base;
-					void __iomem	*ram;
-
-					base = musb->ctrl_base;
-					ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
-							cppi) + base;
-					code = snprintf(buf, max,
-						"    tx dma%d: "
-						"%08x %08x, %08x %08x; "
-						"%08x %08x %08x .. %08x\n",
-						cppi,
-						musb_readl(ram, 0 * 4),
-						musb_readl(ram, 1 * 4),
-						musb_readl(ram, 2 * 4),
-						musb_readl(ram, 3 * 4),
-						musb_readl(ram, 4 * 4),
-						musb_readl(ram, 5 * 4),
-						musb_readl(ram, 6 * 4),
-						musb_readl(ram, 7 * 4));
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				}
-
-				if (hw_ep == musb->control_ep
-						&& !list_empty(
-							&musb->control)) {
-					code = dump_queue(&musb->control,
-							buf, max);
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				} else if (hw_ep == musb->bulk_ep
-						&& !list_empty(
-							&musb->out_bulk)) {
-					code = dump_queue(&musb->out_bulk,
-							buf, max);
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				} else if (musb->periodic[epnum]) {
-					code = dump_qh(musb->periodic[epnum],
-							buf, max);
-					if (code <= 0)
-						break;
-					code = min(code, (int) max);
-					buf += code;
-					max -= code;
-				}
-			}
-		}
-#endif
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-		if (is_peripheral_active(musb)) {
-			code = 0;
-
-			if (hw_ep->ep_in.desc || !epnum) {
-				code = dump_ep(&hw_ep->ep_in, buf, max);
-				if (code <= 0)
-					break;
-				code = min(code, (int) max);
-				buf += code;
-				max -= code;
-			}
-			if (hw_ep->ep_out.desc) {
-				code = dump_ep(&hw_ep->ep_out, buf, max);
-				if (code <= 0)
-					break;
-				code = min(code, (int) max);
-				buf += code;
-				max -= code;
-			}
-		}
-#endif
-	} while (0);
-
-	return buf - aBuffer;
-}
-
-/* Dump the current status and compile options.
- * @param musb the device driver instance
- * @param buffer where to dump the status; it must be big enough to hold the
- * result otherwise "BAD THINGS HAPPENS(TM)".
- */
-static int dump_header_stats(struct musb *musb, char *buffer)
-{
-	int code, count = 0;
-	const void __iomem *mbase = musb->mregs;
-
-	*buffer = 0;
-	count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
-				"(Power=%02x, DevCtl=%02x)\n",
-			(musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
-			musb_readb(mbase, MUSB_POWER),
-			musb_readb(mbase, MUSB_DEVCTL));
-	if (count <= 0)
-		return 0;
-	buffer += count;
-
-	code = sprintf(buffer, "OTG state: %s; %sactive\n",
-			otg_state_string(musb),
-			musb->is_active ? "" : "in");
-	if (code <= 0)
-		goto done;
-	buffer += code;
-	count += code;
-
-	code = sprintf(buffer,
-			"Options: "
-#ifdef CONFIG_MUSB_PIO_ONLY
-			"pio"
-#elif defined(CONFIG_USB_TI_CPPI_DMA)
-			"cppi-dma"
-#elif defined(CONFIG_USB_INVENTRA_DMA)
-			"musb-dma"
-#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
-			"tusb-omap-dma"
-#else
-			"?dma?"
-#endif
-			", "
-#ifdef CONFIG_USB_MUSB_OTG
-			"otg (peripheral+host)"
-#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
-			"peripheral"
-#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
-			"host"
-#endif
-			", debug=%d [eps=%d]\n",
-		debug,
-		musb->nr_endpoints);
-	if (code <= 0)
-		goto done;
-	count += code;
-	buffer += code;
-
-#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
-	code = sprintf(buffer, "Peripheral address: %02x\n",
-			musb_readb(musb->ctrl_base, MUSB_FADDR));
-	if (code <= 0)
-		goto done;
-	buffer += code;
-	count += code;
-#endif
-
-#ifdef	CONFIG_USB_MUSB_HDRC_HCD
-	code = sprintf(buffer, "Root port status: %08x\n",
-			musb->port1_status);
-	if (code <= 0)
-		goto done;
-	buffer += code;
-	count += code;
-#endif
-
-#ifdef	CONFIG_ARCH_DAVINCI
-	code = sprintf(buffer,
-			"DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
-			"\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
-			"\n",
-			musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
-			musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
-			__raw_readl((void __force __iomem *)
-					IO_ADDRESS(USBPHY_CTL_PADDR)),
-			musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
-			musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
-			musb_readl(musb->ctrl_base,
-					DAVINCI_USB_INT_SOURCE_REG),
-			musb_readl(musb->ctrl_base,
-					DAVINCI_USB_INT_MASK_REG));
-	if (code <= 0)
-		goto done;
-	count += code;
-	buffer += code;
-#endif	/* DAVINCI */
-
-#ifdef CONFIG_USB_TUSB6010
-	code = sprintf(buffer,
-			"TUSB6010: devconf %08x, phy enable %08x drive %08x"
-			"\n\totg %03x timer %08x"
-			"\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
-			"\n",
-			musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
-			musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
-			musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
-			musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
-			musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
-			musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
-			musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
-			musb_readl(musb->ctrl_base, TUSB_INT_SRC),
-			musb_readl(musb->ctrl_base, TUSB_INT_MASK));
-	if (code <= 0)
-		goto done;
-	count += code;
-	buffer += code;
-#endif	/* DAVINCI */
-
-	if (is_cppi_enabled() && musb->dma_controller) {
-		code = sprintf(buffer,
-				"CPPI: txcr=%d txsrc=%01x txena=%01x; "
-				"rxcr=%d rxsrc=%01x rxena=%01x "
-				"\n",
-				musb_readl(musb->ctrl_base,
-						DAVINCI_TXCPPI_CTRL_REG),
-				musb_readl(musb->ctrl_base,
-						DAVINCI_TXCPPI_RAW_REG),
-				musb_readl(musb->ctrl_base,
-						DAVINCI_TXCPPI_INTENAB_REG),
-				musb_readl(musb->ctrl_base,
-						DAVINCI_RXCPPI_CTRL_REG),
-				musb_readl(musb->ctrl_base,
-						DAVINCI_RXCPPI_RAW_REG),
-				musb_readl(musb->ctrl_base,
-						DAVINCI_RXCPPI_INTENAB_REG));
-		if (code <= 0)
-			goto done;
-		count += code;
-		buffer += code;
-	}
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-	if (is_peripheral_enabled(musb)) {
-		code = sprintf(buffer, "Gadget driver: %s\n",
-				musb->gadget_driver
-					? musb->gadget_driver->driver.name
-					: "(none)");
-		if (code <= 0)
-			goto done;
-		count += code;
-		buffer += code;
-	}
-#endif
-
-done:
-	return count;
-}
-
-/* Write to ProcFS
- *
- * C soft-connect
- * c soft-disconnect
- * I enable HS
- * i disable HS
- * s stop session
- * F force session (OTG-unfriendly)
- * E rElinquish bus (OTG)
- * H request host mode
- * h cancel host request
- * T start sending TEST_PACKET
- * D<num> set/query the debug level
- */
-static int musb_proc_write(struct file *file, const char __user *buffer,
-			unsigned long count, void *data)
-{
-	char cmd;
-	u8 reg;
-	struct musb *musb = (struct musb *)data;
-	void __iomem *mbase = musb->mregs;
-
-	/* MOD_INC_USE_COUNT; */
-
-	if (unlikely(copy_from_user(&cmd, buffer, 1)))
-		return -EFAULT;
-
-	switch (cmd) {
-	case 'C':
-		if (mbase) {
-			reg = musb_readb(mbase, MUSB_POWER)
-					| MUSB_POWER_SOFTCONN;
-			musb_writeb(mbase, MUSB_POWER, reg);
-		}
-		break;
-
-	case 'c':
-		if (mbase) {
-			reg = musb_readb(mbase, MUSB_POWER)
-					& ~MUSB_POWER_SOFTCONN;
-			musb_writeb(mbase, MUSB_POWER, reg);
-		}
-		break;
-
-	case 'I':
-		if (mbase) {
-			reg = musb_readb(mbase, MUSB_POWER)
-					| MUSB_POWER_HSENAB;
-			musb_writeb(mbase, MUSB_POWER, reg);
-		}
-		break;
-
-	case 'i':
-		if (mbase) {
-			reg = musb_readb(mbase, MUSB_POWER)
-					& ~MUSB_POWER_HSENAB;
-			musb_writeb(mbase, MUSB_POWER, reg);
-		}
-		break;
-
-	case 'F':
-		reg = musb_readb(mbase, MUSB_DEVCTL);
-		reg |= MUSB_DEVCTL_SESSION;
-		musb_writeb(mbase, MUSB_DEVCTL, reg);
-		break;
-
-	case 'H':
-		if (mbase) {
-			reg = musb_readb(mbase, MUSB_DEVCTL);
-			reg |= MUSB_DEVCTL_HR;
-			musb_writeb(mbase, MUSB_DEVCTL, reg);
-			/* MUSB_HST_MODE( ((struct musb*)data) ); */
-			/* WARNING("Host Mode\n"); */
-		}
-		break;
-
-	case 'h':
-		if (mbase) {
-			reg = musb_readb(mbase, MUSB_DEVCTL);
-			reg &= ~MUSB_DEVCTL_HR;
-			musb_writeb(mbase, MUSB_DEVCTL, reg);
-		}
-		break;
-
-	case 'T':
-		if (mbase) {
-			musb_load_testpacket(musb);
-			musb_writeb(mbase, MUSB_TESTMODE,
-					MUSB_TEST_PACKET);
-		}
-		break;
-
-#if (MUSB_DEBUG > 0)
-		/* set/read debug level */
-	case 'D':{
-			if (count > 1) {
-				char digits[8], *p = digits;
-				int i = 0, level = 0, sign = 1;
-				int len = min(count - 1, (unsigned long)8);
-
-				if (copy_from_user(&digits, &buffer[1], len))
-					return -EFAULT;
-
-				/* optional sign */
-				if (*p == '-') {
-					len -= 1;
-					sign = -sign;
-					p++;
-				}
-
-				/* read it */
-				while (i++ < len && *p > '0' && *p < '9') {
-					level = level * 10 + (*p - '0');
-					p++;
-				}
-
-				level *= sign;
-				DBG(1, "debug level %d\n", level);
-				debug = level;
-			}
-		}
-		break;
-
-
-	case '?':
-		INFO("?: you are seeing it\n");
-		INFO("C/c: soft connect enable/disable\n");
-		INFO("I/i: hispeed enable/disable\n");
-		INFO("F: force session start\n");
-		INFO("H: host mode\n");
-		INFO("T: start sending TEST_PACKET\n");
-		INFO("D: set/read dbug level\n");
-		break;
-#endif
-
-	default:
-		ERR("Command %c not implemented\n", cmd);
-		break;
-	}
-
-	musb_platform_try_idle(musb, 0);
-
-	return count;
-}
-
-static int musb_proc_read(char *page, char **start,
-			off_t off, int count, int *eof, void *data)
-{
-	char *buffer = page;
-	int code = 0;
-	unsigned long	flags;
-	struct musb	*musb = data;
-	unsigned	epnum;
-
-	count -= off;
-	count -= 1;		/* for NUL at end */
-	if (count <= 0)
-		return -EINVAL;
-
-	spin_lock_irqsave(&musb->lock, flags);
-
-	code = dump_header_stats(musb, buffer);
-	if (code > 0) {
-		buffer += code;
-		count -= code;
-	}
-
-	/* generate the report for the end points */
-	/* REVISIT ... not unless something's connected! */
-	for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
-			epnum++) {
-		code = dump_end_info(musb, epnum, buffer, count);
-		if (code > 0) {
-			buffer += code;
-			count -= code;
-		}
-	}
-
-	musb_platform_try_idle(musb, 0);
-
-	spin_unlock_irqrestore(&musb->lock, flags);
-	*eof = 1;
-
-	return buffer - page;
-}
-
-void __devexit musb_debug_delete(char *name, struct musb *musb)
-{
-	if (musb->proc_entry)
-		remove_proc_entry(name, NULL);
-}
-
-struct proc_dir_entry *__init
-musb_debug_create(char *name, struct musb *data)
-{
-	struct proc_dir_entry	*pde;
-
-	/* FIXME convert everything to seq_file; then later, debugfs */
-
-	if (!name)
-		return NULL;
-
-	pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL);
-	data->proc_entry = pde;
-	if (pde) {
-		pde->data = data;
-		/* pde->owner = THIS_MODULE; */
-
-		pde->read_proc = musb_proc_read;
-		pde->write_proc = musb_proc_write;
-
-		pde->size = 0;
-
-		pr_debug("Registered /proc/%s\n", name);
-	} else {
-		pr_debug("Cannot create a valid proc file entry");
-	}
-
-	return pde;
-}

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

@@ -173,6 +173,7 @@ static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
 #define KYOCERA_PRODUCT_KPC680			0x180a
 
 #define ANYDATA_VENDOR_ID			0x16d5
+#define ANYDATA_PRODUCT_ADU_620UW		0x6202
 #define ANYDATA_PRODUCT_ADU_E100A		0x6501
 #define ANYDATA_PRODUCT_ADU_500A		0x6502
 
@@ -318,6 +319,7 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8138) },	/* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
+	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
 	{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
 	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
 	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },

+ 3 - 0
include/linux/usb.h

@@ -110,6 +110,8 @@ enum usb_interface_condition {
  * @sysfs_files_created: sysfs attributes exist
  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
  *	capability during autosuspend.
+ * @needs_altsetting0: flag set when a set-interface request for altsetting 0
+ *	has been deferred.
  * @needs_binding: flag set when the driver should be re-probed or unbound
  *	following a reset or suspend operation it doesn't support.
  * @dev: driver model's view of this device
@@ -162,6 +164,7 @@ struct usb_interface {
 	unsigned is_active:1;		/* the interface is not suspended */
 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */
 	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
 
 	struct device dev;		/* interface specific device info */