[vortex] 3c905 oddities

Andrew Morton andrewm@uow.edu.au
Fri, 15 Dec 2000 00:29:38 +1100


Bogdan Costescu wrote:
> 
> To Andrew: Did you receive the data from Richard w.r.t. timing of
> different commands ?

No, I did not.

I think we should all assume false identities and create devfs flamewars
on the kernel list until he submits.  We haven't had one of those for a while.



Richard, here's the patch against test12.  Could you please apply it
to one of your 3c905CX boxes, run some traffic and send us the logs?

Thanks.



--- linux-2.4.0-test12/drivers/net/3c59x.c	Tue Nov 21 20:11:20 2000
+++ linux-akpm/drivers/net/3c59x.c	Fri Dec 15 00:20:06 2000
@@ -118,6 +118,10 @@
    LK1.1.11 13 Nov 2000 andrewm
     - Dump MOD_INC/DEC_USE_COUNT, use SET_MODULE_OWNER
 
+   LK1.1.12 9 Dec 2000 andrewm
+    - Call pci_enable_device before we request our IRQ (Tobias Ringstrom)
+    - Add 3c590 PCI latency timer hack to vortex_probe1 (from 0.99Ra)
+
     - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
     - Also see Documentation/networking/vortex.txt
 */
@@ -203,7 +207,7 @@
 #include <linux/delay.h>
 
 static char version[] __devinitdata =
-"3c59x.c:LK1.1.11 13 Nov 2000  Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.46 $\n";
+"3c59x.c:LK1.1.12 9 Dec 2000  Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.4 $\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver");
@@ -843,10 +847,15 @@
 {
 	int rc;
 
-	rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
-			    ent->driver_data, vortex_cards_found);
-	if (rc == 0)
-		vortex_cards_found++;
+	/* wake up and enable device */		
+	if (pdev && pci_enable_device (pdev)) {
+		rc = -EIO;
+	} else {
+		rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
+				    ent->driver_data, vortex_cards_found);
+		if (rc == 0)
+			vortex_cards_found++;
+	}
 	return rc;
 }
 
@@ -863,7 +872,7 @@
 	struct vortex_private *vp;
 	int option;
 	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
-	int i;
+	int i, step;
 	struct net_device *dev;
 	static int printed_version;
 	int retval;
@@ -906,21 +915,30 @@
 
 	/* PCI-only startup logic */
 	if (pdev) {
+		u8 pci_latency;
+		u8 new_latency = (vci->drv_flags & IS_VORTEX) ? 248 : 32;
+
 		/* EISA resources already marked, so only PCI needs to do this here */
 		/* Ignore return value, because Cardbus drivers already allocate for us */
 		if (request_region(ioaddr, vci->io_size, dev->name) != NULL) {
 			vp->must_free_region = 1;
 		}
 
-		/* wake up and enable device */		
-		if (pci_enable_device (pdev)) {
-			retval = -EIO;
-			goto free_region;
-		}
-
 		/* enable bus-mastering if necessary */		
 		if (vci->flags & PCI_USES_MASTER)
 			pci_set_master (pdev);
+
+		/* Check the PCI latency value.  On the 3c590 series the latency timer
+		   must be set to the maximum value to avoid data corruption that occurs
+		   when the timer expires during a transfer.  This bug exists the Vortex
+		   chip only. */
+		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+		if (pci_latency < new_latency) {
+			printk(KERN_INFO "%s: Overriding PCI latency"
+				" timer (CFLT) setting of %d, new value is %d.\n",
+				dev->name, pci_latency, new_latency);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
+		}
 	}
 
 	spin_lock_init(&vp->lock);
@@ -1025,6 +1043,13 @@
 			   dev->irq);
 #endif
 
+	EL3WINDOW(4);
+	step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
+	printk(KERN_INFO "  product code '%c%c' rev %02x.%d date %02d-"
+		   "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
+		   step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
+
+
 	if (pdev && vci->drv_flags & HAS_CB_FNS) {
 		unsigned long fn_st_addr;			/* Cardbus function status space */
 		unsigned short n;
@@ -1148,14 +1173,19 @@
 	return retval;
 }
 
-static void wait_for_completion(struct net_device *dev, int cmd)
+#define wait_for_completion(dev, cmd) _wait_for_completion(dev, cmd, __LINE__)
+
+static void _wait_for_completion(struct net_device *dev, int cmd, int line)
 {
-	int i = 4000;
+	int i;
 
 	outw(cmd, dev->base_addr + EL3_CMD);
-	while (--i > 0) {
-		if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
+	for (i = 0; i < 4000000; i++) {
+		if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) {
+			if (i > 100)
+				printk("wait_for_completion: line=%d, count=%d\n", line, i);
 			return;
+		}
 	}
 	printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
 			   dev->name, cmd, inw(dev->base_addr + EL3_STATUS));
@@ -1331,6 +1361,7 @@
 	set_rx_mode(dev);
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
+//	wait_for_completion(dev, SetTxStart|0x07ff);
 	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
 	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
 	/* Allow status bits to be seen. */
@@ -1663,6 +1694,12 @@
 			   dev->name, fifo_diag);
 		/* Adapter failure requires Tx/Rx reset and reinit. */
 		if (vp->full_bus_master_tx) {
+			int bus_status = inl(ioaddr + PktStatus);
+			/* 0x80000000 PCI master abort. */
+			/* 0x40000000 PCI target abort. */
+			if (vortex_debug)
+				printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
+
 			/* In this case, blow the card away */
 			vortex_down(dev);
 			wait_for_completion(dev, TotalReset | 0xff);