fcb5ce634a1e0e02621dfb32780e48e31a101a6e
[openwrt.git] / target / linux / lantiq / files / drivers / usb / dwc_otg / dwc_otg_hcd_queue.c
1 /* ==========================================================================
2  * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd_queue.c $
3  * $Revision: 1.1.1.1 $
4  * $Date: 2009-04-17 06:15:34 $
5  * $Change: 537387 $
6  *
7  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9  * otherwise expressly agreed to in writing between Synopsys and you.
10  * 
11  * The Software IS NOT an item of Licensed Software or Licensed Product under
12  * any End User Software License Agreement or Agreement for Licensed Product
13  * with Synopsys or any supplement thereto. You are permitted to use and
14  * redistribute this Software in source and binary forms, with or without
15  * modification, provided that redistributions of source code must retain this
16  * notice. You may not view, use, disclose, copy or distribute this file or
17  * any information contained herein except pursuant to this license grant from
18  * Synopsys. If you do not agree with this notice, including the disclaimer
19  * below, then you are not authorized to use the Software.
20  * 
21  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31  * DAMAGE.
32  * ========================================================================== */
33 #ifndef DWC_DEVICE_ONLY
34
35 /**
36  * @file
37  *
38  * This file contains the functions to manage Queue Heads and Queue
39  * Transfer Descriptors.
40  */
41 #include <linux/kernel.h>
42 #include <linux/module.h>
43 #include <linux/moduleparam.h>
44 #include <linux/init.h>
45 #include <linux/device.h>
46 #include <linux/errno.h>
47 #include <linux/list.h>
48 #include <linux/interrupt.h>
49 #include <linux/string.h>
50
51 #include "dwc_otg_driver.h"
52 #include "dwc_otg_hcd.h"
53 #include "dwc_otg_regs.h"
54
55 /**
56  * This function allocates and initializes a QH.
57  *
58  * @param _hcd The HCD state structure for the DWC OTG controller.
59  * @param[in] _urb Holds the information about the device/endpoint that we need
60  * to initialize the QH.
61  *
62  * @return Returns pointer to the newly allocated QH, or NULL on error. */
63 dwc_otg_qh_t *dwc_otg_hcd_qh_create (dwc_otg_hcd_t *_hcd, struct urb *_urb)
64 {
65         dwc_otg_qh_t *qh;
66
67         /* Allocate memory */
68         /** @todo add memflags argument */
69         qh = dwc_otg_hcd_qh_alloc ();
70         if (qh == NULL) {
71                 return NULL;
72         }
73
74         dwc_otg_hcd_qh_init (_hcd, qh, _urb);
75         return qh;
76 }
77
78 /** Free each QTD in the QH's QTD-list then free the QH.  QH should already be
79  * removed from a list.  QTD list should already be empty if called from URB
80  * Dequeue.
81  *
82  * @param[in] _qh The QH to free.
83  */
84 void dwc_otg_hcd_qh_free (dwc_otg_qh_t *_qh)
85 {
86         dwc_otg_qtd_t *qtd;
87         struct list_head *pos;
88         unsigned long flags;
89
90         /* Free each QTD in the QTD list */
91         local_irq_save (flags);
92         for (pos = _qh->qtd_list.next;
93              pos != &_qh->qtd_list;
94              pos = _qh->qtd_list.next)
95         {
96                 list_del (pos);
97                 qtd = dwc_list_to_qtd (pos);
98                 dwc_otg_hcd_qtd_free (qtd);
99         }
100         local_irq_restore (flags);
101
102         kfree (_qh);
103         return;
104 }
105
106 /** Initializes a QH structure.
107  *
108  * @param[in] _hcd The HCD state structure for the DWC OTG controller.
109  * @param[in] _qh The QH to init.
110  * @param[in] _urb Holds the information about the device/endpoint that we need
111  * to initialize the QH. */
112 #define SCHEDULE_SLOP 10
113 void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, struct urb *_urb)
114 {
115         memset (_qh, 0, sizeof (dwc_otg_qh_t));
116
117         /* Initialize QH */
118         switch (usb_pipetype(_urb->pipe)) {
119         case PIPE_CONTROL:
120                 _qh->ep_type = USB_ENDPOINT_XFER_CONTROL;
121                 break;
122         case PIPE_BULK:
123                 _qh->ep_type = USB_ENDPOINT_XFER_BULK;
124                 break;
125         case PIPE_ISOCHRONOUS:
126                 _qh->ep_type = USB_ENDPOINT_XFER_ISOC;
127                 break;
128         case PIPE_INTERRUPT: 
129                 _qh->ep_type = USB_ENDPOINT_XFER_INT;
130                 break;
131         }
132
133         _qh->ep_is_in = usb_pipein(_urb->pipe) ? 1 : 0;
134
135         _qh->data_toggle = DWC_OTG_HC_PID_DATA0;
136         _qh->maxp = usb_maxpacket(_urb->dev, _urb->pipe, !(usb_pipein(_urb->pipe)));
137         INIT_LIST_HEAD(&_qh->qtd_list);
138         INIT_LIST_HEAD(&_qh->qh_list_entry);
139         _qh->channel = NULL;
140
141         /* FS/LS Enpoint on HS Hub 
142          * NOT virtual root hub */
143         _qh->do_split = 0;
144         _qh->speed = _urb->dev->speed;
145         if (((_urb->dev->speed == USB_SPEED_LOW) || 
146              (_urb->dev->speed == USB_SPEED_FULL)) &&
147                 (_urb->dev->tt) && (_urb->dev->tt->hub) && (_urb->dev->tt->hub->devnum != 1)) {
148                 DWC_DEBUGPL(DBG_HCD, "QH init: EP %d: TT found at hub addr %d, for port %d\n", 
149                            usb_pipeendpoint(_urb->pipe), _urb->dev->tt->hub->devnum, 
150                            _urb->dev->ttport);
151                 _qh->do_split = 1;
152         }
153
154         if (_qh->ep_type == USB_ENDPOINT_XFER_INT ||
155             _qh->ep_type == USB_ENDPOINT_XFER_ISOC) {
156                 /* Compute scheduling parameters once and save them. */
157                 hprt0_data_t hprt;
158
159                 /** @todo Account for split transfers in the bus time. */
160                 int bytecount = dwc_hb_mult(_qh->maxp) * dwc_max_packet(_qh->maxp);
161                 _qh->usecs = NS_TO_US(usb_calc_bus_time(_urb->dev->speed,
162                                                usb_pipein(_urb->pipe),
163                                         (_qh->ep_type == USB_ENDPOINT_XFER_ISOC),bytecount));
164
165                 /* Start in a slightly future (micro)frame. */
166                 _qh->sched_frame = dwc_frame_num_inc(_hcd->frame_number, SCHEDULE_SLOP);
167                 _qh->interval = _urb->interval;
168 #if 0
169                 /* Increase interrupt polling rate for debugging. */
170                 if (_qh->ep_type == USB_ENDPOINT_XFER_INT) {
171                         _qh->interval = 8;
172                 }
173 #endif          
174                 hprt.d32 = dwc_read_reg32(_hcd->core_if->host_if->hprt0);
175                 if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && 
176                     ((_urb->dev->speed == USB_SPEED_LOW) || 
177                      (_urb->dev->speed == USB_SPEED_FULL)))
178                 {
179                         _qh->interval *= 8;
180                         _qh->sched_frame |= 0x7;
181                         _qh->start_split_frame = _qh->sched_frame;
182                 }
183         }
184
185         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
186         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", _qh);
187         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
188                     _urb->dev->devnum);
189         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
190                     usb_pipeendpoint(_urb->pipe),
191                     usb_pipein(_urb->pipe) == USB_DIR_IN ? "IN" : "OUT");
192         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", 
193                     ({ char *speed; switch (_urb->dev->speed) {
194                     case USB_SPEED_LOW: speed = "low";  break;
195                     case USB_SPEED_FULL: speed = "full";        break;
196                     case USB_SPEED_HIGH: speed = "high";        break;
197                     default: speed = "?";       break;
198                     }; speed;}));
199         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n",
200                     ({ char *type; switch (_qh->ep_type) {
201                     case USB_ENDPOINT_XFER_ISOC: type = "isochronous";  break;
202                     case USB_ENDPOINT_XFER_INT: type = "interrupt";     break;
203                     case USB_ENDPOINT_XFER_CONTROL: type = "control";   break;
204                     case USB_ENDPOINT_XFER_BULK: type = "bulk"; break;
205                     default: type = "?";        break;
206                     }; type;}));
207 #ifdef DEBUG
208         if (_qh->ep_type == USB_ENDPOINT_XFER_INT) {
209                 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
210                             _qh->usecs);
211                 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
212                             _qh->interval);
213         }
214 #endif  
215         
216         return;
217 }
218
219 /**
220  * Microframe scheduler
221  * track the total use in hcd->frame_usecs
222  * keep each qh use in qh->frame_usecs
223  * when surrendering the qh then donate the time back
224  */
225 const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
226
227 /*
228  * called from dwc_otg_hcd.c:dwc_otg_hcd_init
229  */
230 int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
231 {
232         int i;
233         for (i=0; i<8; i++) {
234                 _hcd->frame_usecs[i] = max_uframe_usecs[i];
235         }
236         return 0;
237 }
238
239 static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
240 {
241         int i;
242         unsigned short utime;
243         int t_left;
244         int ret;
245         int done;
246
247         ret = -1;
248         utime = _qh->usecs;
249         t_left = utime;
250         i = 0;
251         done = 0;
252         while (done == 0) {
253                 /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
254                 if (utime <= _hcd->frame_usecs[i]) {
255                         _hcd->frame_usecs[i] -= utime;
256                         _qh->frame_usecs[i] += utime;
257                         t_left -= utime;
258                         ret = i;
259                         done = 1;
260                         return ret;
261                 } else {
262                         i++;
263                         if (i == 8) {
264                                 done = 1;
265                                 ret = -1;
266                         }
267                 }
268         }
269         return ret;
270 }
271
272 /*
273  * use this for FS apps that can span multiple uframes
274  */
275 static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
276 {
277         int i;
278         int j;
279         unsigned short utime;
280         int t_left;
281         int ret;
282         int done;
283         unsigned short xtime;
284
285         ret = -1;
286         utime = _qh->usecs;
287         t_left = utime;
288         i = 0;
289         done = 0;
290 loop:
291         while (done == 0) {
292                 if(_hcd->frame_usecs[i] <= 0) {
293                         i++;
294                         if (i == 8) {
295                                 done = 1;
296                                 ret = -1;
297                         }
298                         goto loop;
299                 }
300
301                 /*
302                  * we need n consequtive slots
303                  * so use j as a start slot j plus j+1 must be enough time (for now)
304                  */
305                 xtime= _hcd->frame_usecs[i];
306                 for (j = i+1 ; j < 8 ; j++ ) {
307                         /*
308                          * if we add this frame remaining time to xtime we may
309                          * be OK, if not we need to test j for a complete frame
310                          */
311                         if ((xtime+_hcd->frame_usecs[j]) < utime) {
312                                 if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
313                                         j = 8;
314                                         ret = -1;
315                                         continue;
316                                 }
317                         }
318                         if (xtime >= utime) {
319                                 ret = i;
320                                 j = 8;  /* stop loop with a good value ret */
321                                 continue;
322                         }
323                         /* add the frame time to x time */
324                         xtime += _hcd->frame_usecs[j];
325                         /* we must have a fully available next frame or break */
326                         if ((xtime < utime)
327                             && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
328                                 ret = -1;
329                                 j = 8;  /* stop loop with a bad value ret */
330                                 continue;
331                         }
332                 }
333                 if (ret >= 0) {
334                         t_left = utime;
335                         for (j = i; (t_left>0) && (j < 8); j++ ) {
336                                 t_left -= _hcd->frame_usecs[j];
337                                 if ( t_left <= 0 ) {
338                                         _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
339                                         _hcd->frame_usecs[j]= -t_left;
340                                         ret = i;
341                                         done = 1;
342                                 } else {
343                                         _qh->frame_usecs[j] += _hcd->frame_usecs[j];
344                                         _hcd->frame_usecs[j] = 0;
345                                 }
346                         }
347                 } else {
348                         i++;
349                         if (i == 8) {
350                                 done = 1;
351                                 ret = -1;
352                         }
353                 }
354         }
355         return ret;
356 }
357
358 static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
359 {
360         int ret;
361         ret = -1;
362
363         if (_qh->speed == USB_SPEED_HIGH) {
364                 /* if this is a hs transaction we need a full frame */
365                 ret = find_single_uframe(_hcd, _qh);
366         } else {
367                 /* if this is a fs transaction we may need a sequence of frames */
368                 ret = find_multi_uframe(_hcd, _qh);
369         }
370         return ret;
371 }
372                         
373 /**
374  * Checks that the max transfer size allowed in a host channel is large enough
375  * to handle the maximum data transfer in a single (micro)frame for a periodic
376  * transfer.
377  *
378  * @param _hcd The HCD state structure for the DWC OTG controller.
379  * @param _qh QH for a periodic endpoint.
380  *
381  * @return 0 if successful, negative error code otherwise.
382  */
383 static int check_max_xfer_size(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
384 {
385         int             status;
386         uint32_t        max_xfer_size;
387         uint32_t        max_channel_xfer_size;
388
389         status = 0;
390
391         max_xfer_size = dwc_max_packet(_qh->maxp) * dwc_hb_mult(_qh->maxp);
392         max_channel_xfer_size = _hcd->core_if->core_params->max_transfer_size;
393
394         if (max_xfer_size > max_channel_xfer_size) {
395                 DWC_NOTICE("%s: Periodic xfer length %d > "
396                             "max xfer length for channel %d\n",
397                             __func__, max_xfer_size, max_channel_xfer_size);
398                 status = -ENOSPC;
399         }
400
401         return status;
402 }
403
404 /**
405  * Schedules an interrupt or isochronous transfer in the periodic schedule.
406  *
407  * @param _hcd The HCD state structure for the DWC OTG controller.
408  * @param _qh QH for the periodic transfer. The QH should already contain the
409  * scheduling information.
410  *
411  * @return 0 if successful, negative error code otherwise.
412  */
413 static int schedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
414 {
415         int status = 0;
416
417         int frame;
418         status = find_uframe(_hcd, _qh);
419         frame = -1;
420         if (status == 0) {
421                 frame = 7;
422         } else {
423                 if (status > 0 )
424                         frame = status-1;
425         }
426
427         /* Set the new frame up */
428         if (frame > -1) {
429                 _qh->sched_frame &= ~0x7;
430                 _qh->sched_frame |= (frame & 7);
431         }
432
433         if (status != -1 )
434                 status = 0;
435         if (status) {
436                 DWC_NOTICE("%s: Insufficient periodic bandwidth for "
437                            "periodic transfer.\n", __func__);
438                 return status;
439         }
440
441         status = check_max_xfer_size(_hcd, _qh);
442         if (status) {
443                 DWC_NOTICE("%s: Channel max transfer size too small "
444                             "for periodic transfer.\n", __func__);
445                 return status;
446         }
447
448         /* Always start in the inactive schedule. */
449         list_add_tail(&_qh->qh_list_entry, &_hcd->periodic_sched_inactive);
450
451
452         /* Update claimed usecs per (micro)frame. */
453         _hcd->periodic_usecs += _qh->usecs;
454
455         /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */
456         hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_allocated += _qh->usecs / _qh->interval;
457         if (_qh->ep_type == USB_ENDPOINT_XFER_INT) {
458                 hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_int_reqs++;
459                 DWC_DEBUGPL(DBG_HCD, "Scheduled intr: qh %p, usecs %d, period %d\n",
460                             _qh, _qh->usecs, _qh->interval);
461         } else {
462                 hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_isoc_reqs++;
463                 DWC_DEBUGPL(DBG_HCD, "Scheduled isoc: qh %p, usecs %d, period %d\n",
464                             _qh, _qh->usecs, _qh->interval);
465         }
466                 
467         return status;
468 }
469
470 /**
471  * This function adds a QH to either the non periodic or periodic schedule if
472  * it is not already in the schedule. If the QH is already in the schedule, no
473  * action is taken.
474  *
475  * @return 0 if successful, negative error code otherwise.
476  */
477 int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
478 {
479         unsigned long flags;
480         int status = 0;
481
482         local_irq_save(flags);
483
484         if (!list_empty(&_qh->qh_list_entry)) {
485                 /* QH already in a schedule. */
486                 goto done;
487         }
488
489         /* Add the new QH to the appropriate schedule */
490         if (dwc_qh_is_non_per(_qh)) {
491                 /* Always start in the inactive schedule. */
492                 list_add_tail(&_qh->qh_list_entry, &_hcd->non_periodic_sched_inactive);
493         } else {
494                 status = schedule_periodic(_hcd, _qh);
495         }
496
497  done:
498         local_irq_restore(flags);
499
500         return status;
501 }
502
503 /**
504  * This function adds a QH to the non periodic deferred schedule.
505  *
506  * @return 0 if successful, negative error code otherwise.
507  */
508 int dwc_otg_hcd_qh_add_deferred(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
509 {
510         unsigned long flags;
511         local_irq_save(flags);
512         if (!list_empty(&_qh->qh_list_entry)) {
513                 /* QH already in a schedule. */
514                 goto done;
515         }
516
517         /* Add the new QH to the non periodic deferred schedule */
518         if (dwc_qh_is_non_per(_qh)) {
519                 list_add_tail(&_qh->qh_list_entry,
520                               &_hcd->non_periodic_sched_deferred);
521         }
522 done:
523         local_irq_restore(flags);
524         return 0;
525 }
526
527 /**
528  * Removes an interrupt or isochronous transfer from the periodic schedule.
529  *
530  * @param _hcd The HCD state structure for the DWC OTG controller.
531  * @param _qh QH for the periodic transfer.
532  */
533 static void deschedule_periodic(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
534 {
535         int i;
536         list_del_init(&_qh->qh_list_entry);
537
538
539         /* Update claimed usecs per (micro)frame. */
540         _hcd->periodic_usecs -= _qh->usecs;
541
542         for (i = 0; i < 8; i++) {
543                 _hcd->frame_usecs[i] += _qh->frame_usecs[i];
544                 _qh->frame_usecs[i] = 0;
545         }
546         /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */
547         hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_allocated -= _qh->usecs / _qh->interval;
548
549         if (_qh->ep_type == USB_ENDPOINT_XFER_INT) {
550                 hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_int_reqs--;
551                 DWC_DEBUGPL(DBG_HCD, "Descheduled intr: qh %p, usecs %d, period %d\n",
552                             _qh, _qh->usecs, _qh->interval);
553         } else {
554                 hcd_to_bus(dwc_otg_hcd_to_hcd(_hcd))->bandwidth_isoc_reqs--;
555                 DWC_DEBUGPL(DBG_HCD, "Descheduled isoc: qh %p, usecs %d, period %d\n",
556                             _qh, _qh->usecs, _qh->interval);
557         }
558 }
559
560 /** 
561  * Removes a QH from either the non-periodic or periodic schedule.  Memory is
562  * not freed.
563  *
564  * @param[in] _hcd The HCD state structure.
565  * @param[in] _qh QH to remove from schedule. */
566 void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh)
567 {
568         unsigned long flags;
569
570         local_irq_save(flags);
571
572         if (list_empty(&_qh->qh_list_entry)) {
573                 /* QH is not in a schedule. */
574                 goto done;
575         }
576
577         if (dwc_qh_is_non_per(_qh)) {
578                 if (_hcd->non_periodic_qh_ptr == &_qh->qh_list_entry) {
579                         _hcd->non_periodic_qh_ptr = _hcd->non_periodic_qh_ptr->next;
580                 }
581                 list_del_init(&_qh->qh_list_entry);
582         } else {
583                 deschedule_periodic(_hcd, _qh);
584         }
585
586  done:
587         local_irq_restore(flags);
588 }
589
590 /**
591  * Defers a QH. For non-periodic QHs, removes the QH from the active
592  * non-periodic schedule. The QH is added to the deferred non-periodic
593  * schedule if any QTDs are still attached to the QH.
594  */
595 int dwc_otg_hcd_qh_deferr(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh, int delay)
596 {
597         int deact = 1;
598         unsigned long flags;
599         local_irq_save(flags);
600         if (dwc_qh_is_non_per(_qh)) {
601                 _qh->sched_frame =
602                   dwc_frame_num_inc(_hcd->frame_number,
603                                     delay);
604                 _qh->channel = NULL;
605                 _qh->qtd_in_process = NULL;
606                 deact = 0;
607                 dwc_otg_hcd_qh_remove(_hcd, _qh);
608                 if (!list_empty(&_qh->qtd_list)) {
609                         /* Add back to deferred non-periodic schedule. */
610                         dwc_otg_hcd_qh_add_deferred(_hcd, _qh);
611                 }
612         }
613         local_irq_restore(flags);
614         return deact;
615 }
616
617 /**
618  * Deactivates a QH. For non-periodic QHs, removes the QH from the active
619  * non-periodic schedule. The QH is added to the inactive non-periodic
620  * schedule if any QTDs are still attached to the QH.
621  *
622  * For periodic QHs, the QH is removed from the periodic queued schedule. If
623  * there are any QTDs still attached to the QH, the QH is added to either the
624  * periodic inactive schedule or the periodic ready schedule and its next
625  * scheduled frame is calculated. The QH is placed in the ready schedule if
626  * the scheduled frame has been reached already. Otherwise it's placed in the
627  * inactive schedule. If there are no QTDs attached to the QH, the QH is
628  * completely removed from the periodic schedule.
629  */
630 void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *_hcd, dwc_otg_qh_t *_qh, int sched_next_periodic_split)
631 {
632         unsigned long flags;
633         local_irq_save(flags);
634
635         if (dwc_qh_is_non_per(_qh)) {
636                 dwc_otg_hcd_qh_remove(_hcd, _qh);
637                 if (!list_empty(&_qh->qtd_list)) {
638                         /* Add back to inactive non-periodic schedule. */
639                         dwc_otg_hcd_qh_add(_hcd, _qh);
640                 }
641         } else {
642                 uint16_t frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(_hcd));
643
644                 if (_qh->do_split) {
645                         /* Schedule the next continuing periodic split transfer */
646                         if (sched_next_periodic_split) {
647
648                                 _qh->sched_frame = frame_number;
649                                 if (dwc_frame_num_le(frame_number,
650                                                      dwc_frame_num_inc(_qh->start_split_frame, 1))) {
651                                         /*
652                                          * Allow one frame to elapse after start
653                                          * split microframe before scheduling
654                                          * complete split, but DONT if we are
655                                          * doing the next start split in the
656                                          * same frame for an ISOC out.
657                                          */
658                                         if ((_qh->ep_type != USB_ENDPOINT_XFER_ISOC) || (_qh->ep_is_in != 0)) {
659                                                 _qh->sched_frame = dwc_frame_num_inc(_qh->sched_frame, 1);
660                                         }
661                                 }
662                         } else {
663                                 _qh->sched_frame = dwc_frame_num_inc(_qh->start_split_frame,
664                                                                      _qh->interval);
665                                 if (dwc_frame_num_le(_qh->sched_frame, frame_number)) {
666                                         _qh->sched_frame = frame_number;
667                                 }
668                                 _qh->sched_frame |= 0x7;
669                                 _qh->start_split_frame = _qh->sched_frame;
670                         }
671                 } else {
672                         _qh->sched_frame = dwc_frame_num_inc(_qh->sched_frame, _qh->interval);
673                         if (dwc_frame_num_le(_qh->sched_frame, frame_number)) {
674                                 _qh->sched_frame = frame_number;
675                         }
676                 }
677
678                 if (list_empty(&_qh->qtd_list)) {
679                         dwc_otg_hcd_qh_remove(_hcd, _qh);
680                 } else {
681                         /*
682                          * Remove from periodic_sched_queued and move to
683                          * appropriate queue.
684                          */
685                         if (dwc_frame_num_le(_qh->sched_frame, frame_number)) {
686                                 list_move(&_qh->qh_list_entry,
687                                           &_hcd->periodic_sched_ready);
688                         } else {
689                                 list_move(&_qh->qh_list_entry,
690                                           &_hcd->periodic_sched_inactive);
691                         }
692                 }
693         }
694
695         local_irq_restore(flags);
696 }
697
698 /** 
699  * This function allocates and initializes a QTD. 
700  *
701  * @param[in] _urb The URB to create a QTD from.  Each URB-QTD pair will end up
702  * pointing to each other so each pair should have a unique correlation.
703  *
704  * @return Returns pointer to the newly allocated QTD, or NULL on error. */
705 dwc_otg_qtd_t *dwc_otg_hcd_qtd_create (struct urb *_urb)
706 {
707         dwc_otg_qtd_t *qtd;
708
709         qtd = dwc_otg_hcd_qtd_alloc ();
710         if (qtd == NULL) {
711                 return NULL;
712         }
713
714         dwc_otg_hcd_qtd_init (qtd, _urb);
715         return qtd;
716 }
717
718 /** 
719  * Initializes a QTD structure.
720  *
721  * @param[in] _qtd The QTD to initialize.
722  * @param[in] _urb The URB to use for initialization.  */
723 void dwc_otg_hcd_qtd_init (dwc_otg_qtd_t *_qtd, struct urb *_urb)
724 {
725         memset (_qtd, 0, sizeof (dwc_otg_qtd_t));
726         _qtd->urb = _urb;
727         if (usb_pipecontrol(_urb->pipe)) {
728                 /*
729                  * The only time the QTD data toggle is used is on the data
730                  * phase of control transfers. This phase always starts with
731                  * DATA1.
732                  */
733                 _qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
734                 _qtd->control_phase = DWC_OTG_CONTROL_SETUP;
735         }
736
737         /* start split */
738         _qtd->complete_split = 0;
739         _qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
740         _qtd->isoc_split_offset = 0;
741
742         /* Store the qtd ptr in the urb to reference what QTD. */
743         _urb->hcpriv = _qtd;
744         return;
745 }
746
747 /**
748  * This function adds a QTD to the QTD-list of a QH.  It will find the correct
749  * QH to place the QTD into.  If it does not find a QH, then it will create a
750  * new QH. If the QH to which the QTD is added is not currently scheduled, it
751  * is placed into the proper schedule based on its EP type.
752  *
753  * @param[in] _qtd The QTD to add
754  * @param[in] _dwc_otg_hcd The DWC HCD structure
755  *
756  * @return 0 if successful, negative error code otherwise.
757  */
758 int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * _qtd,  dwc_otg_hcd_t * _dwc_otg_hcd)
759 {
760         struct usb_host_endpoint *ep;
761         dwc_otg_qh_t *qh;
762         unsigned long flags;
763         int retval = 0;
764         struct urb *urb = _qtd->urb;
765
766         local_irq_save(flags);
767
768         /*
769          * Get the QH which holds the QTD-list to insert to. Create QH if it
770          * doesn't exist.
771          */
772         ep = dwc_urb_to_endpoint(urb);
773         qh = (dwc_otg_qh_t *)ep->hcpriv;
774         if (qh == NULL) {
775                 qh = dwc_otg_hcd_qh_create (_dwc_otg_hcd, urb);
776                 if (qh == NULL) {
777                         retval = -1;
778                         goto done;
779                 }
780                 ep->hcpriv = qh;
781         }
782
783         _qtd->qtd_qh_ptr = qh;
784         retval = dwc_otg_hcd_qh_add(_dwc_otg_hcd, qh);
785         if (retval == 0) {
786                 list_add_tail(&_qtd->qtd_list_entry, &qh->qtd_list);
787         }
788
789  done:
790         local_irq_restore(flags);
791         return retval;
792 }
793
794 #endif /* DWC_DEVICE_ONLY */