
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>
---

 25-akpm/drivers/net/iseries_veth.c |   16 +++++++++++-----
 1 files changed, 11 insertions(+), 5 deletions(-)

diff -puN drivers/net/iseries_veth.c~ppc64-iseries-fix-virtual-ethernet-transmit-block drivers/net/iseries_veth.c
--- 25/drivers/net/iseries_veth.c~ppc64-iseries-fix-virtual-ethernet-transmit-block	2004-05-31 16:52:32.362808824 -0700
+++ 25-akpm/drivers/net/iseries_veth.c	2004-05-31 16:52:32.366808216 -0700
@@ -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)
@@ -1020,27 +1025,28 @@ static int veth_start_xmit(struct sk_buf
 		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;
 }
 
@@ -1094,7 +1100,7 @@ static void veth_flush_pending(struct ve
 			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);
_
