From 0c975dc2eadccd8e3096bbdbc14bc3ea958c382b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 2 Nov 2011 13:30:45 +0100 Subject: [PATCH] --- yaml --- r: 280831 b: refs/heads/master c: 5bdb1dcc63304a407e70020c1118fca1642bebaa h: refs/heads/master i: 280829: 134a104e3b6470b65cd12b9528211ea30dd30a7c 280827: 74e4080672eb69b2fea04d53958a20ec935ca68d 280823: 357058113afac0c5158fcf892cca1c9064b03fdb 280815: 6c5c3f023db568233ffacb81f8374080710a1402 280799: fbecc98576ddff37d40fcae96f32ce4d87da4bad 280767: 6fa1d3f48c41052060004a7ab40d1678286ca317 280703: a58ece8ac8266cd0fd43b64b07031714e55571b9 280575: cd71a68d22357df1cd89122de4b852a9f825e274 v: v3 --- [refs] | 2 +- trunk/drivers/usb/dwc3/core.h | 1 + trunk/drivers/usb/dwc3/ep0.c | 26 +++++++++++++++++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 31b8e04639c5..f2e857ba5dbd 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f0f2b2a2db85f99637376caf25e46623af56acad +refs/heads/master: 5bdb1dcc63304a407e70020c1118fca1642bebaa diff --git a/trunk/drivers/usb/dwc3/core.h b/trunk/drivers/usb/dwc3/core.h index cecff5624af3..dc2db165412b 100644 --- a/trunk/drivers/usb/dwc3/core.h +++ b/trunk/drivers/usb/dwc3/core.h @@ -631,6 +631,7 @@ struct dwc3 { unsigned ep0_bounced:1; unsigned ep0_expect_in:1; unsigned start_config_issued:1; + unsigned delayed_status:1; enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; diff --git a/trunk/drivers/usb/dwc3/ep0.c b/trunk/drivers/usb/dwc3/ep0.c index 333278c56690..314acb289d23 100644 --- a/trunk/drivers/usb/dwc3/ep0.c +++ b/trunk/drivers/usb/dwc3/ep0.c @@ -48,11 +48,14 @@ #include #include +#include #include "core.h" #include "gadget.h" #include "io.h" +static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum); + static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) { switch (state) { @@ -122,6 +125,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, struct dwc3_request *req) { + struct dwc3 *dwc = dep->dwc; + u32 type; int ret = 0; req->request.actual = 0; @@ -140,9 +145,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, * IRQ we were waiting for is long gone. */ if (dep->flags & DWC3_EP_PENDING_REQUEST) { - struct dwc3 *dwc = dep->dwc; unsigned direction; - u32 type; direction = !!(dep->flags & DWC3_EP0_DIR_IN); @@ -162,6 +165,10 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, req->request.dma, req->request.length, type); dep->flags &= ~(DWC3_EP_PENDING_REQUEST | DWC3_EP0_DIR_IN); + + } else if (dwc->delayed_status && (dwc->ep0state == EP0_STATUS_PHASE)) { + dwc->delayed_status = false; + dwc3_ep0_do_control_status(dwc, 1); } return ret; @@ -211,6 +218,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) /* stall is always issued on EP0 */ __dwc3_gadget_ep_set_halt(dep, 1); dep->flags = DWC3_EP_ENABLED; + dwc->delayed_status = false; if (!list_empty(&dep->request_list)) { struct dwc3_request *req; @@ -472,8 +480,10 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) if (!cfg) dwc->dev_state = DWC3_ADDRESS_STATE; break; + default: + ret = -EINVAL; } - return 0; + return ret; } static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) @@ -536,6 +546,9 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, else ret = dwc3_ep0_delegate_req(dwc, ctrl); + if (ret == USB_GADGET_DELAYED_STATUS) + dwc->delayed_status = true; + if (ret >= 0) return; @@ -801,6 +814,13 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, dwc3_ep0_stall_and_restart(dwc); return; } + + if (dwc->delayed_status) { + WARN_ON_ONCE(event->endpoint_number != 1); + dev_vdbg(dwc->dev, "Mass Storage delayed status\n"); + return; + } + dwc3_ep0_do_control_status(dwc, event->endpoint_number); } }