patch-2.4.0-test6 linux/drivers/net/ioc3-eth.c

Next file: linux/drivers/net/irda/Makefile
Previous file: linux/drivers/net/hydra.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
@@ -105,8 +105,6 @@
 static void ioc3_timeout(struct net_device *dev);
 static inline unsigned int ioc3_hash(const unsigned char *addr);
 static void ioc3_stop(struct net_device *dev);
-static void ioc3_clean_tx_ring(struct ioc3_private *ip);
-static void ioc3_clean_rx_ring(struct ioc3_private *ip);
 static void ioc3_init(struct net_device *dev);
 
 static const char ioc3_str[] = "IOC3 Ethernet";
@@ -446,7 +444,6 @@
 
 			ip->stats.rx_packets++;		/* Statistics */
 			ip->stats.rx_bytes += len;
-
 		} else {
  			/* The frame is invalid and the skb never
                            reached the network layer so we can just
@@ -464,7 +461,6 @@
 		                ((unsigned long) rxb & TO_PHYS_MASK);
 		rxb->w0 = 0;				/* Clear valid flag */
 		n_entry = (n_entry + 1) & 511;		/* Update erpir */
-		ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
 
 		/* Now go on to the next ring entry.  */
 		rx_entry = (rx_entry + 1) & 511;
@@ -472,6 +468,7 @@
 		rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
 		w0 = rxb->w0;
 	}
+	ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
 	ip->rx_pi = n_entry;
 	ip->rx_ci = rx_entry;
 }
@@ -527,17 +524,26 @@
 ioc3_error(struct net_device *dev, struct ioc3_private *ip,
            struct ioc3 *ioc3, u32 eisr)
 {
-	if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR)) {
-		if (eisr & EISR_RXMEMERR) {
-			printk(KERN_ERR "%s: RX PCI error.\n", dev->name);
-		}
-		if (eisr & EISR_TXMEMERR) {
-			printk(KERN_ERR "%s: TX PCI error.\n", dev->name);
-		}
+	if (eisr & EISR_RXOFLO) {
+		printk(KERN_ERR "%s: RX overflow.\n", dev->name);
+	}
+	if (eisr & EISR_RXBUFOFLO) {
+		printk(KERN_ERR "%s: RX buffer overflow.\n", dev->name);
+	}
+	if (eisr & EISR_RXMEMERR) {
+		printk(KERN_ERR "%s: RX PCI error.\n", dev->name);
+	}
+	if (eisr & EISR_RXPARERR) {
+		printk(KERN_ERR "%s: RX SSRAM parity error.\n", dev->name);
+	}
+	if (eisr & EISR_TXBUFUFLO) {
+		printk(KERN_ERR "%s: TX buffer underflow.\n", dev->name);
+	}
+	if (eisr & EISR_TXMEMERR) {
+		printk(KERN_ERR "%s: TX PCI error.\n", dev->name);
 	}
 
 	ioc3_stop(dev);
-	ioc3_clean_tx_ring(dev->priv);
 	ioc3_init(dev);
 
 	dev->trans_start = jiffies;
@@ -551,8 +557,9 @@
 	struct net_device *dev = (struct net_device *)_dev;
 	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
-	const u32 enabled = EISR_RXTIMERINT | EISR_TXEXPLICIT |
-	                    EISR_RXMEMERR | EISR_TXMEMERR;
+	const u32 enabled = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO |
+	                    EISR_RXMEMERR | EISR_RXPARERR | EISR_TXBUFUFLO |
+	                    EISR_TXEXPLICIT | EISR_TXMEMERR;
 	u32 eisr;
 
 	eisr = ioc3->eisr & enabled;
@@ -560,12 +567,14 @@
 		ioc3->eisr = eisr;
 		ioc3->eisr;				/* Flush */
 
+		if (eisr & (EISR_RXOFLO | EISR_RXBUFOFLO | EISR_RXMEMERR |
+		            EISR_RXPARERR | EISR_TXBUFUFLO | EISR_TXMEMERR))
+			ioc3_error(dev, ip, ioc3, eisr);
 		if (eisr & EISR_RXTIMERINT)
 			ioc3_rx(dev, ip, ioc3);
 		if (eisr & EISR_TXEXPLICIT)
 			ioc3_tx(dev, ip, ioc3);
-		if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR))
-			ioc3_error(dev, ip, ioc3, eisr);
+
 		eisr = ioc3->eisr & enabled;
 	}
 }
@@ -612,15 +621,73 @@
 	mii_write(ioc3, phy, 0, mii0 | 0x3100);
 
 	spin_unlock_irq(&ip->ioc3_lock);
-	mdelay(1000);				/* XXX Yikes XXX */
-	spin_lock_irq(&ip->ioc3_lock);
-
-	mii_status = mii_read(ioc3, phy, 1);
-	spin_unlock_irq(&ip->ioc3_lock);
 
 	return 0;
 }
 
+static inline void
+ioc3_clean_rx_ring(struct ioc3_private *ip)
+{
+	struct sk_buff *skb;
+	int i;
+
+	for (i = ip->rx_ci; i & 15; i++) {
+		ip->rx_skbs[ip->rx_pi] = ip->rx_skbs[ip->rx_ci];
+		ip->rxr[ip->rx_pi++] = ip->rxr[ip->rx_ci++];
+	}
+	ip->rx_pi &= 511;
+	ip->rx_ci &= 511;
+
+	for (i = ip->rx_ci; i != ip->rx_pi; i = (i+1) & 511) {
+		struct ioc3_erxbuf *rxb;
+		skb = ip->rx_skbs[i];
+		rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
+		rxb->w0 = 0;
+	}
+}
+
+static inline void
+ioc3_clean_tx_ring(struct ioc3_private *ip)
+{
+	struct sk_buff *skb;
+	int i;
+
+	for (i=0; i < 128; i++) {
+		skb = ip->tx_skbs[i];
+		if (skb) {
+			ip->tx_skbs[i] = NULL;
+			dev_kfree_skb_any(skb);
+		}
+		ip->txr[i].cmd = 0;
+	}
+	ip->tx_pi = 0;
+	ip->tx_ci = 0;
+}
+
+static void
+ioc3_free_rings(struct ioc3_private *ip)
+{
+	struct sk_buff *skb;
+	int rx_entry, n_entry;
+
+	ioc3_clean_tx_ring(ip);
+	ip->txr = NULL;
+	free_pages((unsigned long)ip->txr, 2);
+
+	n_entry = ip->rx_ci;
+	rx_entry = ip->rx_pi;
+
+	while (n_entry != rx_entry) {
+		skb = ip->rx_skbs[n_entry];
+		if (skb)
+			dev_kfree_skb_any(skb);
+
+		n_entry = (n_entry + 1) & 511;
+	}
+	free_page((unsigned long)ip->rxr);
+	ip->rxr = NULL;
+}
+
 static void
 ioc3_alloc_rings(struct net_device *dev, struct ioc3_private *ip,
 		 struct ioc3 *ioc3)
@@ -676,8 +743,8 @@
 
 	ioc3_alloc_rings(dev, ip, ioc3);
 
-	ioc3_clean_tx_ring(ip);
 	ioc3_clean_rx_ring(ip);
+	ioc3_clean_tx_ring(ip);
 
 	/* Now the rx ring base, consume & produce registers.  */
 	ring = (0xa5UL << 56) | ((unsigned long)ip->rxr & TO_PHYS_MASK);
@@ -698,61 +765,6 @@
 	ioc3->etcir;					/* Flush */
 }
 
-static void
-ioc3_clean_tx_ring(struct ioc3_private *ip)
-{
-	struct sk_buff *skb;
-	int i;
-
-	for (i=0; i < 128; i++) {
-		skb = ip->tx_skbs[i];
-		if (skb) {
-			ip->tx_skbs[i] = NULL;
-			dev_kfree_skb_any(skb);
-		}
-		ip->txr[i].cmd = 0;
-	}
-}
-
-static void
-ioc3_clean_rx_ring(struct ioc3_private *ip)
-{
-	struct sk_buff *skb;
-	int i;
-	
-	for (i = 0; i < RX_BUFFS; i++) {
-		struct ioc3_erxbuf *rxb;
-		skb = ip->rx_skbs[i];
-		rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
-
-		rxb->w0 = 0;
-	}
-}
-
-static void
-ioc3_free_rings(struct ioc3_private *ip)
-{
-	struct sk_buff *skb;
-	int rx_entry, n_entry;
-
-	ioc3_clean_tx_ring(ip);
-	free_pages((unsigned long)ip->txr, 2);
-	ip->txr = NULL;
-
-	n_entry = ip->rx_ci;
-	rx_entry = ip->rx_pi;
-
-	while (n_entry != rx_entry) {
-		skb = ip->rx_skbs[n_entry];
-		if (skb)
-			dev_kfree_skb_any(skb);
-
-		n_entry = (n_entry + 1) & 511;
-	}
-	free_page((unsigned long)ip->rxr);
-	ip->rxr = NULL;
-}
-
 static inline void
 ioc3_ssram_disc(struct ioc3_private *ip)
 {
@@ -797,17 +809,18 @@
 	ioc3->emar_h = (dev->dev_addr[5] << 8) | dev->dev_addr[4];
 	ioc3->emar_l = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
 	               (dev->dev_addr[1] <<  8) | dev->dev_addr[0];
-	ioc3->ehar_h = ioc3->ehar_l = 0;
+	ioc3->ehar_h = ip->ehar_h;
+	ioc3->ehar_l = ip->ehar_l;
 	ioc3->ersr = 42;			/* XXX should be random */
-	//ioc3->erpir = ERPIR_ARM;
 
 	ioc3_init_rings(dev, ip, ioc3);
 
 	ip->emcr |= ((RX_OFFSET / 2) << EMCR_RXOFF_SHIFT) | EMCR_TXDMAEN |
-	              EMCR_TXEN | EMCR_RXDMAEN | EMCR_RXEN;
+	             EMCR_TXEN | EMCR_RXDMAEN | EMCR_RXEN;
 	ioc3->emcr = ip->emcr;
-	ioc3->eier = EISR_RXTIMERINT | EISR_TXEXPLICIT | /* Interrupts ...  */
-	             EISR_RXMEMERR | EISR_TXMEMERR;
+	ioc3->eier = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO |
+	             EISR_RXMEMERR | EISR_RXPARERR | EISR_TXBUFUFLO |
+	             EISR_TXEXPLICIT | EISR_TXMEMERR;
 	ioc3->eier;
 }
 
@@ -817,7 +830,6 @@
 	struct ioc3 *ioc3 = ip->regs;
 
 	ioc3->emcr = 0;				/* Shutup */
-	ip->emcr = 0;
 	ioc3->eier = 0;				/* Disable interrupts */
 	ioc3->eier;				/* Flush */
 }
@@ -825,14 +837,18 @@
 static int
 ioc3_open(struct net_device *dev)
 {
+	struct ioc3_private *ip;
+
 	if (request_irq(dev->irq, ioc3_interrupt, 0, ioc3_str, dev)) {
 		printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq);
 
 		return -EAGAIN;
 	}
 
-	((struct ioc3_private *)dev->priv)->ehar_h = 0;
-	((struct ioc3_private *)dev->priv)->ehar_l = 0;
+	ip = (struct ioc3_private *) dev->priv;
+
+	ip->ehar_h = 0;
+	ip->ehar_l = 0;
 	ioc3_init(dev);
 
 	netif_start_queue(dev);
@@ -1005,7 +1021,6 @@
 	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 
 	ioc3_stop(dev);
-	ioc3_clean_tx_ring(dev->priv);
 	ioc3_init(dev);
 
 	dev->trans_start = jiffies;
@@ -1117,7 +1132,7 @@
 				if (!(*addr & 1))
 					continue;
 
-				ehar |= (1 << ioc3_hash(addr));
+				ehar |= (1UL << ioc3_hash(addr));
 			}
 			ip->ehar_h = ehar >> 32;
 			ip->ehar_l = ehar & 0xffffffff;

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