diff options
Diffstat (limited to 'drivers/net/dm9000.c')
-rw-r--r-- | drivers/net/dm9000.c | 53 |
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; | |||
102 | module_param(watchdog, int, 0400); | 102 | module_param(watchdog, int, 0400); |
103 | MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); | 103 | MODULE_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 ------------------------------- */ |
106 | typedef struct board_info { | 124 | typedef 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, | |||
365 | static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 385 | static 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 | ||
377 | static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 393 | static 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 | ||
390 | static int dm9000_nway_reset(struct net_device *dev) | 400 | static 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 | */ |
999 | static void | 1010 | static void |
1000 | dm9000_read_eeprom(board_info_t * db, int offset, unsigned char *to) | 1011 | dm9000_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) | |||
1016 | static void | 1031 | static void |
1017 | write_srom_word(board_info_t * db, int offset, u16 val) | 1032 | write_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 | ||
1202 | static int | 1227 | static int |