]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64: iSeries fix virtual ethernet transmit block
authorAndrew Morton <akpm@osdl.org>
Tue, 1 Jun 2004 01:47:31 +0000 (18:47 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 1 Jun 2004 01:47:31 +0000 (18:47 -0700)
From: Stephen Rothwell <sfr@canb.auug.org.au>

This patch fixes the virtual ethernet driver so that it will not block the
transmit queue indefinitely.  This patch appplies on top of the previous
patch from Rusty that removed skb_clone.  There is one white space fix in
hte middle of this - I hope that doesn't offend :-).

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/net/iseries_veth.c

index 9e3292df47411c3994537f1f1e39b670579a45e6..f56fde9e77d0a696bc50b3c56436812f12792be8 100644 (file)
@@ -461,6 +461,11 @@ static void veth_statemachine(void *p)
                if (cnx->msgs)
                        for (i = 0; i < VETH_NUMBUFFERS; ++i)
                                veth_recycle_msg(cnx, cnx->msgs + i);
+               spin_unlock_irq(&cnx->lock);
+               veth_flush_pending(cnx);
+               spin_lock_irq(&cnx->lock);
+               if (cnx->state & VETH_STATE_RESET)
+                       goto restart;
        }
 
        if (cnx->state & VETH_STATE_SHUTDOWN)
@@ -975,27 +980,28 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
                lpmask = port->lpar_map;
        }
 
+       spin_lock_irqsave(&port->pending_gate, flags);
+
        lpmask = veth_transmit_to_many(skb, lpmask, dev);
 
        if (! lpmask) {
                dev_kfree_skb(skb);
        } else {
-               spin_lock_irqsave(&port->pending_gate, flags);
                if (port->pending_skb) {
                        veth_error("%s: Tx while skb was pending!\n",
                                   dev->name);
                        dev_kfree_skb(skb);
-                       spin_unlock_irqrestore(&port->pending_gate, flags);
+                       spin_unlock_irqrestore(&port->pending_gate, flags);
                        return 1;
                }
 
                port->pending_skb = skb;
                port->pending_lpmask = lpmask;
                netif_stop_queue(dev);
-
-               spin_unlock_irqrestore(&port->pending_gate, flags);
        }
 
+       spin_unlock_irqrestore(&port->pending_gate, flags);
+
        return 0;
 }
 
@@ -1049,7 +1055,7 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx)
                        if (! port->pending_lpmask) {
                                dev_kfree_skb_any(port->pending_skb);
                                port->pending_skb = NULL;
-                               netif_start_queue(dev);
+                               netif_wake_queue(dev);
                        }
                }
                spin_unlock_irqrestore(&port->pending_gate, flags);