Re: usbtest test-14 failure: MUSBHDRC + Netchip2280

David Brownell <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
On Friday 23 March 2007 5:26 am, Pandita, Vikram wrote:
> Hi 
> 
>   I am testing HS USB HOST controller of OMAP2430 (MUSBHDRC) with
> Netchip2280 device using usbtest. When I run the test.sh control test on
> the OMAP Host, the test 14 fails randomly after some iterations with
> error no -32.

Does this help?  Against the current OMAP tree.  If this morphs the
STALL (-32) into an EREMOTEIO (-121) that may be the same IN DATA ack
error noted below.

=========
Update host side EP0 handling for correctness:  handle zero-length data
stages and continuations of ep0out transfers explicitly, clean up the state
machine a bit.  This means that the full set of host-side ep0 tests pass.
Usbtest cases #9 and #10 were ok before; now case #14 works too.

There is however a curious protocol problem in some full speed tests, at
least on DaVinci:  sometimes the controller won't ack an IN DATA packet,
causing a retry.  If the peripheral doesn't resend that data correctly,
that causes a test failure.  (And my test rig doesn't resend correctly...)

This is based on a patch from "ZHENG LEI <[email protected]>"
against 2.6.10 code, resolving some of the ep0out problems.

Signed-off-by: David Brownell <[email protected]>

--- d26x.orig/drivers/usb/musb/musb_host.c	2007-03-19 11:28:55.000000000 -0700
+++ d26x/drivers/usb/musb/musb_host.c	2007-03-19 11:59:12.000000000 -0700
@@ -936,21 +936,20 @@ static void musb_ep_program(struct musb 
 
 /*
  * Service the default endpoint (ep0) as host.
- * return TRUE if more packets are required for this transaction
+ * Return TRUE until it's time to start the status stage.
  */
-static u8 musb_h_ep0_continue(struct musb *pThis,
+static int musb_h_ep0_continue(struct musb *pThis,
 				u16 wCount, struct urb *pUrb)
 {
-	u8 bMore = FALSE;
+	int			 bMore = FALSE;
 	u8 *pFifoDest = NULL;
 	u16 wFifoCount = 0;
 	struct musb_hw_ep	*pEnd = pThis->control_ep;
 	struct musb_qh		*qh = pEnd->in_qh;
 	struct usb_ctrlrequest	*pRequest;
 
-	pRequest = (struct usb_ctrlrequest *) pUrb->setup_packet;
-	if (MGC_END0_IN == pThis->bEnd0Stage) {
-		/* we are receiving from peripheral */
+	switch (pThis->bEnd0Stage) {
+	case MGC_END0_IN:
 		pFifoDest = pUrb->transfer_buffer + pUrb->actual_length;
 		wFifoCount = min(wCount, ((u16) (pUrb->transfer_buffer_length
 					- pUrb->actual_length)));
@@ -964,50 +963,46 @@ static u8 musb_h_ep0_continue(struct mus
 			/* always terminate on short read; it's
 			 * rarely reported as an error.
 			 */
-			if ((pUrb->transfer_flags & URB_SHORT_NOT_OK)
-					&& (pUrb->actual_length <
-						pUrb->transfer_buffer_length))
-				pUrb->status = -EREMOTEIO;
 		} else if (pUrb->actual_length <
 				pUrb->transfer_buffer_length)
 			bMore = TRUE;
-	} else {
-/*
-	DBG(3, "%s hw%d urb %p spd%d dev%d ep%d%s "
-				"hub%d port%d%s bytes %d\n",
-			is_out ? "-->" : "<--",
-			bEnd, pUrb, pUrb->dev->speed,
-			bAddress, qh->epnum, is_out ? "out" : "in",
-			bHubAddr, bHubPort + 1,
-			bIsMulti ? " multi" : "",
-			dwLength);
-*/
-		if ((MGC_END0_START == pThis->bEnd0Stage)
-				&& (pRequest->bRequestType & USB_DIR_IN)) {
-			/* this means we just did setup; switch to IN */
+		break;
+	case MGC_END0_START:
+		pRequest = (struct usb_ctrlrequest *) pUrb->setup_packet;
+
+		if (!pRequest->wLength) {
+			DBG(4, "start no-DATA\n");
+			break;
+		} else if (pRequest->bRequestType & USB_DIR_IN) {
 			DBG(4, "start IN-DATA\n");
 			pThis->bEnd0Stage = MGC_END0_IN;
 			bMore = TRUE;
-
-		} else if (pRequest->wLength
-				&& (MGC_END0_START == pThis->bEnd0Stage)) {
+			break;
+		} else {
+			DBG(4, "start OUT-DATA\n");
 			pThis->bEnd0Stage = MGC_END0_OUT;
+			bMore = TRUE;
+		}
+		/* FALLTHROUGH */
+	case MGC_END0_OUT:
+		wFifoCount = min(qh->maxpacket, ((u16)
+				(pUrb->transfer_buffer_length
+				- pUrb->actual_length)));
+
+		if (wFifoCount) {
 			pFifoDest = (u8 *) (pUrb->transfer_buffer
 					+ pUrb->actual_length);
-			wFifoCount = min(qh->maxpacket, ((u16)
-					(pUrb->transfer_buffer_length
-					- pUrb->actual_length)));
 			DBG(3, "Sending %d bytes to %p\n",
 					wFifoCount, pFifoDest);
 			musb_write_fifo(pEnd, wFifoCount, pFifoDest);
 
-			qh->segsize = wFifoCount;
 			pUrb->actual_length += wFifoCount;
-			if (pUrb->actual_length
-					< pUrb->transfer_buffer_length) {
-				bMore = TRUE;
-			}
+			bMore = TRUE;
 		}
+		break;
+	default:
+		ERR("bogus ep0 stage %d\n", pThis->bEnd0Stage);
+		break;
 	}
 
 	return bMore;
@@ -1036,7 +1031,9 @@ irqreturn_t musb_h_ep0_irq(struct musb *
 
 	MGC_SelectEnd(pBase, 0);
 	wCsrVal = musb_readw(epio, MGC_O_HDRC_CSR0);
-	wCount = musb_readb(epio, MGC_O_HDRC_COUNT0);
+	wCount = (wCsrVal & MGC_M_CSR0_RXPKTRDY)
+			? musb_readb(epio, MGC_O_HDRC_COUNT0)
+			: 0;
 
 	DBG(4, "<== csr0 %04x, qh %p, count %d, urb %p, stage %d\n",
 		wCsrVal, qh, wCount, pUrb, pThis->bEnd0Stage);
@@ -1117,10 +1114,14 @@ irqreturn_t musb_h_ep0_irq(struct musb *
 				?  MGC_M_CSR0_H_REQPKT : MGC_M_CSR0_TXPKTRDY;
 		} else {
 			/* data transfer complete; perform status phase */
-			wCsrVal = MGC_M_CSR0_H_STATUSPKT
-				| (usb_pipeout(pUrb->pipe)
-					? MGC_M_CSR0_H_REQPKT
-					: MGC_M_CSR0_TXPKTRDY);
+			if (usb_pipeout(pUrb->pipe)
+					|| !pUrb->transfer_buffer_length)
+				wCsrVal = MGC_M_CSR0_H_STATUSPKT
+					| MGC_M_CSR0_H_REQPKT;
+			else
+				wCsrVal = MGC_M_CSR0_H_STATUSPKT
+					| MGC_M_CSR0_TXPKTRDY;
+
 			/* flag status stage */
 			pThis->bEnd0Stage = MGC_END0_STATUS;
 
@@ -1129,7 +1130,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *
 		}
 		musb_writew(epio, MGC_O_HDRC_CSR0, wCsrVal);
 		retval = IRQ_HANDLED;
-	}
+	} else
+		pThis->bEnd0Stage = MGC_END0_IDLE;
 
 	/* call completion handler if done */
 	if (bComplete)
--- d26x.orig/drivers/usb/musb/musbdefs.h	2007-03-19 11:31:06.000000000 -0700
+++ d26x/drivers/usb/musb/musbdefs.h	2007-03-19 12:25:16.000000000 -0700
@@ -176,10 +176,13 @@ static inline void musb_host_rx(struct m
 #endif
 
 /* host side ep0 states */
-#define MGC_END0_START  0x0
-#define MGC_END0_OUT    0x2
-#define MGC_END0_IN     0x4
-#define MGC_END0_STATUS 0x8
+enum musb_h_ep0_state {
+	MGC_END0_IDLE,
+	MGC_END0_START,			/* expect ack of setup */
+	MGC_END0_IN,			/* expect IN DATA */
+	MGC_END0_OUT,			/* expect ack of OUT DATA */
+	MGC_END0_STATUS,		/* expect ack of STATUS */
+} __attribute__ ((packed));
 
 /* peripheral side ep0 states */
 enum musb_g_ep0_state {
@@ -347,7 +350,7 @@ struct musb {
 	u32			port1_status;
 	unsigned long		rh_timer;
 
-	u8 bEnd0Stage;		/* end0 stage while in host */
+	enum musb_h_ep0_state	bEnd0Stage;
 
 	/* bulk traffic normally dedicates endpoint hardware, and each
 	 * direction has its own ring of host side endpoints.

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.