diff options
| author | Jack Pham <jackp@codeaurora.org> | 2015-04-20 22:49:35 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:06:36 -0700 |
| commit | f0487e67e5e62f1b4b6a2061896a62742a19d54b (patch) | |
| tree | c443ce4a7cba8737a5d6e8495e9f6a2c6479cf93 | |
| parent | 88ffd6eb9530fa8c9e51ed4ea2411795a83dc2de (diff) | |
usb: dwc3: Adjust TX FIFO allocation
Optimize the dwc3_gadget_resize_tx_fifos() function to better
allocate the per-endpoint FIFOs depending on a number of factors:
- super- or non-super speed
- bulk/isoc with bursting
- reduced RAM (when QDSS uses some internal RAM)
- endpoint enabled in composition
Signed-off-by: Jack Pham <jackp@codeaurora.org>
| -rw-r--r-- | drivers/usb/dwc3/core.h | 2 | ||||
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 46 | ||||
| -rw-r--r-- | drivers/usb/gadget/composite.c | 6 | ||||
| -rw-r--r-- | include/linux/usb/composite.h | 4 |
4 files changed, 44 insertions, 14 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 23a73345958d..c377250c5c9f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -800,6 +800,7 @@ struct dwc3_scratchpad_array { * @err_evt_seen: previous event in queue was erratic error * @usb3_u1u2_disable: if true, disable U1U2 low power modes in Superspeed mode. * @in_lpm: indicates if controller is in low power mode (no clocks) + * @tx_fifo_size: Available RAM size for TX fifo allocation */ struct dwc3 { struct usb_ctrlrequest *ctrl_req; @@ -953,6 +954,7 @@ struct dwc3 { struct dwc3_gadget_events dbg_gadget_events; atomic_t in_lpm; + int tx_fifo_size; }; /* -------------------------------------------------------------------------- */ diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 211014069acb..9a2adb8b8127 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -29,6 +29,7 @@ #include <linux/dma-mapping.h> #include <linux/usb/ch9.h> +#include <linux/usb/composite.h> #include <linux/usb/gadget.h> #include "debug.h" @@ -178,47 +179,53 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) int fifo_size; int mdwidth; int num; + int num_eps; + struct usb_composite_dev *cdev = get_gadget_data(&dwc->gadget); if (!dwc->needs_fifo_resize) return 0; + /* gadget.num_eps never be greater than dwc->num_in_eps */ + num_eps = min_t(int, dwc->num_in_eps, + cdev->config->num_ineps_used + 1); ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); /* MDWIDTH is represented in bits, we need it in bytes */ mdwidth >>= 3; - /* - * FIXME For now we will only allocate 1 wMaxPacketSize space - * for each enabled endpoint, later patches will come to - * improve this algorithm so that we better use the internal - * FIFO space - */ - for (num = 0; num < dwc->num_in_eps; num++) { + dev_dbg(dwc->dev, "%s: num eps: %d\n", __func__, num_eps); + + for (num = 0; num < num_eps; num++) { /* bit0 indicates direction; 1 means IN ep */ struct dwc3_ep *dep = dwc->eps[(num << 1) | 1]; int mult = 1; int tmp; + int max_packet = 1024; - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; + if (!(dep->flags & DWC3_EP_ENABLED)) { + dev_warn(dwc->dev, "ep%dIn not enabled", num); + tmp = max_packet + mdwidth; + goto resize_fifo; + } - if (usb_endpoint_xfer_bulk(dep->endpoint.desc) + if (((dep->endpoint.maxburst > 1) && + usb_endpoint_xfer_bulk(dep->endpoint.desc)) || usb_endpoint_xfer_isoc(dep->endpoint.desc)) mult = 3; - /* * REVISIT: the following assumes we will always have enough * space available on the FIFO RAM for all possible use cases. * Make sure that's true somehow and change FIFO allocation * accordingly. * - * If we have Bulk or Isochronous endpoints, we want - * them to be able to be very, very fast. So we're giving + * If we have Bulk (burst only) or Isochronous endpoints, we + * want them to be able to be very, very fast. So we're giving * those endpoints a fifo_size which is enough for 3 full * packets */ tmp = mult * (dep->endpoint.maxpacket + mdwidth); +resize_fifo: tmp += mdwidth; fifo_size = DIV_ROUND_UP(tmp, mdwidth); @@ -228,9 +235,20 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) dwc3_trace(trace_dwc3_gadget, "%s: Fifo Addr %04x Size %d", 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(num), fifo_size); - last_fifo_depth += (fifo_size & 0xffff); } return 0; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 50be4fd1d11e..08badc2b23af 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -793,6 +793,8 @@ static int set_config(struct usb_composite_dev *cdev, usb_gadget_set_state(gadget, USB_STATE_CONFIGURED); cdev->config = c; + c->num_ineps_used = 0; + c->num_outeps_used = 0; /* Initialize all interfaces by setting them to altsetting zero. */ for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { @@ -836,6 +838,10 @@ static int set_config(struct usb_composite_dev *cdev, addr = ((ep->bEndpointAddress & 0x80) >> 3) | (ep->bEndpointAddress & 0x0f); set_bit(addr, f->endpoints); + if (usb_endpoint_dir_in(ep)) + c->num_ineps_used++; + else + c->num_outeps_used++; } result = f->set_alt(f, tmp, 0); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index acecf5fa6a63..bc5637ab01df 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -336,6 +336,10 @@ struct usb_configuration { unsigned highspeed:1; unsigned fullspeed:1; struct usb_function *interface[MAX_CONFIG_INTERFACES]; + + /* number of in and out eps used in this configuration */ + int num_ineps_used; + int num_outeps_used; }; int usb_add_config(struct usb_composite_dev *, |
