[rfc/rft/patch 15/19] usb: musb: enabling dma tx for gadget

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Arnaud Mandy <ext-arnaud.2.mandy@xxxxxxxxx>

Enabling dma tx for gadget and adapting rx part.

Signed-off-by: Arnaud Mandy <ext-arnaud.2.mandy@xxxxxxxxx>
Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx>
---
 drivers/usb/musb/musb_gadget.c |  367 ++++++++++++++++++++++++----------------
 drivers/usb/musb/musb_gadget.h |    1 +
 2 files changed, 219 insertions(+), 149 deletions(-)

diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index e70dcf1..a12cc55 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -106,16 +106,15 @@ __acquires(ep->musb->lock)
 {
 	struct musb_request	*req;
 	struct musb		*musb;
-	int			busy = ep->busy;
 
 	req = to_musb_request(request);
+	req->complete = false;
 
 	list_del(&request->list);
 	if (req->request.status == -EINPROGRESS)
 		req->request.status = status;
 	musb = req->musb;
 
-	ep->busy = 1;
 	spin_unlock(&musb->lock);
 	if (request->status == 0)
 		DBG(5, "%s done request %p,  %d/%d\n",
@@ -128,7 +127,6 @@ __acquires(ep->musb->lock)
 				request->status);
 	req->request.complete(&req->ep->end_point, &req->request);
 	spin_lock(&musb->lock);
-	ep->busy = busy;
 }
 
 /**
@@ -267,7 +265,6 @@ static int start_dma(struct musb *musb, struct musb_request *req)
  * @ep:		the enpoint being used
  * @req:	the request to stop
  */
-
 static void stop_dma(struct musb *musb, struct musb_ep *ep,
 			struct musb_request *req)
 {
@@ -317,14 +314,23 @@ static void stop_dma(struct musb *musb, struct musb_ep *ep,
  */
 static void nuke(struct musb_ep *ep, const int status)
 {
+	void __iomem		*epio;
 	struct musb_request	*req = NULL;
-	void __iomem *epio = ep->musb->endpoints[ep->current_epnum].regs;
+	struct musb		*musb;
 
+	musb = ep->musb;
+	epio = musb->endpoints[ep->current_epnum].regs;
 	ep->busy = 1;
 
-	if (is_dma_capable() && ep->dma) {
+	DBG(2, "%s nuke, DMA %p RxCSR %04x TxCSR %04x\n", ep->name, ep->dma,
+		musb_readw(epio, MUSB_RXCSR), musb_readw(epio, MUSB_TXCSR));
+	if (ep->dma) {
 		struct dma_controller	*c = ep->musb->dma_controller;
-		int value;
+
+		BUG_ON(next_request(ep) == NULL);
+		req = to_musb_request(next_request(ep));
+		(void) c->channel_abort(ep->dma);
+		stop_dma(musb, ep, req);
 
 		if (ep->is_in) {
 			/*
@@ -338,16 +344,12 @@ static void nuke(struct musb_ep *ep, const int status)
 					0 | MUSB_TXCSR_FLUSHFIFO);
 		} else {
 			musb_writew(epio, MUSB_RXCSR,
-					0 | MUSB_RXCSR_FLUSHFIFO);
+				    MUSB_RXCSR_DMAMODE | MUSB_RXCSR_FLUSHFIFO);
 			musb_writew(epio, MUSB_RXCSR,
 					0 | MUSB_RXCSR_FLUSHFIFO);
 		}
-
-		value = c->channel_abort(ep->dma);
-		DBG(value ? 1 : 6, "%s: abort DMA --> %d\n", ep->name, value);
-		c->channel_release(ep->dma);
-		ep->dma = NULL;
 	}
+	ep->rx_pending = false;
 
 	while (!list_empty(&(ep->req_list))) {
 		req = container_of(ep->req_list.next, struct musb_request,
@@ -373,10 +375,13 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
 		return ep->packet_sz;
 }
 
-/*
+/**
+ * do_pio_tx - kicks TX pio transfer
+ * @musb:      musb controller pointer
+ * @req:       the request to be transfered via pio
+ *
  * An endpoint is transmitting data. This can be called either from
- * the IRQ routine or from ep.queue() to kickstart a request on an
- * endpoint.
+ * the IRQ routine.
  *
  * Context: controller locked, IRQs blocked, endpoint selected
  */
@@ -390,16 +395,11 @@ static void do_pio_tx(struct musb *musb, struct musb_request *req)
 
 	musb_ep = req->ep;
 
-	/* we shouldn't get here while DMA is active ... but we do ... */
-	if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
-		DBG(4, "dma pending...\n");
-		return;
-	}
-
 	/* read TXCSR before */
 	csr = musb_readw(epio, MUSB_TXCSR);
 
 	request = &req->request;
+
 	fifo_count = min(max_ep_writesize(musb, musb_ep),
 			(int)(request->length - request->actual));
 
@@ -423,6 +423,7 @@ static void do_pio_tx(struct musb *musb, struct musb_request *req)
 			(u8 *) (request->buf + request->actual));
 	request->actual += fifo_count;
 	csr |= MUSB_TXCSR_TXPKTRDY;
+	/* REVISIT wasn't this cleared by musb_g_tx() ? */
 	csr &= ~MUSB_TXCSR_P_UNDERRUN;
 	musb_writew(epio, MUSB_TXCSR, csr);
 
@@ -436,105 +437,155 @@ static void do_pio_tx(struct musb *musb, struct musb_request *req)
 }
 
 /*
+ * Context: controller locked, IRQs blocked.
+ */
+static void musb_ep_restart(struct musb *musb, struct musb_request *req)
+{
+	DBG(3, "<== TX/IN request %p len %u on hw_ep%d%s\n",
+		&req->request, req->request.length, req->epnum,
+		req->ep->dma ? " (dma)" : "(pio)");
+
+	musb_ep_select(musb->mregs, req->epnum);
+
+	if (start_dma(musb, req) < 0)
+		do_pio_tx(musb, req);
+}
+
+/*
  * FIFO state update (e.g. data ready).
  * Called from IRQ,  with controller locked.
  */
 void musb_g_tx(struct musb *musb, u8 epnum)
 {
 	u16			csr;
+	struct musb_request	*req;
 	struct usb_request	*request;
 	u8 __iomem		*mbase = musb->mregs;
 	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_in;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
+	struct dma_channel	*dma;
 
 	musb_ep_select(mbase, epnum);
 	request = next_request(musb_ep);
 
 	csr = musb_readw(epio, MUSB_TXCSR);
+	dma = musb_ep->dma;
 	DBG(4, "<== %s, txcsr %04x\n", musb_ep->name, csr);
 
-	do {
-		/* REVISIT for high bandwidth, MUSB_TXCSR_P_INCOMPTX
-		 * probably rates reporting as a host error
+	if (csr & MUSB_TXCSR_P_SENDSTALL) {
+		DBG(5, "%s stalling, txcsr %04x\n",
+				musb_ep->name, csr);
+		return;
+	}
+
+	/* REVISIT for high bandwidth, MUSB_TXCSR_P_INCOMPTX
+	 * probably rates reporting as a host error
+	 */
+	if (csr & MUSB_TXCSR_P_SENTSTALL) {
+		DBG(5, "ep%d is halted, cannot transfer\n", epnum);
+		csr |= MUSB_TXCSR_P_WZC_BITS;
+		csr &= ~MUSB_TXCSR_P_SENTSTALL;
+		musb_writew(epio, MUSB_TXCSR, csr);
+		if (dma != NULL) {
+			BUG_ON(request == NULL);
+			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+			musb->dma_controller->channel_abort(dma);
+			stop_dma(musb, musb_ep, to_musb_request(request));
+			dma = NULL;
+		}
+
+		if (request && musb_ep->stalled)
+			musb_g_giveback(musb_ep, request, -EPIPE);
+
+		return;
+	}
+
+	if (csr & MUSB_TXCSR_P_UNDERRUN) {
+		/* we NAKed, no big deal ... little reason to care */
+		csr |= MUSB_TXCSR_P_WZC_BITS;
+		csr &= ~MUSB_TXCSR_P_UNDERRUN;
+		musb_writew(epio, MUSB_TXCSR, csr);
+		DBG(2, "underrun on ep%d, req %p\n", epnum, request);
+	}
+
+	if (dma != NULL && dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+		/* SHOULD NOT HAPPEN ... has with cppi though, after
+		 * changing SENDSTALL (and other cases); harmless?
 		 */
-		if (csr & MUSB_TXCSR_P_SENTSTALL) {
-			csr |= MUSB_TXCSR_P_WZC_BITS;
-			csr &= ~MUSB_TXCSR_P_SENTSTALL;
-			musb_writew(epio, MUSB_TXCSR, csr);
+		DBG(3, "%s dma still busy?\n", musb_ep->name);
+		return;
+	}
 
-			if (request)
-				musb_g_giveback(musb_ep, request, -EPIPE);
+	if (request == NULL) {
+		DBG(2, "%s, spurious TX IRQ", musb_ep->name);
+		return;
+	}
 
-			break;
-		}
+	req = to_musb_request(request);
 
-		if (csr & MUSB_TXCSR_P_UNDERRUN) {
-			/* we NAKed, no big deal ... little reason to care */
-			csr |= MUSB_TXCSR_P_WZC_BITS;
-			csr &= ~(MUSB_TXCSR_P_UNDERRUN
-					| MUSB_TXCSR_TXPKTRDY);
-			musb_writew(epio, MUSB_TXCSR, csr);
-			DBG(20, "underrun on ep%d, req %p\n", epnum, request);
+	if (dma) {
+		int short_packet = 0;
+
+		BUG_ON(!(csr & MUSB_TXCSR_DMAENAB));
+
+		request->actual += dma->actual_len;
+		DBG(4, "TxCSR%d %04x, dma finished, len %zu, req %p\n",
+				epnum, csr, dma->actual_len, request);
+
+		stop_dma(musb, musb_ep, req);
+
+		WARN(request->actual != request->length,
+				"actual %d length %d\n", request->actual,
+				request->length);
+
+		if (request->length % musb_ep->packet_sz)
+			short_packet = 1;
+
+		req->complete = true;
+		if (request->zero || short_packet) {
+			csr = musb_readw(epio, MUSB_TXCSR);
+			DBG(4, "sending zero pkt, DMA, TxCSR %04x\n", csr);
+			musb_writew(epio, MUSB_TXCSR,
+					csr | MUSB_TXCSR_TXPKTRDY);
+			return;
 		}
+	}
 
-		if (request) {
-			if (request->actual == request->length) {
-
-				/* First, maybe a terminating short packet.
-				 * Some DMA engines might handle this by
-				 * themselves.
-				 */
-				if ((request->zero
-						&& request->length
-						&& (request->length
-							% musb_ep->packet_sz)
-							== 0)
-				) {
-					/* on dma completion, fifo may not
-					 * be available yet ...
-					 */
-					if (csr & MUSB_TXCSR_TXPKTRDY)
-						break;
-
-					DBG(4, "sending zero pkt\n");
-					musb_writew(epio, MUSB_TXCSR,
-							MUSB_TXCSR_MODE
-							| MUSB_TXCSR_TXPKTRDY);
-					request->zero = 0;
-				}
-
-				/* ... or if not, then complete it */
-				musb_g_giveback(musb_ep, request, 0);
-
-				/* kickstart next transfer if appropriate;
-				 * the packet that just completed might not
-				 * be transmitted for hours or days.
-				 * REVISIT for double buffering...
-				 * FIXME revisit for stalls too...
-				 */
-				musb_ep_select(mbase, epnum);
+	if (request->actual == request->length) {
+		if (!req->complete) {
+			/* Maybe we have to send a zero length packet */
+			if (request->zero && request->length &&
+			    (request->length % musb_ep->packet_sz) == 0) {
 				csr = musb_readw(epio, MUSB_TXCSR);
-				if (csr & MUSB_TXCSR_FIFONOTEMPTY)
-					break;
-				request = musb_ep->desc
-						? next_request(musb_ep)
-						: NULL;
-				if (!request) {
-					DBG(4, "%s idle now\n",
-						musb_ep->name);
-					break;
-				}
+				DBG(4, "sending zero pkt, TxCSR %04x\n", csr);
+				musb_writew(epio, MUSB_TXCSR,
+						csr | MUSB_TXCSR_TXPKTRDY);
+				req->complete = true;
+				return;
 			}
-
-			do_pio_tx(musb, to_musb_request(request));
 		}
+		musb_ep->busy = 1;
+		musb_g_giveback(musb_ep, request, 0);
+		musb_ep->busy = 0;
 
-	} while (0);
+		request = musb_ep->desc	? next_request(musb_ep)	: NULL;
+		if (!request) {
+			DBG(4, "%s idle now\n",	musb_ep->name);
+			return;
+		}
+		musb_ep_restart(musb, to_musb_request(request));
+		return;
+	}
+	do_pio_tx(musb, to_musb_request(request));
 }
 
 /* ------------------------------------------------------------ */
 
 /*
+ * do_pio_rx - kicks RX pio transfer
+ * @musb:       musb controller pointer
+ * @req:        the request to be transfered via pio
+ *
  * Context: controller locked, IRQs blocked, endpoint selected
  */
 static void do_pio_rx(struct musb *musb, struct musb_request *req)
@@ -545,39 +596,43 @@ static void do_pio_rx(struct musb *musb, struct musb_request *req)
 	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
 	unsigned		fifo_count = 0;
-	u16			len = musb_ep->packet_sz;
+	u16			count = musb_ep->packet_sz;
 
 	csr = musb_readw(epio, MUSB_RXCSR);
 
-	if (csr & MUSB_RXCSR_RXPKTRDY) {
-		len = musb_readw(epio, MUSB_RXCOUNT);
-		if (request->actual < request->length) {
+	musb_ep->busy = 1;
 
-			fifo_count = request->length - request->actual;
-			DBG(3, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
-					musb_ep->name,
-					len, fifo_count,
-					musb_ep->packet_sz);
+	count = musb_readw(epio, MUSB_RXCOUNT);
 
-			fifo_count = min_t(unsigned, len, fifo_count);
+	if (request->actual < request->length) {
+		fifo_count = request->length - request->actual;
+		DBG(3, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
+				musb_ep->name,
+				count, fifo_count,
+				musb_ep->packet_sz);
 
-			musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
-					(request->buf + request->actual));
-			request->actual += fifo_count;
+		fifo_count = min_t(unsigned, count, fifo_count);
 
-			/* REVISIT if we left anything in the fifo, flush
-			 * it and report -EOVERFLOW
-			 */
+		musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
+				(request->buf + request->actual));
+		request->actual += fifo_count;
 
-			/* ack the read! */
-			csr |= MUSB_RXCSR_P_WZC_BITS;
-			csr &= ~MUSB_RXCSR_RXPKTRDY;
-			musb_writew(epio, MUSB_RXCSR, csr);
-		}
+		/* REVISIT if we left anything in the fifo, flush
+		 * it and report -EOVERFLOW
+		 */
+
+		/* ack the read! */
+		csr |= MUSB_RXCSR_P_WZC_BITS;
+		csr &= ~MUSB_RXCSR_RXPKTRDY;
+		musb_writew(epio, MUSB_RXCSR, csr);
 	}
 
-	/* reach the end or short packet detected */
-	if (request->actual == request->length || len < musb_ep->packet_sz)
+	musb_ep->busy = 0;
+
+	/* we just received a short packet, it's ok to
+	 * giveback() the request already
+	 */
+	if (request->actual == request->length || count < musb_ep->packet_sz)
 		musb_g_giveback(musb_ep, request, 0);
 }
 
@@ -713,13 +768,15 @@ static int musb_gadget_enable(struct usb_ep *ep,
 	struct musb		*musb;
 	void __iomem	*mbase;
 	u8		epnum;
-	u16		csr;
+	u16		csr = 0;
 	unsigned	tmp;
 	int		status = -EINVAL;
 
 	if (!ep || !desc)
 		return -EINVAL;
 
+	DBG(1, "===> enabling %s\n", ep->name);
+
 	musb_ep = to_musb_ep(ep);
 	hw_ep = musb_ep->hw_ep;
 	regs = hw_ep->regs;
@@ -767,18 +824,15 @@ static int musb_gadget_enable(struct usb_ep *ep,
 		 */
 		musb_writew(regs, MUSB_TXMAXP, tmp);
 
+		/* clear DATAx toggle */
 		csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
+
 		if (musb_readw(regs, MUSB_TXCSR)
 				& MUSB_TXCSR_FIFONOTEMPTY)
 			csr |= MUSB_TXCSR_FLUSHFIFO;
 		if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
 			csr |= MUSB_TXCSR_P_ISO;
-
-		/* set twice in case of double buffering */
-		musb_writew(regs, MUSB_TXCSR, csr);
-		/* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
 		musb_writew(regs, MUSB_TXCSR, csr);
-
 	} else {
 		u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);
 
@@ -804,35 +858,47 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			musb_writew(regs, MUSB_TXCSR, csr);
 		}
 
+		/* clear DATAx toggle */
 		csr = MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG;
-		if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+
+		if (usb_endpoint_xfer_isoc(desc))
 			csr |= MUSB_RXCSR_P_ISO;
-		else if (musb_ep->type == USB_ENDPOINT_XFER_INT)
+		else if (usb_endpoint_xfer_int(desc))
 			csr |= MUSB_RXCSR_DISNYET;
 
-		/* set twice in case of double buffering */
-		musb_writew(regs, MUSB_RXCSR, csr);
 		musb_writew(regs, MUSB_RXCSR, csr);
 	}
 
+	/* NOTE:  all the I/O code _should_ work fine without DMA, in case
+	* for some reason you run out of channels here.
+	*/
+
 	musb_ep->dma = NULL;
 	musb_ep->desc = desc;
 	musb_ep->busy = 0;
 	status = 0;
 
-	pr_debug("%s periph: enabled %s for %s %s, maxpacket %d\n",
+	pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n",
 			musb_driver_name, musb_ep->name,
 			({ char *s; switch (musb_ep->type) {
-			case USB_ENDPOINT_XFER_BULK:	s = "bulk"; break;
-			case USB_ENDPOINT_XFER_INT:	s = "int"; break;
-			default:			s = "iso"; break;
+			case USB_ENDPOINT_XFER_BULK:
+				s = "bulk";
+				break;
+			case USB_ENDPOINT_XFER_INT:
+				s = "int";
+				break;
+			default:
+				s = "iso";
+				break;
 			}; s; }),
 			musb_ep->is_in ? "IN" : "OUT",
+			musb_ep->dma ? "dma, " : "",
 			musb_ep->packet_sz);
 
 	schedule_work(&musb->irq_work);
 
 fail:
+	musb_ep_select(mbase, 0);
 	spin_unlock_irqrestore(&musb->lock, flags);
 	return status;
 }
@@ -850,6 +916,7 @@ static int musb_gadget_disable(struct usb_ep *ep)
 	int		status = 0;
 
 	musb_ep = to_musb_ep(ep);
+	DBG(4, "disabling %s\n", musb_ep->name);
 	musb = musb_ep->musb;
 	epnum = musb_ep->current_epnum;
 	epio = musb->endpoints[epnum].regs;
@@ -863,11 +930,13 @@ static int musb_gadget_disable(struct usb_ep *ep)
 		int_txe &= ~(1 << epnum);
 		musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
 		musb_writew(epio, MUSB_TXMAXP, 0);
+		musb_writew(epio, MUSB_TXCSR, 0);
 	} else {
 		u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE);
 		int_rxe &= ~(1 << epnum);
 		musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe);
 		musb_writew(epio, MUSB_RXMAXP, 0);
+		musb_writew(epio, MUSB_RXCSR, 0);
 	}
 
 	musb_ep->desc = NULL;
@@ -922,19 +991,6 @@ struct free_record {
 	dma_addr_t		dma;
 };
 
-/*
- * Context: controller locked, IRQs blocked.
- */
-static void musb_ep_restart(struct musb *musb, struct musb_request *req)
-{
-	DBG(3, "<== %s request %p len %u on hw_ep%d\n",
-		req->tx ? "TX/IN" : "RX/OUT",
-		&req->request, req->request.length, req->epnum);
-
-	musb_ep_select(musb->mregs, req->epnum);
-	do_pio_tx(musb, req);
-}
-
 static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 			gfp_t gfp_flags)
 {
@@ -958,7 +1014,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 	if (request->ep != musb_ep)
 		return -EINVAL;
 
-	DBG(4, "<== to %s request=%p\n", ep->name, req);
+	DBG(4, "<== to %s request=%p length %d\n", ep->name, req, req->length);
 
 	/* request is mine now... */
 	request->request.actual = 0;
@@ -966,10 +1022,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 	request->epnum = musb_ep->current_epnum;
 	request->tx = musb_ep->is_in;
 
-	if (!req->buf)
-		return -ENODATA;
-	else
-		request->mapped = 0;
+	request->mapped = 0;
 
 	spin_lock_irqsave(&musb->lock, lockflags);
 
@@ -1015,6 +1068,7 @@ static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
 	int			status = 0;
 	struct musb		*musb = musb_ep->musb;
 
+	DBG(4, "%s, dequeueing request %p\n", ep->name, request);
 	if (!ep || !request || to_musb_request(request)->ep != musb_ep)
 		return -EINVAL;
 
@@ -1031,17 +1085,30 @@ static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
 	}
 
 	/* if the hardware doesn't have the request, easy ... */
-	if (musb_ep->req_list.next != &request->list || musb_ep->busy)
+	if (musb_ep->req_list.next != &request->list) {
 		musb_g_giveback(musb_ep, request, -ECONNRESET);
-	else
+
+       /* ... else abort the dma transfer ... */
+	} else if (musb_ep->dma) {
+		struct dma_controller   *c = musb->dma_controller;
+
+		musb_ep_select(musb->mregs, musb_ep->current_epnum);
+		if (c->channel_abort)
+			status = c->channel_abort(musb_ep->dma);
+		else
+		status = -EBUSY;
+	stop_dma(musb, musb_ep, to_musb_request(request));
+	if (status == 0)
+		musb_g_giveback(musb_ep, request, -ECONNRESET);
+	} else {
 		/* NOTE: by sticking to easily tested hardware/driver states,
 		 * we leave counting of in-flight packets imprecise.
 		 */
 		musb_g_giveback(musb_ep, request, -ECONNRESET);
-
+	}
 done:
-	spin_unlock_irqrestore(&musb->lock, flags);
-	return status;
+		spin_unlock_irqrestore(&musb->lock, flags);
+		return status;
 }
 
 /*
@@ -1115,6 +1182,8 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
 		musb_writew(epio, MUSB_RXCSR, csr);
 	}
 
+	musb_ep->stalled = value;
+
 done:
 
 	/* maybe start the first request in the queue */
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index 3e62716..20d660e 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -42,6 +42,7 @@ struct musb_request {
 	u8 tx;			/* endpoint direction */
 	u8 epnum;
 	u8 mapped;
+	u8 complete;
 };
 
 static inline struct musb_request *to_musb_request(struct usb_request *req)
-- 
1.6.4.2.253.g0b1fac

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux