So far rpm doesn't cover cases like unused ports which are never brought up. If they are active at probe time they remain in this state. Included in this patch:
- Let the idle notification check whether we can suspend and let it schedule the suspend. This way we don't need to have calls to pm_schedule_suspend in different places. - At the end of rtl_open and rtl_init_one send an idle notification to allow suspending if the link is down. If a cable is plugged in aneg is finished before the suspend timer expires and the suspend request is cancelled. - Change rtl8169_runtime_suspend to power down the chip if the interface is down. Successfully tested on a RTL8168evl (mac version 34). Signed-off-by: Heiner Kallweit <hkallwe...@gmail.com> --- drivers/net/ethernet/realtek/r8169.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 29edaa4c6..272c5962e 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1689,7 +1689,7 @@ static void rtl8169_check_link_status(struct net_device *dev, } else { netif_carrier_off(dev); netif_info(tp, ifdown, dev, "link down\n"); - pm_schedule_suspend(&tp->pci_dev->dev, 10000); + pm_runtime_idle(&tp->pci_dev->dev); } } @@ -7950,7 +7950,7 @@ static int rtl_open(struct net_device *dev) rtl_unlock_work(tp); tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); rtl8169_check_link_status(dev, tp, ioaddr); out: @@ -8094,8 +8094,10 @@ static int rtl8169_runtime_suspend(struct device *device) struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); - if (!tp->TxDescArray) + if (!tp->TxDescArray) { + rtl_pll_power_down(tp); return 0; + } rtl_lock_work(tp); tp->saved_wolopts = __rtl8169_get_wol(tp); @@ -8137,9 +8139,11 @@ static int rtl8169_runtime_idle(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - return tp->TxDescArray ? -EBUSY : 0; + if (!netif_running(dev) || !netif_carrier_ok(dev)) + pm_schedule_suspend(device, 10000); + + return -EBUSY; } static const struct dev_pm_ops rtl8169_pm_ops = { @@ -8687,11 +8691,11 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl8168_driver_start(tp); } - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - netif_carrier_off(dev); + if (pci_dev_run_wake(pdev)) + pm_runtime_put_sync(&pdev->dev); + return 0; } -- 2.15.1