Skip to content

Commit

Permalink
[PATCH] DM9000 - spinlock fixes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ben Dooks authored and Jeff Garzik committed Aug 18, 2005
1 parent a4cf076 commit 9ef9ac5
Showing 1 changed file with 24 additions and 13 deletions.
37 changes: 24 additions & 13 deletions drivers/net/dm9000.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
* net_device_stats
* * introduced tx_timeout function
* * reworked locking
*
* 01-Jul-2005 Ben Dooks <ben@simtec.co.uk>
* * fixed spinlock call without pointer
* * ensure spinlock is initialised
*/

#include <linux/module.h>
Expand Down Expand Up @@ -322,7 +326,7 @@ static void dm9000_timeout(struct net_device *dev)

/* Save previous register address */
reg_save = readb(db->io_addr);
spin_lock_irqsave(db->lock,flags);
spin_lock_irqsave(&db->lock,flags);

netif_stop_queue(dev);
dm9000_reset(db);
Expand All @@ -333,7 +337,7 @@ static void dm9000_timeout(struct net_device *dev)

/* Restore previous register address */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(db->lock,flags);
spin_unlock_irqrestore(&db->lock,flags);
}


Expand Down Expand Up @@ -405,6 +409,8 @@ dm9000_probe(struct device *dev)
db = (struct board_info *) ndev->priv;
memset(db, 0, sizeof (*db));

spin_lock_init(&db->lock);

if (pdev->num_resources < 2) {
ret = -ENODEV;
goto out;
Expand Down Expand Up @@ -612,7 +618,7 @@ dm9000_open(struct net_device *dev)

/* set and active a timer process */
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.function = &dm9000_timer;
add_timer(&db->timer);
Expand Down Expand Up @@ -864,21 +870,11 @@ dm9000_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
board_info_t *db = (board_info_t *) dev->priv;
u8 reg_save;
unsigned long flags;

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);

/* Restore previous register address */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(db->lock,flags);

/* Set timer again */
db->timer.expires = DM9000_TIMER_WUT;
add_timer(&db->timer);
Expand Down Expand Up @@ -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;
unsigned long flags;
unsigned int reg_save;
int ret;

spin_lock_irqsave(&db->lock,flags);

/* Save previous register address */
reg_save = readb(db->io_addr);

/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);

Expand All @@ -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 */
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);

return ret;
Expand All @@ -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;
unsigned long flags;
unsigned long reg_save;

spin_lock_irqsave(&db->lock,flags);

/* Save previous register address */
reg_save = readb(db->io_addr);

/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);

Expand All @@ -1138,6 +1146,9 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
udelay(500); /* Wait write complete */
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);
}

Expand Down

0 comments on commit 9ef9ac5

Please sign in to comment.