Patchwork [U-Boot] dm9000 patch tftp, nfs fixes.

login
register
mail settings
Submitter Chris Ruehl
Date March 25, 2013, 4:43 p.m.
Message ID <51507EB6.1040900@gtsys.com.hk>
Download mbox | patch
Permalink /patch/230759/
State Changes Requested
Delegated to: Tom Rini
Headers show

Comments

Chris Ruehl - March 25, 2013, 4:43 p.m.
Hi,

I start a project on a freescale imx27 using the dm9000a for network.

I learned that the tftp , nfs and other network related working more less very 
unstable. I start compare the dm9000.c code with the upstream kernel v3.8.4 and 
fix some issues.

issues
tftp
   with many bad checksums and timeouts
nfs
   with not working at all when upload a 38Mbyte rootfs.jffs2


After the patch its works much better for me.
please find my patch attached and consider to merge it the the head branch.

cheers
Chris
Tom Rini - March 28, 2013, 9:50 p.m.
On Mon, Mar 25, 2013 at 06:43:34AM -0000, Chris Ruehl wrote:

> Hi,
> 
> I start a project on a freescale imx27 using the dm9000a for network.
> 
> I learned that the tftp , nfs and other network related working more
> less very unstable. I start compare the dm9000.c code with the
> upstream kernel v3.8.4 and fix some issues.
> 
> issues
> tftp
>    with many bad checksums and timeouts
> nfs
>    with not working at all when upload a 38Mbyte rootfs.jffs2
> 
> 
> After the patch its works much better for me.
> please find my patch attached and consider to merge it the the head branch.
[snip]
> @@ -351,75 +353,82 @@ static int dm9000_eth_rx (struct eth_device *edev)
>  	u32 tmplen, i;
>  	u32 tmpdata;
>  
> +	udelay(2500); // we called in a loop to quick .. give me some time

No // style comments, and "We were called into the loop too quickly".

And I don't know if the big delay here is a good thing or not, without
knowing the hardware.  Jason, you've touched this driver recently and I
assume know the hardware at least a little bit, can you comment here?
For full context see http://patchwork.ozlabs.org/patch/230759/ thanks!
Chris Ruehl - March 29, 2013, 5:32 a.m.
On Friday, March 29, 2013 05:50 AM, Tom Rini wrote:
> On Mon, Mar 25, 2013 at 06:43:34AM -0000, Chris Ruehl wrote:
>
>> Hi,
>>
>> I start a project on a freescale imx27 using the dm9000a for network.
>>
>> I learned that the tftp , nfs and other network related working more
>> less very unstable. I start compare the dm9000.c code with the
>> upstream kernel v3.8.4 and fix some issues.
>>
>> issues
>> tftp
>>     with many bad checksums and timeouts
>> nfs
>>     with not working at all when upload a 38Mbyte rootfs.jffs2
>>
>>
>> After the patch its works much better for me.
>> please find my patch attached and consider to merge it the the head branch.
> [snip]
>> @@ -351,75 +353,82 @@ static int dm9000_eth_rx (struct eth_device *edev)
>>   	u32 tmplen, i;
>>   	u32 tmpdata;
>>
>> +	udelay(2500); // we called in a loop to quick .. give me some time
>
> No // style comments, and "We were called into the loop too quickly".
>
> And I don't know if the big delay here is a good thing or not, without
> knowing the hardware.  Jason, you've touched this driver recently and I
> assume know the hardware at least a little bit, can you comment here?
> For full context see http://patchwork.ozlabs.org/patch/230759/ thanks!
>

Tom,

yeah, .. sorry about the style, I'd missed the comment .. ( I gonna fix this and 
resend my patch later ..)
you right about its hardware dependency, on the mx27 @ 400Mhz I tried it
with delays from 1000-3000 where 2500 give me the best result.
Without a delay its end up in tftp *TTTT#.. and NFS is not working at all.

Chris

Patch

diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index b8ad98d..ce2d97a 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -58,6 +58,7 @@ 
 #define DM9000_ID		0x90000A46
 #define DM9000_PKT_MAX		1536	/* Received packet max size */
 #define DM9000_PKT_RDY		0x01	/* Packet ready to receive */
+#define DM9000_PKT_ERR      0x02
 
 #define DM9000_NCR             0x00
 #define DM9000_NSR             0x01
@@ -163,6 +164,7 @@ 
 #define IMR_ROM			(1<<2)
 #define IMR_PTM			(1<<1)
 #define IMR_PRM			(1<<0)
+#define IMR_LNKCHNG     (1<<5)
 
 struct dm9000_priv {
 	unsigned long iobase;
@@ -351,75 +353,82 @@  static int dm9000_eth_rx (struct eth_device *edev)
 	u32 tmplen, i;
 	u32 tmpdata;
 
+	udelay(2500); // we called in a loop to quick .. give me some time
+
 	/* Check packet ready or not */
 	DM9000_ior(priv, DM9000_MRCMDX);	/* Dummy read */
+	udelay(100);
 	rxbyte = readb(priv->iodata);	/* Got most updated data */
-	if (rxbyte == 0)
-		return 0;
 
 	/* Status check: this byte must be 0 or 1 */
-	if (rxbyte > 1) {
-		DM9000_iow(priv, DM9000_RCR, 0x00);	/* Stop Device */
-		DM9000_iow(priv, DM9000_ISR, 0x80);	/* Stop INT request */
-		debug("rx status check: %d\n", rxbyte);
+	if (rxbyte & DM9000_PKT_ERR) {
+		debug("rx status check failed: %d\n", rxbyte);
+		DM9000_iow(priv, DM9000_RCR, 0x00);  /* Stop Device */
+		DM9000_iow(priv, DM9000_ISR, IMR_PAR);   /* Stop INT request */
+		dm9000_reset(priv);
+		/* re-enable the interupt, rx */
+		DM9000_iow(priv, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+		DM9000_iow(priv, DM9000_ISR, 0x0f);	
 	}
-	debug("receiving packet\n");
-
-	/* A packet ready now  & Get status/length */
-	writeb(DM9000_MRCMD, priv->iobase);
-
-	/* Move data from DM9000 */
-	/* Read received packet from RX SRAM */
-	switch (priv->buswidth) {
-	case DM9000_WIDTH_8:
-		RxStatus = readb(priv->iodata) + (readb(priv->iodata) << 8);
-		RxLen = readb(priv->iodata) + (readb(priv->iodata) << 8);
-		for (i = 0; i < RxLen; i++)
-			rdptr[i] = readb(priv->iodata);
-		break;
-	case DM9000_WIDTH_16:
-		RxStatus = readw(priv->iodata);
-		RxLen = readw(priv->iodata);
-		tmplen = (RxLen + 1) / 2;
-		for (i = 0; i < tmplen; i++)
-			((u16 *) rdptr)[i] = readw(priv->iodata);
-		break;
-	case DM9000_WIDTH_32:
-		tmpdata = readl(priv->iodata);
-		RxStatus = tmpdata;
-		RxLen = tmpdata >> 16;
-		tmplen = (RxLen + 3) / 4;
-		for (i = 0; i < tmplen; i++)
-			((u32 *) rdptr)[i] = readl(priv->iodata);
-		break;
-	default:
-		/* dm9000_probe makes sure this cannot happen */
-		return -EINVAL;
-	}
-
-	if ((RxStatus & 0xbf00) || (RxLen < 0x40)
-	    || (RxLen > DM9000_PKT_MAX)) {
-		if (RxStatus & 0x100) {
-			printf("rx fifo error\n");
-		}
-		if (RxStatus & 0x200) {
-			printf("rx crc error\n");
+	else if ((rxbyte & DM9000_PKT_RDY)) {
+			debug("receiving packet\n");
+
+			/* A packet ready now  & Get status/length */
+			writeb(DM9000_MRCMD, priv->iobase);
+			udelay(100);
+
+			/* Move data from DM9000 */
+			/* Read received packet from RX SRAM */
+			switch (priv->buswidth) {
+				case DM9000_WIDTH_8:
+					RxStatus = readb(priv->iodata) + (readb(priv->iodata) << 8);
+					RxLen = readb(priv->iodata) + (readb(priv->iodata) << 8);
+					for (i = 0; i < RxLen; i++)
+						rdptr[i] = readb(priv->iodata);
+					break;
+				case DM9000_WIDTH_16:
+					RxStatus = readw(priv->iodata);
+					RxLen = readw(priv->iodata);
+					tmplen = (RxLen + 1) / 2;
+					for (i = 0; i < tmplen; i++)
+						((u16 *) rdptr)[i] = readw(priv->iodata);
+					break;
+				case DM9000_WIDTH_32:
+					tmpdata = readl(priv->iodata);
+					RxStatus = tmpdata;
+					RxLen = tmpdata >> 16;
+					tmplen = (RxLen + 3) / 4;
+					for (i = 0; i < tmplen; i++)
+						((u32 *) rdptr)[i] = readl(priv->iodata);
+					break;
+				default:
+					/* dm9000_probe makes sure this cannot happen */
+					return -EINVAL;
+			}
+
+			if ((RxStatus & 0xbf00) || (RxLen < 0x40)
+					|| (RxLen > DM9000_PKT_MAX)) {
+				if (RxStatus & 0x100) {
+					printf("rx fifo error\n");
+				}
+				if (RxStatus & 0x200) {
+					printf("rx crc error\n");
+				}
+				if (RxStatus & 0x8000) {
+					printf("rx length error\n");
+				}
+				if (RxLen > DM9000_PKT_MAX) {
+					printf("rx length too big\n");
+				}
+				dm9000_reset(priv);
+				RxLen = 0;
+			} else {
+				/* Pass to upper layer */
+				debug("passing packet to upper layer\n");
+				NetReceive(NetRxPackets[0], RxLen);
+			}
 		}
-		if (RxStatus & 0x8000) {
-			printf("rx length error\n");
-		}
-		if (RxLen > DM9000_PKT_MAX) {
-			printf("rx length too big\n");
-			dm9000_reset(priv);
-		}
-	} else {
-
-		/* Pass to upper layer */
-		debug("passing packet to upper layer\n");
-		NetReceive(NetRxPackets[0], RxLen);
-		return RxLen;
-	}
-	return 0;
+	return RxLen;
 }
 
 static u16 read_srom_word(struct dm9000_priv *priv, int offset)
@@ -511,7 +520,7 @@  static int dm9000_probe(struct device_d *dev)
 	DM9000_iow(priv, DM9000_TCR, 0);	/* TX Polling clear */
 	DM9000_iow(priv, DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */
 	DM9000_iow(priv, DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));	/* Flow Control : High/Low Water */
-	DM9000_iow(priv, DM9000_FCR, 0x0);	/* SH FIXME: This looks strange! Flow Control */
+	DM9000_iow(priv, DM9000_FCR, 0xFF);	/* Flow Control */
 	DM9000_iow(priv, DM9000_SMCR, 0);	/* Special Mode */
 	DM9000_iow(priv, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);	/* clear TX status */
 	DM9000_iow(priv, DM9000_ISR, 0x0f);	/* Clear interrupt status */
@@ -520,7 +529,7 @@  static int dm9000_probe(struct device_d *dev)
 	DM9000_iow(priv, DM9000_GPCR, 0x01);	/* Let GPIO0 output */
 	DM9000_iow(priv, DM9000_GPR, 0x00);	/* Enable PHY */
 	DM9000_iow(priv, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);	/* RX enable */
-	DM9000_iow(priv, DM9000_IMR, IMR_PAR);	/* Enable TX/RX interrupt mask */
+	DM9000_iow(priv, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM | IMR_LNKCHNG );	/* Enable TX/RX interrupt mask */
 
 	priv->miiphy.read = dm9000_phy_read;
 	priv->miiphy.write = dm9000_phy_write;