aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-02 15:56:33 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-02 15:56:33 -0800
commit3d71769014c55e05b2342b6d9c1464f7fb383322 (patch)
treeb85909f3f949e070bbba86976f81966f180a837c /drivers/usb/dwc3/gadget.c
parentcd70469d084fde198dc07c1a31b8463562228a5a (diff)
parentc2df85ca31645ed3c68c56bd30a3673e034224f1 (diff)
Merge tag 'dwc3-for-v3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
usb: dwc3: changes for v3.4 merge window Here are the changes for v3.4 merge window. It includes a new glue layer for Samsung's Exynos platform, a simplification of memory management on DWC3 driver by using dev_xxx functions, a few optimizations to IRQ handling by dropping memcpy() and using bitshifts, a fix for TI's OMAP5430 TX Fifo Allocation, two fixes on USB2 test mode implementation (one on debugfs and one on ep0), and several minor changes such as whitespace cleanups, simplification of a few parts of the code, decreasing a long delay to something a bit saner, dropping a header which was included twice and so on. The highlight on this merge is the support for Samsung's Exynos platform, increasing the number of different users for this driver to three. Note that Samsung Exynos glue layer will only compile on platforms which provide implementation for the clk API for now. Once Samsung supports pm_runtime, that limitation can be dropped from the Makefile. Conflicts: drivers/usb/dwc3/gadget.c
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c371
1 files changed, 270 insertions, 101 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1009e7e47a2..5255fe975ea 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -54,6 +54,164 @@
#include "gadget.h"
#include "io.h"
+/**
+ * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
+ * @dwc: pointer to our context structure
+ * @mode: the mode to set (J, K SE0 NAK, Force Enable)
+ *
+ * Caller should take care of locking. This function will
+ * return 0 on success or -EINVAL if wrong Test Selector
+ * is passed
+ */
+int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
+{
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_TSTCTRL_MASK;
+
+ switch (mode) {
+ case TEST_J:
+ case TEST_K:
+ case TEST_SE0_NAK:
+ case TEST_PACKET:
+ case TEST_FORCE_EN:
+ reg |= mode << 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ return 0;
+}
+
+/**
+ * dwc3_gadget_set_link_state - Sets USB Link to a particular State
+ * @dwc: pointer to our context structure
+ * @state: the state to put link into
+ *
+ * Caller should take care of locking. This function will
+ * return 0 on success or -ETIMEDOUT.
+ */
+int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
+{
+ int retries = 10000;
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+
+ /* set requested state */
+ reg |= DWC3_DCTL_ULSTCHNGREQ(state);
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ /* wait for a change in DSTS */
+ while (--retries) {
+ reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+
+ if (DWC3_DSTS_USBLNKST(reg) == state)
+ return 0;
+
+ udelay(5);
+ }
+
+ dev_vdbg(dwc->dev, "link state change request timed out\n");
+
+ return -ETIMEDOUT;
+}
+
+/**
+ * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
+ * @dwc: pointer to our context structure
+ *
+ * This function will a best effort FIFO allocation in order
+ * to improve FIFO usage and throughput, while still allowing
+ * us to enable as many endpoints as possible.
+ *
+ * Keep in mind that this operation will be highly dependent
+ * on the configured size for RAM1 - which contains TxFifo -,
+ * the amount of endpoints enabled on coreConsultant tool, and
+ * the width of the Master Bus.
+ *
+ * In the ideal world, we would always be able to satisfy the
+ * following equation:
+ *
+ * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \
+ * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes
+ *
+ * Unfortunately, due to many variables that's not always the case.
+ */
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
+{
+ int last_fifo_depth = 0;
+ int ram1_depth;
+ int fifo_size;
+ int mdwidth;
+ int num;
+
+ if (!dwc->needs_fifo_resize)
+ return 0;
+
+ 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 < DWC3_ENDPOINTS_NUM; num++) {
+ struct dwc3_ep *dep = dwc->eps[num];
+ int fifo_number = dep->number >> 1;
+ int mult = 1;
+ int tmp;
+
+ if (!(dep->number & 1))
+ continue;
+
+ if (!(dep->flags & DWC3_EP_ENABLED))
+ continue;
+
+ if (usb_endpoint_xfer_bulk(dep->desc)
+ || usb_endpoint_xfer_isoc(dep->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
+ * those endpoints a fifo_size which is enough for 3 full
+ * packets
+ */
+ tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+ tmp += mdwidth;
+
+ fifo_size = DIV_ROUND_UP(tmp, mdwidth);
+
+ fifo_size |= (last_fifo_depth << 16);
+
+ dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
+ dep->name, last_fifo_depth, fifo_size & 0xffff);
+
+ dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
+ fifo_size);
+
+ last_fifo_depth += (fifo_size & 0xffff);
+ }
+
+ return 0;
+}
+
void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status)
{
@@ -156,7 +314,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
}
static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
- struct dwc3_trb_hw *trb)
+ struct dwc3_trb *trb)
{
u32 offset = (char *) trb - (char *) dep->trb_pool;
@@ -305,9 +463,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
return ret;
if (!(dep->flags & DWC3_EP_ENABLED)) {
- struct dwc3_trb_hw *trb_st_hw;
- struct dwc3_trb_hw *trb_link_hw;
- struct dwc3_trb trb_link;
+ struct dwc3_trb *trb_st_hw;
+ struct dwc3_trb *trb_link;
ret = dwc3_gadget_set_xfer_resource(dwc, dep);
if (ret)
@@ -327,15 +484,15 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
memset(&trb_link, 0, sizeof(trb_link));
- /* Link TRB for ISOC. The HWO but is never reset */
+ /* Link TRB for ISOC. The HWO bit is never reset */
trb_st_hw = &dep->trb_pool[0];
- trb_link.bplh = dwc3_trb_dma_offset(dep, trb_st_hw);
- trb_link.trbctl = DWC3_TRBCTL_LINK_TRB;
- trb_link.hwo = true;
+ trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1];
- trb_link_hw = &dep->trb_pool[DWC3_TRB_NUM - 1];
- dwc3_trb_to_hw(&trb_link, trb_link_hw);
+ trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
+ trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
+ trb_link->ctrl |= DWC3_TRBCTL_LINK_TRB;
+ trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
}
return 0;
@@ -423,16 +580,16 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
- strncat(dep->name, "-control", sizeof(dep->name));
+ strlcat(dep->name, "-control", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_ISOC:
- strncat(dep->name, "-isoc", sizeof(dep->name));
+ strlcat(dep->name, "-isoc", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_BULK:
- strncat(dep->name, "-bulk", sizeof(dep->name));
+ strlcat(dep->name, "-bulk", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_INT:
- strncat(dep->name, "-int", sizeof(dep->name));
+ strlcat(dep->name, "-int", sizeof(dep->name));
break;
default:
dev_err(dwc->dev, "invalid endpoint transfer type\n");
@@ -522,8 +679,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
unsigned length, unsigned last, unsigned chain)
{
struct dwc3 *dwc = dep->dwc;
- struct dwc3_trb_hw *trb_hw;
- struct dwc3_trb trb;
+ struct dwc3_trb *trb;
unsigned int cur_slot;
@@ -532,7 +688,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
length, last ? " last" : "",
chain ? " chain" : "");
- trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+ trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
cur_slot = dep->free_slot;
dep->free_slot++;
@@ -541,40 +697,32 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
usb_endpoint_xfer_isoc(dep->desc))
return;
- memset(&trb, 0, sizeof(trb));
if (!req->trb) {
dwc3_gadget_move_request_queued(req);
- req->trb = trb_hw;
- req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw);
+ req->trb = trb;
+ req->trb_dma = dwc3_trb_dma_offset(dep, trb);
}
- if (usb_endpoint_xfer_isoc(dep->desc)) {
- trb.isp_imi = true;
- trb.csp = true;
- } else {
- trb.chn = chain;
- trb.lst = last;
- }
-
- if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
- trb.sid_sofn = req->request.stream_id;
+ trb->size = DWC3_TRB_SIZE_LENGTH(length);
+ trb->bpl = lower_32_bits(dma);
+ trb->bph = upper_32_bits(dma);
switch (usb_endpoint_type(dep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
- trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
+ trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP;
break;
case USB_ENDPOINT_XFER_ISOC:
- trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
+ trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
/* IOC every DWC3_TRB_NUM / 4 so we can refill */
if (!(cur_slot % (DWC3_TRB_NUM / 4)))
- trb.ioc = last;
+ trb->ctrl |= DWC3_TRB_CTRL_IOC;
break;
case USB_ENDPOINT_XFER_BULK:
case USB_ENDPOINT_XFER_INT:
- trb.trbctl = DWC3_TRBCTL_NORMAL;
+ trb->ctrl = DWC3_TRBCTL_NORMAL;
break;
default:
/*
@@ -584,11 +732,21 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
BUG();
}
- trb.length = length;
- trb.bplh = dma;
- trb.hwo = true;
+ if (usb_endpoint_xfer_isoc(dep->desc)) {
+ trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
+ trb->ctrl |= DWC3_TRB_CTRL_CSP;
+ } else {
+ if (chain)
+ trb->ctrl |= DWC3_TRB_CTRL_CHN;
+
+ if (last)
+ trb->ctrl |= DWC3_TRB_CTRL_LST;
+ }
- dwc3_trb_to_hw(&trb, trb_hw);
+ if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
+ trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
+
+ trb->ctrl |= DWC3_TRB_CTRL_HWO;
}
/*
@@ -596,14 +754,15 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
* @dep: endpoint for which requests are being prepared
* @starting: true if the endpoint is idle and no requests are queued.
*
- * The functions goes through the requests list and setups TRBs for the
- * transfers. The functions returns once there are not more TRBs available or
- * it run out of requests.
+ * The function goes through the requests list and sets up TRBs for the
+ * transfers. The function returns once there are no more TRBs available or
+ * it runs out of requests.
*/
static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
{
struct dwc3_request *req, *n;
u32 trbs_left;
+ u32 max;
unsigned int last_one = 0;
BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
@@ -611,9 +770,16 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
/* the first request must not be queued */
trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;
+ /* Can't wrap around on a non-isoc EP since there's no link TRB */
+ if (!usb_endpoint_xfer_isoc(dep->desc)) {
+ max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK);
+ if (trbs_left > max)
+ trbs_left = max;
+ }
+
/*
- * if busy & slot are equal than it is either full or empty. If we are
- * starting to proceed requests then we are empty. Otherwise we ar
+ * If busy & slot are equal than it is either full or empty. If we are
+ * starting to process requests then we are empty. Otherwise we are
* full and don't do anything
*/
if (!trbs_left) {
@@ -624,7 +790,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
* In case we start from scratch, we queue the ISOC requests
* starting from slot 1. This is done because we use ring
* buffer and have no LST bit to stop us. Instead, we place
- * IOC bit TRB_NUM/4. We try to avoid to having an interrupt
+ * IOC bit every TRB_NUM/4. We try to avoid having an interrupt
* after the first request so we start at slot 1 and have
* 7 requests proceed before we hit the first IOC.
* Other transfer types don't use the ring buffer and are
@@ -660,8 +826,8 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
length = sg_dma_len(s);
dma = sg_dma_address(s);
- if (i == (request->num_mapped_sgs - 1)
- || sg_is_last(s)) {
+ if (i == (request->num_mapped_sgs - 1) ||
+ sg_is_last(s)) {
last_one = true;
chain = false;
}
@@ -729,8 +895,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
dwc3_prepare_trbs(dep, start_new);
/*
- * req points to the first request where HWO changed
- * from 0 to 1
+ * req points to the first request where HWO changed from 0 to 1
*/
req = next_request(&dep->req_queued);
}
@@ -756,7 +921,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
/*
* FIXME we need to iterate over the list of requests
* here and stop, unmap, free and del each of the linked
- * requests instead of we do now.
+ * requests instead of what we do now.
*/
usb_gadget_unmap_request(&dwc->gadget, &req->request,
req->direction);
@@ -793,7 +958,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
* particular token from the Host side.
*
* This will also avoid Host cancelling URBs due to too
- * many NACKs.
+ * many NAKs.
*/
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->direction);
@@ -819,11 +984,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
int start_trans;
start_trans = 1;
- if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
- dep->flags & DWC3_EP_BUSY)
+ if (usb_endpoint_xfer_isoc(dep->desc) &&
+ (dep->flags & DWC3_EP_BUSY))
start_trans = 0;
- ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans);
+ ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans);
if (ret && ret != -EBUSY) {
struct dwc3 *dwc = dep->dwc;
@@ -976,8 +1141,12 @@ out:
static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3 *dwc = dep->dwc;
+ unsigned long flags;
+ spin_lock_irqsave(&dwc->lock, flags);
dep->flags |= DWC3_EP_WEDGE;
+ spin_unlock_irqrestore(&dwc->lock, flags);
return dwc3_gadget_ep_set_halt(ep, 1);
}
@@ -1067,26 +1236,20 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
goto out;
}
- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-
- /*
- * Switch link state to Recovery. In HS/FS/LS this means
- * RemoteWakeup Request
- */
- reg |= DWC3_DCTL_ULSTCHNG_RECOVERY;
- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
- /* wait for at least 2000us */
- usleep_range(2000, 2500);
+ ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV);
+ if (ret < 0) {
+ dev_err(dwc->dev, "failed to put link in Recovery\n");
+ goto out;
+ }
/* write zeroes to Link Change Request */
reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- /* pool until Link State change to ON */
+ /* poll until Link State changes to ON */
timeout = jiffies + msecs_to_jiffies(100);
- while (!(time_after(jiffies, timeout))) {
+ while (!time_after(jiffies, timeout)) {
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
/* in HS, means ON */
@@ -1109,8 +1272,11 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
int is_selfpowered)
{
struct dwc3 *dwc = gadget_to_dwc(g);
+ unsigned long flags;
+ spin_lock_irqsave(&dwc->lock, flags);
dwc->is_selfpowered = !!is_selfpowered;
+ spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
}
@@ -1121,10 +1287,13 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
u32 timeout = 500;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- if (is_on)
- reg |= DWC3_DCTL_RUN_STOP;
- else
+ if (is_on) {
+ reg &= ~DWC3_DCTL_TRGTULST_MASK;
+ reg |= (DWC3_DCTL_RUN_STOP
+ | DWC3_DCTL_TRGTULST_RX_DET);
+ } else {
reg &= ~DWC3_DCTL_RUN_STOP;
+ }
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@@ -1331,7 +1500,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
const struct dwc3_event_depevt *event, int status)
{
struct dwc3_request *req;
- struct dwc3_trb trb;
+ struct dwc3_trb *trb;
unsigned int count;
unsigned int s_pkt = 0;
@@ -1342,20 +1511,20 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
return 1;
}
- dwc3_trb_to_nat(req->trb, &trb);
+ trb = req->trb;
- if (trb.hwo && status != -ESHUTDOWN)
+ if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
/*
* We continue despite the error. There is not much we
- * can do. If we don't clean in up we loop for ever. If
- * we skip the TRB than it gets overwritten reused after
- * a while since we use them in a ring buffer. a BUG()
- * would help. Lets hope that if this occures, someone
+ * can do. If we don't clean it up we loop forever. If
+ * we skip the TRB then it gets overwritten after a
+ * while since we use them in a ring buffer. A BUG()
+ * would help. Lets hope that if this occurs, someone
* fixes the root cause instead of looking away :)
*/
dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
dep->name, req->trb);
- count = trb.length;
+ count = trb->size & DWC3_TRB_SIZE_MASK;
if (dep->direction) {
if (count) {
@@ -1379,13 +1548,16 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
dwc3_gadget_giveback(dep, req, status);
if (s_pkt)
break;
- if ((event->status & DEPEVT_STATUS_LST) && trb.lst)
+ if ((event->status & DEPEVT_STATUS_LST) &&
+ (trb->ctrl & DWC3_TRB_CTRL_LST))
break;
- if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc)
+ if ((event->status & DEPEVT_STATUS_IOC) &&
+ (trb->ctrl & DWC3_TRB_CTRL_IOC))
break;
} while (1);
- if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc)
+ if ((event->status & DEPEVT_STATUS_IOC) &&
+ (trb->ctrl & DWC3_TRB_CTRL_IOC))
return 0;
return 1;
}
@@ -1400,11 +1572,9 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
if (event->status & DEPEVT_STATUS_BUSERR)
status = -ECONNRESET;
- clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
- if (clean_busy) {
+ clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
+ if (clean_busy)
dep->flags &= ~DWC3_EP_BUSY;
- dep->res_trans_idx = 0;
- }
/*
* WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround.
@@ -1435,7 +1605,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
{
- u32 uf;
+ u32 uf, mask;
if (list_empty(&dep->request_list)) {
dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
@@ -1443,16 +1613,10 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
return;
}
- if (event->parameters) {
- u32 mask;
-
- mask = ~(dep->interval - 1);
- uf = event->parameters & mask;
- /* 4 micro frames in the future */
- uf += dep->interval * 4;
- } else {
- uf = 0;
- }
+ mask = ~(dep->interval - 1);
+ uf = event->parameters & mask;
+ /* 4 micro frames in the future */
+ uf += dep->interval * 4;
__dwc3_gadget_kick_transfer(dep, uf, 1);
}
@@ -1464,8 +1628,8 @@ static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep,
struct dwc3_event_depevt mod_ev = *event;
/*
- * We were asked to remove one requests. It is possible that this
- * request and a few other were started together and have the same
+ * We were asked to remove one request. It is possible that this
+ * request and a few others were started together and have the same
* transfer index. Since we stopped the complete endpoint we don't
* know how many requests were already completed (and not yet)
* reported and how could be done (later). We purge them all until
@@ -1474,7 +1638,7 @@ static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep,
mod_ev.status = DEPEVT_STATUS_LST;
dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN);
dep->flags &= ~DWC3_EP_BUSY;
- /* pending requets are ignored and are queued on XferNotReady */
+ /* pending requests are ignored and are queued on XferNotReady */
}
static void dwc3_ep_cmd_compl(struct dwc3_ep *dep,
@@ -1515,6 +1679,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE:
+ dep->res_trans_idx = 0;
+
if (usb_endpoint_xfer_isoc(dep->desc)) {
dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n",
dep->name);
@@ -1539,7 +1705,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
int ret;
dev_vdbg(dwc->dev, "%s: reason %s\n",
- dep->name, event->status
+ dep->name, event->status &
+ DEPEVT_STATUS_TRANSFER_ACTIVE
? "Transfer Active"
: "Transfer Not Active");
@@ -1750,6 +1917,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+ dwc->test_mode = false;
dwc3_stop_active_transfers(dwc);
dwc3_clear_stall_all_ep(dwc);
@@ -2027,7 +2195,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
while (left > 0) {
union dwc3_event event;
- memcpy(&event.raw, (evt->buf + evt->lpos), sizeof(event.raw));
+ event.raw = *(u32 *) (evt->buf + evt->lpos);
+
dwc3_process_event_entry(dwc, &event);
/*
* XXX we wrap around correctly to the next entry as almost all
@@ -2068,7 +2237,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
/**
* dwc3_gadget_init - Initializes gadget related registers
- * @dwc: Pointer to out controller context structure
+ * @dwc: pointer to our controller context structure
*
* Returns 0 on success otherwise negative errno.
*/