diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2010-12-08 10:32:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-10 14:09:18 -0500 |
commit | e4fbce740f078bbc925ba5c86648d9c883968479 (patch) | |
tree | 079b7536f3139ce745a2d4440fd8e73086a5c5d6 | |
parent | 6934d33556b366d22392a415ca09d720fed6a442 (diff) |
r8169: Fix runtime power management
I noticed that one of the post-2.6.36 patches broke runtime PM of the
r8169 on my MSI Wind test machine in such a way that the link was not
brought up after reconnecting the network cable.
In the process of debugging the issue I realized that we only should
invoke the runtime PM functions in rtl8169_check_link_status() when
link change is reported and if we do so, the problem goes away.
Moreover, this allows rtl8169_runtime_idle() to be simplified quite
a bit.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/r8169.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 7d33ef4bcb4a..53b13deade95 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -744,26 +744,36 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) | |||
744 | mdio_write(ioaddr, MII_BMCR, val & 0xffff); | 744 | mdio_write(ioaddr, MII_BMCR, val & 0xffff); |
745 | } | 745 | } |
746 | 746 | ||
747 | static void rtl8169_check_link_status(struct net_device *dev, | 747 | static void __rtl8169_check_link_status(struct net_device *dev, |
748 | struct rtl8169_private *tp, | 748 | struct rtl8169_private *tp, |
749 | void __iomem *ioaddr) | 749 | void __iomem *ioaddr, |
750 | bool pm) | ||
750 | { | 751 | { |
751 | unsigned long flags; | 752 | unsigned long flags; |
752 | 753 | ||
753 | spin_lock_irqsave(&tp->lock, flags); | 754 | spin_lock_irqsave(&tp->lock, flags); |
754 | if (tp->link_ok(ioaddr)) { | 755 | if (tp->link_ok(ioaddr)) { |
755 | /* This is to cancel a scheduled suspend if there's one. */ | 756 | /* This is to cancel a scheduled suspend if there's one. */ |
756 | pm_request_resume(&tp->pci_dev->dev); | 757 | if (pm) |
758 | pm_request_resume(&tp->pci_dev->dev); | ||
757 | netif_carrier_on(dev); | 759 | netif_carrier_on(dev); |
758 | netif_info(tp, ifup, dev, "link up\n"); | 760 | netif_info(tp, ifup, dev, "link up\n"); |
759 | } else { | 761 | } else { |
760 | netif_carrier_off(dev); | 762 | netif_carrier_off(dev); |
761 | netif_info(tp, ifdown, dev, "link down\n"); | 763 | netif_info(tp, ifdown, dev, "link down\n"); |
762 | pm_schedule_suspend(&tp->pci_dev->dev, 100); | 764 | if (pm) |
765 | pm_schedule_suspend(&tp->pci_dev->dev, 100); | ||
763 | } | 766 | } |
764 | spin_unlock_irqrestore(&tp->lock, flags); | 767 | spin_unlock_irqrestore(&tp->lock, flags); |
765 | } | 768 | } |
766 | 769 | ||
770 | static void rtl8169_check_link_status(struct net_device *dev, | ||
771 | struct rtl8169_private *tp, | ||
772 | void __iomem *ioaddr) | ||
773 | { | ||
774 | __rtl8169_check_link_status(dev, tp, ioaddr, false); | ||
775 | } | ||
776 | |||
767 | #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) | 777 | #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) |
768 | 778 | ||
769 | static u32 __rtl8169_get_wol(struct rtl8169_private *tp) | 779 | static u32 __rtl8169_get_wol(struct rtl8169_private *tp) |
@@ -4600,7 +4610,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) | |||
4600 | } | 4610 | } |
4601 | 4611 | ||
4602 | if (status & LinkChg) | 4612 | if (status & LinkChg) |
4603 | rtl8169_check_link_status(dev, tp, ioaddr); | 4613 | __rtl8169_check_link_status(dev, tp, ioaddr, true); |
4604 | 4614 | ||
4605 | /* We need to see the lastest version of tp->intr_mask to | 4615 | /* We need to see the lastest version of tp->intr_mask to |
4606 | * avoid ignoring an MSI interrupt and having to wait for | 4616 | * avoid ignoring an MSI interrupt and having to wait for |
@@ -4890,11 +4900,7 @@ static int rtl8169_runtime_idle(struct device *device) | |||
4890 | struct net_device *dev = pci_get_drvdata(pdev); | 4900 | struct net_device *dev = pci_get_drvdata(pdev); |
4891 | struct rtl8169_private *tp = netdev_priv(dev); | 4901 | struct rtl8169_private *tp = netdev_priv(dev); |
4892 | 4902 | ||
4893 | if (!tp->TxDescArray) | 4903 | return tp->TxDescArray ? -EBUSY : 0; |
4894 | return 0; | ||
4895 | |||
4896 | rtl8169_check_link_status(dev, tp, tp->mmio_addr); | ||
4897 | return -EBUSY; | ||
4898 | } | 4904 | } |
4899 | 4905 | ||
4900 | static const struct dev_pm_ops rtl8169_pm_ops = { | 4906 | static const struct dev_pm_ops rtl8169_pm_ops = { |