patch-2.3.43 linux/drivers/net/tulip.c

Next file: linux/drivers/net/via-rhine.c
Previous file: linux/drivers/net/tokenring/smctr.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.42/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
@@ -75,6 +75,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -101,10 +102,6 @@
 #define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
 #endif
 
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-
 /* This my implementation of shared IRQs, now only used for 1.2.13. */
 #ifdef HAVE_SHARED_IRQ
 #define USE_SHARED_IRQ
@@ -368,16 +365,9 @@
 	u32 setup_frame[48];		/* Pseudo-Tx frame to init address table. */
 	int chip_id;
 	int revision;
-#if LINUX_VERSION_CODE > 0x20139
 	struct net_device_stats stats;
-#else
-	struct enet_statistics stats;
-#endif
 	struct timer_list timer;	/* Media selection timer. */
-	int interrupt;				/* In-interrupt flag. */
-#ifdef SMP_CHECK
-	int smp_proc_id;			/* Which processor in IRQ handler. */
-#endif
+	spinlock_t tx_lock;       
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
@@ -435,7 +425,7 @@
    This allows the probe routine to use the old driver initialization
    interface. */
 
-int tulip_probe(void)
+static int __init tulip_probe(void)
 {
 	int cards_found = 0;
 	static int pci_index = 0;	/* Static, for multiple probe calls. */
@@ -446,17 +436,13 @@
 	   well with the current structure.  So instead we detect just the
 	   Tulip cards in slot order. */
 
-#if LINUX_VERSION_CODE >= 0x20155
 	if (! pci_present())
 		return -ENODEV;
-#else
-	if (! pcibios_present())
-		return -ENODEV;
-#endif
 	for (;pci_index < 0xff; pci_index++) {
 		u16 vendor, device, pci_command, new_command;
 		unsigned long pci_ioaddr = 0;
 		int chip_idx = 0;
+		struct pci_dev *pdev;
 
 		if (pcibios_find_class
 			(PCI_CLASS_NETWORK_ETHERNET << 8,
@@ -468,10 +454,10 @@
 			else
 				break;
 		}
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
+		
+		pdev = pci_find_slot (pci_bus, pci_device_fn);
+		vendor = pdev->vendor;
+		device = pdev->device;
 
 		for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++)
 			if (vendor == tulip_tbl[chip_idx].vendor_id  &&
@@ -485,12 +471,7 @@
 					   vendor, device);
 			continue;
 		}
-#if LINUX_VERSION_CODE >= 0x20155
 		pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start;
-#else
-		pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0,
-								  &pci_ioaddr);
-#endif
 		/* Remove I/O space marker in bit 0. */
 		pci_ioaddr &= ~3;
 
@@ -501,37 +482,32 @@
 		if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size))
 			continue;
 
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_COMMAND, &pci_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled this"
 				   " device!  Updating PCI command %4.4x->%4.4x.\n",
 				   pci_command, new_command);
-			pcibios_write_config_word(pci_bus, pci_device_fn,
-									  PCI_COMMAND, new_command);
+			pci_write_config_word(pdev, PCI_COMMAND, new_command);
 		}
 
 		if(tulip_probe1(pci_bus, pci_device_fn, chip_idx, cards_found))
 		{
 			/* Get and check the bus-master and latency values. */
 			unsigned char pci_latency;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < 10) {
 				printk(KERN_INFO "  PCI latency timer (CFLT) is "
 					   "unreasonably low at %d.  Setting to 64 clocks.\n",
 					   pci_latency);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER, 64);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 			} else if (tulip_debug > 1)
 				printk(KERN_INFO "  PCI latency timer (CFLT) is %#x, "
 					   " PCI command is %4.4x.\n",
 					   pci_latency, new_command);
 			/* Bring the 21143 out power-down mode. */
 			if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
-				pcibios_write_config_dword(pci_bus, pci_device_fn,
-										   0x40, 0x40000000);
+				pci_write_config_dword(pdev, 0x40, 0x40000000);
 			cards_found++;
 		}
 	}
@@ -753,6 +729,8 @@
 	/* The Tulip-specific entries in the device structure. */
 	dev->open = &tulip_open;
 	dev->hard_start_xmit = &tulip_start_xmit;
+	dev->tx_timeout = &tulip_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->stop = &tulip_close;
 	dev->get_stats = &tulip_get_stats;
 #ifdef HAVE_PRIVATE_IOCTL
@@ -1216,9 +1194,7 @@
 	/* When a module we don't have 'x86' to check. */
 	outl(0x01A00000 | 0x4800, ioaddr + CSR0);
 #else
-#if (LINUX_VERSION_CODE > 0x2014c)
 #define x86 boot_cpu_data.x86
-#endif
 	outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);
 	if (x86 <= 4)
 	  printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "
@@ -1249,6 +1225,7 @@
 
 	MOD_INC_USE_COUNT;
 
+    spin_lock_init(&tp->tx_lock);
 	tulip_init_ring(dev);
 
 	/* This is set_rx_mode(), but without starting the transmitter. */
@@ -1329,10 +1306,6 @@
 	outl(tp->csr6, ioaddr + CSR6);
 	outl(tp->csr6 | 0x2000, ioaddr + CSR6);
 
-	dev->tbusy = 0;
-	tp->interrupt = 0;
-	dev->start = 1;
-
 	/* Enable interrupts by setting the interrupt mask. */
 	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
 	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
@@ -1352,6 +1325,8 @@
 	tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
 	add_timer(&tp->timer);
 
+	netif_start_queue(dev);
+
 	return 0;
 }
 
@@ -1958,9 +1933,13 @@
   struct tulip_private *tp = (struct tulip_private *)dev->priv;
   long ioaddr = dev->base_addr;
 
+  printk("%s: transmit timed out\n", dev->name);
+
   if (media_cap[dev->if_port] & MediaIsMII) {
 	  /* Do nothing -- the media monitor should handle this. */
+#if 0
 	  if (tulip_debug > 1)
+#endif
 		  printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
 				 dev->name);
 	  dev->trans_start = jiffies;
@@ -2090,19 +2069,13 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int entry;
 	u32 flag;
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		tulip_tx_timeout(dev);
-		return 1;
-	}
+	unsigned long cpuflags;
 
 	/* Caution: the write order is important here, set the base address
 	   with the "ownership" bits last. */
 
+	spin_lock_irqsave(&tp->tx_lock, cpuflags);
+
 	/* Calculate the next Tx descriptor entry. */
 	entry = tp->cur_tx % TX_RING_SIZE;
 
@@ -2111,17 +2084,15 @@
 
 	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
 	  flag = 0x60000000; /* No interrupt */
-	  dev->tbusy = 0;
 	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
 	  flag = 0xe0000000; /* Tx-done intr. */
-	  dev->tbusy = 0;
 	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
 	  flag = 0x60000000; /* No Tx-done intr. */
-	  dev->tbusy = 0;
 	} else {
 	  /* Leave room for set_rx_mode() to fill entries. */
 	  flag = 0xe0000000; /* Tx-done intr. */
 	  tp->tx_full = 1;
+	  netif_stop_queue(dev);
 	}
 	if (entry == TX_RING_SIZE-1)
 		flag |= 0xe2000000;
@@ -2129,6 +2100,8 @@
 	tp->tx_ring[entry].length = skb->len | flag;
 	tp->tx_ring[entry].status = 0x80000000;	/* Pass ownership to the chip. */
 	tp->cur_tx++;
+	spin_unlock_irqrestore(&tp->tx_lock, cpuflags);
+
 	/* Trigger an immediate transmit demand. */
 	outl(0, dev->base_addr + CSR1);
 
@@ -2159,20 +2132,6 @@
 
 	ioaddr = dev->base_addr;
 	tp = (struct tulip_private *)dev->priv;
-	if (test_and_set_bit(0, (void*)&tp->interrupt)) {
-#ifdef SMP_CHECK
-		printk(KERN_ERR "%s: Re-entering the interrupt handler with proc %d,"
-			   " proc %d already handling.\n", dev->name,
-			   tp->smp_proc_id, smp_processor_id());
-#else
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-#endif
-		return;
-	}
-	dev->interrupt = 1;
-#ifdef SMP_CHECK
-	tp->smp_proc_id = smp_processor_id();
-#endif
 
 	do {
 		csr5 = inl(ioaddr + CSR5);
@@ -2189,6 +2148,8 @@
 		if (csr5 & (RxIntr | RxNoBuf))
 			work_budget -= tulip_rx(dev);
 
+		spin_lock(&tp->tx_lock);
+
 		if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
 			unsigned int dirty_tx;
 
@@ -2224,19 +2185,13 @@
 #ifdef ETHER_STATS
 					if (status & 0x0001) tp->stats.tx_deferred++;
 #endif
-#if LINUX_VERSION_CODE > 0x20127
 					tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
-#endif
 					tp->stats.collisions += (status >> 3) & 15;
 					tp->stats.tx_packets++;
 				}
 
 				/* Free the original skb. */
-#if (LINUX_VERSION_CODE > 0x20155)
-				dev_kfree_skb(tp->tx_skbuff[entry]);
-#else
-				dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE);
-#endif
+				dev_kfree_skb_irq(tp->tx_skbuff[entry]);
 				tp->tx_skbuff[entry] = 0;
 			}
 
@@ -2248,15 +2203,14 @@
 			}
 #endif
 
-			if (tp->tx_full && dev->tbusy
-				&& tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2) {
+			if (tp->tx_full && tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2) {
 				/* The ring is no longer full, clear tbusy. */
 				tp->tx_full = 0;
-				dev->tbusy = 0;
-				mark_bh(NET_BH);
+				netif_wake_queue(dev);
 			}
 
 			tp->dirty_tx = dirty_tx;
+
 			if (csr5 & TxDied) {
 				if (tulip_debug > 1)
 					printk(KERN_WARNING "%s: The transmitter stopped!"
@@ -2266,6 +2220,7 @@
 				outl(tp->csr6 | 0x2002, ioaddr + CSR6);
 			}
 		}
+		spin_unlock(&tp->tx_lock);
 
 		/* Log errors. */
 		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
@@ -2316,8 +2271,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
 			   dev->name, inl(ioaddr + CSR5));
 
-	dev->interrupt = 0;
-	clear_bit(0, (void*)&tp->interrupt);
 	return;
 }
 
@@ -2397,9 +2350,7 @@
 			netif_rx(skb);
 			dev->last_rx = jiffies;
 			tp->stats.rx_packets++;
-#if LINUX_VERSION_CODE > 0x20127
 			tp->stats.rx_bytes += pkt_len;
-#endif
 		}
 		entry = (++tp->cur_rx) % RX_RING_SIZE;
 	}
@@ -2429,8 +2380,7 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (tulip_debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
@@ -2463,23 +2413,12 @@
 		tp->rx_ring[i].length = 0;
 		tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
 		if (skb) {
-#if LINUX_VERSION_CODE < 0x20100
-			skb->free = 1;
-#endif
-#if (LINUX_VERSION_CODE > 0x20155)
 			dev_kfree_skb(skb);
-#else
-			dev_kfree_skb(skb, FREE_WRITE);
-#endif
 		}
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (tp->tx_skbuff[i])
-#if (LINUX_VERSION_CODE > 0x20155)
 			dev_kfree_skb(tp->tx_skbuff[i]);
-#else
-			dev_kfree_skb(tp->tx_skbuff[i], FREE_WRITE);
-#endif
 		tp->tx_skbuff[i] = 0;
 	}
 
@@ -2495,7 +2434,7 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (dev->start)
+	if (test_bit(LINK_STATE_START, &dev->state))
 		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
 
 	return &tp->stats;
@@ -2601,6 +2540,7 @@
 	long ioaddr = dev->base_addr;
 	int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	unsigned long cpuflags;
 
 	tp->csr6 &= ~0x00D5;
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
@@ -2660,13 +2600,12 @@
 			*setup_frm++ = eaddrs[2];
 		} while (++i < 15);
 		/* Now add this frame to the Tx list. */
+		spin_lock_irqsave(&tp->tx_lock, cpuflags);
 		if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
 			/* Same setup recently queued, we need not add it. */
 		} else {
-			unsigned long flags;
 			unsigned int entry, dummy = 0;
 
-			save_flags(flags); cli();
 			entry = tp->cur_tx++ % TX_RING_SIZE;
 
 			if (entry != 0) {
@@ -2688,12 +2627,12 @@
 			tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
 			tp->tx_ring[entry].status = 0x80000000;
 			if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
-				dev->tbusy = 1;
+				netif_stop_queue(dev);
 				tp->tx_full = 1;
 			}
 			if (dummy >= 0)
 				tp->tx_ring[dummy].status = DescOwned;
-			restore_flags(flags);
+			spin_unlock_irqrestore(&tp->tx_lock, cpuflags);
 			/* Trigger an immediate transmit demand. */
 			outl(0, ioaddr + CSR1);
 		}
@@ -2711,12 +2650,14 @@
 	u32 io;
 	u8 bus, devfn;
 	struct net_device *dev;
+	struct pci_dev *pdev;
 
 	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+	pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+	if (!pdev) return NULL;
 	printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	io = pdev->resource[0].start;
+	dev_id = pdev->device;
 	io &= ~3;
 	dev = tulip_probe1(bus, devfn, DC21142, -1);
 	if (dev) {
@@ -2753,9 +2694,6 @@
 
 #endif  /* Cardbus support */
 
-
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
 MODULE_PARM(debug, "i");
@@ -2764,13 +2702,11 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
 
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 
-int
-init_module(void)
+static int __init tulip_init_module (void)
 {
 	if (debug >= 0)
 		tulip_debug = debug;
@@ -2783,8 +2719,7 @@
 #endif
 }
 
-void
-cleanup_module(void)
+static void __exit tulip_cleanup_module (void)
 {
 	struct net_device *next_dev;
 
@@ -2802,8 +2737,10 @@
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(tulip_init_module);
+module_exit(tulip_cleanup_module);
+
+
 /*
  * Local variables:
  *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"

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