Commit 0a07bc64 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Jeff Garzik

[PATCH] forcedeth: hardirq lockdep warning

BUG: warning at kernel/lockdep.c:1816/trace_hardirqs_on() (Not tainted)

Call Trace:
 show_trace
 dump_stack
 trace_hardirqs_on
 :forcedeth:nv_nic_irq_other
 handle_IRQ_event
 __do_IRQ
 do_IRQ
 ret_from_intr
DWARF2 barf
 default_idle
 cpu_idle
 rest_init
 start_kernel
 _sinittext

These 3 functions nv_nic_irq_tx(), nv_nic_irq_rx() and nv_nic_irq_other()
are reachable from IRQ context and process context. Make use of the
irq-save/restore spinlock variant.

(Compile tested only, since I do not have the hardware)
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Dave Jones <davej@redhat.com>
Cc: Andrew Morton <akpm@osdl.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 70fbf327
...@@ -2497,6 +2497,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) ...@@ -2497,6 +2497,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
u8 __iomem *base = get_hwbase(dev); u8 __iomem *base = get_hwbase(dev);
u32 events; u32 events;
int i; int i;
unsigned long flags;
dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name); dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);
...@@ -2508,16 +2509,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) ...@@ -2508,16 +2509,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
nv_tx_done(dev); nv_tx_done(dev);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
if (events & (NVREG_IRQ_TX_ERR)) { if (events & (NVREG_IRQ_TX_ERR)) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events); dev->name, events);
} }
if (i > max_interrupt_work) { if (i > max_interrupt_work) {
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
pci_push(base); pci_push(base);
...@@ -2527,7 +2528,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) ...@@ -2527,7 +2528,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT); mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
} }
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
break; break;
} }
...@@ -2601,6 +2602,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) ...@@ -2601,6 +2602,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
u8 __iomem *base = get_hwbase(dev); u8 __iomem *base = get_hwbase(dev);
u32 events; u32 events;
int i; int i;
unsigned long flags;
dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name); dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name);
...@@ -2614,14 +2616,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) ...@@ -2614,14 +2616,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
nv_rx_process(dev, dev->weight); nv_rx_process(dev, dev->weight);
if (nv_alloc_rx(dev)) { if (nv_alloc_rx(dev)) {
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
if (!np->in_shutdown) if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL); mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
} }
if (i > max_interrupt_work) { if (i > max_interrupt_work) {
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base); pci_push(base);
...@@ -2631,7 +2633,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) ...@@ -2631,7 +2633,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT); mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
} }
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
break; break;
} }
} }
...@@ -2648,6 +2650,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) ...@@ -2648,6 +2650,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
u8 __iomem *base = get_hwbase(dev); u8 __iomem *base = get_hwbase(dev);
u32 events; u32 events;
int i; int i;
unsigned long flags;
dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name); dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name);
...@@ -2660,14 +2663,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) ...@@ -2660,14 +2663,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
break; break;
if (events & NVREG_IRQ_LINK) { if (events & NVREG_IRQ_LINK) {
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
nv_link_irq(dev); nv_link_irq(dev);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
} }
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
nv_linkchange(dev); nv_linkchange(dev);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
np->link_timeout = jiffies + LINK_TIMEOUT; np->link_timeout = jiffies + LINK_TIMEOUT;
} }
if (events & (NVREG_IRQ_UNKNOWN)) { if (events & (NVREG_IRQ_UNKNOWN)) {
...@@ -2675,7 +2678,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) ...@@ -2675,7 +2678,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
dev->name, events); dev->name, events);
} }
if (i > max_interrupt_work) { if (i > max_interrupt_work) {
spin_lock_irq(&np->lock); spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */ /* disable interrupts on the nic */
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
pci_push(base); pci_push(base);
...@@ -2685,7 +2688,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) ...@@ -2685,7 +2688,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT); mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
} }
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
spin_unlock_irq(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment