aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-02-04 19:02:10 -0500
committerJeff Garzik <jeff@garzik.org>2008-02-11 11:06:28 -0500
commit9a2f037cdbe8409c5ff92e8dce5fcdfe2ebb2084 (patch)
treee3b9570b76c739e9aa1f1a63fc722484b658bdae /drivers
parent86c62fab5aafe33d033d2f616ba8be0527e1c286 (diff)
DM9000: Add mutex to protect access
Add a mutex to serialise access to the chip functions from entries such as the ethtool and the MII code. This should reduce the amount of time the spinlock is held to protect the address register. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/dm9000.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index fa7eb39dbf3c..a769c89a3690 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -102,6 +102,24 @@ static int watchdog = 5000;
102module_param(watchdog, int, 0400); 102module_param(watchdog, int, 0400);
103MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); 103MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
104 104
105/* DM9000 register address locking.
106 *
107 * The DM9000 uses an address register to control where data written
108 * to the data register goes. This means that the address register
109 * must be preserved over interrupts or similar calls.
110 *
111 * During interrupt and other critical calls, a spinlock is used to
112 * protect the system, but the calls themselves save the address
113 * in the address register in case they are interrupting another
114 * access to the device.
115 *
116 * For general accesses a lock is provided so that calls which are
117 * allowed to sleep are serialised so that the address register does
118 * not need to be saved. This lock also serves to serialise access
119 * to the EEPROM and PHY access registers which are shared between
120 * these two devices.
121 */
122
105/* Structure/enum declaration ------------------------------- */ 123/* Structure/enum declaration ------------------------------- */
106typedef struct board_info { 124typedef struct board_info {
107 125
@@ -132,6 +150,8 @@ typedef struct board_info {
132 struct resource *data_req; 150 struct resource *data_req;
133 struct resource *irq_res; 151 struct resource *irq_res;
134 152
153 struct mutex addr_lock; /* phy and eeprom access lock */
154
135 spinlock_t lock; 155 spinlock_t lock;
136 156
137 struct mii_if_info mii; 157 struct mii_if_info mii;
@@ -365,26 +385,16 @@ static void dm9000_get_drvinfo(struct net_device *dev,
365static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 385static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
366{ 386{
367 board_info_t *dm = to_dm9000_board(dev); 387 board_info_t *dm = to_dm9000_board(dev);
368 unsigned long flags;
369 388
370 spin_lock_irqsave(&dm->lock, flags);
371 mii_ethtool_gset(&dm->mii, cmd); 389 mii_ethtool_gset(&dm->mii, cmd);
372 spin_lock_irqsave(&dm->lock, flags);
373
374 return 0; 390 return 0;
375} 391}
376 392
377static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 393static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
378{ 394{
379 board_info_t *dm = to_dm9000_board(dev); 395 board_info_t *dm = to_dm9000_board(dev);
380 unsigned long flags;
381 int rc;
382
383 spin_lock_irqsave(&dm->lock, flags);
384 rc = mii_ethtool_sset(&dm->mii, cmd);
385 spin_lock_irqsave(&dm->lock, flags);
386 396
387 return rc; 397 return mii_ethtool_sset(&dm->mii, cmd);
388} 398}
389 399
390static int dm9000_nway_reset(struct net_device *dev) 400static int dm9000_nway_reset(struct net_device *dev)
@@ -475,6 +485,7 @@ dm9000_probe(struct platform_device *pdev)
475 db->dev = &pdev->dev; 485 db->dev = &pdev->dev;
476 486
477 spin_lock_init(&db->lock); 487 spin_lock_init(&db->lock);
488 mutex_init(&db->addr_lock);
478 489
479 if (pdev->num_resources < 2) { 490 if (pdev->num_resources < 2) {
480 ret = -ENODEV; 491 ret = -ENODEV;
@@ -997,8 +1008,10 @@ dm9000_rx(struct net_device *dev)
997 * Read a word data from EEPROM 1008 * Read a word data from EEPROM
998 */ 1009 */
999static void 1010static void
1000dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to) 1011dm9000_read_eeprom(board_info_t *db, int offset, unsigned char *to)
1001{ 1012{
1013 mutex_lock(&db->addr_lock);
1014
1002 iow(db, DM9000_EPAR, offset); 1015 iow(db, DM9000_EPAR, offset);
1003 iow(db, DM9000_EPCR, EPCR_ERPRR); 1016 iow(db, DM9000_EPCR, EPCR_ERPRR);
1004 mdelay(8); /* according to the datasheet 200us should be enough, 1017 mdelay(8); /* according to the datasheet 200us should be enough,
@@ -1007,6 +1020,8 @@ dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to)
1007 1020
1008 to[0] = ior(db, DM9000_EPDRL); 1021 to[0] = ior(db, DM9000_EPDRL);
1009 to[1] = ior(db, DM9000_EPDRH); 1022 to[1] = ior(db, DM9000_EPDRH);
1023
1024 mutex_unlock(&db->addr_lock);
1010} 1025}
1011 1026
1012#ifdef DM9000_PROGRAM_EEPROM 1027#ifdef DM9000_PROGRAM_EEPROM
@@ -1016,12 +1031,16 @@ dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to)
1016static void 1031static void
1017write_srom_word(board_info_t * db, int offset, u16 val) 1032write_srom_word(board_info_t * db, int offset, u16 val)
1018{ 1033{
1034 mutex_lock(&db->addr_lock);
1035
1019 iow(db, DM9000_EPAR, offset); 1036 iow(db, DM9000_EPAR, offset);
1020 iow(db, DM9000_EPDRH, ((val >> 8) & 0xff)); 1037 iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
1021 iow(db, DM9000_EPDRL, (val & 0xff)); 1038 iow(db, DM9000_EPDRL, (val & 0xff));
1022 iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW); 1039 iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
1023 mdelay(8); /* same shit */ 1040 mdelay(8); /* same shit */
1024 iow(db, DM9000_EPCR, 0); 1041 iow(db, DM9000_EPCR, 0);
1042
1043 mutex_unlock(&db->addr_lock);
1025} 1044}
1026 1045
1027/* 1046/*
@@ -1129,6 +1148,8 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
1129 unsigned int reg_save; 1148 unsigned int reg_save;
1130 int ret; 1149 int ret;
1131 1150
1151 mutex_lock(&db->addr_lock);
1152
1132 spin_lock_irqsave(&db->lock,flags); 1153 spin_lock_irqsave(&db->lock,flags);
1133 1154
1134 /* Save previous register address */ 1155 /* Save previous register address */
@@ -1156,6 +1177,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
1156 writeb(reg_save, db->io_addr); 1177 writeb(reg_save, db->io_addr);
1157 spin_unlock_irqrestore(&db->lock,flags); 1178 spin_unlock_irqrestore(&db->lock,flags);
1158 1179
1180 mutex_unlock(&db->addr_lock);
1159 return ret; 1181 return ret;
1160} 1182}
1161 1183
@@ -1169,6 +1191,8 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
1169 unsigned long flags; 1191 unsigned long flags;
1170 unsigned long reg_save; 1192 unsigned long reg_save;
1171 1193
1194 mutex_lock(&db->addr_lock);
1195
1172 spin_lock_irqsave(&db->lock,flags); 1196 spin_lock_irqsave(&db->lock,flags);
1173 1197
1174 /* Save previous register address */ 1198 /* Save previous register address */
@@ -1184,7 +1208,7 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
1184 iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */ 1208 iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */
1185 1209
1186 writeb(reg_save, db->io_addr); 1210 writeb(reg_save, db->io_addr);
1187 spin_unlock_irqrestore(&db->lock,flags); 1211 spin_unlock_irqrestore(&db->lock, flags);
1188 1212
1189 dm9000_msleep(db, 1); /* Wait write complete */ 1213 dm9000_msleep(db, 1); /* Wait write complete */
1190 1214
@@ -1196,7 +1220,8 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
1196 /* restore the previous address */ 1220 /* restore the previous address */
1197 writeb(reg_save, db->io_addr); 1221 writeb(reg_save, db->io_addr);
1198 1222
1199 spin_unlock_irqrestore(&db->lock,flags); 1223 spin_unlock_irqrestore(&db->lock, flags);
1224 mutex_unlock(&db->addr_lock);
1200} 1225}
1201 1226
1202static int 1227static int