diff options
| author | Ben Hutchings <ben@decadent.org.uk> | 2010-06-23 09:54:31 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-06-29 02:19:18 -0400 |
| commit | a095cfc40ec7ebe63e9532383c5b5c2a27b14075 (patch) | |
| tree | 283359a3658ad91b122cd0674bf90b6f9dc0e3d2 | |
| parent | d2ef8590343f1f236f5f7f070fb4cd3f5c3ffb69 (diff) | |
3c59x: Specify window explicitly for access to windowed registers
Currently much of the code assumes that a specific window has been
selected, while a few functions save and restore the window. This
makes it impossible to introduce fine-grained locking.
Make those assumptions explicit by introducing wrapper functions
to set the window and read/write a register. Use these everywhere
except vortex_interrupt(), vortex_start_xmit() and vortex_rx().
These set the window just once, or not at all in the case of
vortex_rx() as it should always be called from vortex_interrupt().
Cache the current window in struct vortex_private to avoid
unnecessary hardware writes.
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Tested-by: Arne Nordmark <nordmark@mech.kth.se> [against 2.6.32]
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/3c59x.c | 288 |
1 files changed, 140 insertions, 148 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index d75803e6e527..beddef98ad92 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
| @@ -435,7 +435,6 @@ MODULE_DEVICE_TABLE(pci, vortex_pci_tbl); | |||
| 435 | First the windows. There are eight register windows, with the command | 435 | First the windows. There are eight register windows, with the command |
| 436 | and status registers available in each. | 436 | and status registers available in each. |
| 437 | */ | 437 | */ |
| 438 | #define EL3WINDOW(win_num) iowrite16(SelectWindow + (win_num), ioaddr + EL3_CMD) | ||
| 439 | #define EL3_CMD 0x0e | 438 | #define EL3_CMD 0x0e |
| 440 | #define EL3_STATUS 0x0e | 439 | #define EL3_STATUS 0x0e |
| 441 | 440 | ||
| @@ -647,8 +646,35 @@ struct vortex_private { | |||
| 647 | u16 io_size; /* Size of PCI region (for release_region) */ | 646 | u16 io_size; /* Size of PCI region (for release_region) */ |
| 648 | spinlock_t lock; /* Serialise access to device & its vortex_private */ | 647 | spinlock_t lock; /* Serialise access to device & its vortex_private */ |
| 649 | struct mii_if_info mii; /* MII lib hooks/info */ | 648 | struct mii_if_info mii; /* MII lib hooks/info */ |
| 649 | int window; /* Register window */ | ||
| 650 | }; | 650 | }; |
| 651 | 651 | ||
| 652 | static void window_set(struct vortex_private *vp, int window) | ||
| 653 | { | ||
| 654 | if (window != vp->window) { | ||
| 655 | iowrite16(SelectWindow + window, vp->ioaddr + EL3_CMD); | ||
| 656 | vp->window = window; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | #define DEFINE_WINDOW_IO(size) \ | ||
| 661 | static u ## size \ | ||
| 662 | window_read ## size(struct vortex_private *vp, int window, int addr) \ | ||
| 663 | { \ | ||
| 664 | window_set(vp, window); \ | ||
| 665 | return ioread ## size(vp->ioaddr + addr); \ | ||
| 666 | } \ | ||
| 667 | static void \ | ||
| 668 | window_write ## size(struct vortex_private *vp, u ## size value, \ | ||
| 669 | int window, int addr) \ | ||
| 670 | { \ | ||
| 671 | window_set(vp, window); \ | ||
| 672 | iowrite ## size(value, vp->ioaddr + addr); \ | ||
| 673 | } | ||
| 674 | DEFINE_WINDOW_IO(8) | ||
| 675 | DEFINE_WINDOW_IO(16) | ||
| 676 | DEFINE_WINDOW_IO(32) | ||
| 677 | |||
| 652 | #ifdef CONFIG_PCI | 678 | #ifdef CONFIG_PCI |
| 653 | #define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL) | 679 | #define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL) |
| 654 | #else | 680 | #else |
| @@ -711,7 +737,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, | |||
| 711 | static int vortex_up(struct net_device *dev); | 737 | static int vortex_up(struct net_device *dev); |
| 712 | static void vortex_down(struct net_device *dev, int final); | 738 | static void vortex_down(struct net_device *dev, int final); |
| 713 | static int vortex_open(struct net_device *dev); | 739 | static int vortex_open(struct net_device *dev); |
| 714 | static void mdio_sync(void __iomem *ioaddr, int bits); | 740 | static void mdio_sync(struct vortex_private *vp, int bits); |
| 715 | static int mdio_read(struct net_device *dev, int phy_id, int location); | 741 | static int mdio_read(struct net_device *dev, int phy_id, int location); |
| 716 | static void mdio_write(struct net_device *vp, int phy_id, int location, int value); | 742 | static void mdio_write(struct net_device *vp, int phy_id, int location, int value); |
| 717 | static void vortex_timer(unsigned long arg); | 743 | static void vortex_timer(unsigned long arg); |
| @@ -1119,6 +1145,7 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1119 | vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; | 1145 | vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; |
| 1120 | vp->io_size = vci->io_size; | 1146 | vp->io_size = vci->io_size; |
| 1121 | vp->card_idx = card_idx; | 1147 | vp->card_idx = card_idx; |
| 1148 | vp->window = -1; | ||
| 1122 | 1149 | ||
| 1123 | /* module list only for Compaq device */ | 1150 | /* module list only for Compaq device */ |
| 1124 | if (gendev == NULL) { | 1151 | if (gendev == NULL) { |
| @@ -1205,7 +1232,6 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1205 | vp->mii.force_media = vp->full_duplex; | 1232 | vp->mii.force_media = vp->full_duplex; |
| 1206 | vp->options = option; | 1233 | vp->options = option; |
| 1207 | /* Read the station address from the EEPROM. */ | 1234 | /* Read the station address from the EEPROM. */ |
| 1208 | EL3WINDOW(0); | ||
| 1209 | { | 1235 | { |
| 1210 | int base; | 1236 | int base; |
| 1211 | 1237 | ||
| @@ -1218,14 +1244,15 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1218 | 1244 | ||
| 1219 | for (i = 0; i < 0x40; i++) { | 1245 | for (i = 0; i < 0x40; i++) { |
| 1220 | int timer; | 1246 | int timer; |
| 1221 | iowrite16(base + i, ioaddr + Wn0EepromCmd); | 1247 | window_write16(vp, base + i, 0, Wn0EepromCmd); |
| 1222 | /* Pause for at least 162 us. for the read to take place. */ | 1248 | /* Pause for at least 162 us. for the read to take place. */ |
| 1223 | for (timer = 10; timer >= 0; timer--) { | 1249 | for (timer = 10; timer >= 0; timer--) { |
| 1224 | udelay(162); | 1250 | udelay(162); |
| 1225 | if ((ioread16(ioaddr + Wn0EepromCmd) & 0x8000) == 0) | 1251 | if ((window_read16(vp, 0, Wn0EepromCmd) & |
| 1252 | 0x8000) == 0) | ||
| 1226 | break; | 1253 | break; |
| 1227 | } | 1254 | } |
| 1228 | eeprom[i] = ioread16(ioaddr + Wn0EepromData); | 1255 | eeprom[i] = window_read16(vp, 0, Wn0EepromData); |
| 1229 | } | 1256 | } |
| 1230 | } | 1257 | } |
| 1231 | for (i = 0; i < 0x18; i++) | 1258 | for (i = 0; i < 0x18; i++) |
| @@ -1250,9 +1277,8 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1250 | pr_err("*** EEPROM MAC address is invalid.\n"); | 1277 | pr_err("*** EEPROM MAC address is invalid.\n"); |
| 1251 | goto free_ring; /* With every pack */ | 1278 | goto free_ring; /* With every pack */ |
| 1252 | } | 1279 | } |
| 1253 | EL3WINDOW(2); | ||
| 1254 | for (i = 0; i < 6; i++) | 1280 | for (i = 0; i < 6; i++) |
| 1255 | iowrite8(dev->dev_addr[i], ioaddr + i); | 1281 | window_write8(vp, dev->dev_addr[i], 2, i); |
| 1256 | 1282 | ||
| 1257 | if (print_info) | 1283 | if (print_info) |
| 1258 | pr_cont(", IRQ %d\n", dev->irq); | 1284 | pr_cont(", IRQ %d\n", dev->irq); |
| @@ -1261,8 +1287,7 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1261 | pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n", | 1287 | pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n", |
| 1262 | dev->irq); | 1288 | dev->irq); |
| 1263 | 1289 | ||
| 1264 | EL3WINDOW(4); | 1290 | step = (window_read8(vp, 4, Wn4_NetDiag) & 0x1e) >> 1; |
| 1265 | step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; | ||
| 1266 | if (print_info) { | 1291 | if (print_info) { |
| 1267 | pr_info(" product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n", | 1292 | pr_info(" product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n", |
| 1268 | eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], | 1293 | eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], |
| @@ -1285,17 +1310,15 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1285 | (unsigned long long)pci_resource_start(pdev, 2), | 1310 | (unsigned long long)pci_resource_start(pdev, 2), |
| 1286 | vp->cb_fn_base); | 1311 | vp->cb_fn_base); |
| 1287 | } | 1312 | } |
| 1288 | EL3WINDOW(2); | ||
| 1289 | 1313 | ||
| 1290 | n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010; | 1314 | n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010; |
| 1291 | if (vp->drv_flags & INVERT_LED_PWR) | 1315 | if (vp->drv_flags & INVERT_LED_PWR) |
| 1292 | n |= 0x10; | 1316 | n |= 0x10; |
| 1293 | if (vp->drv_flags & INVERT_MII_PWR) | 1317 | if (vp->drv_flags & INVERT_MII_PWR) |
| 1294 | n |= 0x4000; | 1318 | n |= 0x4000; |
| 1295 | iowrite16(n, ioaddr + Wn2_ResetOptions); | 1319 | window_write16(vp, n, 2, Wn2_ResetOptions); |
| 1296 | if (vp->drv_flags & WNO_XCVR_PWR) { | 1320 | if (vp->drv_flags & WNO_XCVR_PWR) { |
| 1297 | EL3WINDOW(0); | 1321 | window_write16(vp, 0x0800, 0, 0); |
| 1298 | iowrite16(0x0800, ioaddr); | ||
| 1299 | } | 1322 | } |
| 1300 | } | 1323 | } |
| 1301 | 1324 | ||
| @@ -1313,14 +1336,13 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
| 1313 | { | 1336 | { |
| 1314 | static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; | 1337 | static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; |
| 1315 | unsigned int config; | 1338 | unsigned int config; |
| 1316 | EL3WINDOW(3); | 1339 | vp->available_media = window_read16(vp, 3, Wn3_Options); |
| 1317 | vp->available_media = ioread16(ioaddr + Wn3_Options); | ||
| 1318 | if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ | 1340 | if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ |
| 1319 | vp->available_media = 0x40; | 1341 | vp->available_media = 0x40; |
| 1320 | config = ioread32(ioaddr + Wn3_Config); | 1342 | config = window_read32(vp, 3, Wn3_Config); |
| 1321 | if (print_info) { | 1343 | if (print_info) { |
| 1322 | pr_debug(" Internal config register is %4.4x, transceivers %#x.\n", | 1344 | pr_debug(" Internal config register is %4.4x, transceivers %#x.\n", |
| 1323 | config, ioread16(ioaddr + Wn3_Options)); | 1345 | config, window_read16(vp, 3, Wn3_Options)); |
| 1324 | pr_info(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", | 1346 | pr_info(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", |
| 1325 | 8 << RAM_SIZE(config), | 1347 | 8 << RAM_SIZE(config), |
| 1326 | RAM_WIDTH(config) ? "word" : "byte", | 1348 | RAM_WIDTH(config) ? "word" : "byte", |
| @@ -1346,7 +1368,6 @@ static int __devinit vortex_probe1(struct device *gendev, | |||
