Commit a095cfc4 authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

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: default avatarBen Hutchings <ben@decadent.org.uk>
Tested-by: Arne Nordmark <nordmark@mech.kth.se> [against 2.6.32]
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d2ef8590
...@@ -435,7 +435,6 @@ MODULE_DEVICE_TABLE(pci, vortex_pci_tbl); ...@@ -435,7 +435,6 @@ MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
First the windows. There are eight register windows, with the command First the windows. There are eight register windows, with the command
and status registers available in each. and status registers available in each.
*/ */
#define EL3WINDOW(win_num) iowrite16(SelectWindow + (win_num), ioaddr + EL3_CMD)
#define EL3_CMD 0x0e #define EL3_CMD 0x0e
#define EL3_STATUS 0x0e #define EL3_STATUS 0x0e
...@@ -647,8 +646,35 @@ struct vortex_private { ...@@ -647,8 +646,35 @@ struct vortex_private {
u16 io_size; /* Size of PCI region (for release_region) */ u16 io_size; /* Size of PCI region (for release_region) */
spinlock_t lock; /* Serialise access to device & its vortex_private */ spinlock_t lock; /* Serialise access to device & its vortex_private */
struct mii_if_info mii; /* MII lib hooks/info */ struct mii_if_info mii; /* MII lib hooks/info */
int window; /* Register window */
}; };
static void window_set(struct vortex_private *vp, int window)
{
if (window != vp->window) {
iowrite16(SelectWindow + window, vp->ioaddr + EL3_CMD);
vp->window = window;
}
}
#define DEFINE_WINDOW_IO(size) \
static u ## size \
window_read ## size(struct vortex_private *vp, int window, int addr) \
{ \
window_set(vp, window); \
return ioread ## size(vp->ioaddr + addr); \
} \
static void \
window_write ## size(struct vortex_private *vp, u ## size value, \
int window, int addr) \
{ \
window_set(vp, window); \
iowrite ## size(value, vp->ioaddr + addr); \
}
DEFINE_WINDOW_IO(8)
DEFINE_WINDOW_IO(16)
DEFINE_WINDOW_IO(32)
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
#define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL) #define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL)
#else #else
...@@ -711,7 +737,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, ...@@ -711,7 +737,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
static int vortex_up(struct net_device *dev); static int vortex_up(struct net_device *dev);
static void vortex_down(struct net_device *dev, int final); static void vortex_down(struct net_device *dev, int final);
static int vortex_open(struct net_device *dev); static int vortex_open(struct net_device *dev);
static void mdio_sync(void __iomem *ioaddr, int bits); static void mdio_sync(struct vortex_private *vp, int bits);
static int mdio_read(struct net_device *dev, int phy_id, int location); static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *vp, int phy_id, int location, int value); static void mdio_write(struct net_device *vp, int phy_id, int location, int value);
static void vortex_timer(unsigned long arg); static void vortex_timer(unsigned long arg);
...@@ -1119,6 +1145,7 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1119,6 +1145,7 @@ static int __devinit vortex_probe1(struct device *gendev,
vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
vp->io_size = vci->io_size; vp->io_size = vci->io_size;
vp->card_idx = card_idx; vp->card_idx = card_idx;
vp->window = -1;
/* module list only for Compaq device */ /* module list only for Compaq device */
if (gendev == NULL) { if (gendev == NULL) {
...@@ -1205,7 +1232,6 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1205,7 +1232,6 @@ static int __devinit vortex_probe1(struct device *gendev,
vp->mii.force_media = vp->full_duplex; vp->mii.force_media = vp->full_duplex;
vp->options = option; vp->options = option;
/* Read the station address from the EEPROM. */ /* Read the station address from the EEPROM. */
EL3WINDOW(0);
{ {
int base; int base;
...@@ -1218,14 +1244,15 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1218,14 +1244,15 @@ static int __devinit vortex_probe1(struct device *gendev,
for (i = 0; i < 0x40; i++) { for (i = 0; i < 0x40; i++) {
int timer; int timer;
iowrite16(base + i, ioaddr + Wn0EepromCmd); window_write16(vp, base + i, 0, Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */ /* Pause for at least 162 us. for the read to take place. */
for (timer = 10; timer >= 0; timer--) { for (timer = 10; timer >= 0; timer--) {
udelay(162); udelay(162);
if ((ioread16(ioaddr + Wn0EepromCmd) & 0x8000) == 0) if ((window_read16(vp, 0, Wn0EepromCmd) &
0x8000) == 0)
break; break;
} }
eeprom[i] = ioread16(ioaddr + Wn0EepromData); eeprom[i] = window_read16(vp, 0, Wn0EepromData);
} }
} }
for (i = 0; i < 0x18; i++) for (i = 0; i < 0x18; i++)
...@@ -1250,9 +1277,8 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1250,9 +1277,8 @@ static int __devinit vortex_probe1(struct device *gendev,
pr_err("*** EEPROM MAC address is invalid.\n"); pr_err("*** EEPROM MAC address is invalid.\n");
goto free_ring; /* With every pack */ goto free_ring; /* With every pack */
} }
EL3WINDOW(2);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
iowrite8(dev->dev_addr[i], ioaddr + i); window_write8(vp, dev->dev_addr[i], 2, i);
if (print_info) if (print_info)
pr_cont(", IRQ %d\n", dev->irq); pr_cont(", IRQ %d\n", dev->irq);
...@@ -1261,8 +1287,7 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1261,8 +1287,7 @@ static int __devinit vortex_probe1(struct device *gendev,
pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n", pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n",
dev->irq); dev->irq);
EL3WINDOW(4); step = (window_read8(vp, 4, Wn4_NetDiag) & 0x1e) >> 1;
step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
if (print_info) { if (print_info) {
pr_info(" product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n", pr_info(" product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n",
eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
...@@ -1285,17 +1310,15 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1285,17 +1310,15 @@ static int __devinit vortex_probe1(struct device *gendev,
(unsigned long long)pci_resource_start(pdev, 2), (unsigned long long)pci_resource_start(pdev, 2),
vp->cb_fn_base); vp->cb_fn_base);
} }
EL3WINDOW(2);
n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010; n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010;
if (vp->drv_flags & INVERT_LED_PWR) if (vp->drv_flags & INVERT_LED_PWR)
n |= 0x10; n |= 0x10;
if (vp->drv_flags & INVERT_MII_PWR) if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000; n |= 0x4000;
iowrite16(n, ioaddr + Wn2_ResetOptions); window_write16(vp, n, 2, Wn2_ResetOptions);
if (vp->drv_flags & WNO_XCVR_PWR) { if (vp->drv_flags & WNO_XCVR_PWR) {
EL3WINDOW(0); window_write16(vp, 0x0800, 0, 0);
iowrite16(0x0800, ioaddr);
} }
} }
...@@ -1313,14 +1336,13 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1313,14 +1336,13 @@ static int __devinit vortex_probe1(struct device *gendev,
{ {
static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
unsigned int config; unsigned int config;
EL3WINDOW(3); vp->available_media = window_read16(vp, 3, Wn3_Options);
vp->available_media = ioread16(ioaddr + Wn3_Options);
if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */
vp->available_media = 0x40; vp->available_media = 0x40;
config = ioread32(ioaddr + Wn3_Config); config = window_read32(vp, 3, Wn3_Config);
if (print_info) { if (print_info) {
pr_debug(" Internal config register is %4.4x, transceivers %#x.\n", pr_debug(" Internal config register is %4.4x, transceivers %#x.\n",
config, ioread16(ioaddr + Wn3_Options)); config, window_read16(vp, 3, Wn3_Options));
pr_info(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", pr_info(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
8 << RAM_SIZE(config), 8 << RAM_SIZE(config),
RAM_WIDTH(config) ? "word" : "byte", RAM_WIDTH(config) ? "word" : "byte",
...@@ -1346,7 +1368,6 @@ static int __devinit vortex_probe1(struct device *gendev, ...@@ -1346,7 +1368,6 @@ static int __devinit vortex_probe1(struct device *gendev,
if ((vp->available_media & 0x40) || (vci->drv_flags & HAS_NWAY) || if ((vp->available_media & 0x40) || (vci->drv_flags & HAS_NWAY) ||
dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int phy, phy_idx = 0; int phy, phy_idx = 0;
EL3WINDOW(4);
mii_preamble_required++; mii_preamble_required++;
if (vp->drv_flags & EXTRA_PREAMBLE) if (vp->drv_flags & EXTRA_PREAMBLE)
mii_preamble_required++; mii_preamble_required++;
...@@ -1478,18 +1499,17 @@ static void ...@@ -1478,18 +1499,17 @@ static void
vortex_set_duplex(struct net_device *dev) vortex_set_duplex(struct net_device *dev)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
pr_info("%s: setting %s-duplex.\n", pr_info("%s: setting %s-duplex.\n",
dev->name, (vp->full_duplex) ? "full" : "half"); dev->name, (vp->full_duplex) ? "full" : "half");
EL3WINDOW(3);
/* Set the full-duplex bit. */ /* Set the full-duplex bit. */
iowrite16(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | window_write16(vp,
(vp->large_frames ? 0x40 : 0) | ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? (vp->large_frames ? 0x40 : 0) |
0x100 : 0), ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ?
ioaddr + Wn3_MAC_Ctrl); 0x100 : 0),
3, Wn3_MAC_Ctrl);
} }
static void vortex_check_media(struct net_device *dev, unsigned int init) static void vortex_check_media(struct net_device *dev, unsigned int init)
...@@ -1529,8 +1549,7 @@ vortex_up(struct net_device *dev) ...@@ -1529,8 +1549,7 @@ vortex_up(struct net_device *dev)
} }
/* Before initializing select the active media port. */ /* Before initializing select the active media port. */
EL3WINDOW(3); config = window_read32(vp, 3, Wn3_Config);
config = ioread32(ioaddr + Wn3_Config);
if (vp->media_override != 7) { if (vp->media_override != 7) {
pr_info("%s: Media override to transceiver %d (%s).\n", pr_info("%s: Media override to transceiver %d (%s).\n",
...@@ -1577,10 +1596,9 @@ vortex_up(struct net_device *dev) ...@@ -1577,10 +1596,9 @@ vortex_up(struct net_device *dev)
config = BFINS(config, dev->if_port, 20, 4); config = BFINS(config, dev->if_port, 20, 4);
if (vortex_debug > 6) if (vortex_debug > 6)
pr_debug("vortex_up(): writing 0x%x to InternalConfig\n", config); pr_debug("vortex_up(): writing 0x%x to InternalConfig\n", config);
iowrite32(config, ioaddr + Wn3_Config); window_write32(vp, config, 3, Wn3_Config);
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
EL3WINDOW(4);
mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR); mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
...@@ -1601,51 +1619,46 @@ vortex_up(struct net_device *dev) ...@@ -1601,51 +1619,46 @@ vortex_up(struct net_device *dev)
iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD); iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
if (vortex_debug > 1) { if (vortex_debug > 1) {
EL3WINDOW(4);
pr_debug("%s: vortex_up() irq %d media status %4.4x.\n", pr_debug("%s: vortex_up() irq %d media status %4.4x.\n",
dev->name, dev->irq, ioread16(ioaddr + Wn4_Media)); dev->name, dev->irq, window_read16(vp, 4, Wn4_Media));
} }
/* Set the station address and mask in window 2 each time opened. */ /* Set the station address and mask in window 2 each time opened. */
EL3WINDOW(2);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
iowrite8(dev->dev_addr[i], ioaddr + i); window_write8(vp, dev->dev_addr[i], 2, i);
for (; i < 12; i+=2) for (; i < 12; i+=2)
iowrite16(0, ioaddr + i); window_write16(vp, 0, 2, i);
if (vp->cb_fn_base) { if (vp->cb_fn_base) {
unsigned short n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010; unsigned short n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010;
if (vp->drv_flags & INVERT_LED_PWR) if (vp->drv_flags & INVERT_LED_PWR)
n |= 0x10; n |= 0x10;
if (vp->drv_flags & INVERT_MII_PWR) if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000; n |= 0x4000;
iowrite16(n, ioaddr + Wn2_ResetOptions); window_write16(vp, n, 2, Wn2_ResetOptions);
} }
if (dev->if_port == XCVR_10base2) if (dev->if_port == XCVR_10base2)
/* Start the thinnet transceiver. We should really wait 50ms...*/ /* Start the thinnet transceiver. We should really wait 50ms...*/
iowrite16(StartCoax, ioaddr + EL3_CMD); iowrite16(StartCoax, ioaddr + EL3_CMD);
if (dev->if_port != XCVR_NWAY) { if (dev->if_port != XCVR_NWAY) {
EL3WINDOW(4); window_write16(vp,
iowrite16((ioread16(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | (window_read16(vp, 4, Wn4_Media) &
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits,
4, Wn4_Media);
} }
/* Switch to the stats window, and clear all stats by reading. */ /* Switch to the stats window, and clear all stats by reading. */
iowrite16(StatsDisable, ioaddr + EL3_CMD); iowrite16(StatsDisable, ioaddr + EL3_CMD);
EL3WINDOW(6);
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
ioread8(ioaddr + i); window_read8(vp, 6, i);
ioread16(ioaddr + 10); window_read16(vp, 6, 10);
ioread16(ioaddr + 12); window_read16(vp, 6, 12);
/* New: On the Vortex we must also clear the BadSSD counter. */ /* New: On the Vortex we must also clear the BadSSD counter. */
EL3WINDOW(4); window_read8(vp, 4, 12);
ioread8(ioaddr + 12);
/* ..and on the Boomerang we enable the extra statistics bits. */ /* ..and on the Boomerang we enable the extra statistics bits. */
iowrite16(0x0040, ioaddr + Wn4_NetDiag); window_write16(vp, 0x0040, 4, Wn4_NetDiag);
/* Switch to register set 7 for normal use. */
EL3WINDOW(7);
if (vp->full_bus_master_rx) { /* Boomerang bus master. */ if (vp->full_bus_master_rx) { /* Boomerang bus master. */
vp->cur_rx = vp->dirty_rx = 0; vp->cur_rx = vp->dirty_rx = 0;
...@@ -1763,7 +1776,7 @@ vortex_timer(unsigned long data) ...@@ -1763,7 +1776,7 @@ vortex_timer(unsigned long data)
void __iomem *ioaddr = vp->ioaddr; void __iomem *ioaddr = vp->ioaddr;
int next_tick = 60*HZ; int next_tick = 60*HZ;
int ok = 0; int ok = 0;
int media_status, old_window; int media_status;
if (vortex_debug > 2) { if (vortex_debug > 2) {
pr_debug("%s: Media selection timer tick happened, %s.\n", pr_debug("%s: Media selection timer tick happened, %s.\n",
...@@ -1772,9 +1785,7 @@ vortex_timer(unsigned long data) ...@@ -1772,9 +1785,7 @@ vortex_timer(unsigned long data)
} }
disable_irq_lockdep(dev->irq); disable_irq_lockdep(dev->irq);
old_window = ioread16(ioaddr + EL3_CMD) >> 13; media_status = window_read16(vp, 4, Wn4_Media);
EL3WINDOW(4);
media_status = ioread16(ioaddr + Wn4_Media);
switch (dev->if_port) { switch (dev->if_port) {
case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) { if (media_status & Media_LnkBeat) {
...@@ -1830,13 +1841,14 @@ vortex_timer(unsigned long data) ...@@ -1830,13 +1841,14 @@ vortex_timer(unsigned long data)
dev->name, media_tbl[dev->if_port].name); dev->name, media_tbl[dev->if_port].name);
next_tick = media_tbl[dev->if_port].wait; next_tick = media_tbl[dev->if_port].wait;
} }
iowrite16((media_status & ~(Media_10TP|Media_SQE)) | window_write16(vp,
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); (media_status & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits,
4, Wn4_Media);
EL3WINDOW(3); config = window_read32(vp, 3, Wn3_Config);
config = ioread32(ioaddr + Wn3_Config);
config = BFINS(config, dev->if_port, 20, 4); config = BFINS(config, dev->if_port, 20, 4);
iowrite32(config, ioaddr + Wn3_Config); window_write32(vp, config, 3, Wn3_Config);
iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD); ioaddr + EL3_CMD);
...@@ -1850,7 +1862,6 @@ vortex_timer(unsigned long data) ...@@ -1850,7 +1862,6 @@ vortex_timer(unsigned long data)
pr_debug("%s: Media selection timer finished, %s.\n", pr_debug("%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name); dev->name, media_tbl[dev->if_port].name);
EL3WINDOW(old_window);
enable_irq_lockdep(dev->irq); enable_irq_lockdep(dev->irq);
mod_timer(&vp->timer, RUN_AT(next_tick)); mod_timer(&vp->timer, RUN_AT(next_tick));
if (vp->deferred) if (vp->deferred)
...@@ -1865,12 +1876,11 @@ static void vortex_tx_timeout(struct net_device *dev) ...@@ -1865,12 +1876,11 @@ static void vortex_tx_timeout(struct net_device *dev)
pr_err("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", pr_err("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
dev->name, ioread8(ioaddr + TxStatus), dev->name, ioread8(ioaddr + TxStatus),
ioread16(ioaddr + EL3_STATUS)); ioread16(ioaddr + EL3_STATUS));
EL3WINDOW(4);
pr_err(" diagnostics: net %04x media %04x dma %08x fifo %04x\n", pr_err(" diagnostics: net %04x media %04x dma %08x fifo %04x\n",
ioread16(ioaddr + Wn4_NetDiag), window_read16(vp, 4, Wn4_NetDiag),
ioread16(ioaddr + Wn4_Media), window_read16(vp, 4, Wn4_Media),
ioread32(ioaddr + PktStatus), ioread32(ioaddr + PktStatus),
ioread16(ioaddr + Wn4_FIFODiag)); window_read16(vp, 4, Wn4_FIFODiag));
/* Slight code bloat to be user friendly. */ /* Slight code bloat to be user friendly. */
if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88) if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88)
pr_err("%s: Transmitter encountered 16 collisions --" pr_err("%s: Transmitter encountered 16 collisions --"
...@@ -1917,9 +1927,6 @@ static void vortex_tx_timeout(struct net_device *dev) ...@@ -1917,9 +1927,6 @@ static void vortex_tx_timeout(struct net_device *dev)
/* Issue Tx Enable */ /* Issue Tx Enable */
iowrite16(TxEnable, ioaddr + EL3_CMD); iowrite16(TxEnable, ioaddr + EL3_CMD);
dev->trans_start = jiffies; /* prevent tx timeout */ dev->trans_start = jiffies; /* prevent tx timeout */
/* Switch to register set 7 for normal use. */
EL3WINDOW(7);
} }
/* /*
...@@ -1980,10 +1987,10 @@ vortex_error(struct net_device *dev, int status) ...@@ -1980,10 +1987,10 @@ vortex_error(struct net_device *dev, int status)
ioread16(ioaddr + EL3_STATUS) & StatsFull) { ioread16(ioaddr + EL3_STATUS) & StatsFull) {
pr_warning("%s: Updating statistics failed, disabling " pr_warning("%s: Updating statistics failed, disabling "
"stats as an interrupt source.\n", dev->name); "stats as an interrupt source.\n", dev->name);
EL3WINDOW(5); iowrite16(SetIntrEnb |
iowrite16(SetIntrEnb | (ioread16(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); (window_read16(vp, 5, 10) & ~StatsFull),
ioaddr + EL3_CMD);
vp->intr_enable &= ~StatsFull; vp->intr_enable &= ~StatsFull;
EL3WINDOW(7);
DoneDidThat++; DoneDidThat++;
} }
} }
...@@ -1993,8 +2000,7 @@ vortex_error(struct net_device *dev, int status) ...@@ -1993,8 +2000,7 @@ vortex_error(struct net_device *dev, int status)
} }
if (status & HostError) { if (status & HostError) {
u16 fifo_diag; u16 fifo_diag;
EL3WINDOW(4); fifo_diag = window_read16(vp, 4, Wn4_FIFODiag);
fifo_diag = ioread16(ioaddr + Wn4_FIFODiag);
pr_err("%s: Host error, FIFO diagnostic register %4.4x.\n", pr_err("%s: Host error, FIFO diagnostic register %4.4x.\n",
dev->name, fifo_diag); dev->name, fifo_diag);
/* Adapter failure requires Tx/Rx reset and reinit. */ /* Adapter failure requires Tx/Rx reset and reinit. */
...@@ -2043,8 +2049,10 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2043,8 +2049,10 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (vp->bus_master) { if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */ /* Set the bus-master controller to transfer the packet. */
int len = (skb->len + 3) & ~3; int len = (skb->len + 3) & ~3;
iowrite32(vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE), vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len,
ioaddr + Wn7_MasterAddr); PCI_DMA_TODEVICE);
window_set(vp, 7);
iowrite32(vp->tx_skb_dma, ioaddr + Wn7_MasterAddr);
iowrite16(len, ioaddr + Wn7_MasterLen); iowrite16(len, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb; vp->tx_skb = skb;
iowrite16(StartDMADown, ioaddr + EL3_CMD); iowrite16(StartDMADown, ioaddr + EL3_CMD);
...@@ -2217,6 +2225,8 @@ vortex_interrupt(int irq, void *dev_id) ...@@ -2217,6 +2225,8 @@ vortex_interrupt(int irq, void *dev_id)
pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n", pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
dev->name, status, ioread8(ioaddr + Timer)); dev->name, status, ioread8(ioaddr + Timer));
window_set(vp, 7);
do { do {
if (vortex_debug > 5) if (vortex_debug > 5)
pr_debug("%s: In interrupt loop, status %4.4x.\n", pr_debug("%s: In interrupt loop, status %4.4x.\n",
...@@ -2760,54 +2770,46 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev) ...@@ -2760,54 +2770,46 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev)
static void update_stats(void __iomem *ioaddr, struct net_device *dev) static void update_stats(void __iomem *ioaddr, struct net_device *dev)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
int old_window = ioread16(ioaddr + EL3_CMD);
if (old_window == 0xffff) /* Chip suspended or ejected. */
return;
/* Unlike the 3c5x9 we need not turn off stats updates while reading. */ /* Unlike the 3c5x9 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */ /* Switch to the stats window, and read everything. */
EL3WINDOW(6); dev->stats.tx_carrier_errors += window_read8(vp, 6, 0);
dev->stats.tx_carrier_errors += ioread8(ioaddr + 0); dev->stats.tx_heartbeat_errors += window_read8(vp, 6, 1);
dev->stats.tx_heartbeat_errors += ioread8(ioaddr + 1); dev->stats.tx_window_errors += window_read8(vp, 6, 4);
dev->stats.tx_window_errors += ioread8(ioaddr + 4); dev->stats.rx_fifo_errors += window_read8(vp, 6, 5);
dev->stats.rx_fifo_errors += ioread8(ioaddr + 5); dev->stats.tx_packets += window_read8(vp, 6, 6);
dev->stats.tx_packets += ioread8(ioaddr + 6); dev->stats.tx_packets += (window_read8(vp, 6, 9) &
dev->stats.tx_packets += (ioread8(ioaddr + 9)&0x30) << 4; 0x30) << 4;
/* Rx packets */ ioread8(ioaddr + 7); /* Must read to clear */ /* Rx packets */ window_read8(vp, 6, 7); /* Must read to clear */
/* Don't bother with register 9, an extension of registers 6&7. /* Don't bother with register 9, an extension of registers 6&7.
If we do use the 6&7 values the atomic update assumption above If we do use the 6&7 values the atomic update assumption above
is invalid. */ is invalid. */
dev->stats.rx_bytes += ioread16(ioaddr + 10); dev->stats.rx_bytes += window_read16(vp, 6, 10);
dev->stats.tx_bytes += ioread16(ioaddr + 12); dev->stats.tx_bytes += window_read16(vp, 6, 12);
/* Extra stats for get_ethtool_stats() */ /* Extra stats for get_ethtool_stats() */
vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2); vp->xstats.tx_multiple_collisions += window_read8(vp, 6, 2);
vp->xstats.tx_single_collisions += ioread8(ioaddr + 3); vp->xstats.tx_single_collisions += window_read8(vp, 6, 3);
vp->xstats.tx_deferred += ioread8(ioaddr + 8); vp->xstats.tx_deferred += window_read8(vp, 6, 8);
EL3WINDOW(4); vp->xstats.rx_bad_ssd += window_read8(vp, 4, 12);
vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12);
dev->stats.collisions = vp->xstats.tx_multiple_collisions dev->stats.collisions = vp->xstats.tx_multiple_collisions
+ vp->xstats.tx_single_collisions + vp->xstats.tx_single_collisions
+ vp->xstats.tx_max_collisions; + vp->xstats.tx_max_collisions;
{ {
u8 up = ioread8(ioaddr + 13); u8 up = window_read8(vp, 4, 13);
dev->stats.rx_bytes += (up & 0x0f) << 16; dev->stats.rx_bytes += (up & 0x0f) << 16;
dev->stats.tx_bytes += (up & 0xf0) << 12; dev->stats.tx_bytes += (up & 0xf0) << 12;
} }
EL3WINDOW(old_window >> 13);
} }
static int vortex_nway_reset(struct net_device *dev) static int vortex_nway_reset(struct net_device *dev)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
unsigned long flags; unsigned long flags;
int rc; int rc;
spin_lock_irqsave(&vp->lock, flags); spin_lock_irqsave(&vp->lock, flags);
EL3WINDOW(4);
rc = mii_nway_restart(&vp->mii); rc = mii_nway_restart(&vp->mii);
spin_unlock_irqrestore(&vp->lock, flags); spin_unlock_irqrestore(&vp->lock, flags);
return rc; return rc;
...@@ -2816,12 +2818,10 @@ static int vortex_nway_reset(struct net_device *dev) ...@@ -2816,12 +2818,10 @@ static int vortex_nway_reset(struct net_device *dev)
static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
unsigned long flags; unsigned long flags;
int rc; int rc;
spin_lock_irqsave(&vp->lock, flags); spin_lock_irqsave(&vp->lock, flags);
EL3WINDOW(4);
rc = mii_ethtool_gset(&vp->mii, cmd); rc = mii_ethtool_gset(&vp->mii, cmd);
spin_unlock_irqrestore(&vp->lock, flags); spin_unlock_irqrestore(&vp->lock, flags);
return rc; return rc;
...@@ -2830,12 +2830,10 @@ static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -2830,12 +2830,10 @@ static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
unsigned long flags; unsigned long flags;
int rc; int rc;
spin_lock_irqsave(&vp->lock, flags); spin_lock_irqsave(&vp->lock, flags);
EL3WINDOW(4);
rc = mii_ethtool_sset(&vp->mii, cmd); rc = mii_ethtool_sset(&vp->mii, cmd);
spin_unlock_irqrestore(&vp->lock, flags); spin_unlock_irqrestore(&vp->lock, flags);
return rc; return rc;
...@@ -2930,7 +2928,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2930,7 +2928,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
int err; int err;
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
unsigned long flags; unsigned long flags;
pci_power_t state = 0; pci_power_t state = 0;
...@@ -2942,7 +2939,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2942,7 +2939,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if(state != 0) if(state != 0)
pci_set_power_state(VORTEX_PCI(vp), PCI_D0); pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
spin_lock_irqsave(&vp->lock, flags); spin_lock_irqsave(&vp->lock, flags);
EL3WINDOW(4);
err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL);
spin_unlock_irqrestore(&vp->lock, flags); spin_unlock_irqrestore(&vp->lock, flags);
if(state != 0) if(state != 0)
...@@ -2985,8 +2981,6 @@ static void set_rx_mode(struct net_device *dev) ...@@ -2985,8 +2981,6 @@ static void set_rx_mode(struct net_device *dev)
static void set_8021q_mode(struct net_device *dev, int enable) static void set_8021q_mode(struct net_device *dev, int enable)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
int old_window = ioread16(ioaddr + EL3_CMD);
int mac_ctrl; int mac_ctrl;
if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) { if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
...@@ -2997,28 +2991,23 @@ static void set_8021q_mode(struct net_device *dev, int enable) ...@@ -2997,28 +2991,23 @@ static void set_8021q_mode(struct net_device *dev, int enable)
if (enable) if (enable)
max_pkt_size += 4; /* 802.1Q VLAN tag */ max_pkt_size += 4; /* 802.1Q VLAN tag */
EL3WINDOW(3); window_write16(vp, max_pkt_size, 3, Wn3_MaxPktSize);
iowrite16(max_pkt_size, ioaddr+Wn3_MaxPktSize);
/* set VlanEtherType to let the hardware checksumming /* set VlanEtherType to let the hardware checksumming
treat tagged frames correctly */ treat tagged frames correctly */
EL3WINDOW(7); window_write16(vp, VLAN_ETHER_TYPE, 7, Wn7_VlanEtherType);
iowrite16(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
} else { } else {
/* on older cards we have to enable large frames */ /* on older cards we have to enable large frames */
vp->large_frames = dev->mtu > 1500 || enable; vp->large_frames = dev->mtu > 1500 || enable;
EL3WINDOW(3); mac_ctrl = window_read16(vp, 3, Wn3_MAC_Ctrl);
mac_ctrl = ioread16(ioaddr+Wn3_MAC_Ctrl);
if (vp->large_frames) if (vp->large_frames)
mac_ctrl |= 0x40; mac_ctrl |= 0x40;
else else
mac_ctrl &= ~0x40; mac_ctrl &= ~0x40;
iowrite16(mac_ctrl, ioaddr+Wn3_MAC_Ctrl); window_write16(vp, mac_ctrl, 3, Wn3_MAC_Ctrl);
} }
EL3WINDOW(old_window);
} }
#else #else
...@@ -3037,7 +3026,10 @@ static void set_8021q_mode(struct net_device *dev, int enable) ...@@ -3037,7 +3026,10 @@ static void set_8021q_mode(struct net_device *dev, int enable)
/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back PCI I/O cycles, but we insert a delay to avoid met by back-to-back PCI I/O cycles, but we insert a delay to avoid
"overclocking" issues. */ "overclocking" issues. */
#define mdio_delay() ioread32(mdio_addr) static void mdio_delay(struct vortex_private *vp)
{
window_read32(vp, 4, Wn4_PhysicalMgmt);
}
#define MDIO_SHIFT_CLK 0x01 #define MDIO_SHIFT_CLK 0x01
#define MDIO_DIR_WRITE 0x04 #define MDIO_DIR_WRITE 0x04
...@@ -3048,16 +3040,15 @@ static void set_8021q_mode(struct net_device *dev, int enable) ...@@ -3048,16 +3040,15 @@ static void set_8021q_mode(struct net_device *dev, int enable)
/* Generate the preamble required for initial synchronization and /* Generate the preamble required for initial synchronization and
a few older transceivers. */ a few older transceivers. */
static void mdio_sync(void __iomem *ioaddr, int bits) static void mdio_sync(struct vortex_private *vp, int bits)
{ {
void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
/* Establish sync by sending at least 32 logic ones. */ /* Establish sync by sending at least 32 logic ones. */
while (-- bits >= 0) { while (-- bits >= 0) {
iowrite16(MDIO_DATA_WRITE1, mdio_addr); window_write16(vp, MDIO_DATA_WRITE1, 4, Wn4_PhysicalMgmt);
mdio_delay(); mdio_delay(vp);
iowrite16(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); window_write16(vp, MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK,
mdio_delay(); 4, Wn4_PhysicalMgmt);
mdio_delay(vp);
} }
} }
...@@ -3065,29 +3056,31 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) ...@@ -3065,29 +3056,31 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
{ {
int i; int i;
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned int retval = 0; unsigned int retval = 0;
void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
if (mii_preamble_required) if (mii_preamble_required)
mdio_sync(ioaddr, 32); mdio_sync(vp, 32);
/* Shift the read command bits out. */ /* Shift the read command bits out. */
for (i = 14; i >= 0; i--) { for (i = 14; i >= 0; i--) {
int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
iowrite16(dataval, mdio_addr); window_write16(vp, dataval, 4, Wn4_PhysicalMgmt);
mdio_delay(); mdio_delay(vp);
iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr); window_write16(vp, dataval | MDIO_SHIFT_CLK,
mdio_delay(); 4, Wn4_PhysicalMgmt);
mdio_delay(vp);
} }
/* Read the two transition, 16 data, and wire-idle bits. */ /* Read the two transition, 16 data, and wire-idle bits. */
for (i = 19; i > 0; i--) { for (i = 19; i > 0; i--) {
iowrite16(MDIO_ENB_IN, mdio_addr); window_write16(vp, MDIO_ENB_IN, 4, Wn4_PhysicalMgmt);
mdio_delay(); mdio_delay(vp);
retval = (retval << 1) | ((ioread16(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); retval = (retval << 1) |
iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); ((window_read16(vp, 4, Wn4_PhysicalMgmt) &
mdio_delay(); MDIO_DATA_READ) ? 1 : 0);
window_write16(vp, MDIO_ENB_IN | MDIO_SHIFT_CLK,
4, Wn4_PhysicalMgmt);
mdio_delay(vp);
} }
return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
} }
...@@ -3095,28 +3088,28 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) ...@@ -3095,28 +3088,28 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
static void mdio_write(struct net_device *dev, int phy_id, int location, int value) static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{ {
struct vortex_private *vp = netdev_priv(dev); struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
int i; int i;
if (mii_preamble_required) if (mii_preamble_required)
mdio_sync(ioaddr, 32); mdio_sync(vp, 32);
/* Shift the command bits out. */ /* Shift the command bits out. */
for (i = 31; i >= 0; i--) { for (i = 31; i >= 0; i--) {
int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
iowrite16(dataval, mdio_addr); window_write16(vp, dataval, 4, Wn4_PhysicalMgmt);
mdio_delay(); mdio_delay(vp);
iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr); window_write16(vp, dataval | MDIO_SHIFT_CLK,
mdio_delay(); 4, Wn4_PhysicalMgmt);
mdio_delay(vp);
} }
/* Leave the interface idle. */ /* Leave the interface idle. */
for (i = 1; i >= 0; i--) { for (i = 1; i >= 0; i--) {
iowrite16(MDIO_ENB_IN, mdio_addr); window_write16(vp, MDIO_ENB_IN, 4, Wn4_PhysicalMgmt);
mdio_delay(); mdio_delay(vp);
iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); window_write16(vp, MDIO_ENB_IN | MDIO_SHIFT_CLK,
mdio_delay(); 4, Wn4_PhysicalMgmt);
mdio_delay(vp);
} }
} }
...@@ -3131,8 +3124,7 @@ static void acpi_set_WOL(struct net_device *dev) ...@@ -3131,8 +3124,7 @@ static void acpi_set_WOL(struct net_device *dev)
if (vp->enable_wol) { if (vp->enable_wol) {
/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */ /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
EL3WINDOW(7); window_write16(vp, 2, 7, 0x0c);
iowrite16(2, ioaddr + 0x0c);
/* The RxFilter must accept the WOL frames. */ /* The RxFilter must accept the WOL frames. */
iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
iowrite16(RxEnable, ioaddr + EL3_CMD); iowrite16(RxEnable, ioaddr + EL3_CMD);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment