aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-omap-2.6.27/musb-fix-endpoints.diff
blob: 5d1201f01457346ef769127b712a0f72d294da27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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 */