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