Commit b4f4b53f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: iSeries fix virtual ethernet transmit block

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: default avatarStephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6175a486
...@@ -461,6 +461,11 @@ static void veth_statemachine(void *p) ...@@ -461,6 +461,11 @@ static void veth_statemachine(void *p)
if (cnx->msgs) if (cnx->msgs)
for (i = 0; i < VETH_NUMBUFFERS; ++i) for (i = 0; i < VETH_NUMBUFFERS; ++i)
veth_recycle_msg(cnx, cnx->msgs + 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) if (cnx->state & VETH_STATE_SHUTDOWN)
...@@ -975,27 +980,28 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -975,27 +980,28 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
lpmask = port->lpar_map; lpmask = port->lpar_map;
} }
spin_lock_irqsave(&port->pending_gate, flags);
lpmask = veth_transmit_to_many(skb, lpmask, dev); lpmask = veth_transmit_to_many(skb, lpmask, dev);
if (! lpmask) { if (! lpmask) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
} else { } else {
spin_lock_irqsave(&port->pending_gate, flags);
if (port->pending_skb) { if (port->pending_skb) {
veth_error("%s: Tx while skb was pending!\n", veth_error("%s: Tx while skb was pending!\n",
dev->name); dev->name);
dev_kfree_skb(skb); dev_kfree_skb(skb);
spin_unlock_irqrestore(&port->pending_gate, flags); spin_unlock_irqrestore(&port->pending_gate, flags);
return 1; return 1;
} }
port->pending_skb = skb; port->pending_skb = skb;
port->pending_lpmask = lpmask; port->pending_lpmask = lpmask;
netif_stop_queue(dev); netif_stop_queue(dev);
spin_unlock_irqrestore(&port->pending_gate, flags);
} }
spin_unlock_irqrestore(&port->pending_gate, flags);
return 0; return 0;
} }
...@@ -1049,7 +1055,7 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx) ...@@ -1049,7 +1055,7 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx)
if (! port->pending_lpmask) { if (! port->pending_lpmask) {
dev_kfree_skb_any(port->pending_skb); dev_kfree_skb_any(port->pending_skb);
port->pending_skb = NULL; port->pending_skb = NULL;
netif_start_queue(dev); netif_wake_queue(dev);
} }
} }
spin_unlock_irqrestore(&port->pending_gate, flags); spin_unlock_irqrestore(&port->pending_gate, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment