aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/3c59x.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-28 18:42:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-28 18:42:44 -0400
commit29cfcddc0e745b515ec360ffe2ee4e7a4015efd8 (patch)
tree1682b6caaf84d4863e65b2e4e387afa6a972146f /drivers/net/3c59x.c
parent303fd2c2ce5addef1aacac962a5b099cc0af71ea (diff)
parentc34186ed008229e7f7e3f1de8e6acf6374995358 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: net/ipv4: Eliminate kstrdup memory leak net/caif/cfrfml.c: use asm/unaligned.h ax25: missplaced sock_put(sk) qlge: reset the chip before freeing the buffers l2tp: test for ethernet header in l2tp_eth_dev_recv() tcp: select(writefds) don't hang up when a peer close connection tcp: fix three tcp sysctls tuning tcp: Combat per-cpu skew in orphan tests. pxa168_eth: silence gcc warnings pxa168_eth: update call to phy_mii_ioctl() pxa168_eth: fix error handling in prope pxa168_eth: remove unneeded null check phylib: Fix race between returning phydev and calling adjust_link caif-driver: add HAS_DMA dependency 3c59x: Fix deadlock between boomerang_interrupt and boomerang_start_tx qlcnic: fix poll implementation netxen: fix poll implementation bridge: netfilter: fix a memory leak
Diffstat (limited to 'drivers/net/3c59x.c')
-rw-r--r--drivers/net/3c59x.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index c754d88e5ec9..c685a55fc2f4 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -633,7 +633,8 @@ struct vortex_private {
633 open:1, 633 open:1,
634 medialock:1, 634 medialock:1,
635 must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ 635 must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */
636 large_frames:1; /* accept large frames */ 636 large_frames:1, /* accept large frames */
637 handling_irq:1; /* private in_irq indicator */
637 int drv_flags; 638 int drv_flags;
638 u16 status_enable; 639 u16 status_enable;
639 u16 intr_enable; 640 u16 intr_enable;
@@ -2133,6 +2134,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
2133 dev->name, vp->cur_tx); 2134 dev->name, vp->cur_tx);
2134 } 2135 }
2135 2136
2137 /*
2138 * We can't allow a recursion from our interrupt handler back into the
2139 * tx routine, as they take the same spin lock, and that causes
2140 * deadlock. Just return NETDEV_TX_BUSY and let the stack try again in
2141 * a bit
2142 */
2143 if (vp->handling_irq)
2144 return NETDEV_TX_BUSY;
2145
2136 if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { 2146 if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
2137 if (vortex_debug > 0) 2147 if (vortex_debug > 0)
2138 pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n", 2148 pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n",
@@ -2335,11 +2345,13 @@ boomerang_interrupt(int irq, void *dev_id)
2335 2345
2336 ioaddr = vp->ioaddr; 2346 ioaddr = vp->ioaddr;
2337 2347
2348
2338 /* 2349 /*
2339 * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout 2350 * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
2340 * and boomerang_start_xmit 2351 * and boomerang_start_xmit
2341 */ 2352 */
2342 spin_lock(&vp->lock); 2353 spin_lock(&vp->lock);
2354 vp->handling_irq = 1;
2343 2355
2344 status = ioread16(ioaddr + EL3_STATUS); 2356 status = ioread16(ioaddr + EL3_STATUS);
2345 2357
@@ -2447,6 +2459,7 @@ boomerang_interrupt(int irq, void *dev_id)
2447 pr_debug("%s: exiting interrupt, status %4.4x.\n", 2459 pr_debug("%s: exiting interrupt, status %4.4x.\n",
2448 dev->name, status); 2460 dev->name, status);
2449handler_exit: 2461handler_exit:
2462 vp->handling_irq = 0;
2450 spin_unlock(&vp->lock); 2463 spin_unlock(&vp->lock);
2451 return IRQ_HANDLED; 2464 return IRQ_HANDLED;
2452} 2465}