diff options
Diffstat (limited to 'target/linux/brcm2708/patches-3.10/0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch')
-rw-r--r-- | target/linux/brcm2708/patches-3.10/0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.10/0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch b/target/linux/brcm2708/patches-3.10/0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch new file mode 100644 index 0000000000..6d3499dad3 --- /dev/null +++ b/target/linux/brcm2708/patches-3.10/0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch @@ -0,0 +1,115 @@ +From 2b66f2f4f07ed87db0e241489d4e93881fe50a85 Mon Sep 17 00:00:00 2001 +From: P33M <P33M@github.com> +Date: Tue, 30 Jul 2013 09:58:48 +0100 +Subject: [PATCH 085/174] dwc_otg: fiq_split: use TTs with more granularity + +This fixes certain issues with split transaction scheduling. + +- Isochronous multi-packet OUT transactions now hog the TT until + they are completed - this prevents hubs aborting transactions + if they get a periodic start-split out-of-order +- Don't perform TT allocation on non-periodic endpoints - this + allows simultaneous use of the TT's bulk/control and periodic + transaction buffers + +This commit will mainly affect USB audio playback. +--- + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 26 +++++++++++++------------- + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 20 ++++++++++++++++---- + 2 files changed, 29 insertions(+), 17 deletions(-) + +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -1356,6 +1356,7 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s + { + dwc_list_link_t *qh_ptr; + dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *qtd; + int num_channels; + dwc_irqflags_t flags; + dwc_spinlock_t *channel_lock = hcd->channel_lock; +@@ -1379,11 +1380,18 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s + + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); + +- if(qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh)) +- { +- qh_ptr = DWC_LIST_NEXT(qh_ptr); +- g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); +- continue; ++ if(qh->do_split) { ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ if(!(qh->ep_type == UE_ISOCHRONOUS && ++ (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || ++ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) { ++ if(dwc_otg_hcd_allocate_port(hcd, qh)) ++ { ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); ++ continue; ++ } ++ } + } + + if (microframe_schedule) { +@@ -1451,18 +1459,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s + } + } + +- if (qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh)) +- { +- g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); +- qh_ptr = DWC_LIST_NEXT(qh_ptr); +- continue; +- } +- + if (microframe_schedule) { + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + if (hcd->available_host_channels < 1) { + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); +- if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh); + break; + } + hcd->available_host_channels--; +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -1328,10 +1328,20 @@ static void release_channel(dwc_otg_hcd_ + #ifdef FIQ_DEBUG + int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0; + #endif ++ int hog_port = 0; + + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", + __func__, hc->hc_num, halt_status, hc->xfer_len); + ++ if(fiq_split_enable && hc->do_split) { ++ if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) { ++ if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID || ++ hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) { ++ hog_port = 1; ++ } ++ } ++ } ++ + switch (halt_status) { + case DWC_OTG_HC_XFER_URB_COMPLETE: + free_qtd = 1; +@@ -1417,12 +1427,14 @@ cleanup: + fiq_print(FIQDBG_ERR, "PRTNOTAL"); + //BUG(); + } +- +- hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr); ++ if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC || ++ hc->ep_type == DWC_OTG_EP_TYPE_INTR)) { ++ hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr); + #ifdef FIQ_DEBUG +- hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1; ++ hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1; + #endif +- fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp); ++ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp); ++ } + } + + /* Try to queue more transfers now that there's a free channel. */ |