Hi,

David Brownell wrote:

> Rather than resending, please come up with a new patch resolving the
> various issues noted previously.  Including not just the locking issue
> reported to you by lockdep ...

Fixed that minors and lockdep. I thought I folded the changes into the patch...


>From 0f92f07d1f61bd33f882505f23efad6803e7ef18 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <[EMAIL PROTECTED]>
Date: Sun, 10 Feb 2008 03:29:17 +0300
Subject: [PATCH] Fix the pxa2xx_udc to balance calls to clk_enable/clk_disable

Signed-off-by: Dmitry Baryshkov [EMAIL PROTECTED]
---
 drivers/usb/gadget/pxa2xx_udc.c |   84 +++++++++++++++++++++++----------------
 drivers/usb/gadget/pxa2xx_udc.h |    6 ++-
 2 files changed, 54 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 2900556..8e32d07 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -680,7 +680,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request 
*_req, gfp_t gfp_flags)
 
        /* kickstart this i/o queue? */
        if (list_empty(&ep->queue) && !ep->stopped) {
-               if (ep->desc == 0 /* ep0 */) {
+               if (ep->desc == NULL /* ep0 */) {
                        unsigned        length = _req->length;
 
                        switch (dev->ep0state) {
@@ -734,7 +734,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request 
*_req, gfp_t gfp_flags)
        }
 
        /* pio or dma irq handler advances the queue. */
-       if (likely (req != 0))
+       if (likely (req != NULL))
                list_add_tail(&req->queue, &ep->queue);
        local_irq_restore(flags);
 
@@ -934,20 +934,35 @@ static void udc_disable(struct pxa2xx_udc *);
 /* We disable the UDC -- and its 48 MHz clock -- whenever it's not
  * in active use.
  */
-static int pullup(struct pxa2xx_udc *udc, int is_active)
+static int pullup(struct pxa2xx_udc *udc)
 {
-       is_active = is_active && udc->vbus && udc->pullup;
+       int is_active = udc->vbus && udc->pullup && ! udc->suspended;
        DMSG("%s\n", is_active ? "active" : "inactive");
-       if (is_active)
-               udc_enable(udc);
-       else {
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-                       DMSG("disconnect %s\n", udc->driver
-                               ? udc->driver->driver.name
-                               : "(no driver)");
-                       stop_activity(udc, udc->driver);
+       if (is_active) {
+               if (!udc->active) {
+                       udc->active = 1;
+#ifdef CONFIG_ARCH_PXA
+                       /* Enable clock for USB device */
+                       clk_enable(udc->clk);
+#endif
+                       udc_enable(udc);
                }
-               udc_disable(udc);
+       } else {
+               if (udc->active) {
+                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               DMSG("disconnect %s\n", udc->driver
+                                       ? udc->driver->driver.name
+                                       : "(no driver)");
+                               stop_activity(udc, udc->driver);
+                       }
+                       udc_disable(udc);
+#ifdef CONFIG_ARCH_PXA
+                       /* Disable clock for USB device */
+                       clk_disable(udc->clk);
+#endif
+                       udc->active = 0;
+               }
+
        }
        return 0;
 }
@@ -958,9 +973,9 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget 
*_gadget, int is_active)
        struct pxa2xx_udc       *udc;
 
        udc = container_of(_gadget, struct pxa2xx_udc, gadget);
-       udc->vbus = is_active = (is_active != 0);
+       udc->vbus = (is_active != 0);
        DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
-       pullup(udc, is_active);
+       pullup(udc);
        return 0;
 }
 
@@ -975,9 +990,8 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, 
int is_active)
        if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
                return -EOPNOTSUPP;
 
-       is_active = (is_active != 0);
-       udc->pullup = is_active;
-       pullup(udc, is_active);
+       udc->pullup = (is_active != 0);
+       pullup(udc);
        return 0;
 }
 
@@ -998,7 +1012,7 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = {
 
 static struct pxa2xx_udc memory;
 static int
-udc_seq_show(struct seq_file *m, void *d)
+udc_seq_show(struct seq_file *m, void *_d)
 {
        struct pxa2xx_udc       *dev = m->private;
        unsigned long           flags;
@@ -1145,11 +1159,6 @@ static void udc_disable(struct pxa2xx_udc *dev)
 
        udc_clear_mask_UDCCR(UDCCR_UDE);
 
-#ifdef CONFIG_ARCH_PXA
-        /* Disable clock for USB device */
-       clk_disable(dev->clk);
-#endif
-
        ep0_idle (dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
 }
@@ -1190,11 +1199,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
 {
        udc_clear_mask_UDCCR(UDCCR_UDE);
 
-#ifdef CONFIG_ARCH_PXA
-        /* Enable clock for USB device */
-       clk_enable(dev->clk);
-#endif
-
        /* try to clear these bits before we enable the udc */
        udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
 
@@ -1285,7 +1289,7 @@ fail:
         * for set_configuration as well as eventual disconnect.
         */
        DMSG("registered gadget driver '%s'\n", driver->driver.name);
-       pullup(dev, 1);
+       pullup(dev);
        dump_state(dev);
        return 0;
 }
@@ -1328,7 +1332,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver 
*driver)
                return -EINVAL;
 
        local_irq_disable();
-       pullup(dev, 0);
+       dev->pullup = 0;
+       pullup(dev);
        stop_activity(dev, driver);
        local_irq_enable();
 
@@ -2267,7 +2272,9 @@ static int __exit pxa2xx_udc_remove(struct 
platform_device *pdev)
        if (dev->driver)
                return -EBUSY;
 
-       udc_disable(dev);
+       dev->pullup = 0;
+       pullup(dev);
+
        remove_debug_files(dev);
 
        if (dev->got_irq) {
@@ -2315,10 +2322,15 @@ static int __exit pxa2xx_udc_remove(struct 
platform_device *pdev)
 static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
 {
        struct pxa2xx_udc       *udc = platform_get_drvdata(dev);
+       unsigned long flags;
 
        if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
                WARN("USB host won't detect disconnect!\n");
-       pullup(udc, 0);
+       udc->suspended = 1;
+
+       local_irq_save(flags);
+       pullup(udc);
+       local_irq_restore(flags);
 
        return 0;
 }
@@ -2326,8 +2338,12 @@ static int pxa2xx_udc_suspend(struct platform_device 
*dev, pm_message_t state)
 static int pxa2xx_udc_resume(struct platform_device *dev)
 {
        struct pxa2xx_udc       *udc = platform_get_drvdata(dev);
+       unsigned long flags;
 
-       pullup(udc, 1);
+       udc->suspended = 0;
+       local_irq_save(flags);
+       pullup(udc);
+       local_irq_restore(flags);
 
        return 0;
 }
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index c08b1a2..93586b2 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -119,7 +119,9 @@ struct pxa2xx_udc {
                                                has_cfr : 1,
                                                req_pending : 1,
                                                req_std : 1,
-                                               req_config : 1;
+                                               req_config : 1,
+                                               suspended : 1,
+                                               active : 1;
 
 #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
        struct timer_list                       timer;
@@ -239,7 +241,7 @@ dump_state(struct pxa2xx_udc *dev)
                dev->stats.read.bytes, dev->stats.read.ops);
 
        for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-               if (dev->ep [i].desc == 0)
+               if (dev->ep [i].desc == NULL)
                        continue;
                DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
        }
-- 
1.5.3.8


-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to