From 4f8a42fc0e8f088bb15bd0830e3a59bbcfdde80b Mon Sep 17 00:00:00 2001 From: "kaf24@labyrinth.cl.cam.ac.uk" Date: Thu, 27 Feb 2003 18:12:27 +0000 Subject: bitkeeper revision 1.105.1.3 (3e5e550bzMuNp7GfT1LItXmDa_coaA) network.c: Fix up net ring handling -- set tx events a bit better. --- .../arch/xeno/drivers/network/network.c | 59 ++++++++++++---------- 1 file changed, 33 insertions(+), 26 deletions(-) (limited to 'xenolinux-2.4.21-pre4-sparse/arch') 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(); -- cgit v1.2.3