patch-2.3.48 linux/drivers/net/sgiseeq.c

Next file: linux/drivers/net/sgiseeq.h
Previous file: linux/drivers/net/pcmcia/3c589_cs.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.47/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c
@@ -31,7 +31,8 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/sgihpc.h>
+#include <asm/sgi/sgihpc.h>
+#include <asm/sgi/sgint23.h>
 #include <asm/sgialib.h>
 
 #include "sgiseeq.h"
@@ -70,12 +71,12 @@
 
 struct sgiseeq_rx_desc {
 	struct hpc_dma_desc rdma;
-	unsigned long buf_vaddr;
+	signed int buf_vaddr;
 };
 
 struct sgiseeq_tx_desc {
 	struct hpc_dma_desc tdma;
-	unsigned long buf_vaddr;
+	signed int buf_vaddr;
 };
 
 /* Warning: This structure is layed out in a certain way because
@@ -86,7 +87,7 @@
 	/* Ptrs to the descriptors in KSEG1 uncached space. */
 	struct sgiseeq_rx_desc *rx_desc;
 	struct sgiseeq_tx_desc *tx_desc;
-	unsigned long _padding[30]; /* Pad out to largest cache line size. */
+	unsigned int _padding[30]; /* Pad out to largest cache line size. */
 
 	struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS];
 	struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS];
@@ -140,7 +141,7 @@
 	int i;
 
 	sregs->tstat = SEEQ_TCMD_RB0;
-	for(i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++)
 		sregs->rw.eth_addr[i] = dev->dev_addr[i];
 }
 
@@ -154,7 +155,7 @@
 	volatile struct sgiseeq_init_block *ib = &sp->srings;
 	int i;
 
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	sp->rx_new = sp->tx_new = 0;
 	sp->rx_old = sp->tx_old = 0;
 
@@ -180,8 +181,8 @@
 	}
 
 	/* And now the rx ring. */
-	for(i = 0; i < SEEQ_RX_BUFFERS; i++) {
-		if(!ib->rx_desc[i].rdma.pbuf) {
+	for (i = 0; i < SEEQ_RX_BUFFERS; i++) {
+		if (!ib->rx_desc[i].rdma.pbuf) {
 			unsigned long buffer;
 
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
@@ -210,29 +211,29 @@
 		return;
 	once++;
 	printk("RING DUMP:\n");
-	for(i = 0; i < SEEQ_RX_BUFFERS; i++) {
-		printk("RX [%d]: @(%p) [%08lx,%08lx,%08lx] ",
+	for (i = 0; i < SEEQ_RX_BUFFERS; i++) {
+		printk("RX [%d]: @(%p) [%08x,%08x,%08x] ",
 		       i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo,
 		       r[i].rdma.pnext);
 		i += 1;
-		printk("-- [%d]: @(%p) [%08lx,%08lx,%08lx]\n",
+		printk("-- [%d]: @(%p) [%08x,%08x,%08x]\n",
 		       i, (&r[i]), r[i].rdma.pbuf, r[i].rdma.cntinfo,
 		       r[i].rdma.pnext);
 	}
-	for(i = 0; i < SEEQ_TX_BUFFERS; i++) {
-		printk("TX [%d]: @(%p) [%08lx,%08lx,%08lx] ",
+	for (i = 0; i < SEEQ_TX_BUFFERS; i++) {
+		printk("TX [%d]: @(%p) [%08x,%08x,%08x] ",
 		       i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo,
 		       t[i].tdma.pnext);
 		i += 1;
-		printk("-- [%d]: @(%p) [%08lx,%08lx,%08lx]\n",
+		printk("-- [%d]: @(%p) [%08x,%08x,%08x]\n",
 		       i, (&t[i]), t[i].tdma.pbuf, t[i].tdma.cntinfo,
 		       t[i].tdma.pnext);
 	}
 	printk("INFO: [rx_new = %d rx_old=%d] [tx_new = %d tx_old = %d]\n",
 	       gpriv->rx_new, gpriv->rx_old, gpriv->tx_new, gpriv->tx_old);
-	printk("RREGS: rx_cbptr[%08lx] rx_ndptr[%08lx] rx_ctrl[%08lx]\n",
+	printk("RREGS: rx_cbptr[%08x] rx_ndptr[%08x] rx_ctrl[%08x]\n",
 	       hregs->rx_cbptr, hregs->rx_ndptr, hregs->rx_ctrl);
-	printk("TREGS: tx_cbptr[%08lx] tx_ndptr[%08lx] tx_ctrl[%08lx]\n",
+	printk("TREGS: tx_cbptr[%08x] tx_ndptr[%08x] tx_ctrl[%08x]\n",
 	       hregs->tx_cbptr, hregs->tx_ndptr, hregs->tx_ctrl);
 }
 #endif
@@ -250,7 +251,7 @@
 	seeq_init_ring(dev);
 
 	/* Setup to field the proper interrupt types. */
-	if(sp->is_edlc) {
+	if (sp->is_edlc) {
 		sregs->tstat = (TSTAT_INIT_EDLC);
 		sregs->rw.wregs.control = sp->control;
 		sregs->rw.wregs.frame_gap = 0;
@@ -269,14 +270,14 @@
 static inline void record_rx_errors(struct sgiseeq_private *sp,
 				    unsigned char status)
 {
-	if(status & SEEQ_RSTAT_OVERF ||
-	   status & SEEQ_RSTAT_SFRAME)
+	if (status & SEEQ_RSTAT_OVERF ||
+	    status & SEEQ_RSTAT_SFRAME)
 		sp->stats.rx_over_errors++;
-	if(status & SEEQ_RSTAT_CERROR)
+	if (status & SEEQ_RSTAT_CERROR)
 		sp->stats.rx_crc_errors++;
-	if(status & SEEQ_RSTAT_DERROR)
+	if (status & SEEQ_RSTAT_DERROR)
 		sp->stats.rx_frame_errors++;
-	if(status & SEEQ_RSTAT_REOF)
+	if (status & SEEQ_RSTAT_REOF)
 		sp->stats.rx_errors++;
 }
 
@@ -284,7 +285,7 @@
 				    volatile struct hpc3_ethregs *hregs,
 				    volatile struct sgiseeq_regs *sregs)
 {
-	if(!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
+	if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
 		hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]);
 		seeq_go(sp, hregs, sregs);
 	}
@@ -308,14 +309,14 @@
 	/* Service every received packet. */
 	for_each_rx(rd, sp) {
 		len = (PKT_BUF_SZ - (rd->rdma.cntinfo & HPCDMA_BCNT) - 3);
-		pkt_pointer = (unsigned char *)rd->buf_vaddr;
+		pkt_pointer = (unsigned char *)(long)rd->buf_vaddr;
 		pkt_status = pkt_pointer[len + 2];
 
-		if(pkt_status & SEEQ_RSTAT_FIG) {
+		if (pkt_status & SEEQ_RSTAT_FIG) {
 			/* Packet is OK. */
 			skb = dev_alloc_skb(len + 2);
 
-			if(skb) {
+			if (skb) {
 				skb->dev = dev;
 				skb_reserve(skb, 2);
 				skb_put(skb, len);
@@ -346,7 +347,7 @@
 static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
 					     volatile struct sgiseeq_regs *sregs)
 {
-	if(sp->is_edlc) {
+	if (sp->is_edlc) {
 		sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT);
 		sregs->rw.wregs.control = sp->control;
 	}
@@ -361,11 +362,10 @@
 	 * adapter.  The following code is only safe iff the HPCDMA
 	 * is not active!
 	 */
-	while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
+	while ((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
 	      (HPCDMA_XIU | HPCDMA_ETXD))
-		td = (struct sgiseeq_tx_desc *)
-			KSEG1ADDR(td->tdma.pnext);
-	if(td->tdma.cntinfo & HPCDMA_XIU) {
+		td = (struct sgiseeq_tx_desc *)(long) KSEG1ADDR(td->tdma.pnext);
+	if (td->tdma.cntinfo & HPCDMA_XIU) {
 		hregs->tx_ndptr = PHYSADDR(td);
 		hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
 	}
@@ -381,23 +381,23 @@
 
 	tx_maybe_reset_collisions(sp, sregs);
 
-	if(!(status & (HPC3_ETXCTRL_ACTIVE | SEEQ_TSTAT_PTRANS))) {
+	if (!(status & (HPC3_ETXCTRL_ACTIVE | SEEQ_TSTAT_PTRANS))) {
 		/* Oops, HPC detected some sort of error. */
-		if(status & SEEQ_TSTAT_R16)
+		if (status & SEEQ_TSTAT_R16)
 			sp->stats.tx_aborted_errors++;
-		if(status & SEEQ_TSTAT_UFLOW)
+		if (status & SEEQ_TSTAT_UFLOW)
 			sp->stats.tx_fifo_errors++;
-		if(status & SEEQ_TSTAT_LCLS)
+		if (status & SEEQ_TSTAT_LCLS)
 			sp->stats.collisions++;
 	}
 
 	/* Ack 'em... */
-	for(j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) {
+	for (j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) {
 		td = &sp->srings.tx_desc[j];
 
-		if(!(td->tdma.cntinfo & (HPCDMA_XIU)))
+		if (!(td->tdma.cntinfo & (HPCDMA_XIU)))
 			break;
-		if(!(td->tdma.cntinfo & (HPCDMA_ETXD))) {
+		if (!(td->tdma.cntinfo & (HPCDMA_ETXD))) {
 			if(!(status & HPC3_ETXCTRL_ACTIVE)) {
 				hregs->tx_ndptr = PHYSADDR(td);
 				hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
@@ -411,15 +411,6 @@
 	}
 }
 
-static inline void tx_maybe_unbusy(struct sgiseeq_private *sp,
-				   struct net_device *dev)
-{
-	if((TX_BUFFS_AVAIL(sp) >= 0) && dev->tbusy) {
-		dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-}
-
 static void sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
@@ -429,17 +420,17 @@
 
 	/* Ack the IRQ and set software state. */
 	hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
-	dev->interrupt = 1;
 
 	/* Always check for received packets. */
 	sgiseeq_rx(dev, sp, hregs, sregs);
 
 	/* Only check for tx acks iff we have something queued. */
-	if(sp->tx_old != sp->tx_new)
+	if (sp->tx_old != sp->tx_new)
 		sgiseeq_tx(dev, sp, hregs, sregs);
 
-	tx_maybe_unbusy(sp, dev);
-	dev->interrupt = 0;
+	if ((TX_BUFFS_AVAIL(sp) > 0) && netif_queue_stopped(dev)) {
+		netif_wake_queue(dev);
+	}
 }
 
 static int sgiseeq_open(struct net_device *dev)
@@ -449,7 +440,7 @@
 	unsigned long flags;
 
 	save_flags(flags); cli();
-	if(request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, (void *) dev)) {
+	if (request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, (void *) dev)) {
 		printk("Seeq8003: Can't get irq %d\n", dev->irq);
 		restore_flags(flags);
 		return -EAGAIN;
@@ -457,9 +448,7 @@
 
 	init_seeq(dev, sp, sregs);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 	restore_flags(flags);
 	return 0;
 }
@@ -469,8 +458,7 @@
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
 	volatile struct sgiseeq_regs *sregs = sp->sregs;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	/* Shutdown the Seeq. */
 	reset_hpc3_and_seeq(sp->hregs, sregs);
@@ -488,9 +476,7 @@
 	init_seeq(dev, sp, sregs);
 
 	dev->trans_start = jiffies;
-	dev->interrupt = 0;
-	dev->start = 1;
-	dev->tbusy = 0;
+	netif_wake_queue(dev);
 
 	return 0;
 }
@@ -501,34 +487,6 @@
 	sgiseeq_reset(gdev);
 }
 
-static inline int verify_tx(struct sgiseeq_private *sp,
-			    struct net_device *dev,
-			    struct sk_buff *skb)
-{
-	/* Are we bolixed? */
-	if(dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 20)
-			return 1;
-
-		printk("%s: transmit timed out, ticks=%d resetting\n",
-		       dev->name, tickssofar);
-		sgiseeq_reset(dev);
-		return 0;
-	}
-	/* Are we getting in someone else's way? */
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("%s: Transmitter access conflict.\n", dev->name);
-		return -1;
-	}
-
-	/* Can we even send anything? */
-	if(!TX_BUFFS_AVAIL(sp))
-		return -1;
-
-	return 0;
-}
-
 static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
@@ -537,10 +495,7 @@
 	struct sgiseeq_tx_desc *td;
 	int skblen, len, entry;
 
-	if(verify_tx(sp, dev, skb))
-		return -1; /* Yeee... */
-
-	save_flags(flags); cli();
+	save_and_cli(flags);
 
 	/* Setup... */
 	skblen = skb->len;
@@ -561,10 +516,10 @@
 	 *    entry and the HPC got to the end of the chain before we
 	 *    added this new entry and restarted it.
 	 */
-	memcpy((char *)td->buf_vaddr, skb->data, skblen);
-	td->tdma.cntinfo = ((len) & HPCDMA_BCNT) |
-		(HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX);
-	if(sp->tx_old != sp->tx_new) {
+	memcpy((char *)(long)td->buf_vaddr, skb->data, skblen);
+	td->tdma.cntinfo = (len & HPCDMA_BCNT) |
+	                   (HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX);
+	if (sp->tx_old != sp->tx_new) {
 		struct sgiseeq_tx_desc *backend;
 
 		backend = &sp->srings.tx_desc[PREV_TX(sp->tx_new)];
@@ -573,18 +528,28 @@
 	sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */
 
 	/* Maybe kick the HPC back into motion. */
-	if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE))
+	if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE))
 		kick_tx(&sp->srings.tx_desc[sp->tx_old], hregs);
 
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
 
-	if(TX_BUFFS_AVAIL(sp))
-		dev->tbusy = 0;
+	if (!TX_BUFFS_AVAIL(sp))
+		netif_stop_queue(dev);
 	restore_flags(flags);
+
 	return 0;
 }
 
+static void timeout(struct net_device *dev)
+{
+	printk("%s: transmit timed out, resetting\n", dev->name);
+	sgiseeq_reset(dev);
+
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+}
+
 static struct enet_statistics *sgiseeq_get_stats(struct net_device *dev)
 {
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
@@ -600,7 +565,7 @@
 {
 	int i = 0;
 
-	while(i < (nbufs - 1)) {
+	while (i < (nbufs - 1)) {
 		buf[i].tdma.pnext = PHYSADDR(&buf[i + 1]);
 		buf[i].tdma.pbuf = 0;
 		i++;
@@ -612,7 +577,7 @@
 {
 	int i = 0;
 
-	while(i < (nbufs - 1)) {
+	while (i < (nbufs - 1)) {
 		buf[i].rdma.pnext = PHYSADDR(&buf[i + 1]);
 		buf[i].rdma.pbuf = 0;
 		i++;
@@ -632,20 +597,20 @@
 	int i;
 	struct sgiseeq_private *sp;
 
-	if(dev == NULL) {
+	if (dev == NULL) {
 		dev = init_etherdev(0, sizeof(struct sgiseeq_private));
 	} else {
 		dev->priv = (struct sgiseeq_private *) get_free_page(GFP_KERNEL);
-		if(dev->priv == NULL)
+		if (dev->priv == NULL)
 			return -ENOMEM;
 	}
 
-	if(!version_printed++)
+	if (!version_printed++)
 		printk(version);
 
 	printk("%s: SGI Seeq8003 ", dev->name);
 
-	for(i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++)
 		printk("%2.2x%c",
 		       dev->dev_addr[i] = onboard_eth_addr[i],
 		       i == 5 ? ' ': ':');
@@ -679,7 +644,7 @@
 	hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs);
 
 	sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff);
-	if(sp->is_edlc) {
+	if (sp->is_edlc) {
 		sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT |
 			       SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT |
 			       SEEQ_CTRL_ENCARR);
@@ -688,6 +653,8 @@
 	dev->open                 = sgiseeq_open;
 	dev->stop                 = sgiseeq_close;
 	dev->hard_start_xmit      = sgiseeq_start_xmit;
+	dev->tx_timeout           = timeout;
+	dev->watchdog_timeo       = (200 * HZ) / 1000;
 	dev->get_stats            = sgiseeq_get_stats;
 	dev->set_multicast_list   = sgiseeq_set_multicast;
 	dev->irq                  = irq;
@@ -699,9 +666,9 @@
 
 static inline unsigned char str2hexnum(unsigned char c)
 {
-	if(c >= '0' && c <= '9')
+	if (c >= '0' && c <= '9')
 		return c - '0';
-	if(c >= 'a' && c <= 'f')
+	if (c >= 'a' && c <= 'f')
 		return c - 'a' + 10;
 	return 0; /* foo */
 }
@@ -710,7 +677,7 @@
 {
 	int i;
 
-	for(i = 0; i < 6; i++) {
+	for (i = 0; i < 6; i++) {
 		unsigned char num;
 
 		if(*str == ':')
@@ -732,11 +699,12 @@
 
 	/* First get the ethernet address of the onboard
 	 * interface from ARCS.
-	 * (This is fragile; PROM doesn't like running from cache.)
+	 * This is fragile; PROM doesn't like running from cache.
+	 * On MIPS64 it crashes for some other, yet unknown reason.
 	 */
 	ep = romvec->get_evar("eaddr");
 	str2eaddr(onboard_eth_addr, ep);
 	return sgiseeq_init(dev,
 			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
-			    &hpc3c0->ethregs, 3);
+			    &hpc3c0->ethregs, SGI_ENET_IRQ);
 }

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