pandora-libpnd: bump for eventmap changes
[openpandora.oe.git] / recipes / linux / omap3-pandora-kernel / musb-fix-endpoints.diff
1 From: Ajay Kumar Gupta <ajay.gupta@ti.com>
2 To: linux-usb@vger.kernel.org
3 Cc: linux-omap@vger.kernel.org, david-b@pacbell.net, me@felipebalbi.com,
4         Ajay Kumar Gupta <ajay.gupta@ti.com>
5 Subject: [PATCH] MUSB: BULK request on different available endpoints
6 Date:   Tue,  7 Oct 2008 11:12:24 +0530
7
8 Fixes co-working issue of usb serial device with usb/net devices while
9 oter endpoints are free and can be used.This patch implements the policy
10 that if endpoint resources are available then different BULK request goes
11 to different endpoint otherwise they are multiplexed to one reserved
12 endpoint as currently done.
13
14 NAK limit scheme has to be added for multiplexed BULK request scenario
15 to avoid endpoint starvation due to usb/net devices.
16
17 musb->periodic[] flag setting is also updated.It use to set this flag for
18 an endpoint even when only rx or tx is used.Now flag setting is done on
19 rx/tx basis of an endpoint.
20
21 Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
22 ---
23  drivers/usb/musb/musb_host.c |   94 ++++++++++++++++++++++++------------------
24  drivers/usb/musb/musb_host.h |    1 +
25  2 files changed, 55 insertions(+), 40 deletions(-)
26  
27 --- /tmp/musb_host.c    2008-10-07 10:10:49.000000000 +0200
28 +++ git/drivers/usb/musb/musb_host.c    2008-10-07 10:13:59.000000000 +0200
29 @@ -378,27 +378,32 @@
30  
31                 switch (qh->type) {
32  
33 +               case USB_ENDPOINT_XFER_CONTROL:
34 +               case USB_ENDPOINT_XFER_BULK:
35 +                       /* fifo policy for these lists, except that NAKing
36 +                        * should rotate a qh to the end (for fairness).
37 +                        */
38 +                       if (qh->mux == 1) {
39 +                               head = qh->ring.prev;
40 +                               list_del(&qh->ring);
41 +                               kfree(qh);
42 +                               qh = first_qh(head);
43 +                               break;
44 +                       }
45                 case USB_ENDPOINT_XFER_ISOC:
46                 case USB_ENDPOINT_XFER_INT:
47                         /* this is where periodic bandwidth should be
48                          * de-allocated if it's tracked and allocated;
49                          * and where we'd update the schedule tree...
50                          */
51 -                       musb->periodic[ep->epnum] = NULL;
52 +                       if (is_in)
53 +                               musb->periodic[2 * ep->epnum - 2] = NULL;
54 +                       else
55 +                               musb->periodic[2 * ep->epnum - 1] = NULL;
56                         kfree(qh);
57                         qh = NULL;
58                         break;
59  
60 -               case USB_ENDPOINT_XFER_CONTROL:
61 -               case USB_ENDPOINT_XFER_BULK:
62 -                       /* fifo policy for these lists, except that NAKing
63 -                        * should rotate a qh to the end (for fairness).
64 -                        */
65 -                       head = qh->ring.prev;
66 -                       list_del(&qh->ring);
67 -                       kfree(qh);
68 -                       qh = first_qh(head);
69 -                       break;
70                 }
71         }
72         return qh;
73 @@ -1728,22 +1733,9 @@
74         u16                     maxpacket;
75  
76         /* use fixed hardware for control and bulk */
77 -       switch (qh->type) {
78 -       case USB_ENDPOINT_XFER_CONTROL:
79 +       if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
80                 head = &musb->control;
81                 hw_ep = musb->control_ep;
82 -               break;
83 -       case USB_ENDPOINT_XFER_BULK:
84 -               hw_ep = musb->bulk_ep;
85 -               if (is_in)
86 -                       head = &musb->in_bulk;
87 -               else
88 -                       head = &musb->out_bulk;
89 -               break;
90 -       }
91 -       if (head) {
92 -               idle = list_empty(head);
93 -               list_add_tail(&qh->ring, head);
94                 goto success;
95         }
96  
97 @@ -1778,7 +1770,8 @@
98         for (epnum = 1; epnum < musb->nr_endpoints; epnum++) {
99                 int     diff;
100  
101 -               if (musb->periodic[epnum])
102 +               if ((is_in && musb->periodic[2 * epnum - 2]) ||
103 +                       (!is_in && musb->periodic[2 * epnum - 1]))
104                         continue;
105                 hw_ep = &musb->endpoints[epnum];
106                 if (hw_ep == musb->bulk_ep)
107 @@ -1789,19 +1782,36 @@
108                 else
109                         diff = hw_ep->max_packet_sz_tx - maxpacket;
110  
111 -               if (diff > 0 && best_diff > diff) {
112 +               if (diff >= 0 && best_diff > diff) {
113                         best_diff = diff;
114                         best_end = epnum;
115                 }
116         }
117 -       if (best_end < 0)
118 +       /* use bulk reserved ep1 if no other ep is free*/
119 +       if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
120 +               hw_ep = musb->bulk_ep;
121 +               if (is_in)
122 +                       head = &musb->in_bulk;
123 +               else
124 +                       head = &musb->out_bulk;
125 +               goto success;
126 +       } else if (best_end < 0)
127                 return -ENOSPC;
128  
129         idle = 1;
130 +       qh->mux = 0;
131         hw_ep = musb->endpoints + best_end;
132 -       musb->periodic[best_end] = qh;
133 -       DBG(4, "qh %p periodic slot %d\n", qh, best_end);
134 +       if (is_in)
135 +               musb->periodic[2 * best_end - 2] = qh;
136 +       else
137 +               musb->periodic[2 * best_end - 1] = qh;
138 +       DBG(4, "qh %p periodic slot %d%s\n", qh, best_end, is_in ? "Rx" : "Tx");
139  success:
140 +       if (head) {
141 +               idle = list_empty(head);
142 +               list_add_tail(&qh->ring, head);
143 +               qh->mux = 1;
144 +       }
145         qh->hw_ep = hw_ep;
146         qh->hep->hcpriv = qh;
147         if (idle)
148 @@ -2065,11 +2075,13 @@
149                         sched = &musb->control;
150                         break;
151                 case USB_ENDPOINT_XFER_BULK:
152 -                       if (usb_pipein(urb->pipe))
153 -                               sched = &musb->in_bulk;
154 -                       else
155 -                               sched = &musb->out_bulk;
156 -                       break;
157 +                       if (qh->mux == 1) {
158 +                               if (usb_pipein(urb->pipe))
159 +                                       sched = &musb->in_bulk;
160 +                               else
161 +                                       sched = &musb->out_bulk;
162 +                               break;
163 +                       }
164                 default:
165                         /* REVISIT when we get a schedule tree, periodic
166                          * transfers won't always be at the head of a
167 @@ -2131,11 +2143,13 @@
168                 sched = &musb->control;
169                 break;
170         case USB_ENDPOINT_XFER_BULK:
171 -               if (is_in)
172 -                       sched = &musb->in_bulk;
173 -               else
174 -                       sched = &musb->out_bulk;
175 -               break;
176 +               if (qh->mux == 1) {
177 +                       if (is_in)
178 +                               sched = &musb->in_bulk;
179 +                       else
180 +                               sched = &musb->out_bulk;
181 +                       break;
182 +               }
183         case USB_ENDPOINT_XFER_ISOC:
184         case USB_ENDPOINT_XFER_INT:
185                 for (i = 0; i < musb->nr_endpoints; i++) {
186 --- /tmp/musb_host.h    2008-10-07 08:59:38.000000000 +0200
187 +++ git/drivers/usb/musb/musb_host.h    2008-10-07 10:10:54.000000000 +0200
188 @@ -53,7 +53,8 @@
189  
190         struct list_head        ring;           /* of musb_qh */
191         /* struct musb_qh               *next; */       /* for periodic tree */
192 -
193 +       u8          mux;        /* qh multiplexed to hw_ep */
194 +       
195         unsigned                offset;         /* in urb->transfer_buffer */
196         unsigned                segsize;        /* current xfer fragment */
197