summaryrefslogtreecommitdiff
path: root/packages/linux/linux-omap/musb-fix-endpoints.diff
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-omap/musb-fix-endpoints.diff')
-rw-r--r--packages/linux/linux-omap/musb-fix-endpoints.diff197
1 files changed, 197 insertions, 0 deletions
diff --git a/packages/linux/linux-omap/musb-fix-endpoints.diff b/packages/linux/linux-omap/musb-fix-endpoints.diff
new file mode 100644
index 0000000000..5d1201f014
--- /dev/null
+++ b/packages/linux/linux-omap/musb-fix-endpoints.diff
@@ -0,0 +1,197 @@
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+To: linux-usb@vger.kernel.org
+Cc: linux-omap@vger.kernel.org, david-b@pacbell.net, me@felipebalbi.com,
+ Ajay Kumar Gupta <ajay.gupta@ti.com>
+Subject: [PATCH] MUSB: BULK request on different available endpoints
+Date: Tue, 7 Oct 2008 11:12:24 +0530
+
+Fixes co-working issue of usb serial device with usb/net devices while
+oter endpoints are free and can be used.This patch implements the policy
+that if endpoint resources are available then different BULK request goes
+to different endpoint otherwise they are multiplexed to one reserved
+endpoint as currently done.
+
+NAK limit scheme has to be added for multiplexed BULK request scenario
+to avoid endpoint starvation due to usb/net devices.
+
+musb->periodic[] flag setting is also updated.It use to set this flag for
+an endpoint even when only rx or tx is used.Now flag setting is done on
+rx/tx basis of an endpoint.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/musb/musb_host.c | 94 ++++++++++++++++++++++++------------------
+ drivers/usb/musb/musb_host.h | 1 +
+ 2 files changed, 55 insertions(+), 40 deletions(-)
+
+--- /tmp/musb_host.c 2008-10-07 10:10:49.000000000 +0200
++++ git/drivers/usb/musb/musb_host.c 2008-10-07 10:13:59.000000000 +0200
+@@ -378,27 +378,32 @@
+
+ switch (qh->type) {
+
++ case USB_ENDPOINT_XFER_CONTROL:
++ case USB_ENDPOINT_XFER_BULK:
++ /* fifo policy for these lists, except that NAKing
++ * should rotate a qh to the end (for fairness).
++ */
++ if (qh->mux == 1) {
++ head = qh->ring.prev;
++ list_del(&qh->ring);
++ kfree(qh);
++ qh = first_qh(head);
++ break;
++ }
+ case USB_ENDPOINT_XFER_ISOC:
+ case USB_ENDPOINT_XFER_INT:
+ /* this is where periodic bandwidth should be
+ * de-allocated if it's tracked and allocated;
+ * and where we'd update the schedule tree...
+ */
+- musb->periodic[ep->epnum] = NULL;
++ if (is_in)
++ musb->periodic[2 * ep->epnum - 2] = NULL;
++ else
++ musb->periodic[2 * ep->epnum - 1] = NULL;
+ kfree(qh);
+ qh = NULL;
+ break;
+
+- case USB_ENDPOINT_XFER_CONTROL:
+- case USB_ENDPOINT_XFER_BULK:
+- /* fifo policy for these lists, except that NAKing
+- * should rotate a qh to the end (for fairness).
+- */
+- head = qh->ring.prev;
+- list_del(&qh->ring);
+- kfree(qh);
+- qh = first_qh(head);
+- break;
+ }
+ }
+ return qh;
+@@ -1728,22 +1733,9 @@
+ u16 maxpacket;
+
+ /* use fixed hardware for control and bulk */
+- switch (qh->type) {
+- case USB_ENDPOINT_XFER_CONTROL:
++ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+ head = &musb->control;
+ hw_ep = musb->control_ep;
+- break;
+- case USB_ENDPOINT_XFER_BULK:
+- hw_ep = musb->bulk_ep;
+- if (is_in)
+- head = &musb->in_bulk;
+- else
+- head = &musb->out_bulk;
+- break;
+- }
+- if (head) {
+- idle = list_empty(head);
+- list_add_tail(&qh->ring, head);
+ goto success;
+ }
+
+@@ -1778,7 +1770,8 @@
+ for (epnum = 1; epnum < musb->nr_endpoints; epnum++) {
+ int diff;
+
+- if (musb->periodic[epnum])
++ if ((is_in && musb->periodic[2 * epnum - 2]) ||
++ (!is_in && musb->periodic[2 * epnum - 1]))
+ continue;
+ hw_ep = &musb->endpoints[epnum];
+ if (hw_ep == musb->bulk_ep)
+@@ -1789,19 +1782,36 @@
+ else
+ diff = hw_ep->max_packet_sz_tx - maxpacket;
+
+- if (diff > 0 && best_diff > diff) {
++ if (diff >= 0 && best_diff > diff) {
+ best_diff = diff;
+ best_end = epnum;
+ }
+ }
+- if (best_end < 0)
++ /* use bulk reserved ep1 if no other ep is free*/
++ if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
++ hw_ep = musb->bulk_ep;
++ if (is_in)
++ head = &musb->in_bulk;
++ else
++ head = &musb->out_bulk;
++ goto success;
++ } else if (best_end < 0)
+ return -ENOSPC;
+
+ idle = 1;
++ qh->mux = 0;
+ hw_ep = musb->endpoints + best_end;
+- musb->periodic[best_end] = qh;
+- DBG(4, "qh %p periodic slot %d\n", qh, best_end);
++ if (is_in)
++ musb->periodic[2 * best_end - 2] = qh;
++ else
++ musb->periodic[2 * best_end - 1] = qh;
++ DBG(4, "qh %p periodic slot %d%s\n", qh, best_end, is_in ? "Rx" : "Tx");
+ success:
++ if (head) {
++ idle = list_empty(head);
++ list_add_tail(&qh->ring, head);
++ qh->mux = 1;
++ }
+ qh->hw_ep = hw_ep;
+ qh->hep->hcpriv = qh;
+ if (idle)
+@@ -2065,11 +2075,13 @@
+ sched = &musb->control;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+- if (usb_pipein(urb->pipe))
+- sched = &musb->in_bulk;
+- else
+- sched = &musb->out_bulk;
+- break;
++ if (qh->mux == 1) {
++ if (usb_pipein(urb->pipe))
++ sched = &musb->in_bulk;
++ else
++ sched = &musb->out_bulk;
++ break;
++ }
+ default:
+ /* REVISIT when we get a schedule tree, periodic
+ * transfers won't always be at the head of a
+@@ -2131,11 +2143,13 @@
+ sched = &musb->control;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+- if (is_in)
+- sched = &musb->in_bulk;
+- else
+- sched = &musb->out_bulk;
+- break;
++ if (qh->mux == 1) {
++ if (is_in)
++ sched = &musb->in_bulk;
++ else
++ sched = &musb->out_bulk;
++ break;
++ }
+ case USB_ENDPOINT_XFER_ISOC:
+ case USB_ENDPOINT_XFER_INT:
+ for (i = 0; i < musb->nr_endpoints; i++) {
+--- /tmp/musb_host.h 2008-10-07 08:59:38.000000000 +0200
++++ git/drivers/usb/musb/musb_host.h 2008-10-07 10:10:54.000000000 +0200
+@@ -53,7 +53,8 @@
+
+ struct list_head ring; /* of musb_qh */
+ /* struct musb_qh *next; */ /* for periodic tree */
+-
++ u8 mux; /* qh multiplexed to hw_ep */
++
+ unsigned offset; /* in urb->transfer_buffer */
+ unsigned segsize; /* current xfer fragment */
+