diff options
author | Andrew Ruder <andrew.ruder@elecsyscorp.com> | 2014-06-04 18:28:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-05 18:12:11 -0400 |
commit | 582379839bbdb76f2f0ad956a39f920cfd84fcea (patch) | |
tree | 8d3fb538f4c94b13d9dad30d99da4022e6fdbdfa | |
parent | aac6d02280e61bc30302024ffd7541e0951a2cf6 (diff) |
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>
-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 { | |||
109 | u8 imr_all; | 109 | u8 imr_all; |
110 | 110 | ||
111 | unsigned int flags; | 111 | unsigned int flags; |
112 | unsigned int in_timeout:1; | ||
112 | unsigned int in_suspend:1; | 113 | unsigned int in_suspend:1; |
113 | unsigned int wake_supported:1; | 114 | unsigned int wake_supported:1; |
114 | 115 | ||
@@ -273,7 +274,7 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count) | |||
273 | */ | 274 | */ |
274 | static void dm9000_msleep(board_info_t *db, unsigned int ms) | 275 | static void dm9000_msleep(board_info_t *db, unsigned int ms) |
275 | { | 276 | { |
276 | if (db->in_suspend) | 277 | if (db->in_suspend || db->in_timeout) |
277 | mdelay(ms); | 278 | mdelay(ms); |
278 | else | 279 | else |
279 | msleep(ms); | 280 | msleep(ms); |
@@ -334,7 +335,8 @@ dm9000_phy_write(struct net_device *dev, | |||
334 | unsigned long reg_save; | 335 | unsigned long reg_save; |
335 | 336 | ||
336 | dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); | 337 | dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); |
337 | mutex_lock(&db->addr_lock); | 338 | if (!db->in_timeout) |
339 | mutex_lock(&db->addr_lock); | ||
338 | 340 | ||
339 | spin_lock_irqsave(&db->lock, flags); | 341 | spin_lock_irqsave(&db->lock, flags); |
340 | 342 | ||
@@ -365,7 +367,8 @@ dm9000_phy_write(struct net_device *dev, | |||
365 | writeb(reg_save, db->io_addr); | 367 | writeb(reg_save, db->io_addr); |
366 | 368 | ||
367 | spin_unlock_irqrestore(&db->lock, flags); | 369 | spin_unlock_irqrestore(&db->lock, flags); |
368 | mutex_unlock(&db->addr_lock); | 370 | if (!db->in_timeout) |
371 | mutex_unlock(&db->addr_lock); | ||
369 | } | 372 | } |
370 | 373 | ||
371 | /* dm9000_set_io | 374 | /* dm9000_set_io |
@@ -971,6 +974,7 @@ static void dm9000_timeout(struct net_device *dev) | |||
971 | 974 | ||
972 | /* Save previous register address */ | 975 | /* Save previous register address */ |
973 | spin_lock_irqsave(&db->lock, flags); | 976 | spin_lock_irqsave(&db->lock, flags); |
977 | db->in_timeout = 1; | ||
974 | reg_save = readb(db->io_addr); | 978 | reg_save = readb(db->io_addr); |
975 | 979 | ||
976 | netif_stop_queue(dev); | 980 | netif_stop_queue(dev); |
@@ -982,6 +986,7 @@ static void dm9000_timeout(struct net_device *dev) | |||
982 | 986 | ||
983 | /* Restore previous register address */ | 987 | /* Restore previous register address */ |
984 | writeb(reg_save, db->io_addr); | 988 | writeb(reg_save, db->io_addr); |
989 | db->in_timeout = 0; | ||
985 | spin_unlock_irqrestore(&db->lock, flags); | 990 | spin_unlock_irqrestore(&db->lock, flags); |
986 | } | 991 | } |
987 | 992 | ||