aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dm9000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dm9000.c')
-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