On 07 Oct 2004 at 11h10, David S. Miller wrote:
Hi again,
> So, netpoll needs to have the NETIF_F_LLTX stuff added to it.
This patch should do that. It works OK for me, but I'd like it checked
before sent upstream...
However, it doesn't fix the hang. it looks like this hang is really
coming from sungem.
--- a/net/core/netpoll.c 2004-10-05 21:09:49.000000000 +0200
+++ b/net/core/netpoll.c 2004-10-07 22:48:58.000000000 +0200
@@ -181,6 +181,7 @@
void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
+ unsigned must_lock;
repeat:
if(!np || !np->dev || !netif_running(np->dev)) {
@@ -188,29 +189,51 @@
return;
}
- spin_lock(&np->dev->xmit_lock);
- np->dev->xmit_lock_owner = smp_processor_id();
+ must_lock = !(np->dev->features & NETIF_F_LLTX);
+
+ if (must_lock) {
+ if (!spin_trylock(&np->dev->xmit_lock)) {
+ if (np->dev->xmit_lock_owner ==
smp_processor_id()) {
+ __kfree_skb(skb);
+ return;
+ }
+ goto repeat;
+ }
+ np->dev->xmit_lock_owner = smp_processor_id();
+ }
+
/*
* network drivers do not expect to be called if the queue is
* stopped.
*/
if (netif_queue_stopped(np->dev)) {
np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+
+ if (must_lock)
+ spin_unlock(&np->dev->xmit_lock);
netpoll_poll(np);
goto repeat;
}
status = np->dev->hard_start_xmit(skb, np->dev);
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+
+ if (must_lock) {
+ np->dev->xmit_lock_owner = -1;
+ spin_unlock(&np->dev->xmit_lock);
+ }
/* transmit busy */
- if(status) {
+ if (status == NETDEV_TX_LOCKED) {
netpoll_poll(np);
goto repeat;
+ }
+
+ /* hard error */
+ if (status == NETDEV_TX_BUSY) {
+ __kfree_skb(skb);
+ return;
}
}
|