diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/forcedeth.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 69ef117674ef..26fc00a9ff83 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -109,6 +109,7 @@ | |||
109 | * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. | 109 | * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. |
110 | * 0.55: 22 Mar 2006: Add flow control (pause frame). | 110 | * 0.55: 22 Mar 2006: Add flow control (pause frame). |
111 | * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. | 111 | * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. |
112 | * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections. | ||
112 | * | 113 | * |
113 | * Known bugs: | 114 | * Known bugs: |
114 | * We suspect that on some hardware no TX done interrupts are generated. | 115 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -120,7 +121,7 @@ | |||
120 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 121 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
121 | * superfluous timer interrupts from the nic. | 122 | * superfluous timer interrupts from the nic. |
122 | */ | 123 | */ |
123 | #define FORCEDETH_VERSION "0.56" | 124 | #define FORCEDETH_VERSION "0.57" |
124 | #define DRV_NAME "forcedeth" | 125 | #define DRV_NAME "forcedeth" |
125 | 126 | ||
126 | #include <linux/module.h> | 127 | #include <linux/module.h> |
@@ -262,7 +263,8 @@ enum { | |||
262 | NvRegRingSizes = 0x108, | 263 | NvRegRingSizes = 0x108, |
263 | #define NVREG_RINGSZ_TXSHIFT 0 | 264 | #define NVREG_RINGSZ_TXSHIFT 0 |
264 | #define NVREG_RINGSZ_RXSHIFT 16 | 265 | #define NVREG_RINGSZ_RXSHIFT 16 |
265 | NvRegUnknownTransmitterReg = 0x10c, | 266 | NvRegTransmitPoll = 0x10c, |
267 | #define NVREG_TRANSMITPOLL_MAC_ADDR_REV 0x00008000 | ||
266 | NvRegLinkSpeed = 0x110, | 268 | NvRegLinkSpeed = 0x110, |
267 | #define NVREG_LINKSPEED_FORCE 0x10000 | 269 | #define NVREG_LINKSPEED_FORCE 0x10000 |
268 | #define NVREG_LINKSPEED_10 1000 | 270 | #define NVREG_LINKSPEED_10 1000 |
@@ -1178,7 +1180,7 @@ static void nv_stop_tx(struct net_device *dev) | |||
1178 | KERN_INFO "nv_stop_tx: TransmitterStatus remained busy"); | 1180 | KERN_INFO "nv_stop_tx: TransmitterStatus remained busy"); |
1179 | 1181 | ||
1180 | udelay(NV_TXSTOP_DELAY2); | 1182 | udelay(NV_TXSTOP_DELAY2); |
1181 | writel(0, base + NvRegUnknownTransmitterReg); | 1183 | writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); |
1182 | } | 1184 | } |
1183 | 1185 | ||
1184 | static void nv_txrx_reset(struct net_device *dev) | 1186 | static void nv_txrx_reset(struct net_device *dev) |
@@ -3917,7 +3919,7 @@ static int nv_open(struct net_device *dev) | |||
3917 | oom = nv_init_ring(dev); | 3919 | oom = nv_init_ring(dev); |
3918 | 3920 | ||
3919 | writel(0, base + NvRegLinkSpeed); | 3921 | writel(0, base + NvRegLinkSpeed); |
3920 | writel(0, base + NvRegUnknownTransmitterReg); | 3922 | writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); |
3921 | nv_txrx_reset(dev); | 3923 | nv_txrx_reset(dev); |
3922 | writel(0, base + NvRegUnknownSetupReg6); | 3924 | writel(0, base + NvRegUnknownSetupReg6); |
3923 | 3925 | ||
@@ -4082,7 +4084,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
4082 | unsigned long addr; | 4084 | unsigned long addr; |
4083 | u8 __iomem *base; | 4085 | u8 __iomem *base; |
4084 | int err, i; | 4086 | int err, i; |
4085 | u32 powerstate; | 4087 | u32 powerstate, txreg; |
4086 | 4088 | ||
4087 | dev = alloc_etherdev(sizeof(struct fe_priv)); | 4089 | dev = alloc_etherdev(sizeof(struct fe_priv)); |
4088 | err = -ENOMEM; | 4090 | err = -ENOMEM; |
@@ -4269,12 +4271,30 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
4269 | np->orig_mac[0] = readl(base + NvRegMacAddrA); | 4271 | np->orig_mac[0] = readl(base + NvRegMacAddrA); |
4270 | np->orig_mac[1] = readl(base + NvRegMacAddrB); | 4272 | np->orig_mac[1] = readl(base + NvRegMacAddrB); |
4271 | 4273 | ||
4272 | dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; | 4274 | /* check the workaround bit for correct mac address order */ |
4273 | dev->dev_addr[1] = (np->orig_mac[1] >> 0) & 0xff; | 4275 | txreg = readl(base + NvRegTransmitPoll); |
4274 | dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff; | 4276 | if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) { |
4275 | dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff; | 4277 | /* mac address is already in correct order */ |
4276 | dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; | 4278 | dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; |
4277 | dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; | 4279 | dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; |
4280 | dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff; | ||
4281 | dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; | ||
4282 | dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; | ||
4283 | dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; | ||
4284 | } else { | ||
4285 | /* need to reverse mac address to correct order */ | ||
4286 | dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; | ||
4287 | dev->dev_addr[1] = (np->orig_mac[1] >> 0) & 0xff; | ||
4288 | dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff; | ||
4289 | dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff; | ||
4290 | dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; | ||
4291 | dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; | ||
4292 | /* set permanent address to be correct aswell */ | ||
4293 | np->orig_mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) + | ||
4294 | (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24); | ||
4295 | np->orig_mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8); | ||
4296 | writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); | ||
4297 | } | ||
4278 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); | 4298 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); |
4279 | 4299 | ||
4280 | if (!is_valid_ether_addr(dev->perm_addr)) { | 4300 | if (!is_valid_ether_addr(dev->perm_addr)) { |