diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2006-12-17 17:03:15 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-26 16:24:11 -0500 |
commit | d15e9c4d9a75702b30e00cdf95c71c88e3f3f51e (patch) | |
tree | e7ba1469eac6f732a7d2b9debc7713d8173dc0a2 | |
parent | 79f3d3996f06ee339c6f173e573826eccd3914ab (diff) |
netpoll: drivers must not enable IRQ unconditionally in their NAPI handler
net/core/netpoll.c::netpoll_send_skb() calls the poll handler when
it is available. As netconsole can be used from almost any context,
IRQ must not be enabled blindly in the NAPI handler of a driver which
supports netpoll.
b57bd06655a028aba7b92e1c19c2093e7fcfb341 fixed the issue for the
8139too.c driver.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/net/8139cp.c | 6 | ||||
-rw-r--r-- | drivers/net/b44.c | 6 | ||||
-rw-r--r-- | drivers/net/forcedeth.c | 11 | ||||
-rw-r--r-- | drivers/net/skge.c | 5 |
4 files changed, 18 insertions, 10 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 458dd9f830c4..e2cb19b582a1 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -617,13 +617,15 @@ rx_next: | |||
617 | * this round of polling | 617 | * this round of polling |
618 | */ | 618 | */ |
619 | if (rx_work) { | 619 | if (rx_work) { |
620 | unsigned long flags; | ||
621 | |||
620 | if (cpr16(IntrStatus) & cp_rx_intr_mask) | 622 | if (cpr16(IntrStatus) & cp_rx_intr_mask) |
621 | goto rx_status_loop; | 623 | goto rx_status_loop; |
622 | 624 | ||
623 | local_irq_disable(); | 625 | local_irq_save(flags); |
624 | cpw16_f(IntrMask, cp_intr_mask); | 626 | cpw16_f(IntrMask, cp_intr_mask); |
625 | __netif_rx_complete(dev); | 627 | __netif_rx_complete(dev); |
626 | local_irq_enable(); | 628 | local_irq_restore(flags); |
627 | 629 | ||
628 | return 0; /* done */ | 630 | return 0; /* done */ |
629 | } | 631 | } |
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 474a4e3438db..5eb2ec68393f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -879,12 +879,14 @@ static int b44_poll(struct net_device *netdev, int *budget) | |||
879 | } | 879 | } |
880 | 880 | ||
881 | if (bp->istat & ISTAT_ERRORS) { | 881 | if (bp->istat & ISTAT_ERRORS) { |
882 | spin_lock_irq(&bp->lock); | 882 | unsigned long flags; |
883 | |||
884 | spin_lock_irqsave(&bp->lock, flags); | ||
883 | b44_halt(bp); | 885 | b44_halt(bp); |
884 | b44_init_rings(bp); | 886 | b44_init_rings(bp); |
885 | b44_init_hw(bp, 1); | 887 | b44_init_hw(bp, 1); |
886 | netif_wake_queue(bp->dev); | 888 | netif_wake_queue(bp->dev); |
887 | spin_unlock_irq(&bp->lock); | 889 | spin_unlock_irqrestore(&bp->lock, flags); |
888 | done = 1; | 890 | done = 1; |
889 | } | 891 | } |
890 | 892 | ||
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 439f41338291..820f8c798420 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -2576,14 +2576,15 @@ static int nv_napi_poll(struct net_device *dev, int *budget) | |||
2576 | int pkts, limit = min(*budget, dev->quota); | 2576 | int pkts, limit = min(*budget, dev->quota); |
2577 | struct fe_priv *np = netdev_priv(dev); | 2577 | struct fe_priv *np = netdev_priv(dev); |
2578 | u8 __iomem *base = get_hwbase(dev); | 2578 | u8 __iomem *base = get_hwbase(dev); |
2579 | unsigned long flags; | ||
2579 | 2580 | ||
2580 | pkts = nv_rx_process(dev, limit); | 2581 | pkts = nv_rx_process(dev, limit); |
2581 | 2582 | ||
2582 | if (nv_alloc_rx(dev)) { | 2583 | if (nv_alloc_rx(dev)) { |
2583 | spin_lock_irq(&np->lock); | 2584 | spin_lock_irqsave(&np->lock, flags); |
2584 | if (!np->in_shutdown) | 2585 | if (!np->in_shutdown) |
2585 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | 2586 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); |
2586 | spin_unlock_irq(&np->lock); | 2587 | spin_unlock_irqrestore(&np->lock, flags); |
2587 | } | 2588 | } |
2588 | 2589 | ||
2589 | if (pkts < limit) { | 2590 | if (pkts < limit) { |
@@ -2591,13 +2592,15 @@ static int nv_napi_poll(struct net_device *dev, int *budget) | |||
2591 | netif_rx_complete(dev); | 2592 | netif_rx_complete(dev); |
2592 | 2593 | ||
2593 | /* re-enable receive interrupts */ | 2594 | /* re-enable receive interrupts */ |
2594 | spin_lock_irq(&np->lock); | 2595 | spin_lock_irqsave(&np->lock, flags); |
2596 | |||
2595 | np->irqmask |= NVREG_IRQ_RX_ALL; | 2597 | np->irqmask |= NVREG_IRQ_RX_ALL; |
2596 | if (np->msi_flags & NV_MSI_X_ENABLED) | 2598 | if (np->msi_flags & NV_MSI_X_ENABLED) |
2597 | writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); | 2599 | writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); |
2598 | else | 2600 | else |
2599 | writel(np->irqmask, base + NvRegIrqMask); | 2601 | writel(np->irqmask, base + NvRegIrqMask); |
2600 | spin_unlock_irq(&np->lock); | 2602 | |
2603 | spin_unlock_irqrestore(&np->lock, flags); | ||
2601 | return 0; | 2604 | return 0; |
2602 | } else { | 2605 | } else { |
2603 | /* used up our quantum, so reschedule */ | 2606 | /* used up our quantum, so reschedule */ |
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 8a39376f87dc..deedfd5f8226 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -2920,6 +2920,7 @@ static int skge_poll(struct net_device *dev, int *budget) | |||
2920 | struct skge_hw *hw = skge->hw; | 2920 | struct skge_hw *hw = skge->hw; |
2921 | struct skge_ring *ring = &skge->rx_ring; | 2921 | struct skge_ring *ring = &skge->rx_ring; |
2922 | struct skge_element *e; | 2922 | struct skge_element *e; |
2923 | unsigned long flags; | ||
2923 | int to_do = min(dev->quota, *budget); | 2924 | int to_do = min(dev->quota, *budget); |
2924 | int work_done = 0; | 2925 | int work_done = 0; |
2925 | 2926 | ||
@@ -2957,12 +2958,12 @@ static int skge_poll(struct net_device *dev, int *budget) | |||
2957 | if (work_done >= to_do) | 2958 | if (work_done >= to_do) |
2958 | return 1; /* not done */ | 2959 | return 1; /* not done */ |
2959 | 2960 | ||
2960 | spin_lock_irq(&hw->hw_lock); | 2961 | spin_lock_irqsave(&hw->hw_lock, flags); |
2961 | __netif_rx_complete(dev); | 2962 | __netif_rx_complete(dev); |
2962 | hw->intr_mask |= irqmask[skge->port]; | 2963 | hw->intr_mask |= irqmask[skge->port]; |
2963 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2964 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
2964 | skge_read32(hw, B0_IMSK); | 2965 | skge_read32(hw, B0_IMSK); |
2965 | spin_unlock_irq(&hw->hw_lock); | 2966 | spin_unlock_irqrestore(&hw->hw_lock, flags); |
2966 | 2967 | ||
2967 | return 0; | 2968 | return 0; |
2968 | } | 2969 | } |