patch-2.4.0-test9 linux/drivers/net/acenic.c

Next file: linux/drivers/net/acenic.h
Previous file: linux/drivers/net/Space.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
@@ -29,7 +29,16 @@
  *                                       infrastructure and Sparc support
  *   Pierrick Pinasseau (CERN): For lending me an Ultra 5 to test the
  *                              driver under Linux/Sparc64
- *   Matt Domsch <Matt_Domsch@dell.com>: Detect 1000baseT cards
+ *   Matt Domsch <Matt_Domsch@dell.com>: Detect Alteon 1000baseT cards
+ *   Chip Salzenberg <chip@valinux.com>: Fix race condition between tx
+ *                                       handler and close() cleanup.
+ *   Ken Aaker <kdaaker@rchland.vnet.ibm.com>: Correct check for whether
+ *                                       memory mapped IO is enabled to
+ *                                       make the driver work on RS/6000.
+ *   Takayoshi Kouchi <kouchi@hpc.bs1.fc.nec.co.jp>: Identifying problem
+ *                                       where the driver would disable
+ *                                       bus master mode if it had to disable
+ *                                       write and invalidate.
  */
 
 #include <linux/config.h>
@@ -83,8 +92,13 @@
 #define PCI_VENDOR_ID_NETGEAR		0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
 #endif
+#ifndef PCI_DEVICE_ID_NETGEAR_GA620T
+#define PCI_DEVICE_ID_NETGEAR_GA620T	0x630a
+#endif
+
 /*
- * They used the DEC vendor ID by mistake
+ * Farallon used the DEC vendor ID by mistake and they seem not
+ * to care - stinky!
  */
 #ifndef PCI_DEVICE_ID_FARALLON_PN9000SX
 #define PCI_DEVICE_ID_FARALLON_PN9000SX	0x1a
@@ -379,22 +393,22 @@
 #define DEF_TRACE		0
 #define DEF_STAT		(2 * TICKS_PER_SEC)
 
-static int link[ACE_MAX_MOD_PARMS] = {0, };
-static int trace[ACE_MAX_MOD_PARMS] = {0, };
-static int tx_coal_tick[ACE_MAX_MOD_PARMS] = {0, };
-static int rx_coal_tick[ACE_MAX_MOD_PARMS] = {0, };
-static int max_tx_desc[ACE_MAX_MOD_PARMS] = {0, };
-static int max_rx_desc[ACE_MAX_MOD_PARMS] = {0, };
-static int tx_ratio[ACE_MAX_MOD_PARMS] = {0, };
+static int link[ACE_MAX_MOD_PARMS];
+static int trace[ACE_MAX_MOD_PARMS];
+static int tx_coal_tick[ACE_MAX_MOD_PARMS];
+static int rx_coal_tick[ACE_MAX_MOD_PARMS];
+static int max_tx_desc[ACE_MAX_MOD_PARMS];
+static int max_rx_desc[ACE_MAX_MOD_PARMS];
+static int tx_ratio[ACE_MAX_MOD_PARMS];
 static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 
-static const char __initdata *version = 
-  "acenic.c: v0.44 05/11/2000  Jes Sorensen, linux-acenic@SunSITE.auc.dk\n"
+static char version[] __initdata = 
+  "acenic.c: v0.47 09/18/2000  Jes Sorensen, linux-acenic@SunSITE.auc.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
-static struct net_device *root_dev = NULL;
+static struct net_device *root_dev;
 
-static int probed __initdata = 0;
+static int probed __initdata;
 
 
 #ifdef NEW_NETINIT
@@ -429,7 +443,8 @@
 		    !((pdev->vendor == PCI_VENDOR_ID_3COM) &&
 		      (pdev->device == PCI_DEVICE_ID_3COM_3C985)) &&
 		    !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) &&
-		      (pdev->device == PCI_DEVICE_ID_NETGEAR_GA620)) &&
+		      ((pdev->device == PCI_DEVICE_ID_NETGEAR_GA620) || 
+		       (pdev->device == PCI_DEVICE_ID_NETGEAR_GA620T))) &&
 		/*
 		 * Farallon used the DEC vendor ID on their cards by
 		 * mistake for a while
@@ -477,10 +492,17 @@
 			printk(version);
 		}
 
+		/*
+		 * Enable master mode before we start playing with the
+		 * pci_command word since pci_set_master() will modify
+		 * it.
+		 */
+		pci_set_master(pdev);
+
 		pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
 
 		/* OpenFirmware on Mac's does not set this - DOH.. */ 
-		if (!ap->pci_command & PCI_COMMAND_MEMORY) {
+		if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
 			printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
 			       "access - was not enabled by BIOS/Firmware\n",
 			       dev->name);
@@ -498,8 +520,6 @@
 					      ap->pci_latency);
 		}
 
-		pci_set_master(pdev);
-
 		/*
 		 * Remap the regs into kernel space - this is abuse of
 		 * dev->base_addr since it was means for I/O port
@@ -606,9 +626,9 @@
 MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-
 #endif
 
+
 void __exit ace_module_cleanup(void)
 {
 	struct ace_private *ap;
@@ -713,6 +733,7 @@
 }
 
 
+#ifdef MODULE
 #if (LINUX_VERSION_CODE < 0x02032a)
 int init_module(void)
 {
@@ -728,6 +749,7 @@
 module_init(ace_module_init);
 module_exit(ace_module_cleanup);
 #endif
+#endif
 
 
 static void ace_free_descriptors(struct net_device *dev)
@@ -1994,18 +2016,34 @@
 	if (txcsm != idx) {
 		do {
 			struct sk_buff *skb;
-			dma_addr_t mapping;
 
 			skb = ap->skb->tx_skbuff[idx].skb;
-			mapping = ap->skb->tx_skbuff[idx].mapping;
+			/*
+			 * Race condition between the code cleaning
+			 * the tx queue in the interrupt handler and the
+			 * interface close,
+			 *
+			 * This is a kludge that really should be fixed 
+			 * by preventing the driver from generating a tx
+			 * interrupt when the packet has already been
+			 * removed from the tx queue.
+			 *
+			 * Nailed by Don Dugger and Chip Salzenberg of
+			 * VA Linux.
+			 */
+			if (skb) {
+				dma_addr_t mapping;
 
-			ap->stats.tx_packets++;
-			ap->stats.tx_bytes += skb->len;
-			pci_unmap_single(ap->pdev, mapping, skb->len,
-					 PCI_DMA_TODEVICE);
-			dev_kfree_skb_irq(skb);
+				mapping = ap->skb->tx_skbuff[idx].mapping;
 
-			ap->skb->tx_skbuff[idx].skb = NULL;
+				ap->stats.tx_packets++;
+				ap->stats.tx_bytes += skb->len;
+				pci_unmap_single(ap->pdev, mapping, skb->len,
+						 PCI_DMA_TODEVICE);
+				dev_kfree_skb_irq(skb);
+
+				ap->skb->tx_skbuff[idx].skb = NULL;
+			}
 
 			/*
 			 * Question here is whether one should not skip

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)