Commit f51d4a10 authored by Chun-Hao Lin's avatar Chun-Hao Lin Committed by David S. Miller

r8169: fix nic may not work after changing mac address.

When there is no AC power, NIC may not work after changing mac address.
Please refer to following link.
http://www.spinics.net/lists/netdev/msg356572.html

This issue is caused by runtime power management. When there is no AC
power, if we put NIC down (ifconfig down), the driver will be in runtime
suspend state and hardware will be put into D3 state. During this time,
driver cannot access hardware regisers. So if you set new mac address
during this time, it will not be set to hardware. After resume, NIC will
keep using the old mac address and the network will not work normally.

In this patch I add detecting runtime pm status when setting mac address.
If driver is in runtime suspend state, it will skip setting mac address, keep
the new mac address, and set the new mac address during runtime resume.
Signed-off-by: default avatarChunhao Lin <hau@realtek.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e0636236
...@@ -4480,6 +4480,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) ...@@ -4480,6 +4480,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
static int rtl_set_mac_address(struct net_device *dev, void *p) static int rtl_set_mac_address(struct net_device *dev, void *p)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
struct device *d = &tp->pci_dev->dev;
struct sockaddr *addr = p; struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data)) if (!is_valid_ether_addr(addr->sa_data))
...@@ -4487,8 +4488,13 @@ static int rtl_set_mac_address(struct net_device *dev, void *p) ...@@ -4487,8 +4488,13 @@ static int rtl_set_mac_address(struct net_device *dev, void *p)
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
pm_runtime_get_noresume(d);
if (pm_runtime_active(d))
rtl_rar_set(tp, dev->dev_addr); rtl_rar_set(tp, dev->dev_addr);
pm_runtime_put_noidle(d);
return 0; return 0;
} }
...@@ -7890,6 +7896,7 @@ static int rtl8169_runtime_resume(struct device *device) ...@@ -7890,6 +7896,7 @@ static int rtl8169_runtime_resume(struct device *device)
struct pci_dev *pdev = to_pci_dev(device); struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
rtl_rar_set(tp, dev->dev_addr);
if (!tp->TxDescArray) if (!tp->TxDescArray)
return 0; return 0;
......
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