aboutsummaryrefslogtreecommitdiffstats
path: root/xenolinux-2.4.21-pre4-sparse
diff options
context:
space:
mode:
authorkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>2003-02-27 18:12:27 +0000
committerkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>2003-02-27 18:12:27 +0000
commit4f8a42fc0e8f088bb15bd0830e3a59bbcfdde80b (patch)
tree9d0ef62a09999ccbf5efbcd2b48cf615ee8d7cc7 /xenolinux-2.4.21-pre4-sparse
parent01ff0e70895202693f699281cc4933c9068d1a05 (diff)
downloadxen-4f8a42fc0e8f088bb15bd0830e3a59bbcfdde80b.tar.gz
xen-4f8a42fc0e8f088bb15bd0830e3a59bbcfdde80b.tar.bz2
xen-4f8a42fc0e8f088bb15bd0830e3a59bbcfdde80b.zip
bitkeeper revision 1.105.1.3 (3e5e550bzMuNp7GfT1LItXmDa_coaA)
network.c: Fix up net ring handling -- set tx events a bit better.
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse')
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c59
1 files changed, 33 insertions, 26 deletions
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c
index 5bd1396a49..adcff526b4 100644
--- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c
@@ -65,15 +65,17 @@ struct net_private
spinlock_t tx_lock;
};
-
+
static void dbg_network_int(int irq, void *dev_id, struct pt_regs *ptregs)
{
- struct net_device *dev = (struct net_device *)dev_id;
- struct net_private *np = dev->priv;
- printk(KERN_ALERT "tx_full = %d, tx_entries = %d, tx_idx = %d, tx_cons = %d, tx_prod = %d, tx_event = %d, state=%d\n",
- np->tx_full, np->tx_entries, np->tx_idx,
- np->net_ring->tx_cons,np->net_ring->tx_prod,np->net_ring->tx_event,
- test_bit(__LINK_STATE_XOFF, &dev->state));
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct net_private *np = dev->priv;
+ printk(KERN_ALERT "tx_full = %d, tx_entries = %d, tx_idx = %d,"
+ " tx_cons = %d, tx_prod = %d, tx_event = %d, state=%d\n",
+ np->tx_full, atomic_read(&np->tx_entries), np->tx_idx,
+ np->net_ring->tx_cons, np->net_ring->tx_prod,
+ np->net_ring->tx_event,
+ test_bit(__LINK_STATE_XOFF, &dev->state));
}
@@ -134,10 +136,13 @@ static int network_open(struct net_device *dev)
goto fail;
}
-#if 1
- request_irq( _EVENT_DEBUG, dbg_network_int, SA_SHIRQ, "debug", dev);
-#endif
-
+ error = request_irq(_EVENT_DEBUG, dbg_network_int, SA_SHIRQ,
+ "debug", dev);
+ if ( error )
+ {
+ printk(KERN_WARNING "%s: Non-fatal error -- no debug interrupt\n",
+ dev->name);
+ }
printk("XenoLinux Virtual Network Driver installed as %s\n", dev->name);
@@ -163,17 +168,27 @@ static void network_tx_buf_gc(struct net_device *dev)
struct net_private *np = dev->priv;
struct sk_buff *skb;
unsigned long flags;
+ unsigned int cons;
spin_lock_irqsave(&np->tx_lock, flags);
- for ( i = np->tx_idx; i != np->net_ring->tx_cons; i = TX_RING_INC(i) )
- {
- skb = np->tx_skb_ring[i];
- dev_kfree_skb_any(skb);
- atomic_dec(&np->tx_entries);
- }
+ do {
+ cons = np->net_ring->tx_cons;
- np->tx_idx = i;
+ for ( i = np->tx_idx; i != cons; i = TX_RING_INC(i) )
+ {
+ skb = np->tx_skb_ring[i];
+ dev_kfree_skb_any(skb);
+ atomic_dec(&np->tx_entries);
+ }
+
+ np->tx_idx = i;
+
+ /* Set a new event, then check for race with update of tx_cons. */
+ np->net_ring->tx_event = TX_RING_INC(cons);
+ smp_mb();
+ }
+ while ( cons != np->net_ring->tx_cons );
if ( np->tx_full && (atomic_read(&np->tx_entries) < TX_MAX_ENTRIES) )
{
@@ -278,17 +293,9 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
np->tx_full = 1;
netif_stop_queue(dev);
- np->net_ring->tx_event =
- TX_RING_ADD(np->tx_idx, atomic_read(&np->tx_entries) >> 1);
- }
- else
- {
- /* Avoid unnecessary tx interrupts. */
- np->net_ring->tx_event = np->net_ring->tx_prod;
}
spin_unlock_irq(&np->tx_lock);
- /* Must do this after setting tx_event: race with updates of tx_cons. */
network_tx_buf_gc(dev);
HYPERVISOR_net_update();