aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAyaz Abdulla <aabdulla@nvidia.com>2008-04-11 00:30:35 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-12 04:38:12 -0400
commita376e79c6079c2ba6c5fadb0e85a3bb7e465ad89 (patch)
treeb00f23487d23a93fe2cce93d5ad682deb27cbad9 /drivers
parent72cfe92266540d8510946921a599f140a3d4aaa8 (diff)
forcedeth: mac address fix
This critical patch fixes a mac address issue recently introduced. If the device's mac address was in correct order and the flag NVREG_TRANSMITPOLL_MAC_ADDR_REV was set, during nv_remove the flag would get cleared. During next load, the mac address would get reversed because the flag is missing. As it has been indicated previously, the flag is cleared across a low power transition. Therefore, the driver should set the mac address back into the reversed order when clearing the flag. Also, the driver should set back the flag after a low power transition to protect against kexec command calling nv_probe a second time. Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com> Cc: "Yinghai Lu" <yhlu.kernel@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/forcedeth.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 419f533006ab..9f088a47d8b1 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -5316,8 +5316,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
5316 5316
5317 /* check the workaround bit for correct mac address order */ 5317 /* check the workaround bit for correct mac address order */
5318 txreg = readl(base + NvRegTransmitPoll); 5318 txreg = readl(base + NvRegTransmitPoll);
5319 if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) || 5319 if (id->driver_data & DEV_HAS_CORRECT_MACADDR) {
5320 (id->driver_data & DEV_HAS_CORRECT_MACADDR)) {
5321 /* mac address is already in correct order */ 5320 /* mac address is already in correct order */
5322 dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; 5321 dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff;
5323 dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; 5322 dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff;
@@ -5325,6 +5324,22 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
5325 dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; 5324 dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
5326 dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; 5325 dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff;
5327 dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; 5326 dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff;
5327 } else if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) {
5328 /* mac address is already in correct order */
5329 dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff;
5330 dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff;
5331 dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff;
5332 dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
5333 dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff;
5334 dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff;
5335 /*
5336 * Set orig mac address back to the reversed version.
5337 * This flag will be cleared during low power transition.
5338 * Therefore, we should always put back the reversed address.
5339 */
5340 np->orig_mac[0] = (dev->dev_addr[5] << 0) + (dev->dev_addr[4] << 8) +
5341 (dev->dev_addr[3] << 16) + (dev->dev_addr[2] << 24);
5342 np->orig_mac[1] = (dev->dev_addr[1] << 0) + (dev->dev_addr[0] << 8);
5328 } else { 5343 } else {
5329 /* need to reverse mac address to correct order */ 5344 /* need to reverse mac address to correct order */
5330 dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; 5345 dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff;
@@ -5595,7 +5610,9 @@ out:
5595static int nv_resume(struct pci_dev *pdev) 5610static int nv_resume(struct pci_dev *pdev)
5596{ 5611{
5597 struct net_device *dev = pci_get_drvdata(pdev); 5612 struct net_device *dev = pci_get_drvdata(pdev);
5613 u8 __iomem *base = get_hwbase(dev);
5598 int rc = 0; 5614 int rc = 0;
5615 u32 txreg;
5599 5616
5600 if (!netif_running(dev)) 5617 if (!netif_running(dev))
5601 goto out; 5618 goto out;
@@ -5606,6 +5623,11 @@ static int nv_resume(struct pci_dev *pdev)
5606 pci_restore_state(pdev); 5623 pci_restore_state(pdev);
5607 pci_enable_wake(pdev, PCI_D0, 0); 5624 pci_enable_wake(pdev, PCI_D0, 0);
5608 5625
5626 /* restore mac address reverse flag */
5627 txreg = readl(base + NvRegTransmitPoll);
5628 txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV;
5629 writel(txreg, base + NvRegTransmitPoll);
5630
5609 rc = nv_open(dev); 5631 rc = nv_open(dev);
5610out: 5632out:
5611 return rc; 5633 return rc;