瀏覽代碼

[PATCH] DM9000 - spinlock fixes

Fix DM9000 driver usage of spinlocks, which mainly came to light
when running a kernel with spinlock debugging. These come down to:

1) Un-initialised spin lock

2) Several cases of using  spin_xxx(lock) and not spin_xxx(&lock)

3) move the locking around the phy reg for read/write to only
   keep the lock when actually reading or writing to the phy.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Ben Dooks 20 年之前
父節點
當前提交
9ef9ac51cc
共有 1 個文件被更改,包括 24 次插入13 次删除
  1. 24 13
      drivers/net/dm9000.c

+ 24 - 13
drivers/net/dm9000.c

@@ -48,6 +48,10 @@
  *                        net_device_stats
  *                        net_device_stats
  *                      * introduced tx_timeout function
  *                      * introduced tx_timeout function
  *                      * reworked locking
  *                      * reworked locking
+ *
+ *	  01-Jul-2005   Ben Dooks <ben@simtec.co.uk>
+ *			* fixed spinlock call without pointer
+ *			* ensure spinlock is initialised
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -322,7 +326,7 @@ static void dm9000_timeout(struct net_device *dev)
 
 
 	/* Save previous register address */
 	/* Save previous register address */
 	reg_save = readb(db->io_addr);
 	reg_save = readb(db->io_addr);
-	spin_lock_irqsave(db->lock,flags);
+	spin_lock_irqsave(&db->lock,flags);
 
 
 	netif_stop_queue(dev);
 	netif_stop_queue(dev);
 	dm9000_reset(db);
 	dm9000_reset(db);
@@ -333,7 +337,7 @@ static void dm9000_timeout(struct net_device *dev)
 
 
 	/* Restore previous register address */
 	/* Restore previous register address */
 	writeb(reg_save, db->io_addr);
 	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(db->lock,flags);
+	spin_unlock_irqrestore(&db->lock,flags);
 }
 }
 
 
 
 
@@ -405,6 +409,8 @@ dm9000_probe(struct device *dev)
 	db = (struct board_info *) ndev->priv;
 	db = (struct board_info *) ndev->priv;
 	memset(db, 0, sizeof (*db));
 	memset(db, 0, sizeof (*db));
 
 
+	spin_lock_init(&db->lock);
+
 	if (pdev->num_resources < 2) {
 	if (pdev->num_resources < 2) {
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto out;
 		goto out;
@@ -612,7 +618,7 @@ dm9000_open(struct net_device *dev)
 
 
 	/* set and active a timer process */
 	/* set and active a timer process */
 	init_timer(&db->timer);
 	init_timer(&db->timer);
-	db->timer.expires  = DM9000_TIMER_WUT * 2;
+	db->timer.expires  = DM9000_TIMER_WUT;
 	db->timer.data     = (unsigned long) dev;
 	db->timer.data     = (unsigned long) dev;
 	db->timer.function = &dm9000_timer;
 	db->timer.function = &dm9000_timer;
 	add_timer(&db->timer);
 	add_timer(&db->timer);
@@ -864,21 +870,11 @@ dm9000_timer(unsigned long data)
 {
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct net_device *dev = (struct net_device *) data;
 	board_info_t *db = (board_info_t *) dev->priv;
 	board_info_t *db = (board_info_t *) dev->priv;
-	u8 reg_save;
-	unsigned long flags;
 
 
 	PRINTK3("dm9000_timer()\n");
 	PRINTK3("dm9000_timer()\n");
 
 
-	spin_lock_irqsave(db->lock,flags);
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
 	mii_check_media(&db->mii, netif_msg_link(db), 0);
 	mii_check_media(&db->mii, netif_msg_link(db), 0);
 
 
-	/* Restore previous register address */
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(db->lock,flags);
-
 	/* Set timer again */
 	/* Set timer again */
 	db->timer.expires = DM9000_TIMER_WUT;
 	db->timer.expires = DM9000_TIMER_WUT;
 	add_timer(&db->timer);
 	add_timer(&db->timer);
@@ -1098,9 +1094,14 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 {
 {
 	board_info_t *db = (board_info_t *) dev->priv;
 	board_info_t *db = (board_info_t *) dev->priv;
 	unsigned long flags;
 	unsigned long flags;
+	unsigned int reg_save;
 	int ret;
 	int ret;
 
 
 	spin_lock_irqsave(&db->lock,flags);
 	spin_lock_irqsave(&db->lock,flags);
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
 	/* Fill the phyxcer register into REG_0C */
 	/* Fill the phyxcer register into REG_0C */
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
 
@@ -1111,6 +1112,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 	/* The read data keeps on REG_0D & REG_0E */
 	/* The read data keeps on REG_0D & REG_0E */
 	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
 	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
 
 
+	/* restore the previous address */
+	writeb(reg_save, db->io_addr);
+
 	spin_unlock_irqrestore(&db->lock,flags);
 	spin_unlock_irqrestore(&db->lock,flags);
 
 
 	return ret;
 	return ret;
@@ -1124,9 +1128,13 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
 {
 {
 	board_info_t *db = (board_info_t *) dev->priv;
 	board_info_t *db = (board_info_t *) dev->priv;
 	unsigned long flags;
 	unsigned long flags;
+	unsigned long reg_save;
 
 
 	spin_lock_irqsave(&db->lock,flags);
 	spin_lock_irqsave(&db->lock,flags);
 
 
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
 	/* Fill the phyxcer register into REG_0C */
 	/* Fill the phyxcer register into REG_0C */
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
 
@@ -1138,6 +1146,9 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
 	udelay(500);		/* Wait write complete */
 	udelay(500);		/* Wait write complete */
 	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
 	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
 
 
+	/* restore the previous address */
+	writeb(reg_save, db->io_addr);
+
 	spin_unlock_irqrestore(&db->lock,flags);
 	spin_unlock_irqrestore(&db->lock,flags);
 }
 }