diff options
author | Ben Dooks <ben-netdev@fluff.org> | 2005-07-23 12:25:18 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-18 16:59:14 -0400 |
commit | 9ef9ac51cc5fa5f5811230b5fb242536b636ff47 (patch) | |
tree | 228175f622065b3683e2c2b94468210752004804 /drivers/net/dm9000.c | |
parent | a4cf0761493495681d72dcc0b34efb86e94a5527 (diff) |
[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>
Diffstat (limited to 'drivers/net/dm9000.c')
-rw-r--r-- | drivers/net/dm9000.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 5fddc0ff8878..1d92ddd1ec35 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c | |||
@@ -48,6 +48,10 @@ | |||
48 | * net_device_stats | 48 | * net_device_stats |
49 | * * introduced tx_timeout function | 49 | * * introduced tx_timeout function |
50 | * * reworked locking | 50 | * * reworked locking |
51 | * | ||
52 | * 01-Jul-2005 Ben Dooks <ben@simtec.co.uk> | ||
53 | * * fixed spinlock call without pointer | ||
54 | * * ensure spinlock is initialised | ||
51 | */ | 55 | */ |
52 | 56 | ||
53 | #include <linux/module.h> | 57 | #include <linux/module.h> |
@@ -322,7 +326,7 @@ static void dm9000_timeout(struct net_device *dev) | |||
322 | 326 | ||
323 | /* Save previous register address */ | 327 | /* Save previous register address */ |
324 | reg_save = readb(db->io_addr); | 328 | reg_save = readb(db->io_addr); |
325 | spin_lock_irqsave(db->lock,flags); | 329 | spin_lock_irqsave(&db->lock,flags); |
326 | 330 | ||
327 | netif_stop_queue(dev); | 331 | netif_stop_queue(dev); |
328 | dm9000_reset(db); | 332 | dm9000_reset(db); |
@@ -333,7 +337,7 @@ static void dm9000_timeout(struct net_device *dev) | |||
333 | 337 | ||
334 | /* Restore previous register address */ | 338 | /* Restore previous register address */ |
335 | writeb(reg_save, db->io_addr); | 339 | writeb(reg_save, db->io_addr); |
336 | spin_unlock_irqrestore(db->lock,flags); | 340 | spin_unlock_irqrestore(&db->lock,flags); |
337 | } | 341 | } |
338 | 342 | ||
339 | 343 | ||
@@ -405,6 +409,8 @@ dm9000_probe(struct device *dev) | |||
405 | db = (struct board_info *) ndev->priv; | 409 | db = (struct board_info *) ndev->priv; |
406 | memset(db, 0, sizeof (*db)); | 410 | memset(db, 0, sizeof (*db)); |
407 | 411 | ||
412 | spin_lock_init(&db->lock); | ||
413 | |||
408 | if (pdev->num_resources < 2) { | 414 | if (pdev->num_resources < 2) { |
409 | ret = -ENODEV; | 415 | ret = -ENODEV; |
410 | goto out; | 416 | goto out; |
@@ -612,7 +618,7 @@ dm9000_open(struct net_device *dev) | |||
612 | 618 | ||
613 | /* set and active a timer process */ | 619 | /* set and active a timer process */ |
614 | init_timer(&db->timer); | 620 | init_timer(&db->timer); |
615 | db->timer.expires = DM9000_TIMER_WUT * 2; | 621 | db->timer.expires = DM9000_TIMER_WUT; |
616 | db->timer.data = (unsigned long) dev; | 622 | db->timer.data = (unsigned long) dev; |
617 | db->timer.function = &dm9000_timer; | 623 | db->timer.function = &dm9000_timer; |
618 | add_timer(&db->timer); | 624 | add_timer(&db->timer); |
@@ -864,21 +870,11 @@ dm9000_timer(unsigned long data) | |||
864 | { | 870 | { |
865 | struct net_device *dev = (struct net_device *) data; | 871 | struct net_device *dev = (struct net_device *) data; |
866 | board_info_t *db = (board_info_t *) dev->priv; | 872 | board_info_t *db = (board_info_t *) dev->priv; |
867 | u8 reg_save; | ||
868 | unsigned long flags; | ||
869 | 873 | ||
870 | PRINTK3("dm9000_timer()\n"); | 874 | PRINTK3("dm9000_timer()\n"); |
871 | 875 | ||
872 | spin_lock_irqsave(db->lock,flags); | ||
873 | /* Save previous register address */ | ||
874 | reg_save = readb(db->io_addr); | ||
875 | |||
876 | mii_check_media(&db->mii, netif_msg_link(db), 0); | 876 | mii_check_media(&db->mii, netif_msg_link(db), 0); |
877 | 877 | ||
878 | /* Restore previous register address */ | ||
879 | writeb(reg_save, db->io_addr); | ||
880 | spin_unlock_irqrestore(db->lock,flags); | ||
881 | |||
882 | /* Set timer again */ | 878 | /* Set timer again */ |
883 | db->timer.expires = DM9000_TIMER_WUT; | 879 | db->timer.expires = DM9000_TIMER_WUT; |
884 | add_timer(&db->timer); | 880 | add_timer(&db->timer); |
@@ -1098,9 +1094,14 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) | |||
1098 | { | 1094 | { |
1099 | board_info_t *db = (board_info_t *) dev->priv; | 1095 | board_info_t *db = (board_info_t *) dev->priv; |
1100 | unsigned long flags; | 1096 | unsigned long flags; |
1097 | unsigned int reg_save; | ||
1101 | int ret; | 1098 | int ret; |
1102 | 1099 | ||
1103 | spin_lock_irqsave(&db->lock,flags); | 1100 | spin_lock_irqsave(&db->lock,flags); |
1101 | |||
1102 | /* Save previous register address */ | ||
1103 | reg_save = readb(db->io_addr); | ||
1104 | |||
1104 | /* Fill the phyxcer register into REG_0C */ | 1105 | /* Fill the phyxcer register into REG_0C */ |
1105 | iow(db, DM9000_EPAR, DM9000_PHY | reg); | 1106 | iow(db, DM9000_EPAR, DM9000_PHY | reg); |
1106 | 1107 | ||
@@ -1111,6 +1112,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) | |||
1111 | /* The read data keeps on REG_0D & REG_0E */ | 1112 | /* The read data keeps on REG_0D & REG_0E */ |
1112 | ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); | 1113 | ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); |
1113 | 1114 | ||
1115 | /* restore the previous address */ | ||
1116 | writeb(reg_save, db->io_addr); | ||
1117 | |||
1114 | spin_unlock_irqrestore(&db->lock,flags); | 1118 | spin_unlock_irqrestore(&db->lock,flags); |
1115 | 1119 | ||
1116 | return ret; | 1120 | return ret; |
@@ -1124,9 +1128,13 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) | |||
1124 | { | 1128 | { |
1125 | board_info_t *db = (board_info_t *) dev->priv; | 1129 | board_info_t *db = (board_info_t *) dev->priv; |
1126 | unsigned long flags; | 1130 | unsigned long flags; |
1131 | unsigned long reg_save; | ||
1127 | 1132 | ||
1128 | spin_lock_irqsave(&db->lock,flags); | 1133 | spin_lock_irqsave(&db->lock,flags); |
1129 | 1134 | ||
1135 | /* Save previous register address */ | ||
1136 | reg_save = readb(db->io_addr); | ||
1137 | |||
1130 | /* Fill the phyxcer register into REG_0C */ | 1138 | /* Fill the phyxcer register into REG_0C */ |
1131 | iow(db, DM9000_EPAR, DM9000_PHY | reg); | 1139 | iow(db, DM9000_EPAR, DM9000_PHY | reg); |
1132 | 1140 | ||
@@ -1138,6 +1146,9 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) | |||
1138 | udelay(500); /* Wait write complete */ | 1146 | udelay(500); /* Wait write complete */ |
1139 | iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ | 1147 | iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ |
1140 | 1148 | ||
1149 | /* restore the previous address */ | ||
1150 | writeb(reg_save, db->io_addr); | ||
1151 | |||
1141 | spin_unlock_irqrestore(&db->lock,flags); | 1152 | spin_unlock_irqrestore(&db->lock,flags); |
1142 | } | 1153 | } |
1143 | 1154 | ||