USB: dwc3: Allocate 3KB FIFO for bulk and isochronous endpoints
Currently dwc3 driver will allocate fifo size of maximum endpoint
packet size for TX endpoints depending on operating speed. Due
to this, double buffering may not work for TX endpoints in both high
speed and superspeed. Hence implement policy that allocates 3KB of
fifo for all bulk and isochronous endpoints irrespective of speed.
Policy is to allocate 3KB for bulk and isochronous endpoints and
allocate maximum packet size for control and interrupt endpoints.
This policy will improve the TX throughput numbers for function
drivers like MTP, mass storage. But side effect is we can't accomodate
more than nine bulk + isochronous endpoints in non QDSS composition
and five bulk + isochronous endpoints in QDSS composition. Otherwise
last interfaces in the USB composition will not work.
CRs-Fixed: 532070
Change-Id: I5e947f21f25fada7829c84eba45980295497cfbc
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 328f6f4..674efb3 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -693,6 +693,7 @@
* @mem: points to start of memory which is used for this struct.
* @hwparams: copy of hwparams registers
* @root: debugfs root folder pointer
+ * @tx_fifo_size: Available RAM size for TX fifo allocation
*/
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
@@ -778,6 +779,7 @@
/* Indicate if software connect was issued by the usb_gadget_driver */
bool softconnect;
void (*notify_event) (struct dwc3 *, unsigned);
+ int tx_fifo_size;
};
/* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d7721dc..f43affb 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -223,6 +223,8 @@
unsigned int vdd_no_vol_level;
unsigned int vdd_low_vol_level;
unsigned int vdd_high_vol_level;
+ unsigned int tx_fifo_size;
+ unsigned int qdss_tx_fifo_size;
bool vbus_active;
bool ext_inuse;
enum dwc3_id_state id_state;
@@ -1028,6 +1030,19 @@
}
EXPORT_SYMBOL(msm_ep_unconfig);
+void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enabled)
+{
+ struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ if (qdss_enabled)
+ dwc->tx_fifo_size = mdwc->qdss_tx_fifo_size;
+ else
+ dwc->tx_fifo_size = mdwc->tx_fifo_size;
+}
+EXPORT_SYMBOL(dwc3_tx_fifo_resize_request);
+
static void dwc3_restart_usb_work(struct work_struct *w)
{
struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
@@ -1490,6 +1505,7 @@
"DWC3_CONTROLLER_POST_RESET_EVENT received\n");
dwc3_msm_qscratch_reg_init(mdwc,
DWC3_CONTROLLER_POST_RESET_EVENT);
+ dwc->tx_fifo_size = mdwc->tx_fifo_size;
break;
default:
dev_dbg(mdwc->dev, "unknown dwc3 event\n");
@@ -2963,6 +2979,17 @@
ret = -ENODEV;
goto disable_hs_ldo;
}
+
+ if (of_property_read_u32(node, "qcom,dwc-usb3-msm-tx-fifo-size",
+ &mdwc->tx_fifo_size))
+ dev_err(&pdev->dev,
+ "unable to read platform data tx fifo size\n");
+
+ if (of_property_read_u32(node, "qcom,dwc-usb3-msm-qdss-tx-fifo-size",
+ &mdwc->qdss_tx_fifo_size))
+ dev_err(&pdev->dev,
+ "unable to read platform data qdss tx fifo size\n");
+
dwc3_set_notifier(&dwc3_msm_notify_event);
/* usb_psy required only for vbus_notifications or charging support */
if (mdwc->ext_xceiv.otg_capability ||
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8cf8a6d..d5dfaca 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -233,6 +233,17 @@
* packets
*/
tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+
+ if (dwc->tx_fifo_size &&
+ (usb_endpoint_xfer_bulk(dep->endpoint.desc)
+ || usb_endpoint_xfer_isoc(dep->endpoint.desc)))
+ /*
+ * Allocate 3KB fifo size for bulk and isochronous TX
+ * endpoints irrespective of speed. For interrupt
+ * endpoint, allocate fifo size of endpoint maxpacket.
+ */
+ tmp = 3 * (1024 + mdwidth);
+
tmp += mdwidth;
fifo_size = DIV_ROUND_UP(tmp, mdwidth);
@@ -242,10 +253,21 @@
dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
dep->name, last_fifo_depth, fifo_size & 0xffff);
+ last_fifo_depth += (fifo_size & 0xffff);
+ if (dwc->tx_fifo_size &&
+ (last_fifo_depth >= dwc->tx_fifo_size)) {
+ /*
+ * Fifo size allocated exceeded available RAM size.
+ * Hence return error.
+ */
+ dev_err(dwc->dev, "Fifosize(%d) > available RAM(%d)\n",
+ last_fifo_depth, dwc->tx_fifo_size);
+ return -ENOMEM;
+ }
+
dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
fifo_size);
- last_fifo_depth += (fifo_size & 0xffff);
}
return 0;