From 8c5c41c65a8dcee28271381d969c6be8fa4ca675 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Aug 2010 05:12:57 +0000 Subject: [PATCH] --- yaml --- r: 210130 b: refs/heads/master c: aa25ab7d943a5e1e6bcc2a65ff6669144f5b5d60 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/net/3c59x.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 21f6ea46e4e2..6e1fed538a1c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bf82791ed667758a0f18a4b76be2d931d2c1b39d +refs/heads/master: aa25ab7d943a5e1e6bcc2a65ff6669144f5b5d60 diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index c754d88e5ec9..c685a55fc2f4 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -633,7 +633,8 @@ struct vortex_private { open:1, medialock:1, must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ - large_frames:1; /* accept large frames */ + large_frames:1, /* accept large frames */ + handling_irq:1; /* private in_irq indicator */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -2133,6 +2134,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->name, vp->cur_tx); } + /* + * We can't allow a recursion from our interrupt handler back into the + * tx routine, as they take the same spin lock, and that causes + * deadlock. Just return NETDEV_TX_BUSY and let the stack try again in + * a bit + */ + if (vp->handling_irq) + return NETDEV_TX_BUSY; + if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { if (vortex_debug > 0) pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n", @@ -2335,11 +2345,13 @@ boomerang_interrupt(int irq, void *dev_id) ioaddr = vp->ioaddr; + /* * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout * and boomerang_start_xmit */ spin_lock(&vp->lock); + vp->handling_irq = 1; status = ioread16(ioaddr + EL3_STATUS); @@ -2447,6 +2459,7 @@ boomerang_interrupt(int irq, void *dev_id) pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status); handler_exit: + vp->handling_irq = 0; spin_unlock(&vp->lock); return IRQ_HANDLED; }