aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2012-07-19 02:05:35 -0400
committerFelipe Balbi <balbi@ti.com>2012-08-03 02:28:26 -0400
commitfca8892ae552668e726ec9dad6ba7a26743e9a09 (patch)
tree67cd1713fbc39eec0934e937926e089eeb0c4ad5 /drivers/usb/dwc3
parent77fa6df82f154535293beb9bc68851f75c2c22cb (diff)
usb: dwc3: ep0: move DATA phase away from on-demand
We uncovered a limitation of this core WRT to the Link Layer Compliance Suite's TD7.06. On that test, host will start a GetDescriptor(DEVICE) standard request, but it will do so only on the SETUP phase, meaning there will *NOT* be any DATA or STATUS phases. The idea of the test is to verify robustness of the IP WRT framing errors, so the test will send a sequence of different SETUP_DPs each with a different framing error and the Suite expects us to be able to receive all SETUP_DPs with no timeouts. This core, has the ability to tell us which phase the host is expecting before we start it. Whenever we receive a TP or DP when no transfers are cached on the internal IP's caches, the IP will generate a XferNotReady event with status informing us (in case of physical ep0/ep1) if it's related to DATA or STATUS phases - SETUP phase is expected to be prestarted. Because we're always waiting for XferNotReady events for DATA and STATUS phases, we will never be able to know that the Host wants to start another SETUP phase instead, which will render us "not compliant" with TD7.06. In order to "fix" the problem we must not rely on XferNotReady events for the DATA phase and try to always pre-start DATA transfers on physical endpoints 0 and 1. If host goes back to SETUP phase from DATA phase we will receive a XferComplete for that phase with TRB's status set to SETUP_PENDING, which is only useful for printing a debugging log as the core expects us to still go through to the STATUS phase, initiate a CONTROL_STATUS TRB just so it completes right away and, only then, we go back to the pending SETUP phase. SNPS has decided to modify the programming model of the core so that on-demand DATA phases will not be supported anymore. Note that this limitation does not affect 2-stage transfers, meaning that if TD7.06 would start a 2-stage transfer instead of a 3-stage transfer, we would receive a "fake" XferNotReady(STATUS) which would complete right after being initiated with SETUP_PENDING status. Other endpoints are also not affected, so we can still use on-demand transfers on Bulk/Isoc/Interrupt endpoints. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/ep0.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 39abc589187a..69d5741a4db0 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -174,6 +174,49 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
174 return 0; 174 return 0;
175 } 175 }
176 176
177 /*
178 * Unfortunately we have uncovered a limitation wrt the Data Phase.
179 *
180 * Section 9.4 says we can wait for the XferNotReady(DATA) event to
181 * come before issueing Start Transfer command, but if we do, we will
182 * miss situations where the host starts another SETUP phase instead of
183 * the DATA phase. Such cases happen at least on TD.7.6 of the Link
184 * Layer Compliance Suite.
185 *
186 * The problem surfaces due to the fact that in case of back-to-back
187 * SETUP packets there will be no XferNotReady(DATA) generated and we
188 * will be stuck waiting for XferNotReady(DATA) forever.
189 *
190 * By looking at tables 9-13 and 9-14 of the Databook, we can see that
191 * it tells us to start Data Phase right away. It also mentions that if
192 * we receive a SETUP phase instead of the DATA phase, core will issue
193 * XferComplete for the DATA phase, before actually initiating it in
194 * the wire, with the TRB's status set to "SETUP_PENDING". Such status
195 * can only be used to print some debugging logs, as the core expects
196 * us to go through to the STATUS phase and start a CONTROL_STATUS TRB,
197 * just so it completes right away, without transferring anything and,
198 * only then, we can go back to the SETUP phase.
199 *
200 * Because of this scenario, SNPS decided to change the programming
201 * model of control transfers and support on-demand transfers only for
202 * the STATUS phase. To fix the issue we have now, we will always wait
203 * for gadget driver to queue the DATA phase's struct usb_request, then
204 * start it right away.
205 *
206 * If we're actually in a 2-stage transfer, we will wait for
207 * XferNotReady(STATUS).
208 */
209 if (dwc->three_stage_setup) {
210 unsigned direction;
211
212 direction = dwc->ep0_expect_in;
213 dwc->ep0state = EP0_DATA_PHASE;
214
215 __dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req);
216
217 dep->flags &= ~DWC3_EP0_DIR_IN;
218 }
219
177 return 0; 220 return 0;
178} 221}
179 222
@@ -707,6 +750,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
707 struct dwc3_trb *trb; 750 struct dwc3_trb *trb;
708 struct dwc3_ep *ep0; 751 struct dwc3_ep *ep0;
709 u32 transferred; 752 u32 transferred;
753 u32 status;
710 u32 length; 754 u32 length;
711 u8 epnum; 755 u8 epnum;
712 756
@@ -719,6 +763,17 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
719 ur = &r->request; 763 ur = &r->request;
720 764
721 trb = dwc->ep0_trb; 765 trb = dwc->ep0_trb;
766
767 status = DWC3_TRB_SIZE_TRBSTS(trb->size);
768 if (status == DWC3_TRBSTS_SETUP_PENDING) {
769 dev_dbg(dwc->dev, "Setup Pending received\n");
770
771 if (r)
772 dwc3_gadget_giveback(ep0, r, -ECONNRESET);
773
774 return;
775 }
776
722 length = trb->size & DWC3_TRB_SIZE_MASK; 777 length = trb->size & DWC3_TRB_SIZE_MASK;
723 778
724 if (dwc->ep0_bounced) { 779 if (dwc->ep0_bounced) {
@@ -755,8 +810,11 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
755{ 810{
756 struct dwc3_request *r; 811 struct dwc3_request *r;
757 struct dwc3_ep *dep; 812 struct dwc3_ep *dep;
813 struct dwc3_trb *trb;
814 u32 status;
758 815
759 dep = dwc->eps[0]; 816 dep = dwc->eps[0];
817 trb = dwc->ep0_trb;
760 818
761 if (!list_empty(&dep->request_list)) { 819 if (!list_empty(&dep->request_list)) {
762 r = next_request(&dep->request_list); 820 r = next_request(&dep->request_list);
@@ -776,6 +834,10 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
776 } 834 }
777 } 835 }
778 836
837 status = DWC3_TRB_SIZE_TRBSTS(trb->size);
838 if (status == DWC3_TRBSTS_SETUP_PENDING)
839 dev_dbg(dwc->dev, "Setup Pending received\n");
840
779 dwc->ep0state = EP0_SETUP_PHASE; 841 dwc->ep0state = EP0_SETUP_PHASE;
780 dwc3_ep0_out_start(dwc); 842 dwc3_ep0_out_start(dwc);
781} 843}