patch-2.2.15 linux/drivers/net/3c527.c
Next file: linux/drivers/net/82596.c
Previous file: linux/drivers/net/3c509.c
Back to the patch index
Back to the overall index
- Lines: 173
- Date:
Fri Apr 21 12:46:15 2000
- Orig file:
v2.2.14/drivers/net/3c527.c
- Orig date:
Wed Oct 20 01:12:38 1999
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/net/3c527.c linux/drivers/net/3c527.c
@@ -3,6 +3,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.
@@ -16,7 +17,7 @@
*/
static const char *version =
- "3c527.c:v0.06 1999/09/16 Alan Cox (alan@redhat.com)\n";
+ "3c527.c:v0.08 2000/02/22 Alan Cox (alan@redhat.com)\n";
/*
* Things you need
@@ -100,6 +101,7 @@
u32 base;
u16 rx_halted;
u16 tx_halted;
+ u16 rx_pending; /* ring due a service */
u16 exec_pending;
u16 mc_reload_wait; /* a multicast load request is pending */
atomic_t tx_count; /* buffers left */
@@ -418,6 +420,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;
dev->hard_start_xmit = mc32_send_packet;
@@ -426,6 +431,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);
@@ -579,6 +585,7 @@
mc32_ring_poll(dev);
lp->rx_halted=0;
+ lp->rx_pending=0;
}
static void mc32_tx_abort(struct device *dev)
@@ -783,6 +790,7 @@
static int mc32_send_packet(struct sk_buff *skb, struct device *dev)
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
+ int ioaddr = dev->base_addr;
if (dev->tbusy) {
/*
@@ -833,6 +841,14 @@
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);
@@ -841,7 +857,7 @@
np->control |= (1<<6); /* EOL */
wmb();
-
+
np->length = skb->len;
if(np->length < 60)
@@ -857,7 +873,9 @@
dev->tbusy = 0; /* Keep feeding me */
+ while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
lp->tx_box->mbox=0;
+ outb(5, ioaddr+HOST_CMD); /* Restart TX */
restore_flags(flags);
}
return 0;
@@ -926,17 +944,15 @@
}
while(x++<48);
- /*
- * This is curious. It seems the receive stop and receive continue
- * commands race against each other, even though we poll for
- * command ready to be issued. The delay is hackish but is a workaround
- * while I investigate in depth
- */
+ /*
+ * 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;
}
@@ -949,7 +965,6 @@
struct 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);
@@ -1011,7 +1026,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:
@@ -1024,9 +1047,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",
@@ -1060,11 +1084,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;
+ }
dev->interrupt = 0;
return;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)