netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6.6-bk8] pcnet32: fix bogus carrier errors with 79c973
@ 2004-05-24 19:33 Don Fry
  2004-05-27 17:12 ` Jeff Garzik
  0 siblings, 1 reply; 2+ messages in thread
From: Don Fry @ 2004-05-24 19:33 UTC (permalink / raw)
  To: tsbogend, jgarzik, netdev

The 79C973 version of the pcnet32 chipset would report all transmit
operations as being sent with a carrier error.  The root cause was
writing reserved bits in bcr33.  It caused the 973 to report xmit
as errors, and caused 975 and 976 to hard hang when reading bcr34.

My thanks to Bruce Penrod for his help in finding the cause of this
bug.

--- linux-2.6.6-bk8/drivers/net/limit.pcnet32.c	Sat May 22 15:16:50 2004
+++ linux-2.6.6-bk8/drivers/net/pcnet32.c	Mon May 24 11:24:22 2004
@@ -22,8 +22,8 @@
  *************************************************************************/
 
 #define DRV_NAME	"pcnet32"
-#define DRV_VERSION	"1.30a"
-#define DRV_RELDATE	"05.22.2004"
+#define DRV_VERSION	"1.30b"
+#define DRV_RELDATE	"05.24.2004"
 #define PFX		DRV_NAME ": "
 
 static const char *version =
@@ -132,7 +132,7 @@
 };
 #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
 
-#define PCNET32_NUM_REGS 146
+#define PCNET32_NUM_REGS 168
 
 #define MAX_UNITS 8	/* More are supported, limit only on options */
 static int options[MAX_UNITS];
@@ -242,6 +242,8 @@
  * v1.30   18 May 2004 Don Fry removed timer and Last Transmit Interrupt
  *	   (ltint) as they added complexity and didn't give good throughput.
  * v1.30a  22 May 2004 Don Fry limit frames received during interrupt.
+ * v1.30b  24 May 2004 Don Fry fix bogus tx carrier errors with 79c973,
+ *	   assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>.
  */
 
 
@@ -889,15 +891,25 @@
     for (i=0; i<16; i += 2)
 	*buff++ = inw(ioaddr + i);
 
-    for (i = 0; i <= 89; i++) {
+    /* read control and status registers */
+    for (i=0; i<90; i++) {
 	*buff++ = a->read_csr(ioaddr, i);
     }
 
     *buff++ = a->read_csr(ioaddr, 112);
     *buff++ = a->read_csr(ioaddr, 114);
 
-    for (i = 0; i <= 35; i++) {
-	*buff++ = (i == 34) ? 0xdead : a->read_bcr(ioaddr, i);
+    /* read bus configuration registers */
+    for (i=0; i<36; i++) {
+	*buff++ = a->read_bcr(ioaddr, i);
+    }
+
+    /* read mii phy registers */
+    if (lp->mii) {
+	for (i=0; i<32; i++) {
+	    lp->a.write_bcr(ioaddr, 33, ((lp->mii_if.phy_id) << 5) | i);
+	    *buff++ = lp->a.read_bcr(ioaddr, 34);
+	}
     }
 
     if (!(csr0 & 0x0004)) {	/* If not stopped */
@@ -1751,6 +1763,9 @@
 		    /* There was an major error, log it. */
 		    int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
 		    lp->stats.tx_errors++;
+		    if (netif_msg_tx_err(lp))
+			printk(KERN_ERR "%s: Tx error status=%04x err_status=%08x\n",
+				dev->name, status, err_status);
 		    if (err_status & 0x04000000) lp->stats.tx_aborted_errors++;
 		    if (err_status & 0x08000000) lp->stats.tx_carrier_errors++;
 		    if (err_status & 0x10000000) lp->stats.tx_window_errors++;
@@ -2116,39 +2131,33 @@
     spin_unlock_irqrestore(&lp->lock, flags);
 }
 
+/* This routine assumes that the lp->lock is held */
 static int mdio_read(struct net_device *dev, int phy_id, int reg_num)
 {
     struct pcnet32_private *lp = dev->priv;
     unsigned long ioaddr = dev->base_addr;
     u16 val_out;
-    int phyaddr;
 
     if (!lp->mii)
 	return 0;
 
-    phyaddr = lp->a.read_bcr(ioaddr, 33);
-
     lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
     val_out = lp->a.read_bcr(ioaddr, 34);
-    lp->a.write_bcr(ioaddr, 33, phyaddr);
 
     return val_out;
 }
 
+/* This routine assumes that the lp->lock is held */
 static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
 {
     struct pcnet32_private *lp = dev->priv;
     unsigned long ioaddr = dev->base_addr;
-    int phyaddr;
 
     if (!lp->mii)
 	return;
 
-    phyaddr = lp->a.read_bcr(ioaddr, 33);
-
     lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
     lp->a.write_bcr(ioaddr, 34, val);
-    lp->a.write_bcr(ioaddr, 33, phyaddr);
 }
 
 static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)

-- 
Don Fry
brazilnut@us.ibm.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 2.6.6-bk8] pcnet32: fix bogus carrier errors with 79c973
  2004-05-24 19:33 [PATCH 2.6.6-bk8] pcnet32: fix bogus carrier errors with 79c973 Don Fry
@ 2004-05-27 17:12 ` Jeff Garzik
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Garzik @ 2004-05-27 17:12 UTC (permalink / raw)
  To: Don Fry; +Cc: tsbogend, netdev

applied to 2.4 and 2.6

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-05-27 17:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-24 19:33 [PATCH 2.6.6-bk8] pcnet32: fix bogus carrier errors with 79c973 Don Fry
2004-05-27 17:12 ` Jeff Garzik

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).