Skip to content

Commit

Permalink
dm9000: locking bugfix
Browse files Browse the repository at this point in the history
This fixes a locking bug in the dm9000 driver.  It calls
request_irq() without setting IRQF_DISABLED ... which is
correct for handlers that support IRQ sharing, since that
behavior is not guaranteed for shared IRQs.  However, its
IRQ handler then wrongly assumes that IRQs are blocked.
So the fix just uses the right spinlock primitives in the
IRQ handler.

NOTE:  this is a classic example of the type of bug which
lockdep currently masks by forcibly setting IRQF_DISABLED
on IRQ handlers that did not request that flag.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David Brownell authored and davem330 committed Mar 23, 2009
1 parent 6580f57 commit e3162d3
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions drivers/net/dm9000.c
Expand Up @@ -930,13 +930,15 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
struct net_device *dev = dev_id;
board_info_t *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save;

dm9000_dbg(db, 3, "entering %s\n", __func__);

/* A real interrupt coming */

spin_lock(&db->lock);
/* holders of db->lock must always block IRQs */
spin_lock_irqsave(&db->lock, flags);

/* Save previous register address */
reg_save = readb(db->io_addr);
Expand Down Expand Up @@ -972,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
/* Restore previous register address */
writeb(reg_save, db->io_addr);

spin_unlock(&db->lock);
spin_unlock_irqrestore(&db->lock, flags);

return IRQ_HANDLED;
}
Expand Down

0 comments on commit e3162d3

Please sign in to comment.