ixp4xx: remove linux 3.10 support
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0085-dwc_otg-fiq_split-use-TTs-with-more-granularity.patch
1 From fa6cd2944967a33088bc4cb66d1dc0323665b7c6 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/196] 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 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
22 index 3c619b4..c42172f 100644
23 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
24 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
25 @@ -1356,6 +1356,7 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
26  {
27         dwc_list_link_t *qh_ptr;
28         dwc_otg_qh_t *qh;
29 +       dwc_otg_qtd_t *qtd;
30         int num_channels;
31         dwc_irqflags_t flags;
32         dwc_spinlock_t *channel_lock = hcd->channel_lock;
33 @@ -1379,11 +1380,18 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
34  
35                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
36  
37 -               if(qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh))
38 -               {
39 -                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
40 -                       g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
41 -                       continue;
42 +               if(qh->do_split) {
43 +                       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
44 +                       if(!(qh->ep_type == UE_ISOCHRONOUS &&
45 +                                       (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
46 +                                       qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {
47 +                               if(dwc_otg_hcd_allocate_port(hcd, qh))
48 +                               {
49 +                                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
50 +                                       g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
51 +                                       continue;
52 +                               }
53 +                       }
54                 }
55  
56                 if (microframe_schedule) {
57 @@ -1451,18 +1459,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
58                         }
59                 }
60  
61 -               if (qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh))
62 -               {
63 -                       g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
64 -                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
65 -                       continue;
66 -               }
67 -
68                 if (microframe_schedule) {
69                                 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
70                                 if (hcd->available_host_channels < 1) {
71                                         DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
72 -                                       if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
73                                         break;
74                                 }
75                                 hcd->available_host_channels--;
76 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
77 index 488defb..7d521d9 100644
78 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
79 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
80 @@ -1328,10 +1328,20 @@ static void release_channel(dwc_otg_hcd_t * hcd,
81  #ifdef FIQ_DEBUG
82         int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
83  #endif
84 +       int hog_port = 0;
85  
86         DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
87                     __func__, hc->hc_num, halt_status, hc->xfer_len);
88  
89 +       if(fiq_split_enable && hc->do_split) {
90 +               if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
91 +                       if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID || 
92 +                                       hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
93 +                               hog_port = 1;
94 +                       }
95 +               }
96 +       }
97 +
98         switch (halt_status) {
99         case DWC_OTG_HC_XFER_URB_COMPLETE:
100                 free_qtd = 1;
101 @@ -1417,12 +1427,14 @@ cleanup:
102                         fiq_print(FIQDBG_ERR, "PRTNOTAL");
103                         //BUG();
104                 }
105 -
106 -               hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
107 +               if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||
108 +                               hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {
109 +                       hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
110  #ifdef FIQ_DEBUG
111 -               hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
112 +                       hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
113  #endif
114 -               fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
115 +                       fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
116 +               }
117         }
118  
119         /* Try to queue more transfers now that there's a free channel. */
120 -- 
121 1.9.1
122