Changeset 33579


Ignore:
Timestamp:
2012-09-28T19:31:22+02:00 (5 years ago)
Author:
kaloz
Message:

USB iso mode fixes

Resolves an issue where isochronouse USB would cause the driver to hang as
well as scheduling issues.


Signed-off-by: Tim Harvey <tharvey@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/cns3xxx/patches-3.3/200-dwc_otg.patch

    r33484 r33579  
    78887888--- /dev/null 
    78897889+++ b/drivers/usb/dwc/otg_hcd.c 
    7890 @@ -0,0 +1,2735 @@ 
     7890@@ -0,0 +1,2752 @@ 
    78917891+/* ========================================================================== 
    78927892+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ 
     
    80578057+       struct list_head        *qtd_item; 
    80588058+       dwc_otg_qtd_t           *qtd; 
    8059 + 
     8059+       unsigned long           flags; 
     8060+ 
     8061+       SPIN_LOCK_IRQSAVE(&hcd->lock, flags); 
    80608062+       list_for_each(qh_item, qh_list) { 
    80618063+               qh = list_entry(qh_item, dwc_otg_qh_t, qh_list_entry); 
     
    80718073+               } 
    80728074+       } 
     8075+       SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags); 
    80738076+} 
    80748077+ 
     
    83148317+       hcd->self.otg_port = 1; 
    83158318+ 
     8319+       /* Integrate TT in root hub, by default this is disbled. */ 
     8320+       hcd->has_tt = 1; 
     8321+ 
    83168322+       /* Initialize the DWC OTG HCD. */ 
    83178323+       dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); 
    83188324+       dwc_otg_hcd->core_if = otg_dev->core_if; 
    83198325+       otg_dev->hcd = dwc_otg_hcd; 
     8326+       init_hcd_usecs(dwc_otg_hcd); 
    83208327+ 
    83218328+       /* */ 
     
    85358542+       struct list_head        *item; 
    85368543+       dwc_otg_qh_t            *qh; 
     8544+       unsigned long flags; 
    85378545+ 
    85388546+       if (!qh_list->next) { 
     
    85448552+       kill_urbs_in_qh_list(hcd, qh_list); 
    85458553+ 
     8554+       SPIN_LOCK_IRQSAVE(&hcd->lock, flags); 
    85468555+       for (item = qh_list->next; item != qh_list; item = qh_list->next) { 
    85478556+               qh = list_entry(item, dwc_otg_qh_t, qh_list_entry); 
    85488557+               dwc_otg_hcd_qh_remove_and_free(hcd, qh); 
    85498558+       } 
     8559+       SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags); 
    85508560+} 
    85518561+ 
     
    88398849+       qh = (dwc_otg_qh_t *)ep->hcpriv; 
    88408850+ 
     8851+       if (urb_qtd == NULL) { 
     8852+               SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); 
     8853+               return 0; 
     8854+       } 
    88418855+#ifdef DEBUG 
    88428856+       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { 
     
    88708884+       dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd, urb_qtd); 
    88718885+       if (urb_qtd == qh->qtd_in_process) { 
     8886+               /* Note that dwc_otg_hcd_qh_deactivate() locks the spin_lock again */ 
     8887+               SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); 
    88728888+               dwc_otg_hcd_qh_deactivate(dwc_otg_hcd, qh, 0); 
    88738889+               qh->channel = NULL; 
    88748890+               qh->qtd_in_process = NULL; 
    8875 +       } else if (list_empty(&qh->qtd_list)) { 
    8876 +               dwc_otg_hcd_qh_remove(dwc_otg_hcd, qh); 
    8877 +       } 
    8878 + 
    8879 +       SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); 
     8891+       } else { 
     8892+               if (list_empty(&qh->qtd_list)) 
     8893+                       dwc_otg_hcd_qh_remove(dwc_otg_hcd, qh); 
     8894+               SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); 
     8895+       } 
    88808896+ 
    88818897+       urb->hcpriv = NULL; 
     
    89298945+done: 
    89308946+       SPIN_UNLOCK_IRQRESTORE(&dwc_otg_hcd->lock, flags); 
    8931 + 
    89328947+} 
    89338948+ 
     
    1008610101+#endif 
    1008710102+ 
     10103+       spin_lock(&hcd->lock); 
    1008810104+       /* Process entries in the periodic ready list. */ 
    1008910105+       qh_ptr = hcd->periodic_sched_ready.next; 
     
    1013410150+               hcd->non_periodic_channels++; 
    1013510151+       } 
     10152+       spin_unlock(&hcd->lock); 
    1013610153+ 
    1013710154+       return ret_val; 
     
    1062610643--- /dev/null 
    1062710644+++ b/drivers/usb/dwc/otg_hcd.h 
    10628 @@ -0,0 +1,647 @@ 
     10645@@ -0,0 +1,652 @@ 
    1062910646+/* ========================================================================== 
    1063010647+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ 
     
    1082610843+       uint16_t                start_split_frame; 
    1082710844+ 
     10845+       u16 speed; 
     10846+       u16 frame_usecs[8]; 
     10847+ 
    1082810848+       /** @} */ 
    1082910849+ 
     
    1092810948+        */ 
    1092910949+       uint16_t                periodic_usecs; 
     10950+ 
     10951+       /* 
     10952+        * Total bandwidth claimed so far for all periodic transfers 
     10953+        * in a frame. 
     10954+        * This will include a mixture of HS and FS transfers. 
     10955+        * Units are microseconds per (micro)frame. 
     10956+        * We have a budget per frame and have to schedule 
     10957+        * transactions accordingly. 
     10958+        * Watch out for the fact that things are actually scheduled for the 
     10959+        * "next frame". 
     10960+        */ 
     10961+       u16 frame_usecs[8]; 
    1093010962+ 
    1093110963+       /** 
     
    1109011122+ 
    1109111123+/* Implemented in dwc_otg_hcd_queue.c */ 
     11124+extern int init_hcd_usecs(dwc_otg_hcd_t *hcd); 
    1109211125+extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t *hcd, struct urb *urb); 
    1109311126+extern void dwc_otg_hcd_qh_init(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, struct urb *urb); 
     
    1113111164+} 
    1113211165+ 
    11133 +/** Removes a QTD from list. 
    11134 + * @param[in] hcd HCD instance. 
    11135 + * @param[in] qtd QTD to remove from list. */ 
    11136 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t *hcd, dwc_otg_qtd_t *qtd) 
    11137 +{ 
    11138 +       unsigned long flags; 
    11139 +       SPIN_LOCK_IRQSAVE(&hcd->lock, flags); 
    11140 +       list_del(&qtd->qtd_list_entry); 
    11141 +       SPIN_UNLOCK_IRQRESTORE(&hcd->lock, flags); 
    11142 +} 
    11143 + 
    1114411166+/** Remove and free a QTD */ 
    1114511167+static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t *hcd, dwc_otg_qtd_t *qtd) 
    1114611168+{ 
    11147 +       dwc_otg_hcd_qtd_remove(hcd, qtd); 
     11169+       list_del(&qtd->qtd_list_entry); 
    1114811170+       dwc_otg_hcd_qtd_free(qtd); 
    1114911171+} 
     
    1127611298--- /dev/null 
    1127711299+++ b/drivers/usb/dwc/otg_hcd_intr.c 
    11278 @@ -0,0 +1,1826 @@ 
     11300@@ -0,0 +1,1828 @@ 
    1127911301+/* ========================================================================== 
    1128011302+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ 
     
    1188511907+       DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); 
    1188611908+ 
     11909+       spin_lock(&hcd->lock); 
    1188711910+       qtd = list_entry(qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); 
    1188811911+ 
     
    1190111924+       qh->channel = NULL; 
    1190211925+       qh->qtd_in_process = NULL; 
     11926+       spin_unlock(&hcd->lock); 
    1190311927+       dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); 
    1190411928+} 
     
    1310513129--- /dev/null 
    1310613130+++ b/drivers/usb/dwc/otg_hcd_queue.c 
    13107 @@ -0,0 +1,713 @@ 
     13131@@ -0,0 +1,794 @@ 
    1310813132+/* ========================================================================== 
    1310913133+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ 
     
    1326313287+       INIT_LIST_HEAD(&qh->qh_list_entry); 
    1326413288+       qh->channel = NULL; 
     13289+       qh->speed = urb->dev->speed; 
    1326513290+ 
    1326613291+       /* FS/LS Enpoint on HS Hub 
     
    1328413309+               /** @todo Account for split transfers in the bus time. */ 
    1328513310+               int bytecount = dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); 
    13286 +               qh->usecs = usb_calc_bus_time(urb->dev->speed, 
     13311+               qh->usecs = NS_TO_US(usb_calc_bus_time(urb->dev->speed, 
    1328713312+                                              usb_pipein(urb->pipe), 
    1328813313+                                              (qh->ep_type == USB_ENDPOINT_XFER_ISOC), 
    13289 +                                              bytecount); 
     13314+                                              bytecount)); 
    1329013315+ 
    1329113316+               /* Start in a slightly future (micro)frame. */ 
     
    1336613391+ 
    1336713392+/** 
    13368 + * Checks that a channel is available for a periodic transfer. 
    13369 + * 
    13370 + * @return 0 if successful, negative error code otherise. 
    13371 + */ 
    13372 +static int periodic_channel_available(dwc_otg_hcd_t *hcd) 
    13373 +{ 
    13374 +       /* 
    13375 +        * Currently assuming that there is a dedicated host channnel for each 
    13376 +        * periodic transaction plus at least one host channel for 
    13377 +        * non-periodic transactions. 
    13378 +        */ 
    13379 +       int status; 
    13380 +       int num_channels; 
    13381 + 
    13382 +       num_channels = hcd->core_if->core_params->host_channels; 
    13383 +       if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) && 
    13384 +           (hcd->periodic_channels < num_channels - 1)) { 
    13385 +               status = 0; 
    13386 +       } 
    13387 +       else { 
    13388 +               DWC_NOTICE("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", 
    13389 +                          __func__, num_channels, hcd->periodic_channels, 
    13390 +                          hcd->non_periodic_channels); 
    13391 +               status = -ENOSPC; 
    13392 +       } 
    13393 + 
    13394 +       return status; 
    13395 +} 
    13396 + 
    13397 +/** 
    13398 + * Checks that there is sufficient bandwidth for the specified QH in the 
    13399 + * periodic schedule. For simplicity, this calculation assumes that all the 
    13400 + * transfers in the periodic schedule may occur in the same (micro)frame. 
    13401 + * 
    13402 + * @param hcd The HCD state structure for the DWC OTG controller. 
    13403 + * @param qh QH containing periodic bandwidth required. 
    13404 + * 
    13405 + * @return 0 if successful, negative error code otherwise. 
    13406 + */ 
    13407 +static int check_periodic_bandwidth(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) 
    13408 +{ 
    13409 +       int             status; 
    13410 +       uint16_t        max_claimed_usecs; 
    13411 + 
    13412 +       status = 0; 
    13413 + 
    13414 +       if (hcd->core_if->core_params->speed == DWC_SPEED_PARAM_HIGH) { 
     13393+ * Microframe scheduler 
     13394+ * track the total use in hcd->frame_usecs 
     13395+ * keep each qh use in qh->frame_usecs 
     13396+ * when surrendering the qh then donate the time back 
     13397+ */ 
     13398+static const u16 max_uframe_usecs[] = { 100, 100, 100, 100, 100, 100, 30, 0 }; 
     13399+ 
     13400+/* 
     13401+ * called from dwc_otg_hcd.c:dwc_otg_hcd_init 
     13402+ */ 
     13403+int init_hcd_usecs(dwc_otg_hcd_t *hcd) 
     13404+{ 
     13405+       int i; 
     13406+ 
     13407+       for (i = 0; i < 8; i++) 
     13408+               hcd->frame_usecs[i] = max_uframe_usecs[i]; 
     13409+ 
     13410+       return 0; 
     13411+} 
     13412+ 
     13413+static int find_single_uframe(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) 
     13414+{ 
     13415+       int i; 
     13416+       u16 utime; 
     13417+       int t_left; 
     13418+       int ret; 
     13419+       int done; 
     13420+ 
     13421+       ret = -1; 
     13422+       utime = qh->usecs; 
     13423+       t_left = utime; 
     13424+       i = 0; 
     13425+       done = 0; 
     13426+       while (done == 0) { 
     13427+               /* At the start hcd->frame_usecs[i] = max_uframe_usecs[i]; */ 
     13428+               if (utime <= hcd->frame_usecs[i]) { 
     13429+                       hcd->frame_usecs[i] -= utime; 
     13430+                       qh->frame_usecs[i] += utime; 
     13431+                       t_left -= utime; 
     13432+                       ret = i; 
     13433+                       done = 1; 
     13434+                       return ret; 
     13435+               } else { 
     13436+                       i++; 
     13437+                       if (i == 8) { 
     13438+                               done = 1; 
     13439+                               ret = -1; 
     13440+                       } 
     13441+               } 
     13442+       } 
     13443+       return ret; 
     13444+} 
     13445+ 
     13446+/* 
     13447+ * use this for FS apps that can span multiple uframes 
     13448+ */ 
     13449+static int find_multi_uframe(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) 
     13450+{ 
     13451+       int i; 
     13452+       int j; 
     13453+       u16 utime; 
     13454+       int t_left; 
     13455+       int ret; 
     13456+       int done; 
     13457+       u16 xtime; 
     13458+ 
     13459+       ret = -1; 
     13460+       utime = qh->usecs; 
     13461+       t_left = utime; 
     13462+       i = 0; 
     13463+       done = 0; 
     13464+loop: 
     13465+       while (done == 0) { 
     13466+               if (hcd->frame_usecs[i] <= 0) { 
     13467+                       i++; 
     13468+                       if (i == 8) { 
     13469+                               done = 1; 
     13470+                               ret = -1; 
     13471+                       } 
     13472+                       goto loop; 
     13473+               } 
     13474+ 
    1341513475+               /* 
    13416 +                * High speed mode. 
    13417 +                * Max periodic usecs is 80% x 125 usec = 100 usec. 
     13476+                * We need n consequtive slots so use j as a start slot. 
     13477+                * j plus j+1 must be enough time (for now) 
    1341813478+                */ 
    13419 +               max_claimed_usecs = 100 - qh->usecs; 
    13420 +       } else { 
    13421 +               /* 
    13422 +                * Full speed mode. 
    13423 +                * Max periodic usecs is 90% x 1000 usec = 900 usec. 
    13424 +                */ 
    13425 +               max_claimed_usecs = 900 - qh->usecs; 
    13426 +       } 
    13427 + 
    13428 +       if (hcd->periodic_usecs > max_claimed_usecs) { 
    13429 +               DWC_NOTICE("%s: already claimed usecs %d, required usecs %d\n", 
    13430 +                          __func__, hcd->periodic_usecs, qh->usecs); 
    13431 +               status = -ENOSPC; 
    13432 +       } 
    13433 + 
    13434 +       return status; 
     13479+               xtime = hcd->frame_usecs[i]; 
     13480+               for (j = i + 1; j < 8; j++) { 
     13481+                       /* 
     13482+                        * if we add this frame remaining time to xtime we may 
     13483+                        * be OK, if not we need to test j for a complete frame. 
     13484+                        */ 
     13485+                       if ((xtime + hcd->frame_usecs[j]) < utime) { 
     13486+                               if (hcd->frame_usecs[j] < max_uframe_usecs[j]) { 
     13487+                                       j = 8; 
     13488+                                       ret = -1; 
     13489+                                       continue; 
     13490+                               } 
     13491+                       } 
     13492+                       if (xtime >= utime) { 
     13493+                               ret = i; 
     13494+                               j = 8;  /* stop loop with a good value ret */ 
     13495+                               continue; 
     13496+                       } 
     13497+                       /* add the frame time to x time */ 
     13498+                       xtime += hcd->frame_usecs[j]; 
     13499+                       /* we must have a fully available next frame or break */ 
     13500+                       if ((xtime < utime) && 
     13501+                           (hcd->frame_usecs[j] == max_uframe_usecs[j])) { 
     13502+                               ret = -1; 
     13503+                               j = 8;  /* stop loop with a bad value ret */ 
     13504+                               continue; 
     13505+                       } 
     13506+               } 
     13507+               if (ret >= 0) { 
     13508+                       t_left = utime; 
     13509+                       for (j = i; (t_left > 0) && (j < 8); j++) { 
     13510+                               t_left -= hcd->frame_usecs[j]; 
     13511+                               if (t_left <= 0) { 
     13512+                                       qh->frame_usecs[j] += 
     13513+                                           hcd->frame_usecs[j] + t_left; 
     13514+                                       hcd->frame_usecs[j] = -t_left; 
     13515+                                       ret = i; 
     13516+                                       done = 1; 
     13517+                               } else { 
     13518+                                       qh->frame_usecs[j] += 
     13519+                                           hcd->frame_usecs[j]; 
     13520+                                       hcd->frame_usecs[j] = 0; 
     13521+                               } 
     13522+                       } 
     13523+               } else { 
     13524+                       i++; 
     13525+                       if (i == 8) { 
     13526+                               done = 1; 
     13527+                               ret = -1; 
     13528+                       } 
     13529+               } 
     13530+       } 
     13531+       return ret; 
     13532+} 
     13533+ 
     13534+static int find_uframe(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) 
     13535+{ 
     13536+       int ret = -1; 
     13537+ 
     13538+       if (qh->speed == USB_SPEED_HIGH) 
     13539+               /* if this is a hs transaction we need a full frame */ 
     13540+               ret = find_single_uframe(hcd, qh); 
     13541+       else 
     13542+               /* FS transaction may need a sequence of frames */ 
     13543+               ret = find_multi_uframe(hcd, qh); 
     13544+ 
     13545+       return ret; 
    1343513546+} 
    1343613547+ 
     
    1346813579+/** 
    1346913580+ * Schedules an interrupt or isochronous transfer in the periodic schedule. 
    13470 + * 
    13471 + * @param hcd The HCD state structure for the DWC OTG controller. 
    13472 + * @param qh QH for the periodic transfer. The QH should already contain the 
    13473 + * scheduling information. 
    13474 + * 
    13475 + * @return 0 if successful, negative error code otherwise. 
    1347613581+ */ 
    1347713582+static int schedule_periodic(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) 
    1347813583+{ 
    13479 +       int status = 0; 
    13480 + 
    13481 +       status = periodic_channel_available(hcd); 
     13584+       int status; 
     13585+       struct usb_bus *bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd)); 
     13586+       int frame; 
     13587+ 
     13588+       status = find_uframe(hcd, qh); 
     13589+       frame = -1; 
     13590+       if (status == 0) { 
     13591+               frame = 7; 
     13592+       } else { 
     13593+               if (status > 0) 
     13594+                       frame = status - 1; 
     13595+       } 
     13596+       /* Set the new frame up */ 
     13597+       if (frame > -1) { 
     13598+               qh->sched_frame &= ~0x7; 
     13599+               qh->sched_frame |= (frame & 7); 
     13600+       } 
     13601+       if (status != -1) 
     13602+               status = 0; 
    1348213603+       if (status) { 
    13483 +               DWC_NOTICE("%s: No host channel available for periodic " 
    13484 +                          "transfer.\n", __func__); 
     13604+               pr_notice("%s: Insufficient periodic bandwidth for " 
     13605+                         "periodic transfer.\n", __func__); 
    1348513606+               return status; 
    1348613607+       } 
    13487 + 
    13488 +       status = check_periodic_bandwidth(hcd, qh); 
    13489 +       if (status) { 
    13490 +               DWC_NOTICE("%s: Insufficient periodic bandwidth for " 
    13491 +                          "periodic transfer.\n", __func__); 
    13492 +               return status; 
    13493 +       } 
    13494 + 
    1349513608+       status = check_max_xfer_size(hcd, qh); 
    1349613609+       if (status) { 
    13497 +               DWC_NOTICE("%s: Channel max transfer size too small " 
    13498 +                           "for periodic transfer.\n", __func__); 
     13610+               pr_notice("%s: Channel max transfer size too small " 
     13611+                         "for periodic transfer.\n", __func__); 
    1349913612+               return status; 
    1350013613+       } 
    13501 + 
    1350213614+       /* Always start in the inactive schedule. */ 
    1350313615+       list_add_tail(&qh->qh_list_entry, &hcd->periodic_sched_inactive); 
    1350413616+ 
    13505 +       /* Reserve the periodic channel. */ 
    13506 +       hcd->periodic_channels++; 
    13507 + 
    1350813617+       /* Update claimed usecs per (micro)frame. */ 
    1350913618+       hcd->periodic_usecs += qh->usecs; 
    1351013619+ 
    13511 +       /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */ 
    13512 +       hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated += qh->usecs / qh->interval; 
    13513 +       if (qh->ep_type == USB_ENDPOINT_XFER_INT) { 
    13514 +               hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs++; 
    13515 +               DWC_DEBUGPL(DBG_HCD, "Scheduled intr: qh %p, usecs %d, period %d\n", 
    13516 +                           qh, qh->usecs, qh->interval); 
    13517 +       } else { 
    13518 +               hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs++; 
    13519 +               DWC_DEBUGPL(DBG_HCD, "Scheduled isoc: qh %p, usecs %d, period %d\n", 
    13520 +                           qh, qh->usecs, qh->interval); 
    13521 +       } 
     13620+       /* 
     13621+        * Update average periodic bandwidth claimed and # periodic reqs for 
     13622+        * usbfs. 
     13623+        */ 
     13624+       bus->bandwidth_allocated += qh->usecs / qh->interval; 
     13625+ 
     13626+       if (qh->ep_type == USB_ENDPOINT_XFER_INT) 
     13627+               bus->bandwidth_int_reqs++; 
     13628+       else 
     13629+               bus->bandwidth_isoc_reqs++; 
    1352213630+ 
    1352313631+       return status; 
     
    1357013678+/** 
    1357113679+ * Removes an interrupt or isochronous transfer from the periodic schedule. 
    13572 + * 
    13573 + * @param hcd The HCD state structure for the DWC OTG controller. 
    13574 + * @param qh QH for the periodic transfer. 
    1357513680+ */ 
    1357613681+static void deschedule_periodic(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) 
    1357713682+{ 
     13683+       struct usb_bus *bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd)); 
     13684+       int i; 
     13685+ 
    1357813686+       list_del_init(&qh->qh_list_entry); 
    13579 + 
    13580 +       /* Release the periodic channel reservation. */ 
    13581 +       hcd->periodic_channels--; 
    13582 + 
    1358313687+       /* Update claimed usecs per (micro)frame. */ 
    1358413688+       hcd->periodic_usecs -= qh->usecs; 
    13585 + 
    13586 +       /* Update average periodic bandwidth claimed and # periodic reqs for usbfs. */ 
    13587 +       hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated -= qh->usecs / qh->interval; 
    13588 + 
    13589 +       if (qh->ep_type == USB_ENDPOINT_XFER_INT) { 
    13590 +               hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs--; 
    13591 +               DWC_DEBUGPL(DBG_HCD, "Descheduled intr: qh %p, usecs %d, period %d\n", 
    13592 +                           qh, qh->usecs, qh->interval); 
    13593 +       } else { 
    13594 +               hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs--; 
    13595 +               DWC_DEBUGPL(DBG_HCD, "Descheduled isoc: qh %p, usecs %d, period %d\n", 
    13596 +                           qh, qh->usecs, qh->interval); 
    13597 +       } 
     13689+       for (i = 0; i < 8; i++) { 
     13690+               hcd->frame_usecs[i] += qh->frame_usecs[i]; 
     13691+               qh->frame_usecs[i] = 0; 
     13692+       } 
     13693+       /* 
     13694+        * Update average periodic bandwidth claimed and # periodic reqs for 
     13695+        * usbfs. 
     13696+        */ 
     13697+       bus->bandwidth_allocated -= qh->usecs / qh->interval; 
     13698+ 
     13699+       if (qh->ep_type == USB_ENDPOINT_XFER_INT) 
     13700+               bus->bandwidth_int_reqs--; 
     13701+       else 
     13702+               bus->bandwidth_isoc_reqs--; 
    1359813703+} 
    1359913704+ 
Note: See TracChangeset for help on using the changeset viewer.