From: Stephen Rothwell 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 Signed-off-by: Andrew Morton --- 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); _