From f4d4d8daa5a318fd7c3a2ec9b4b0242d3c964221 Mon Sep 17 00:00:00 2001 From: Koen Kooi Date: Tue, 7 Oct 2008 09:14:11 +0000 Subject: linux-omap git: add another MUSB fix --- packages/linux/linux-omap/musb-fix-endpoints.diff | 197 ++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 packages/linux/linux-omap/musb-fix-endpoints.diff (limited to 'packages/linux/linux-omap/musb-fix-endpoints.diff') 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 +To: linux-usb@vger.kernel.org +Cc: linux-omap@vger.kernel.org, david-b@pacbell.net, me@felipebalbi.com, + Ajay Kumar Gupta +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 +--- + 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 */ + -- cgit v1.2.3