root/src/linux/rt2880/linux-2.6.23/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c

Revision 12433, 20.3 kB (checked in by BrainSlayer, 5 months ago)

fixes usb issues with some devices

Line 
1 /* ==========================================================================
2  * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_hcd_queue.c $
3  * $Revision: 1.5 $
4  * $Date: 2008-12-15 06:51:32 $
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 //#include <asm/arch/lm.h>
51 #include <asm/rt2880/lm.h>
52 //#include <asm/arch/irqs.h>
53 #include <linux/dma-mapping.h>
54
55 #include "dwc_otg_driver.h"
56 #include "dwc_otg_hcd.h"
57 #include "dwc_otg_regs.h"
58
59 /**
60  * This function allocates and initializes a QH.
61  *
62  * @param hcd The HCD state structure for the DWC OTG controller.
63  * @param[in] urb Holds the information about the device/endpoint that we need
64  * to initialize the QH.
65  *
66  * @return Returns pointer to the newly allocated QH, or NULL on error. */
67 dwc_otg_qh_t *dwc_otg_hcd_qh_create (dwc_otg_hcd_t *hcd, struct urb *urb)
68 {
69         dwc_otg_qh_t *qh;
70
71         /* Allocate memory */
72         /** @todo add memflags argument */
73         qh = dwc_otg_hcd_qh_alloc ();
74         if (qh == NULL) {
75                 return NULL;
76         }
77
78         dwc_otg_hcd_qh_init (hcd, qh, urb);
79         return qh;
80 }
81
82 /** Free each QTD in the QH's QTD-list then free the QH.  QH should already be
83  * removed from a list.  QTD list should already be empty if called from URB
84  * Dequeue.
85  *
86  * @param[in] hcd HCD instance.
87  * @param[in] qh The QH to free.
88  */
89 void dwc_otg_hcd_qh_free (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
90 {
91         dwc_otg_qtd_t *qtd;
92         struct list_head *pos;
93         unsigned long flags;
94
95         /* Free each QTD in the QTD list */
96         SPIN_LOCK_IRQSAVE(&hcd->lock, flags)
97         for (pos = qh->qtd_list.next;
98              pos != &qh->qtd_list;
99              pos = qh->qtd_list.next)
100         {
101                 list_del (pos);
102                 qtd = dwc_list_to_qtd (pos);
103                 dwc_otg_hcd_qtd_free (qtd);
104         }
105         SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags)
106
107         if (qh->dw_align_buf) {
108                 dma_free_coherent((dwc_otg_hcd_to_hcd(hcd))->self.controller,
109                                   hcd->core_if->core_params->max_transfer_size,
110                                   qh->dw_align_buf,
111                                   qh->dw_align_buf_dma);
112         }
113        
114         kfree (qh);
115         return;
116 }
117
118 /** Initializes a QH structure.
119  *
120  * @param[in] hcd The HCD state structure for the DWC OTG controller.
121  * @param[in] qh The QH to init.
122  * @param[in] urb Holds the information about the device/endpoint that we need
123  * to initialize the QH. */
124 #define SCHEDULE_SLOP 10
125 void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, struct urb *urb)
126 {
127         char *speed, *type;
128         memset (qh, 0, sizeof (dwc_otg_qh_t));
129
130         /* Initialize QH */
131         switch (usb_pipetype(urb->pipe)) {
132         case PIPE_CONTROL:
133                 qh->ep_type = USB_ENDPOINT_XFER_CONTROL;
134                 break;
135         case PIPE_BULK:
136                 qh->ep_type = USB_ENDPOINT_XFER_BULK;
137                 break;
138         case PIPE_ISOCHRONOUS:
139                 qh->ep_type = USB_ENDPOINT_XFER_ISOC;
140                 break;
141         case PIPE_INTERRUPT:
142                 qh->ep_type = USB_ENDPOINT_XFER_INT;
143                 break;
144         }
145
146         qh->ep_is_in = usb_pipein(urb->pipe) ? 1 : 0;
147
148         qh->data_toggle = DWC_OTG_HC_PID_DATA0;
149         qh->maxp = usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe)));
150 #if 0 /* marklin 20090310 : patch from mobiletechnika */
151         /* Special hook for SQN11x0 */
152         if( (qh->ep_type == USB_ENDPOINT_XFER_BULK)
153                 && (urb->dev->speed == USB_SPEED_HIGH) ) {
154                 struct usb_device_descriptor *desc = &urb->dev->descriptor;
155                 if (desc->idVendor == 0x148e &&
156                         (desc->idProduct == 0x0900 || desc->idProduct == 0x0A00) ) {
157                         if( 256 < dwc_max_packet(qh->maxp) ){
158                                 qh->maxp&= ~0x07FF;
159                                 qh->maxp|= 256;
160                         }
161                         printk("SQN pathed qh->maxp= 0x%x,maxp= 0x%x,%s\n",qh->maxp
162                                         ,usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe)))
163                                         ,qh->ep_is_in?"in":"out");
164                 }
165         }
166 #endif
167         INIT_LIST_HEAD(&qh->qtd_list);
168         INIT_LIST_HEAD(&qh->qh_list_entry);
169         qh->channel = NULL;
170
171         /* FS/LS Enpoint on HS Hub
172          * NOT virtual root hub */
173         qh->do_split = 0;
174         if (((urb->dev->speed == USB_SPEED_LOW) ||
175              (urb->dev->speed == USB_SPEED_FULL)) &&
176             (urb->dev->tt) && (urb->dev->tt->hub->devnum != 1))
177         {
178                 DWC_DEBUGPL(DBG_HCD, "QH init: EP %d: TT found at hub addr %d, for port %d\n",
179                            usb_pipeendpoint(urb->pipe), urb->dev->tt->hub->devnum,
180                            urb->dev->ttport);
181                 qh->do_split = 1;
182         }
183
184         if (qh->ep_type == USB_ENDPOINT_XFER_INT ||
185             qh->ep_type == USB_ENDPOINT_XFER_ISOC) {
186                 /* Compute scheduling parameters once and save them. */
187                 hprt0_data_t hprt;
188
189                 /** @todo Account for split transfers in the bus time. */
190                 int bytecount = dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
191
192                 /* FIXME: work-around patch by Steven */
193                 qh->usecs = NS_TO_US(usb_calc_bus_time(urb->dev->speed,
194                                                usb_pipein(urb->pipe),
195                                                (qh->ep_type == USB_ENDPOINT_XFER_ISOC),
196                                                bytecount));
197
198                 /* Start in a slightly future (micro)frame. */
199                 qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
200                                                      SCHEDULE_SLOP);
201                 qh->interval = urb->interval;
202 #if 0
203                 /* Increase interrupt polling rate for debugging. */
204                 if (qh->ep_type == USB_ENDPOINT_XFER_INT) {
205                         qh->interval = 8;
206                 }
207 #endif         
208                 hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0);
209                 if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
210                     ((urb->dev->speed == USB_SPEED_LOW) ||
211                      (urb->dev->speed == USB_SPEED_FULL))) {
212                         qh->interval *= 8;
213                         qh->sched_frame |= 0x7;
214                         qh->start_split_frame = qh->sched_frame;
215                 }
216
217         }
218
219         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
220         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);
221         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
222                     urb->dev->devnum);
223         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
224                     usb_pipeendpoint(urb->pipe),
225                     usb_pipein(urb->pipe) == USB_DIR_IN ? "IN" : "OUT");
226
227         switch(urb->dev->speed) {
228         case USB_SPEED_LOW:
229                 speed = "low"; 
230                 break;
231         case USB_SPEED_FULL:
232                 speed = "full";
233                 break;
234         case USB_SPEED_HIGH:
235                 speed = "high";
236                 break;
237         default:
238                 speed = "?";   
239                 break;
240         }
241         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);
242        
243         switch (qh->ep_type) {
244         case USB_ENDPOINT_XFER_ISOC:
245                 type = "isochronous";   
246                 break;
247         case USB_ENDPOINT_XFER_INT:
248                 type = "interrupt";     
249                 break;
250         case USB_ENDPOINT_XFER_CONTROL:
251                 type = "control";       
252                 break;
253         case USB_ENDPOINT_XFER_BULK:
254                 type = "bulk"; 
255                 break;
256         default:
257                 type = "?";     
258                 break;
259         }
260         DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n",type);
261        
262 #ifdef DEBUG
263         if (qh->ep_type == USB_ENDPOINT_XFER_INT) {
264                 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
265                             qh->usecs);
266                 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
267                             qh->interval);
268         }
269 #endif 
270         qh->dw_align_buf = NULL;
271         return;
272 }
273
274 /**
275  * Checks that a channel is available for a periodic transfer.
276  *
277  * @return 0 if successful, negative error code otherise.
278  */
279 static int periodic_channel_available(dwc_otg_hcd_t *hcd)
280 {
281         /*
282          * Currently assuming that there is a dedicated host channnel for each
283          * periodic transaction plus at least one host channel for
284          * non-periodic transactions.
285          */
286         int status;
287         int num_channels;
288
289         num_channels = hcd->core_if->core_params->host_channels;
290         if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) &&
291             (hcd->periodic_channels < num_channels - 1)) {
292                 status = 0;
293         }
294         else {
295                 DWC_NOTICE("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
296                            __func__, num_channels, hcd->periodic_channels,
297                            hcd->non_periodic_channels);
298                 status = -ENOSPC;
299         }
300
301         return status;
302 }
303
304 /**
305  * Checks that there is sufficient bandwidth for the specified QH in the
306  * periodic schedule. For simplicity, this calculation assumes that all the
307  * transfers in the periodic schedule may occur in the same (micro)frame.
308  *
309  * @param hcd The HCD state structure for the DWC OTG controller.
310  * @param qh QH containing periodic bandwidth required.
311  *
312  * @return 0 if successful, negative error code otherwise.
313  */
314 static int check_periodic_bandwidth(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
315 {
316         int             status;
317         uint16_t        max_claimed_usecs;
318
319         status = 0;
320
321         if (hcd->core_if->core_params->speed == DWC_SPEED_PARAM_HIGH) {
322                 /*
323                  * High speed mode.
324                  * Max periodic usecs is 80% x 125 usec = 100 usec.
325                  */
326                 max_claimed_usecs = 100 - qh->usecs;
327         } else {
328                 /*
329                  * Full speed mode.
330                  * Max periodic usecs is 90% x 1000 usec = 900 usec.
331                  */
332                 max_claimed_usecs = 900 - qh->usecs;
333         }
334
335         if (hcd->periodic_usecs > max_claimed_usecs) {
336                 DWC_NOTICE("%s: already claimed usecs %d, required usecs %d\n",
337                            __func__, hcd->periodic_usecs, qh->usecs);
338                 status = -ENOSPC;
339         }
340
341         return status;
342 }
343                        
344 /**
345  * Checks that the max transfer size allowed in a host channel is large enough
346  * to handle the maximum data transfer in a single (micro)frame for a periodic
347  * transfer.
348  *
349  * @param hcd The HCD state structure for the DWC OTG controller.
350  * @param qh QH for a periodic endpoint.
351  *
352  * @return 0 if successful, negative error code otherwise.
353  */
354 static int check_max_xfer_size(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
355 {
356         int             status;
357         uint32_t        max_xfer_size;
358         uint32_t        max_channel_xfer_size;
359
360         status = 0;
361
362         max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
363         max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
364
365         if (max_xfer_size > max_channel_xfer_size) {
366                 DWC_NOTICE("%s: Periodic xfer length %d > "
367                             "max xfer length for channel %d\n",
368                             __func__, max_xfer_size, max_channel_xfer_size);
369                 status = -ENOSPC;
370         }
371
372         return status;
373 }
374
375 /**
376  * Schedules an interrupt or isochronous transfer in the periodic schedule.
377  *
378  * @param hcd The HCD state structure for the DWC OTG controller.
379  * @param qh QH for the periodic transfer. The QH should already contain the
380  * scheduling information.
381  *
382  * @return 0 if successful, negative error code otherwise.
383  */
384 static int schedule_periodic(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
385 {
386         int status = 0;
387
388         status = periodic_channel_available(hcd);
389         if (status) {
390                 DWC_NOTICE("%s: No host channel available for periodic "
391                            "transfer.\n", __func__);
392                 return status;
393         }
394
395         status = check_periodic_bandwidth(hcd, qh);
396         if (status) {
397                 DWC_NOTICE("%s: Insufficient periodic bandwidth for "
398                            "periodic transfer.\n", __func__);
399                 return status;
400         }
401
402         status = check_max_xfer_size(hcd, qh);
403         if (status) {
404                 DWC_NOTICE("%s: Channel max transfer size too small "
405                             "for periodic transfer.\n", __func__);
406                 return status;
407         }
408
409         /* Always start in the inactive schedule. */
410         list_add_tail(&qh->qh_list_entry, &hcd->periodic_sched_inactive);
411
412         /* Reserve the periodic channel. */
413         hcd->periodic_channels++;
414
415         /* Update claimed usecs per (micro)frame. */
416         hcd->periodic_usecs += qh->usecs;
417
418         /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */
419         hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated += qh->usecs / qh->interval;
420         if (qh->ep_type == USB_ENDPOINT_XFER_INT) {
421                 hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs++;
422                 DWC_DEBUGPL(DBG_HCD, "Scheduled intr: qh %p, usecs %d, period %d\n",
423                             qh, qh->usecs, qh->interval);
424         } else {
425                 hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs++;
426                 DWC_DEBUGPL(DBG_HCD, "Scheduled isoc: qh %p, usecs %d, period %d\n",
427                             qh, qh->usecs, qh->interval);
428         }
429                
430         return status;
431 }
432
433 /**
434  * This function adds a QH to either the non periodic or periodic schedule if
435  * it is not already in the schedule. If the QH is already in the schedule, no
436  * action is taken.
437  *
438  * @return 0 if successful, negative error code otherwise.
439  */
440 int dwc_otg_hcd_qh_add (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
441 {
442         unsigned long flags;
443         int status = 0;
444
445         SPIN_LOCK_IRQSAVE(&hcd->lock, flags)
446
447         if (!list_empty(&qh->qh_list_entry)) {
448                 /* QH already in a schedule. */
449                 goto done;
450         }
451
452         /* Add the new QH to the appropriate schedule */
453         if (dwc_qh_is_non_per(qh)) {
454                 /* Always start in the inactive schedule. */
455                 list_add_tail(&qh->qh_list_entry, &hcd->non_periodic_sched_inactive);
456         } else {
457                 status = schedule_periodic(hcd, qh);
458         }
459
460  done:
461         SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags)
462
463         return status;
464 }
465
466 /**
467  * Removes an interrupt or isochronous transfer from the periodic schedule.
468  *
469  * @param hcd The HCD state structure for the DWC OTG controller.
470  * @param qh QH for the periodic transfer.
471  */
472 static void deschedule_periodic(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
473 {
474         list_del_init(&qh->qh_list_entry);
475
476         /* Release the periodic channel reservation. */
477         hcd->periodic_channels--;
478
479         /* Update claimed usecs per (micro)frame. */
480         hcd->periodic_usecs -= qh->usecs;
481
482         /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */
483         hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated -= qh->usecs / qh->interval;
484
485         if (qh->ep_type == USB_ENDPOINT_XFER_INT) {
486                 hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs--;
487                 DWC_DEBUGPL(DBG_HCD, "Descheduled intr: qh %p, usecs %d, period %d\n",
488                             qh, qh->usecs, qh->interval);
489         } else {
490                 hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs--;
491                 DWC_DEBUGPL(DBG_HCD, "Descheduled isoc: qh %p, usecs %d, period %d\n",
492                             qh, qh->usecs, qh->interval);
493         }
494 }
495
496 /**
497  * Removes a QH from either the non-periodic or periodic schedule.  Memory is
498  * not freed.
499  *
500  * @param[in] hcd The HCD state structure.
501  * @param[in] qh QH to remove from schedule. */
502 void dwc_otg_hcd_qh_remove (dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
503 {
504         unsigned long flags;
505
506         SPIN_LOCK_IRQSAVE(&hcd->lock, flags);
507
508         if (list_empty(&qh->qh_list_entry)) {
509                 /* QH is not in a schedule. */
510                 goto done;
511         }
512
513         if (dwc_qh_is_non_per(qh)) {
514                 if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
515                         hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
516                 }
517                 list_del_init(&qh->qh_list_entry);
518         } else {
519                 deschedule_periodic(hcd, qh);
520         }
521
522  done:
523         SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags)
524 }
525
526 /**
527  * Deactivates a QH. For non-periodic QHs, removes the QH from the active
528  * non-periodic schedule. The QH is added to the inactive non-periodic
529  * schedule if any QTDs are still attached to the QH.
530  *
531  * For periodic QHs, the QH is removed from the periodic queued schedule. If
532  * there are any QTDs still attached to the QH, the QH is added to either the
533  * periodic inactive schedule or the periodic ready schedule and its next
534  * scheduled frame is calculated. The QH is placed in the ready schedule if
535  * the scheduled frame has been reached already. Otherwise it's placed in the
536  * inactive schedule. If there are no QTDs attached to the QH, the QH is
537  * completely removed from the periodic schedule.
538  */
539 void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, int sched_next_periodic_split)
540 {
541         unsigned long flags;
542         SPIN_LOCK_IRQSAVE(&hcd->lock, flags);
543
544         if (dwc_qh_is_non_per(qh)) {
545                 dwc_otg_hcd_qh_remove(hcd, qh);
546                 if (!list_empty(&qh->qtd_list)) {
547                         /* Add back to inactive non-periodic schedule. */
548                         dwc_otg_hcd_qh_add(hcd, qh);
549                 }
550         } else {
551                 uint16_t frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd));
552
553                 if (qh->do_split) {
554                         /* Schedule the next continuing periodic split transfer */
555                         if (sched_next_periodic_split) {
556
557                                 qh->sched_frame = frame_number;
558                                 if (dwc_frame_num_le(frame_number,
559                                                      dwc_frame_num_inc(qh->start_split_frame, 1))) {
560                                         /*
561                                          * Allow one frame to elapse after start
562                                          * split microframe before scheduling
563                                          * complete split, but DONT if we are
564                                          * doing the next start split in the
565                                          * same frame for an ISOC out.
566                                          */
567                                         if ((qh->ep_type != USB_ENDPOINT_XFER_ISOC) || (qh->ep_is_in != 0)) {
568                                                 qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, 1);
569                                         }
570                                 }
571                         } else {
572                                 qh->sched_frame = dwc_frame_num_inc(qh->start_split_frame,
573                                                                      qh->interval);
574                                 if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
575                                         qh->sched_frame = frame_number;
576                                 }
577                                 qh->sched_frame |= 0x7;
578                                 qh->start_split_frame = qh->sched_frame;
579                         }
580                 } else {
581                         qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, qh->interval);
582                         if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
583                                 qh->sched_frame = frame_number;
584                         }
585                 }
586
587                 if (list_empty(&qh->qtd_list)) {
588                         dwc_otg_hcd_qh_remove(hcd, qh);
589                 } else {
590                         /*
591                          * Remove from periodic_sched_queued and move to
592                          * appropriate queue.
593                          */
594                         if (qh->sched_frame == frame_number) {
595                                 list_move(&qh->qh_list_entry,
596                                           &hcd->periodic_sched_ready);
597                         } else {
598                                 list_move(&qh->qh_list_entry,
599                                           &hcd->periodic_sched_inactive);
600                         }
601                 }
602         }
603
604         SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags);
605 }
606
607 /**
608  * This function allocates and initializes a QTD.
609  *
610  * @param[in] urb The URB to create a QTD from.  Each URB-QTD pair will end up
611  * pointing to each other so each pair should have a unique correlation.
612  *
613  * @return Returns pointer to the newly allocated QTD, or NULL on error. */
614 dwc_otg_qtd_t *dwc_otg_hcd_qtd_create (struct urb *urb)
615 {
616         dwc_otg_qtd_t *qtd;
617
618         qtd = dwc_otg_hcd_qtd_alloc ();
619         if (qtd == NULL) {
620                 return NULL;
621         }
622
623         dwc_otg_hcd_qtd_init (qtd, urb);
624         return qtd;
625 }
626
627 /**
628  * Initializes a QTD structure.
629  *
630  * @param[in] qtd The QTD to initialize.
631  * @param[in] urb The URB to use for initialization.  */
632 void dwc_otg_hcd_qtd_init (dwc_otg_qtd_t *qtd, struct urb *urb)
633 {
634         memset (qtd, 0, sizeof (dwc_otg_qtd_t));
635         qtd->urb = urb;
636         if (usb_pipecontrol(urb->pipe)) {
637                 /*
638                  * The only time the QTD data toggle is used is on the data
639                  * phase of control transfers. This phase always starts with
640                  * DATA1.
641                  */
642                 qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
643                 qtd->control_phase = DWC_OTG_CONTROL_SETUP;
644         }
645
646         /* start split */
647         qtd->complete_split = 0;
648         qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
649         qtd->isoc_split_offset = 0;
650
651         /* Store the qtd ptr in the urb to reference what QTD. */
652         urb->hcpriv = qtd;
653         return;
654 }
655
656 /**
657  * This function adds a QTD to the QTD-list of a QH.  It will find the correct
658  * QH to place the QTD into.  If it does not find a QH, then it will create a
659  * new QH. If the QH to which the QTD is added is not currently scheduled, it
660  * is placed into the proper schedule based on its EP type.
661  *
662  * @param[in] qtd The QTD to add
663  * @param[in] dwc_otg_hcd The DWC HCD structure
664  *
665  * @return 0 if successful, negative error code otherwise.
666  */
667 int dwc_otg_hcd_qtd_add (dwc_otg_qtd_t *qtd,
668                          dwc_otg_hcd_t *dwc_otg_hcd)
669 {
670         struct usb_host_endpoint *ep;
671         dwc_otg_qh_t *qh;
672         unsigned long flags;
673         int retval = 0;
674
675         struct urb *urb = qtd->urb;
676
677         SPIN_LOCK_IRQSAVE(&dwc_otg_hcd->lock, flags);
678
679         /*
680          * Get the QH which holds the QTD-list to insert to. Create QH if it
681          * doesn't exist.
682          */
683         ep = dwc_urb_to_endpoint(urb);
684         qh = (dwc_otg_qh_t *)ep->hcpriv;
685         if (qh == NULL) {
686                 qh = dwc_otg_hcd_qh_create (dwc_otg_hcd, urb);
687                 if (qh == NULL) {
688                         goto done;
689                 }
690                 ep->hcpriv = qh;
691         }
692
693         retval = dwc_otg_hcd_qh_add(dwc_otg_hcd, qh);
694         if (retval == 0) {
695                 list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
696         }
697
698  done:
699         SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags);
700
701         return retval;
702 }
703
704 #endif /* DWC_DEVICE_ONLY */
Note: See TracBrowser for help on using the browser.