aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.10/0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch
diff options
context:
space:
mode:
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.patch115
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. */