brcm2708: update against latest rpi-3.10.y branch
[openwrt/svn-archive/archive.git] / target / linux / brcm2708 / patches-3.10 / 0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch
1 From 2b66f2f4f07ed87db0e241489d4e93881fe50a85 Mon Sep 17 00:00:00 2001
2 From: P33M <P33M@github.com>
3 Date: Tue, 30 Jul 2013 09:58:48 +0100
4 Subject: [PATCH 085/174] dwc_otg: fiq_split: use TTs with more granularity
5
6 This fixes certain issues with split transaction scheduling.
7
8 - Isochronous multi-packet OUT transactions now hog the TT until
9 they are completed - this prevents hubs aborting transactions
10 if they get a periodic start-split out-of-order
11 - Don't perform TT allocation on non-periodic endpoints - this
12 allows simultaneous use of the TT's bulk/control and periodic
13 transaction buffers
14
15 This commit will mainly affect USB audio playback.
16 ---
17 drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 26 +++++++++++++-------------
18 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 20 ++++++++++++++++----
19 2 files changed, 29 insertions(+), 17 deletions(-)
20
21 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
22 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
23 @@ -1356,6 +1356,7 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
24 {
25 dwc_list_link_t *qh_ptr;
26 dwc_otg_qh_t *qh;
27 + dwc_otg_qtd_t *qtd;
28 int num_channels;
29 dwc_irqflags_t flags;
30 dwc_spinlock_t *channel_lock = hcd->channel_lock;
31 @@ -1379,11 +1380,18 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
32
33 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
34
35 - if(qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh))
36 - {
37 - qh_ptr = DWC_LIST_NEXT(qh_ptr);
38 - g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
39 - continue;
40 + if(qh->do_split) {
41 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
42 + if(!(qh->ep_type == UE_ISOCHRONOUS &&
43 + (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
44 + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {
45 + if(dwc_otg_hcd_allocate_port(hcd, qh))
46 + {
47 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
48 + g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
49 + continue;
50 + }
51 + }
52 }
53
54 if (microframe_schedule) {
55 @@ -1451,18 +1459,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
56 }
57 }
58
59 - if (qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh))
60 - {
61 - g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
62 - qh_ptr = DWC_LIST_NEXT(qh_ptr);
63 - continue;
64 - }
65 -
66 if (microframe_schedule) {
67 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
68 if (hcd->available_host_channels < 1) {
69 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
70 - if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
71 break;
72 }
73 hcd->available_host_channels--;
74 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
75 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
76 @@ -1328,10 +1328,20 @@ static void release_channel(dwc_otg_hcd_
77 #ifdef FIQ_DEBUG
78 int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
79 #endif
80 + int hog_port = 0;
81
82 DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
83 __func__, hc->hc_num, halt_status, hc->xfer_len);
84
85 + if(fiq_split_enable && hc->do_split) {
86 + if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
87 + if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||
88 + hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
89 + hog_port = 1;
90 + }
91 + }
92 + }
93 +
94 switch (halt_status) {
95 case DWC_OTG_HC_XFER_URB_COMPLETE:
96 free_qtd = 1;
97 @@ -1417,12 +1427,14 @@ cleanup:
98 fiq_print(FIQDBG_ERR, "PRTNOTAL");
99 //BUG();
100 }
101 -
102 - hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
103 + if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||
104 + hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {
105 + hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
106 #ifdef FIQ_DEBUG
107 - hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
108 + hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
109 #endif
110 - fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
111 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
112 + }
113 }
114
115 /* Try to queue more transfers now that there's a free channel. */