From 7b9cc7a2b101cc73f6abe3468441381c98817e54 Mon Sep 17 00:00:00 2001 From: Konrad Leszczynski Date: Fri, 12 Feb 2016 15:21:46 +0000 Subject: [PATCH] usb: dwc3: gadget: give better command return code if Start Transfer command fails, let's try a little harder to figure out why the command failed and give slightly better return codes. This will be usefulf or isochronous endpoints, at least, which could decide to retry a given request. Signed-off-by: Konrad Leszczynski Signed-off-by: Rafal Redzimski Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 4 ++++ drivers/usb/dwc3/gadget.c | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index bbbd1789596e..87df6dd20d23 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -970,6 +970,10 @@ struct dwc3_event_depevt { #define DEPEVT_STATUS_CONTROL_DATA 1 #define DEPEVT_STATUS_CONTROL_STATUS 2 +/* In response to Start Transfer */ +#define DEPEVT_TRANSFER_NO_RESOURCE 1 +#define DEPEVT_TRANSFER_BUS_EXPIRY 2 + u32 parameters:16; } __packed; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 88fd30bf0c46..43efb627d1cf 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -287,12 +287,39 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, do { reg = dwc3_readl(dwc->regs, DWC3_DEPCMD(ep)); if (!(reg & DWC3_DEPCMD_CMDACT)) { + int cmd_status = DWC3_DEPCMD_STATUS(reg); + dwc3_trace(trace_dwc3_gadget, "Command Complete --> %d", - DWC3_DEPCMD_STATUS(reg)); - if (DWC3_DEPCMD_STATUS(reg)) + cmd_status); + + switch (cmd_status) { + case 0: + ret = 0; + break; + case DEPEVT_TRANSFER_NO_RESOURCE: + dwc3_trace(trace_dwc3_gadget, "%s: no resource available"); + ret = -EINVAL; break; - ret = 0; + case DEPEVT_TRANSFER_BUS_EXPIRY: + /* + * SW issues START TRANSFER command to + * isochronous ep with future frame interval. If + * future interval time has already passed when + * core receives the command, it will respond + * with an error status of 'Bus Expiry'. + * + * Instead of always returning -EINVAL, let's + * give a hint to the gadget driver that this is + * the case by returning -EAGAIN. + */ + dwc3_trace(trace_dwc3_gadget, "%s: bus expiry"); + ret = -EAGAIN; + break; + default: + dev_WARN(dwc->dev, "UNKNOWN cmd status\n"); + } + break; } -- 2.39.5