Skip to content

Commit

Permalink
[PATCH] forcedeth: hardirq lockdep warning
Browse files Browse the repository at this point in the history
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: Peter 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: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Peter Zijlstra authored and Jeff Garzik committed Oct 5, 2006
1 parent 70fbf32 commit 0a07bc6
Showing 1 changed file with 17 additions and 14 deletions.
31 changes: 17 additions & 14 deletions drivers/net/forcedeth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
u32 events;
int i;
unsigned long flags;

dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);

Expand All @@ -2508,16 +2509,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask))
break;

spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
nv_tx_done(dev);
spin_unlock_irq(&np->lock);
spin_unlock_irqrestore(&np->lock, flags);

if (events & (NVREG_IRQ_TX_ERR)) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events);
}
if (i > max_interrupt_work) {
spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
pci_push(base);
Expand All @@ -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);
}
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;
}

Expand Down Expand Up @@ -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);
u32 events;
int i;
unsigned long flags;

dprintk(KERN_DEBUG "%s: nv_nic_irq_rx\n", dev->name);

Expand All @@ -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);
if (nv_alloc_rx(dev)) {
spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock_irq(&np->lock);
spin_unlock_irqrestore(&np->lock, flags);
}

if (i > max_interrupt_work) {
spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base);
Expand All @@ -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);
}
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;
}
}
Expand All @@ -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);
u32 events;
int i;
unsigned long flags;

dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name);

Expand All @@ -2660,22 +2663,22 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
break;

if (events & NVREG_IRQ_LINK) {
spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
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)) {
spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
nv_linkchange(dev);
spin_unlock_irq(&np->lock);
spin_unlock_irqrestore(&np->lock, flags);
np->link_timeout = jiffies + LINK_TIMEOUT;
}
if (events & (NVREG_IRQ_UNKNOWN)) {
printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
dev->name, events);
}
if (i > max_interrupt_work) {
spin_lock_irq(&np->lock);
spin_lock_irqsave(&np->lock, flags);
/* disable interrupts on the nic */
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
pci_push(base);
Expand All @@ -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);
}
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;
}

Expand Down

0 comments on commit 0a07bc6

Please sign in to comment.