linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eli Carter <eli.carter@inet.com>
To: linux-arm-kernel@lists.arm.linux.org.uk,
	linux-kernel@vger.kernel.org, tsbogend@alpha.franken.de
Cc: eli.carter@inet.com, alan@redhat.com
Subject: [PATCH] pcnet32.c ARM support & AM79C973 improvements
Date: Thu, 18 Jan 2001 10:46:13 -0600	[thread overview]
Message-ID: <3A671DD5.51B4DEE@inet.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1096 bytes --]

All,

Here is a patch that adds the following to the pcnet32.c driver:
- adds dma_cache_*() calls to support ARM processors.  Based on
Russell's changes to the tulip driver.
- add DXSUFLO to the AM79C973
- made DXSUFLO the default
- utilized the internal SRAM of the AM79C973
- added a 32 bit write & reset to the detection code since that was
needed on my system
- tried to improve the readability of the "Ring data dump" slightly
- According to the Am79C973/Am79C975 docs from AMD, The collision bits
are only valid if ENP is set, so I added a check for that.

The patch is against 2.2.18 and should apply cleanly.  I'm sending it as
an attachment since I've had difficulties other ways and I don't have a
handy place to leave it for ftp.

This can probably be done better... I'd like pointers for ways to
improve my changes.  Feedback on testing would be welcomed as well.

Comments?

Eli 
--------------------. "To the systems programmer, users and applications
Eli Carter          | serve only to provide a test load."
eli.carter@inet.com `---------------------------------- (random fortune)

[-- Attachment #2: patch-pcnet32-arm --]
[-- Type: text/plain, Size: 6184 bytes --]

--- linux/drivers/net/pcnet32.c	2001/01/17 17:42:48	1.3
+++ linux/drivers/net/pcnet32.c	2001/01/18 16:16:13
@@ -41,6 +41,13 @@
 #include <linux/skbuff.h>
 #include <asm/spinlock.h>
 
+/* try to take care of non-cache-coherant systems */
+#ifndef dma_cache_inv
+#define dma_cache_inv(start, size)
+#define dma_cache_wback(start, size)
+#define dma_cache_wback_inv(start, size)
+#endif
+
 static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
 
 static int pcnet32_debug = 1;
@@ -166,6 +173,7 @@
  * v1.25kf Added No Interrupt on successful Tx for some Tx's <kaf@fc.hp.com>
  */
 
+#define DO_DXSUFLO
 
 /*
  * Set the number of Tx and Rx buffers, using Log_2(# buffers).
@@ -553,6 +561,10 @@
     if (pcnet32_wio_read_csr (ioaddr, 0) == 4 && pcnet32_wio_check (ioaddr)) {
 	a = &pcnet32_wio;
     } else {
+	/* try to force it to 32bit mode by doing a safe write */
+	pcnet32_dwio_write_csr (ioaddr, 0, 0);
+	/* and a reset */
+	pcnet32_dwio_reset(ioaddr);
 	if (pcnet32_dwio_read_csr (ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) {
 	    a = &pcnet32_dwio;
 	} else
@@ -613,7 +625,21 @@
 	break;
      case 0x2625:
 	chipname = "PCnet/FAST III 79C973";
+	/* To prevent Tx FIFO underflows ... (may increase Tx latency) */
+	/* Set BCR18:NOUFLO to not start Tx until reach Tx start point */
+	/* Looks like EEPROM sets BCR18:5/6 for BurstWrite/Read */
+        a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800 | (3<<5) ));
+	/* Set CSR80:XMTSP, Tx start point = 20|64|128|220 bytes or size of frame */
+        i = a->read_csr(ioaddr, 80) & ~0x0C00; /* Clear bits we are touching */
+        a->write_csr(ioaddr, 80, i | (tx_start << 10));
 	fdx = 1; mii = 1;
+#ifdef DO_DXSUFLO
+	dxsuflo = 1;
+#endif
+	ltint = 1;
+	/* Try using the chip's internal SRAM for better performance */
+	a->write_bcr(ioaddr, 25, 20);
+	a->write_bcr(ioaddr, 26, 10 );
 	break;
      case 0x2626:
 	chipname = "PCnet/Home 79C978";
@@ -861,6 +887,8 @@
     if (pcnet32_init_ring(dev))
 	return -ENOMEM;
     
+    dma_cache_wback( &lp->init_block, sizeof(struct pcnet32_init_block) );
+
     /* Re-initialize the PCNET32, and start it when done. */
     lp->a.write_csr (ioaddr, 1, virt_to_bus(&lp->init_block) &0xffff);
     lp->a.write_csr (ioaddr, 2, virt_to_bus(&lp->init_block) >> 16);
@@ -955,6 +983,10 @@
 	lp->init_block.phys_addr[i] = dev->dev_addr[i];
     lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring));
     lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring));
+
+    dma_cache_wback(lp->rx_ring, RX_RING_SIZE * sizeof(struct pcnet32_rx_head));
+    dma_cache_wback(lp->tx_ring, TX_RING_SIZE * sizeof(struct pcnet32_tx_head));
+
     return 0;
 }
 
@@ -1002,12 +1034,14 @@
 	    printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
 		   lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
 		   lp->cur_rx);
+	    printk("\nrx_ring:");
 	    for (i = 0 ; i < RX_RING_SIZE; i++)
-		printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+		printk("%s %08x %04x %08x %4.4x", i & 1 ? "" : "\n ",
 		       lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
 		       lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status);
+	    printk("\ntx_ring:");
 	    for (i = 0 ; i < TX_RING_SIZE; i++)
-		printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+		printk("%s %08x %04x %08x %4.4x", i & 1 ? "" : "\n ",
 		       lp->tx_ring[i].base, -lp->tx_ring[i].length,
 		       lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status);
 	    printk("\n");
@@ -1064,10 +1098,14 @@
 
     lp->tx_skbuff[entry] = skb;
     lp->tx_ring[entry].base = (u32)le32_to_cpu(virt_to_bus(skb->data));
+    dma_cache_wback((unsigned long)skb->data, skb->len);
+    dma_cache_wback((unsigned long)&lp->tx_ring[entry], sizeof(&lp->tx_ring[entry]));
 
     lp->tx_ring[entry].status = le16_to_cpu(status);
 
     lp->cur_tx++;
+    dma_cache_wback((unsigned long)&lp->tx_ring[entry].status, sizeof(&lp->tx_ring[entry].status));
+
     lp->stats.tx_bytes += skb->len;
 
     /* Trigger an immediate send poll. */
@@ -1128,7 +1166,11 @@
 
 	    while (dirty_tx < lp->cur_tx) {
 		int entry = dirty_tx & TX_RING_MOD_MASK;
-		int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
+		int status;
+
+		dma_cache_wback_inv((unsigned long)&lp->tx_ring[entry].status, sizeof(&lp->tx_ring[entry].status));
+
+		status = (short)le16_to_cpu(lp->tx_ring[entry].status);
 			
 		if (status < 0)
 		    break;		/* It still hasn't been Txed */
@@ -1164,7 +1206,8 @@
 		    }
 #endif
 		} else {
-		    if (status & 0x1800)
+		    /* MORE and ONE are only valid if ENP is set */
+		    if (status & 0x0040 && status & 0x1800)
 			lp->stats.collisions++;
 		    lp->stats.tx_packets++;
 		}
@@ -1244,6 +1287,7 @@
     int i;
 
     /* If we own the next entry, it's a new packet. Send it up. */
+    dma_cache_inv((unsigned long)&lp->rx_ring[entry],sizeof(&lp->rx_ring[entry]));
     while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
 	int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8;
 
@@ -1303,6 +1347,7 @@
 		}
 		skb->dev = dev;
 		if (!rx_in_place) {
+		    dma_cache_inv(bus_to_virt(le32_to_cpu(lp->rx_ring[entry].base)), pkt_len);
 		    skb_reserve(skb,2);	/* 16 byte align */
 		    skb_put(skb,pkt_len);	/* Make room */
 		    eth_copy_and_sum(skb,
@@ -1320,8 +1365,11 @@
 	 * of QNX reports that some revs of the 79C965 clear it.
 	 */
 	lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	dma_cache_wback((unsigned long)&lp->rx_ring[entry], sizeof(&lp->rx_ring[entry]));
 	lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
+	dma_cache_wback((unsigned long)&lp->rx_ring[entry].status, sizeof(&lp->rx_ring[entry].status));
 	entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+	dma_cache_inv((unsigned long)&lp->rx_ring[entry], sizeof(&lp->rx_ring[entry]));
     }
 
     return 0;
@@ -1357,6 +1405,7 @@
     /* free all allocated skbuffs */
     for (i = 0; i < RX_RING_SIZE; i++) {
 	lp->rx_ring[i].status = 0;	    	    	    
+	dma_cache_wback((unsigned long)&lp->rx_ring[i].status, sizeof(&lp->rx_ring[i].status));
 	if (lp->rx_skbuff[i])
 	    dev_kfree_skb(lp->rx_skbuff[i]);
 	lp->rx_skbuff[i] = NULL;

             reply	other threads:[~2001-01-18 16:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-01-18 16:46 Eli Carter [this message]
2001-01-18 18:37 ` [PATCH] pcnet32.c ARM support & AM79C973 improvements Eli Carter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3A671DD5.51B4DEE@inet.com \
    --to=eli.carter@inet.com \
    --cc=alan@redhat.com \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tsbogend@alpha.franken.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).