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