diff options
author | Andrew Ruder <andrew.ruder@elecsyscorp.com> | 2014-06-05 02:28:49 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-06 02:12:11 +0400 |
commit | 582379839bbdb76f2f0ad956a39f920cfd84fcea (patch) | |
tree | 8d3fb538f4c94b13d9dad30d99da4022e6fdbdfa /drivers/net/ethernet/davicom | |
parent | aac6d02280e61bc30302024ffd7541e0951a2cf6 (diff) | |
download | linux-582379839bbdb76f2f0ad956a39f920cfd84fcea.tar.xz |
dm9000: avoid sleeping in dm9000_timeout callback
On the DM9000B, dm9000_msleep() is called during the dm9000_timeout()
routine. Since dm9000_timeout() holds the main spinlock through the
entire routine, mdelay() needs to be used rather than msleep().
Furthermore, the mutex_lock()/mutex_unlock() should be avoided so as to
not sleep with spinlocks held.
Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/davicom')
-rw-r--r-- | drivers/net/ethernet/davicom/dm9000.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 48870a8b39a4..13723c96d1a2 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -109,6 +109,7 @@ typedef struct board_info { u8 imr_all; unsigned int flags; + unsigned int in_timeout:1; unsigned int in_suspend:1; unsigned int wake_supported:1; @@ -273,7 +274,7 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count) */ static void dm9000_msleep(board_info_t *db, unsigned int ms) { - if (db->in_suspend) + if (db->in_suspend || db->in_timeout) mdelay(ms); else msleep(ms); @@ -334,7 +335,8 @@ dm9000_phy_write(struct net_device *dev, unsigned long reg_save; dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); - mutex_lock(&db->addr_lock); + if (!db->in_timeout) + mutex_lock(&db->addr_lock); spin_lock_irqsave(&db->lock, flags); @@ -365,7 +367,8 @@ dm9000_phy_write(struct net_device *dev, writeb(reg_save, db->io_addr); spin_unlock_irqrestore(&db->lock, flags); - mutex_unlock(&db->addr_lock); + if (!db->in_timeout) + mutex_unlock(&db->addr_lock); } /* dm9000_set_io @@ -971,6 +974,7 @@ static void dm9000_timeout(struct net_device *dev) /* Save previous register address */ spin_lock_irqsave(&db->lock, flags); + db->in_timeout = 1; reg_save = readb(db->io_addr); netif_stop_queue(dev); @@ -982,6 +986,7 @@ static void dm9000_timeout(struct net_device *dev) /* Restore previous register address */ writeb(reg_save, db->io_addr); + db->in_timeout = 0; spin_unlock_irqrestore(&db->lock, flags); } |