Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 325959
b: refs/heads/master
c: fca8892
h: refs/heads/master
i:
  325957: a4e25f9
  325955: 54eb697
  325951: 02fd559
v: v3
  • Loading branch information
Felipe Balbi committed Aug 3, 2012
1 parent 71f1b24 commit e1cba9d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 77fa6df82f154535293beb9bc68851f75c2c22cb
refs/heads/master: fca8892ae552668e726ec9dad6ba7a26743e9a09
62 changes: 62 additions & 0 deletions trunk/drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,49 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
return 0;
}

/*
* Unfortunately we have uncovered a limitation wrt the Data Phase.
*
* Section 9.4 says we can wait for the XferNotReady(DATA) event to
* come before issueing Start Transfer command, but if we do, we will
* miss situations where the host starts another SETUP phase instead of
* the DATA phase. Such cases happen at least on TD.7.6 of the Link
* Layer Compliance Suite.
*
* The problem surfaces due to the fact that in case of back-to-back
* SETUP packets there will be no XferNotReady(DATA) generated and we
* will be stuck waiting for XferNotReady(DATA) forever.
*
* By looking at tables 9-13 and 9-14 of the Databook, we can see that
* it tells us to start Data Phase right away. It also mentions that if
* we receive a SETUP phase instead of the DATA phase, core will issue
* XferComplete for the DATA phase, before actually initiating it in
* the wire, with the TRB's status set to "SETUP_PENDING". Such status
* can only be used to print some debugging logs, as the core expects
* us to go through to the STATUS phase and start a CONTROL_STATUS TRB,
* just so it completes right away, without transferring anything and,
* only then, we can go back to the SETUP phase.
*
* Because of this scenario, SNPS decided to change the programming
* model of control transfers and support on-demand transfers only for
* the STATUS phase. To fix the issue we have now, we will always wait
* for gadget driver to queue the DATA phase's struct usb_request, then
* start it right away.
*
* If we're actually in a 2-stage transfer, we will wait for
* XferNotReady(STATUS).
*/
if (dwc->three_stage_setup) {
unsigned direction;

direction = dwc->ep0_expect_in;
dwc->ep0state = EP0_DATA_PHASE;

__dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req);

dep->flags &= ~DWC3_EP0_DIR_IN;
}

return 0;
}

Expand Down Expand Up @@ -707,6 +750,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
struct dwc3_trb *trb;
struct dwc3_ep *ep0;
u32 transferred;
u32 status;
u32 length;
u8 epnum;

Expand All @@ -719,6 +763,17 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
ur = &r->request;

trb = dwc->ep0_trb;

status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING) {
dev_dbg(dwc->dev, "Setup Pending received\n");

if (r)
dwc3_gadget_giveback(ep0, r, -ECONNRESET);

return;
}

length = trb->size & DWC3_TRB_SIZE_MASK;

if (dwc->ep0_bounced) {
Expand Down Expand Up @@ -755,8 +810,11 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
{
struct dwc3_request *r;
struct dwc3_ep *dep;
struct dwc3_trb *trb;
u32 status;

dep = dwc->eps[0];
trb = dwc->ep0_trb;

if (!list_empty(&dep->request_list)) {
r = next_request(&dep->request_list);
Expand All @@ -776,6 +834,10 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
}
}

status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING)
dev_dbg(dwc->dev, "Setup Pending received\n");

dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
}
Expand Down

0 comments on commit e1cba9d

Please sign in to comment.