summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/usb/dwc3.txt8
-rw-r--r--drivers/usb/dwc3/core.h6
-rw-r--r--drivers/usb/dwc3/gadget.c34
3 files changed, 36 insertions, 12 deletions
diff --git a/Documentation/usb/dwc3.txt b/Documentation/usb/dwc3.txt
index 2f658532b9db..7b590edae145 100644
--- a/Documentation/usb/dwc3.txt
+++ b/Documentation/usb/dwc3.txt
@@ -3,14 +3,6 @@
~~~~~~
Please pick something while reading :)
-- Implement streaming support for BULK endpoints
- Tatyana's patch "usb: Add streams support to the gadget framework"
- introduces streaming support for the gadget driver.
- Every usb_request has new field called stream_id which holds its id.
- Every usb_ep has a field num_supported_strms which describes the max
- number of streams supported (for this ep).
- UAS is AFAIK the only gadget with streaming support.
-
- Convert interrupt handler to per-ep-thread-irq
As it turns out some DWC3-commands ~1ms to complete. Currently we spin
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 502582ce1fc6..c6de53c812a9 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -329,6 +329,7 @@ struct dwc3_event_buffer {
* @interval: the intervall on which the ISOC transfer is started
* @name: a human readable name e.g. ep1out-bulk
* @direction: true for TX, false for RX
+ * @stream_capable: true when streams are enabled
*/
struct dwc3_ep {
struct usb_ep endpoint;
@@ -362,6 +363,7 @@ struct dwc3_ep {
char name[20];
unsigned direction:1;
+ unsigned stream_capable:1;
};
enum dwc3_phy {
@@ -650,6 +652,10 @@ struct dwc3_event_depevt {
#define DEPEVT_STATUS_IOC (1 << 2)
#define DEPEVT_STATUS_LST (1 << 3)
+/* Stream event only */
+#define DEPEVT_STREAMEVT_FOUND 1
+#define DEPEVT_STREAMEVT_NOTFOUND 2
+
/* Control-only Status */
#define DEPEVT_STATUS_CONTROL_SETUP 0
#define DEPEVT_STATUS_CONTROL_DATA 1
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 524ff91bf393..8d8502373db6 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -264,6 +264,12 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
params.param1.depcfg.xfer_complete_enable = true;
params.param1.depcfg.xfer_not_ready_enable = true;
+ if (usb_endpoint_xfer_bulk(desc) && dep->endpoint.max_streams) {
+ params.param1.depcfg.stream_capable = true;
+ params.param1.depcfg.stream_event_enable = true;
+ dep->stream_capable = true;
+ }
+
if (usb_endpoint_xfer_isoc(desc))
params.param1.depcfg.xfer_in_progress_enable = true;
@@ -391,15 +397,16 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
struct dwc3 *dwc = dep->dwc;
u32 reg;
- dep->flags &= ~DWC3_EP_ENABLED;
dwc3_remove_requests(dwc, dep);
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
+ dep->stream_capable = false;
dep->desc = NULL;
dep->type = 0;
+ dep->flags = 0;
return 0;
}
@@ -633,6 +640,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep,
trb.lst = last_one;
}
+ if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
+ trb.sid_sofn = req->request.stream_id;
+
switch (usb_endpoint_type(dep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
@@ -1505,12 +1515,28 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
}
break;
+ case DWC3_DEPEVT_STREAMEVT:
+ if (!usb_endpoint_xfer_bulk(dep->desc)) {
+ dev_err(dwc->dev, "Stream event for non-Bulk %s\n",
+ dep->name);
+ return;
+ }
+
+ switch (event->status) {
+ case DEPEVT_STREAMEVT_FOUND:
+ dev_vdbg(dwc->dev, "Stream %d found and started\n",
+ event->parameters);
+
+ break;
+ case DEPEVT_STREAMEVT_NOTFOUND:
+ /* FALLTHROUGH */
+ default:
+ dev_dbg(dwc->dev, "Couldn't find suitable stream\n");
+ }
+ break;
case DWC3_DEPEVT_RXTXFIFOEVT:
dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name);
break;
- case DWC3_DEPEVT_STREAMEVT:
- dev_dbg(dwc->dev, "%s Stream Event\n", dep->name);
- break;
case DWC3_DEPEVT_EPCMDCMPLT:
dwc3_ep_cmd_compl(dep, event);
break;