[PATCH] forcedeth: keep mac addr to orignal Impact: fix mac reverse for wol some BIOS may already reverse that, try to don't touch the mac addr, so don't confuse the WOL Signed-off-by: Yinghai Lu --- drivers/net/forcedeth.c | 50 +++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) Index: linux-2.6/drivers/net/forcedeth.c =================================================================== --- linux-2.6.orig/drivers/net/forcedeth.c +++ linux-2.6/drivers/net/forcedeth.c @@ -748,6 +748,8 @@ struct fe_priv { /* General data: RO fields */ dma_addr_t ring_addr; struct pci_dev *pci_dev; + /* wonder if bios already reverse that */ + int orig_mac_status; u32 orig_mac[2]; u32 irqmask; u32 desc_ver; @@ -5639,14 +5641,17 @@ static int __devinit nv_probe(struct pci /* check the workaround bit for correct mac address order */ txreg = readl(base + NvRegTransmitPoll); if (id->driver_data & DEV_HAS_CORRECT_MACADDR) { - /* 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; + np->orig_mac_status = -1; } else if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) { + np->orig_mac_status = 1; + printk(KERN_DEBUG "nv_probe: workaround bit for reversed mac addr is set\n"); + } else { + np->orig_mac_status = 0; + writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, + base + NvRegTransmitPoll); + printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n"); + } + if (np->orig_mac_status) { /* 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; @@ -5654,14 +5659,6 @@ static int __devinit nv_probe(struct pci 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 { /* need to reverse mac address to correct order */ dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; @@ -5670,8 +5667,6 @@ static int __devinit nv_probe(struct pci dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff; dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; - writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); - printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n"); } memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); @@ -5923,14 +5918,31 @@ static void nv_restore_mac_addr(struct p { struct net_device *dev = pci_get_drvdata(pci_dev); struct fe_priv *np = netdev_priv(dev); - u8 __iomem *base = get_hwbase(dev); + u8 __iomem *base; + u32 txreg; + + if (np->orig_mac_status == -1) + return; + + base = get_hwbase(dev); + txreg = readl(base + NvRegTransmitPoll); + if (np->orig_mac_status == 1) { + /* + * Set orig mac address back to the reversed version. + * This flag will be cleared during low power transition. + * Therefore, set that bit don't confuse other... + */ + writel(txreg | NVREG_TRANSMITPOLL_MAC_ADDR_REV, + base + NvRegTransmitPoll); + return; + } /* special op: write back the misordered MAC address - otherwise * the next nv_probe would see a wrong address. */ writel(np->orig_mac[0], base + NvRegMacAddrA); writel(np->orig_mac[1], base + NvRegMacAddrB); - writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, + writel(txreg & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); }