patch-2.4.11-dontuse linux/drivers/net/3c507.c

Next file: linux/drivers/net/3c509.c
Previous file: linux/drivers/net/3c505.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.10/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
@@ -126,6 +126,7 @@
 	ushort tx_head;
 	ushort tx_cmd_link;
 	ushort tx_reap;
+	ushort tx_pkts_in_ring;
 	spinlock_t lock;
 };
 
@@ -194,7 +195,7 @@
 #define DUMP_DATA	0x56	/* A 170 byte buffer for dump and Set-MC into. */
 
 #define TX_BUF_START	0x0100
-#define NUM_TX_BUFS 	4
+#define NUM_TX_BUFS 	5
 #define TX_BUF_SIZE 	(1518+14+20+16) /* packet+header+TBD */
 
 #define RX_BUF_START	0x2000
@@ -463,6 +464,7 @@
 			printk ("Resetting board.\n");
 		/* Completely reset the adaptor. */
 		init_82586_mem (dev);
+		lp->tx_pkts_in_ring = 0;
 	} else {
 		/* Issue the channel attention signal and hope it "gets better". */
 		if (net_debug > 1)
@@ -538,30 +540,34 @@
 	outb(0x80, ioaddr + MISC_CTRL);
 
 	/* Reap the Tx packet buffers. */
-	while (lp->tx_reap != lp->tx_head) {
+	while (lp->tx_pkts_in_ring) {
 	  unsigned short tx_status = isa_readw(shmem+lp->tx_reap);
-
-	  if (tx_status == 0) {
-		if (net_debug > 5)  printk("Couldn't reap %#x.\n", lp->tx_reap);
+	  if (!(tx_status & 0x8000)) {
+		if (net_debug > 5) 
+			printk("Tx command incomplete (%#x).\n", lp->tx_reap);
 		break;
 	  }
-	  if (tx_status & 0x2000) {
-		lp->stats.tx_packets++;
-		lp->stats.collisions += tx_status & 0xf;
-		netif_wake_queue(dev);
-	  } else {
+	  /* Tx unsuccessful or some interesting status bit set. */
+	  if (!(tx_status & 0x2000) || (tx_status & 0x0f3f)) {
 		lp->stats.tx_errors++;
 		if (tx_status & 0x0600)  lp->stats.tx_carrier_errors++;
 		if (tx_status & 0x0100)  lp->stats.tx_fifo_errors++;
 		if (!(tx_status & 0x0040))  lp->stats.tx_heartbeat_errors++;
 		if (tx_status & 0x0020)  lp->stats.tx_aborted_errors++;
+		lp->stats.collisions += tx_status & 0xf;
 	  }
+	  lp->stats.tx_packets++;
 	  if (net_debug > 5)
 		  printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
 	  lp->tx_reap += TX_BUF_SIZE;
 	  if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
 		lp->tx_reap = TX_BUF_START;
-	  if (++boguscount > 4)
+
+	  lp->tx_pkts_in_ring--;
+	  /* There is always more space in the Tx ring buffer now. */
+	  netif_wake_queue(dev);
+
+	  if (++boguscount > 10)
 		break;
 	}
 
@@ -782,7 +788,8 @@
 			   dev->name, ioaddr, length, tx_block, lp->tx_head);
 	}
 
-	if (lp->tx_head != lp->tx_reap)
+	/* Grimly block further packets if there has been insufficient reaping. */
+	if (++lp->tx_pkts_in_ring < NUM_TX_BUFS) 
 		netif_wake_queue(dev);
 }
 
@@ -892,6 +899,8 @@
 	release_region(dev_3c507.base_addr, EL16_IO_EXTENT);
 }
 #endif /* MODULE */
+MODULE_LICENSE("GPL");
+
 
 /*
  * Local variables:

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