From: Andrew Ruder Date: Wed, 4 Jun 2014 22:28:49 +0000 (-0500) Subject: dm9000: avoid sleeping in dm9000_timeout callback X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=582379839bbdb76f2f0ad956a39f920cfd84fcea;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git 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 Signed-off-by: David S. Miller --- 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); }