aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadopenembedded-core-contrib-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch202
1 files changed, 202 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch
new file mode 100644
index 0000000000..7115b152d9
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch
@@ -0,0 +1,202 @@
+From 5424305125492a2417bde7c6d23ee4b84e25f6be Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Date: Fri, 27 Mar 2009 12:52:43 -0700
+Subject: [PATCH] musb_gadget: fix unhandled endpoint 0 IRQs
+
+The gadget EP0 code routinely ignores an interrupt at end of
+the data phase because of musb_g_ep0_giveback() resetting the
+state machine to "idle, waiting for SETUP" phase prematurely.
+
+The driver also prematurely leaves the status phase on
+receiving the SetupEnd interrupt.
+
+As there were still unhandled endpoint 0 interrupts happening
+from time to time after fixing these issues, there turned to
+be yet another culprit: two distinct gadget states collapsed
+into one.
+
+The (missing) state that comes after STATUS IN/OUT states was
+typically indiscernible from them since the corresponding
+interrupts tend to happen within too little period of time
+(due to only a zero-length status packet in between) and so
+they got coalesced; yet this state is not the same as the next
+one which is associated with the reception of a SETUP packet.
+
+Adding this extra state seems to have fixed the rest of the
+unhandled interrupts that generic_interrupt() and
+davinci_interrupt() hid by faking their result and only
+emitting a debug message -- so, stop doing that.
+
+Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
+Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+---
+ drivers/usb/musb/davinci.c | 7 +----
+ drivers/usb/musb/musb_core.c | 8 +-----
+ drivers/usb/musb/musb_core.h | 3 +-
+ drivers/usb/musb/musb_gadget_ep0.c | 45 +++++++++++++++++++++++++++++++----
+ 4 files changed, 43 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
+index 2dc7606..399c435 100644
+--- a/drivers/usb/musb/davinci.c
++++ b/drivers/usb/musb/davinci.c
+@@ -357,12 +357,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+- /* REVISIT we sometimes get unhandled IRQs
+- * (e.g. ep0). not clear why...
+- */
+- if (retval != IRQ_HANDLED)
+- DBG(5, "unhandled? %08x\n", tmp);
+- return IRQ_HANDLED;
++ return retval;
+ }
+
+ int musb_platform_set_mode(struct musb *musb, u8 mode)
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 3019725..a1de43b 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1481,13 +1481,7 @@ static irqreturn_t generic_interrupt(int irq, void *__hci)
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+- /* REVISIT we sometimes get spurious IRQs on g_ep0
+- * not clear why...
+- */
+- if (retval != IRQ_HANDLED)
+- DBG(5, "spurious?\n");
+-
+- return IRQ_HANDLED;
++ return retval;
+ }
+
+ #else
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index adf1806..f56a56c 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -171,7 +171,8 @@ enum musb_h_ep0_state {
+
+ /* peripheral side ep0 states */
+ enum musb_g_ep0_state {
+- MUSB_EP0_STAGE_SETUP, /* idle, waiting for setup */
++ MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */
++ MUSB_EP0_STAGE_SETUP, /* received SETUP */
+ MUSB_EP0_STAGE_TX, /* IN data */
+ MUSB_EP0_STAGE_RX, /* OUT data */
+ MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */
+diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
+index 3f5e30d..ec0e899 100644
+--- a/drivers/usb/musb/musb_gadget_ep0.c
++++ b/drivers/usb/musb/musb_gadget_ep0.c
+@@ -4,6 +4,7 @@
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
++ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+@@ -58,7 +59,8 @@
+ static char *decode_ep0stage(u8 stage)
+ {
+ switch (stage) {
+- case MUSB_EP0_STAGE_SETUP: return "idle";
++ case MUSB_EP0_STAGE_IDLE: return "idle";
++ case MUSB_EP0_STAGE_SETUP: return "setup";
+ case MUSB_EP0_STAGE_TX: return "in";
+ case MUSB_EP0_STAGE_RX: return "out";
+ case MUSB_EP0_STAGE_ACKWAIT: return "wait";
+@@ -628,7 +630,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ musb_writew(regs, MUSB_CSR0,
+ csr & ~MUSB_CSR0_P_SENTSTALL);
+ retval = IRQ_HANDLED;
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ csr = musb_readw(regs, MUSB_CSR0);
+ }
+
+@@ -636,7 +638,18 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ if (csr & MUSB_CSR0_P_SETUPEND) {
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND);
+ retval = IRQ_HANDLED;
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ /* Transition into the early status phase */
++ switch (musb->ep0_state) {
++ case MUSB_EP0_STAGE_TX:
++ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
++ break;
++ case MUSB_EP0_STAGE_RX:
++ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
++ break;
++ default:
++ ERR("SetupEnd came in a wrong ep0stage %s",
++ decode_ep0stage(musb->ep0_state));
++ }
+ csr = musb_readw(regs, MUSB_CSR0);
+ /* NOTE: request may need completion */
+ }
+@@ -697,11 +710,31 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ if (req)
+ musb_g_ep0_giveback(musb, req);
+ }
++
++ /*
++ * In case when several interrupts can get coalesced,
++ * check to see if we've already received a SETUP packet...
++ */
++ if (csr & MUSB_CSR0_RXPKTRDY)
++ goto setup;
++
++ retval = IRQ_HANDLED;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
++ break;
++
++ case MUSB_EP0_STAGE_IDLE:
++ /*
++ * This state is typically (but not always) indiscernible
++ * from the status states since the corresponding interrupts
++ * tend to happen within too little period of time (with only
++ * a zero-length packet in between) and so get coalesced...
++ */
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+ /* FALLTHROUGH */
+
+ case MUSB_EP0_STAGE_SETUP:
++setup:
+ if (csr & MUSB_CSR0_RXPKTRDY) {
+ struct usb_ctrlrequest setup;
+ int handled = 0;
+@@ -783,7 +816,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
+ stall:
+ DBG(3, "stall (%d)\n", handled);
+ musb->ackpend |= MUSB_CSR0_P_SENDSTALL;
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ finish:
+ musb_writew(regs, MUSB_CSR0,
+ musb->ackpend);
+@@ -803,7 +836,7 @@ finish:
+ /* "can't happen" */
+ WARN_ON(1);
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL);
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ break;
+ }
+
+@@ -959,7 +992,7 @@ static int musb_g_ep0_halt(struct usb_ep *e, int value)
+
+ csr |= MUSB_CSR0_P_SENDSTALL;
+ musb_writew(regs, MUSB_CSR0, csr);
+- musb->ep0_state = MUSB_EP0_STAGE_SETUP;
++ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ musb->ackpend = 0;
+ break;
+ default:
+--
+1.6.0.4
+