Commit a376e79c authored by Ayaz Abdulla's avatar Ayaz Abdulla Committed by Jeff Garzik

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: default avatarAyaz Abdulla <aabdulla@nvidia.com>
Cc: "Yinghai Lu" <yhlu.kernel@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 72cfe922
...@@ -5316,8 +5316,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -5316,8 +5316,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
/* check the workaround bit for correct mac address order */ /* check the workaround bit for correct mac address order */
txreg = readl(base + NvRegTransmitPoll); txreg = readl(base + NvRegTransmitPoll);
if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) || if (id->driver_data & DEV_HAS_CORRECT_MACADDR) {
(id->driver_data & DEV_HAS_CORRECT_MACADDR)) {
/* mac address is already in correct order */ /* mac address is already in correct order */
dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff;
dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; 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,6 +5324,22 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff;
dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff;
} else if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) {
/* mac address is already in correct order */
dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff;
dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff;
dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff;
dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff;
dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff;
/*
* Set orig mac address back to the reversed version.
* This flag will be cleared during low power transition.
* Therefore, we should always put back the reversed address.
*/
np->orig_mac[0] = (dev->dev_addr[5] << 0) + (dev->dev_addr[4] << 8) +
(dev->dev_addr[3] << 16) + (dev->dev_addr[2] << 24);
np->orig_mac[1] = (dev->dev_addr[1] << 0) + (dev->dev_addr[0] << 8);
} else { } else {
/* need to reverse mac address to correct order */ /* need to reverse mac address to correct order */
dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff;
...@@ -5595,7 +5610,9 @@ static int nv_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -5595,7 +5610,9 @@ static int nv_suspend(struct pci_dev *pdev, pm_message_t state)
static int nv_resume(struct pci_dev *pdev) static int nv_resume(struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
u8 __iomem *base = get_hwbase(dev);
int rc = 0; int rc = 0;
u32 txreg;
if (!netif_running(dev)) if (!netif_running(dev))
goto out; goto out;
...@@ -5606,6 +5623,11 @@ static int nv_resume(struct pci_dev *pdev) ...@@ -5606,6 +5623,11 @@ static int nv_resume(struct pci_dev *pdev)
pci_restore_state(pdev); pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D0, 0); pci_enable_wake(pdev, PCI_D0, 0);
/* restore mac address reverse flag */
txreg = readl(base + NvRegTransmitPoll);
txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV;
writel(txreg, base + NvRegTransmitPoll);
rc = nv_open(dev); rc = nv_open(dev);
out: out:
return rc; return rc;
......
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