[PATCH] USB: pxa2xx_udc updates

This has several small updates to the px2xx UDC driver:

  * small fixes from Eugeny S. Mints <emints@ru.mvista.com>
     - local_irq_save() around potential endpoint disable race
     - fix handling of enqueue to OUT endpoints (potential oops)
  * add shutdown() method to disable any D+ pullup
  * rename methods accessing raw signals, referencing the signals
  * describes itself as for "pxa25x", since pxa27x is different

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index b8b4524..6a0b957 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -1,6 +1,6 @@
 /*
  * linux/drivers/usb/gadget/pxa2xx_udc.c
- * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers
+ * Intel PXA25x and IXP4xx on-chip full speed USB device controllers
  *
  * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
  * Copyright (C) 2003 Robert Schwebel, Pengutronix
@@ -63,7 +63,7 @@
 
 
 /*
- * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
  * series processors.  The UDC for the IXP 4xx series is very similar.
  * There are fifteen endpoints, in addition to ep0.
  *
@@ -79,8 +79,8 @@
  * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
  */
 
-#define	DRIVER_VERSION	"14-Dec-2003"
-#define	DRIVER_DESC	"PXA 2xx USB Device Controller driver"
+#define	DRIVER_VERSION	"4-May-2005"
+#define	DRIVER_DESC	"PXA 25x USB Device Controller driver"
 
 
 static const char driver_name [] = "pxa2xx_udc";
@@ -290,6 +290,7 @@
 static int pxa2xx_ep_disable (struct usb_ep *_ep)
 {
 	struct pxa2xx_ep	*ep;
+	unsigned long		flags;
 
 	ep = container_of (_ep, struct pxa2xx_ep, ep);
 	if (!_ep || !ep->desc) {
@@ -297,6 +298,8 @@
 			_ep ? ep->ep.name : NULL);
 		return -EINVAL;
 	}
+	local_irq_save(flags);
+
 	nuke (ep, -ESHUTDOWN);
 
 #ifdef	USE_DMA
@@ -313,6 +316,7 @@
 	ep->desc = NULL;
 	ep->stopped = 1;
 
+	local_irq_restore(flags);
 	DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
 	return 0;
 }
@@ -971,10 +975,10 @@
 			kick_dma(ep, req);
 #endif
 		/* can the FIFO can satisfy the request immediately? */
-		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
-				&& (*ep->reg_udccs & UDCCS_BI_TFS) != 0
-				&& write_fifo(ep, req)) {
-			req = NULL;
+		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+			if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
+					&& write_fifo(ep, req))
+				req = NULL;
 		} else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
 				&& read_fifo(ep, req)) {
 			req = NULL;
@@ -1290,7 +1294,7 @@
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
 		driver_name, DRIVER_VERSION SIZE_STR DMASTR,
 		dev->driver ? dev->driver->driver.name : "(none)",
-		is_usb_connected() ? "full speed" : "disconnected");
+		is_vbus_present() ? "full speed" : "disconnected");
 	size -= t;
 	next += t;
 
@@ -1339,7 +1343,7 @@
 		next += t;
 	}
 
-	if (!is_usb_connected() || !dev->driver)
+	if (!is_vbus_present() || !dev->driver)
 		goto done;
 
 	t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
@@ -1454,7 +1458,7 @@
 	UFNRH = UFNRH_SIM;
 
 	/* if hardware supports it, disconnect from usb */
-	make_usb_disappear();
+	pullup_off();
 
 	udc_clear_mask_UDCCR(UDCCR_UDE);
 
@@ -1567,7 +1571,7 @@
 	UICR0 &= ~UICR0_IM0;
 
 	/* if hardware supports it, pullup D+ and wait for reset */
-	let_usb_appear();
+	pullup_on();
 }
 
 
@@ -2052,10 +2056,10 @@
 		if (unlikely(udccr & UDCCR_SUSIR)) {
 			udc_ack_int_UDCCR(UDCCR_SUSIR);
 			handled = 1;
-			DBG(DBG_VERBOSE, "USB suspend%s\n", is_usb_connected()
+			DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present()
 				? "" : "+disconnect");
 
-			if (!is_usb_connected())
+			if (!is_vbus_present())
 				stop_activity(dev, dev->driver);
 			else if (dev->gadget.speed != USB_SPEED_UNKNOWN
 					&& dev->driver
@@ -2073,7 +2077,7 @@
 			if (dev->gadget.speed != USB_SPEED_UNKNOWN
 					&& dev->driver
 					&& dev->driver->resume
-					&& is_usb_connected())
+					&& is_vbus_present())
 				dev->driver->resume(&dev->gadget);
 		}
 
@@ -2509,7 +2513,7 @@
 	udc_disable(dev);
 	udc_reinit(dev);
 
-	dev->vbus = is_usb_connected();
+	dev->vbus = is_vbus_present();
 
 	/* irq setup after old hardware state is cleaned up */
 	retval = request_irq(IRQ_USB, pxa2xx_udc_irq,
@@ -2555,6 +2559,12 @@
 
 	return 0;
 }
+
+static void pxa2xx_udc_shutdown(struct device *_dev)
+{
+	pullup_off();
+}
+
 static int __exit pxa2xx_udc_remove(struct device *_dev)
 {
 	struct pxa2xx_udc *dev = dev_get_drvdata(_dev);
@@ -2624,6 +2634,7 @@
 	.name		= "pxa2xx-udc",
 	.bus		= &platform_bus_type,
 	.probe		= pxa2xx_udc_probe,
+	.shutdown	= pxa2xx_udc_shutdown,
 	.remove		= __exit_p(pxa2xx_udc_remove),
 	.suspend	= pxa2xx_udc_suspend,
 	.resume		= pxa2xx_udc_resume,
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 1f3a7d9..d0bc396 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -177,23 +177,23 @@
 
 static struct pxa2xx_udc *the_controller;
 
-/* one GPIO should be used to detect host disconnect */
-static inline int is_usb_connected(void)
+/* one GPIO should be used to detect VBUS from the host */
+static inline int is_vbus_present(void)
 {
 	if (!the_controller->mach->udc_is_connected)
 		return 1;
 	return the_controller->mach->udc_is_connected();
 }
 
-/* one GPIO should force the host to see this device (or not) */
-static inline void make_usb_disappear(void)
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+static inline void pullup_off(void)
 {
 	if (!the_controller->mach->udc_command)
 		return;
 	the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
 
-static inline void let_usb_appear(void)
+static inline void pullup_on(void)
 {
 	if (!the_controller->mach->udc_command)
 		return;