diff options
Diffstat (limited to 'drivers/net/3c59x.c')
-rw-r--r-- | drivers/net/3c59x.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c754d88e5ec9..a045559c81cf 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; |
@@ -646,7 +647,7 @@ struct vortex_private { | |||
646 | u16 io_size; /* Size of PCI region (for release_region) */ | 647 | u16 io_size; /* Size of PCI region (for release_region) */ |
647 | 648 | ||
648 | /* Serialises access to hardware other than MII and variables below. | 649 | /* Serialises access to hardware other than MII and variables below. |
649 | * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */ | 650 | * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */ |
650 | spinlock_t lock; | 651 | spinlock_t lock; |
651 | 652 | ||
652 | spinlock_t mii_lock; /* Serialises access to MII */ | 653 | spinlock_t mii_lock; /* Serialises access to MII */ |
@@ -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); |
2449 | handler_exit: | 2461 | handler_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 | } |
@@ -2971,7 +2984,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
2971 | { | 2984 | { |
2972 | int err; | 2985 | int err; |
2973 | struct vortex_private *vp = netdev_priv(dev); | 2986 | struct vortex_private *vp = netdev_priv(dev); |
2974 | unsigned long flags; | ||
2975 | pci_power_t state = 0; | 2987 | pci_power_t state = 0; |
2976 | 2988 | ||
2977 | if(VORTEX_PCI(vp)) | 2989 | if(VORTEX_PCI(vp)) |
@@ -2981,9 +2993,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
2981 | 2993 | ||
2982 | if(state != 0) | 2994 | if(state != 0) |
2983 | pci_set_power_state(VORTEX_PCI(vp), PCI_D0); | 2995 | pci_set_power_state(VORTEX_PCI(vp), PCI_D0); |
2984 | spin_lock_irqsave(&vp->lock, flags); | ||
2985 | err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); | 2996 | err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); |
2986 | spin_unlock_irqrestore(&vp->lock, flags); | ||
2987 | if(state != 0) | 2997 | if(state != 0) |
2988 | pci_set_power_state(VORTEX_PCI(vp), state); | 2998 | pci_set_power_state(VORTEX_PCI(vp), state); |
2989 | 2999 | ||