patch-2.3.99-pre1 linux/drivers/net/3c527.c
Next file: linux/drivers/net/3c59x.c
Previous file: linux/drivers/ide/via82cxxx.c
Back to the patch index
Back to the overall index
- Lines: 161
- Date:
Sun Mar 12 19:18:55 2000
- Orig file:
v2.3.51/linux/drivers/net/3c527.c
- Orig date:
Sat Feb 12 11:22:10 2000
diff -u --recursive --new-file v2.3.51/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
@@ -2,6 +2,7 @@
*
* (c) Copyright 1998 Red Hat Software Inc
* Written by Alan Cox.
+ * Further debugging by Carl Drougge.
*
* Based on skeleton.c written 1993-94 by Donald Becker and ne2.c
* (for the MCA stuff) written by Wim Dumon.
@@ -15,7 +16,7 @@
*/
static const char *version =
- "3c527.c:v0.07 2000/01/18 Alan Cox (alan@redhat.com)\n";
+ "3c527.c:v0.08 2000/02/22 Alan Cox (alan@redhat.com)\n";
/**
* DOC: Traps for the unwary
@@ -122,6 +123,7 @@
u32 base;
u16 rx_halted;
u16 tx_halted;
+ u16 rx_pending;
u16 exec_pending;
u16 mc_reload_wait; /* a multicast load request is pending */
atomic_t tx_count; /* buffers left */
@@ -451,6 +453,9 @@
printk("%s: %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
dev->name, lp->rx_len, lp->tx_len, lp->base);
+
+ if(lp->tx_len > TX_RING_MAX)
+ lp->tx_len = TX_RING_MAX;
dev->open = mc32_open;
dev->stop = mc32_close;
@@ -462,6 +467,7 @@
lp->rx_halted = 1;
lp->tx_halted = 1;
+ lp->rx_pending = 0;
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
@@ -652,6 +658,7 @@
mc32_ring_poll(dev);
lp->rx_halted=0;
+ lp->rx_pending=0;
}
/**
@@ -944,6 +951,7 @@
static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
+ int ioaddr = dev->base_addr;
unsigned long flags;
u16 tx_head;
@@ -967,7 +975,16 @@
lp->tx_skb[lp->tx_skb_end] = skb;
lp->tx_skb_end++;
lp->tx_skb_end&=(TX_RING_MAX-1);
+
+ /* TX suspend - shouldnt be needed but apparently is.
+ This is a research item ... */
+
+ while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
+ lp->tx_box->mbox=0;
+ outb(3, ioaddr+HOST_CMD);
+ /* Transmit now stopped */
+
/* P is the last sending/sent buffer as a pointer */
p=(struct skb_header *)bus_to_virt(lp->base+tx_head);
@@ -990,7 +1007,9 @@
p->status = 0;
p->control &= ~(1<<6);
+ while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
lp->tx_box->mbox=0;
+ outb(5, ioaddr+HOST_CMD); /* Restart TX */
restore_flags(flags);
netif_wake_queue(dev);
@@ -1096,11 +1115,16 @@
base = p->next;
}
while(x++<48);
+
+ /*
+ * Restart ring processing
+ */
while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
lp->rx_box->mbox=0;
lp->rx_box->data[0] = top;
outb(1<<3, ioaddr+HOST_CMD);
+ lp->rx_halted=0;
}
@@ -1123,7 +1147,6 @@
struct net_device *dev = dev_id;
struct mc32_local *lp;
int ioaddr, status, boguscount = 0;
- int rx_event = 0;
if (dev == NULL) {
printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
@@ -1182,7 +1205,15 @@
case 0:
break;
case 2: /* RX */
- rx_event=1;
+ lp->rx_pending=1;
+ if(!lp->rx_halted)
+ {
+ /*
+ * Halt ring receive
+ */
+ while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
+ outb(3<<3, ioaddr+HOST_CMD);
+ }
break;
case 3:
case 4:
@@ -1195,9 +1226,10 @@
break;
case 6:
/* Out of RX buffers stat */
- /* Must restart */
lp->net_stats.rx_dropped++;
- rx_event = 1; /* To restart */
+ lp->rx_pending=1;
+ /* Must restart */
+ lp->rx_halted=1;
break;
default:
printk("%s: strange rx ack %d\n",
@@ -1231,11 +1263,17 @@
}
/*
- * Process and restart the receive ring.
+ * Process and restart the receive ring. This has some state
+ * as we must halt the ring to process it and halting the ring
+ * might not occur in the same IRQ handling loop as we issue
+ * the halt.
*/
- if(rx_event)
+ if(lp->rx_pending && lp->rx_halted)
+ {
mc32_rx_ring(dev);
+ lp->rx_pending = 0;
+ }
return;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)