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

Submitted by Chris Ruehl on March 25, 2013, 4:43 p.m.

Details

Message ID 51507EB6.1040900@gtsys.com.hk
State Changes Requested
Delegated to: Tom Rini
Headers show

Commit Message

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

Comments

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 hide | download patch | download mbox

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;