diff options
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 180 |
1 files changed, 145 insertions, 35 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dbb1f5a1824c..340da3915b96 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/tcp.h> | 23 | #include <linux/tcp.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/pm_runtime.h> | ||
26 | 27 | ||
27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
28 | #include <asm/io.h> | 29 | #include <asm/io.h> |
@@ -509,6 +510,7 @@ struct rtl8169_private { | |||
509 | 510 | ||
510 | struct mii_if_info mii; | 511 | struct mii_if_info mii; |
511 | struct rtl8169_counters counters; | 512 | struct rtl8169_counters counters; |
513 | u32 saved_wolopts; | ||
512 | }; | 514 | }; |
513 | 515 | ||
514 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); | 516 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); |
@@ -748,53 +750,61 @@ static void rtl8169_check_link_status(struct net_device *dev, | |||
748 | 750 | ||
749 | spin_lock_irqsave(&tp->lock, flags); | 751 | spin_lock_irqsave(&tp->lock, flags); |
750 | if (tp->link_ok(ioaddr)) { | 752 | if (tp->link_ok(ioaddr)) { |
753 | /* This is to cancel a scheduled suspend if there's one. */ | ||
754 | pm_request_resume(&tp->pci_dev->dev); | ||
751 | netif_carrier_on(dev); | 755 | netif_carrier_on(dev); |
752 | netif_info(tp, ifup, dev, "link up\n"); | 756 | netif_info(tp, ifup, dev, "link up\n"); |
753 | } else { | 757 | } else { |
754 | netif_carrier_off(dev); | 758 | netif_carrier_off(dev); |
755 | netif_info(tp, ifdown, dev, "link down\n"); | 759 | netif_info(tp, ifdown, dev, "link down\n"); |
760 | pm_schedule_suspend(&tp->pci_dev->dev, 100); | ||
756 | } | 761 | } |
757 | spin_unlock_irqrestore(&tp->lock, flags); | 762 | spin_unlock_irqrestore(&tp->lock, flags); |
758 | } | 763 | } |
759 | 764 | ||
760 | static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | 765 | #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) |
766 | |||
767 | static u32 __rtl8169_get_wol(struct rtl8169_private *tp) | ||
761 | { | 768 | { |
762 | struct rtl8169_private *tp = netdev_priv(dev); | ||
763 | void __iomem *ioaddr = tp->mmio_addr; | 769 | void __iomem *ioaddr = tp->mmio_addr; |
764 | u8 options; | 770 | u8 options; |
765 | 771 | u32 wolopts = 0; | |
766 | wol->wolopts = 0; | ||
767 | |||
768 | #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) | ||
769 | wol->supported = WAKE_ANY; | ||
770 | |||
771 | spin_lock_irq(&tp->lock); | ||
772 | 772 | ||
773 | options = RTL_R8(Config1); | 773 | options = RTL_R8(Config1); |
774 | if (!(options & PMEnable)) | 774 | if (!(options & PMEnable)) |
775 | goto out_unlock; | 775 | return 0; |
776 | 776 | ||
777 | options = RTL_R8(Config3); | 777 | options = RTL_R8(Config3); |
778 | if (options & LinkUp) | 778 | if (options & LinkUp) |
779 | wol->wolopts |= WAKE_PHY; | 779 | wolopts |= WAKE_PHY; |
780 | if (options & MagicPacket) | 780 | if (options & MagicPacket) |
781 | wol->wolopts |= WAKE_MAGIC; | 781 | wolopts |= WAKE_MAGIC; |
782 | 782 | ||
783 | options = RTL_R8(Config5); | 783 | options = RTL_R8(Config5); |
784 | if (options & UWF) | 784 | if (options & UWF) |
785 | wol->wolopts |= WAKE_UCAST; | 785 | wolopts |= WAKE_UCAST; |
786 | if (options & BWF) | 786 | if (options & BWF) |
787 | wol->wolopts |= WAKE_BCAST; | 787 | wolopts |= WAKE_BCAST; |
788 | if (options & MWF) | 788 | if (options & MWF) |
789 | wol->wolopts |= WAKE_MCAST; | 789 | wolopts |= WAKE_MCAST; |
790 | 790 | ||
791 | out_unlock: | 791 | return wolopts; |
792 | spin_unlock_irq(&tp->lock); | ||
793 | } | 792 | } |
794 | 793 | ||
795 | static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | 794 | static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) |
796 | { | 795 | { |
797 | struct rtl8169_private *tp = netdev_priv(dev); | 796 | struct rtl8169_private *tp = netdev_priv(dev); |
797 | |||
798 | spin_lock_irq(&tp->lock); | ||
799 | |||
800 | wol->supported = WAKE_ANY; | ||
801 | wol->wolopts = __rtl8169_get_wol(tp); | ||
802 | |||
803 | spin_unlock_irq(&tp->lock); | ||
804 | } | ||
805 | |||
806 | static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) | ||
807 | { | ||
798 | void __iomem *ioaddr = tp->mmio_addr; | 808 | void __iomem *ioaddr = tp->mmio_addr; |
799 | unsigned int i; | 809 | unsigned int i; |
800 | static const struct { | 810 | static const struct { |
@@ -811,23 +821,29 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
811 | { WAKE_ANY, Config5, LanWake } | 821 | { WAKE_ANY, Config5, LanWake } |
812 | }; | 822 | }; |
813 | 823 | ||
814 | spin_lock_irq(&tp->lock); | ||
815 | |||
816 | RTL_W8(Cfg9346, Cfg9346_Unlock); | 824 | RTL_W8(Cfg9346, Cfg9346_Unlock); |
817 | 825 | ||
818 | for (i = 0; i < ARRAY_SIZE(cfg); i++) { | 826 | for (i = 0; i < ARRAY_SIZE(cfg); i++) { |
819 | u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; | 827 | u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; |
820 | if (wol->wolopts & cfg[i].opt) | 828 | if (wolopts & cfg[i].opt) |
821 | options |= cfg[i].mask; | 829 | options |= cfg[i].mask; |
822 | RTL_W8(cfg[i].reg, options); | 830 | RTL_W8(cfg[i].reg, options); |
823 | } | 831 | } |
824 | 832 | ||
825 | RTL_W8(Cfg9346, Cfg9346_Lock); | 833 | RTL_W8(Cfg9346, Cfg9346_Lock); |
834 | } | ||
835 | |||
836 | static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
837 | { | ||
838 | struct rtl8169_private *tp = netdev_priv(dev); | ||
839 | |||
840 | spin_lock_irq(&tp->lock); | ||
826 | 841 | ||
827 | if (wol->wolopts) | 842 | if (wol->wolopts) |
828 | tp->features |= RTL_FEATURE_WOL; | 843 | tp->features |= RTL_FEATURE_WOL; |
829 | else | 844 | else |
830 | tp->features &= ~RTL_FEATURE_WOL; | 845 | tp->features &= ~RTL_FEATURE_WOL; |
846 | __rtl8169_set_wol(tp, wol->wolopts); | ||
831 | device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); | 847 | device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); |
832 | 848 | ||
833 | spin_unlock_irq(&tp->lock); | 849 | spin_unlock_irq(&tp->lock); |
@@ -1042,14 +1058,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, | |||
1042 | } | 1058 | } |
1043 | 1059 | ||
1044 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | 1060 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, |
1045 | struct sk_buff *skb) | 1061 | struct sk_buff *skb, int polling) |
1046 | { | 1062 | { |
1047 | u32 opts2 = le32_to_cpu(desc->opts2); | 1063 | u32 opts2 = le32_to_cpu(desc->opts2); |
1048 | struct vlan_group *vlgrp = tp->vlgrp; | 1064 | struct vlan_group *vlgrp = tp->vlgrp; |
1049 | int ret; | 1065 | int ret; |
1050 | 1066 | ||
1051 | if (vlgrp && (opts2 & RxVlanTag)) { | 1067 | if (vlgrp && (opts2 & RxVlanTag)) { |
1052 | vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); | 1068 | __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); |
1053 | ret = 0; | 1069 | ret = 0; |
1054 | } else | 1070 | } else |
1055 | ret = -1; | 1071 | ret = -1; |
@@ -1066,7 +1082,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, | |||
1066 | } | 1082 | } |
1067 | 1083 | ||
1068 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | 1084 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, |
1069 | struct sk_buff *skb) | 1085 | struct sk_buff *skb, int polling) |
1070 | { | 1086 | { |
1071 | return -1; | 1087 | return -1; |
1072 | } | 1088 | } |
@@ -3187,6 +3203,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3187 | 3203 | ||
3188 | device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); | 3204 | device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); |
3189 | 3205 | ||
3206 | if (pci_dev_run_wake(pdev)) { | ||
3207 | pm_runtime_set_active(&pdev->dev); | ||
3208 | pm_runtime_enable(&pdev->dev); | ||
3209 | } | ||
3210 | pm_runtime_idle(&pdev->dev); | ||
3211 | |||
3190 | out: | 3212 | out: |
3191 | return rc; | 3213 | return rc; |
3192 | 3214 | ||
@@ -3209,10 +3231,18 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) | |||
3209 | struct net_device *dev = pci_get_drvdata(pdev); | 3231 | struct net_device *dev = pci_get_drvdata(pdev); |
3210 | struct rtl8169_private *tp = netdev_priv(dev); | 3232 | struct rtl8169_private *tp = netdev_priv(dev); |
3211 | 3233 | ||
3234 | pm_runtime_get_sync(&pdev->dev); | ||
3235 | |||
3212 | flush_scheduled_work(); | 3236 | flush_scheduled_work(); |
3213 | 3237 | ||
3214 | unregister_netdev(dev); | 3238 | unregister_netdev(dev); |
3215 | 3239 | ||
3240 | if (pci_dev_run_wake(pdev)) { | ||
3241 | pm_runtime_disable(&pdev->dev); | ||
3242 | pm_runtime_set_suspended(&pdev->dev); | ||
3243 | } | ||
3244 | pm_runtime_put_noidle(&pdev->dev); | ||
3245 | |||
3216 | /* restore original MAC address */ | 3246 | /* restore original MAC address */ |
3217 | rtl_rar_set(tp, dev->perm_addr); | 3247 | rtl_rar_set(tp, dev->perm_addr); |
3218 | 3248 | ||
@@ -3239,6 +3269,7 @@ static int rtl8169_open(struct net_device *dev) | |||
3239 | struct pci_dev *pdev = tp->pci_dev; | 3269 | struct pci_dev *pdev = tp->pci_dev; |
3240 | int retval = -ENOMEM; | 3270 | int retval = -ENOMEM; |
3241 | 3271 | ||
3272 | pm_runtime_get_sync(&pdev->dev); | ||
3242 | 3273 | ||
3243 | /* | 3274 | /* |
3244 | * Note that we use a magic value here, its wierd I know | 3275 | * Note that we use a magic value here, its wierd I know |
@@ -3259,7 +3290,7 @@ static int rtl8169_open(struct net_device *dev) | |||
3259 | tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, | 3290 | tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, |
3260 | &tp->TxPhyAddr); | 3291 | &tp->TxPhyAddr); |
3261 | if (!tp->TxDescArray) | 3292 | if (!tp->TxDescArray) |
3262 | goto out; | 3293 | goto err_pm_runtime_put; |
3263 | 3294 | ||
3264 | tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, | 3295 | tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, |
3265 | &tp->RxPhyAddr); | 3296 | &tp->RxPhyAddr); |
@@ -3286,6 +3317,9 @@ static int rtl8169_open(struct net_device *dev) | |||
3286 | 3317 | ||
3287 | rtl8169_request_timer(dev); | 3318 | rtl8169_request_timer(dev); |
3288 | 3319 | ||
3320 | tp->saved_wolopts = 0; | ||
3321 | pm_runtime_put_noidle(&pdev->dev); | ||
3322 | |||
3289 | rtl8169_check_link_status(dev, tp, tp->mmio_addr); | 3323 | rtl8169_check_link_status(dev, tp, tp->mmio_addr); |
3290 | out: | 3324 | out: |
3291 | return retval; | 3325 | return retval; |
@@ -3295,9 +3329,13 @@ err_release_ring_2: | |||
3295 | err_free_rx_1: | 3329 | err_free_rx_1: |
3296 | pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, | 3330 | pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, |
3297 | tp->RxPhyAddr); | 3331 | tp->RxPhyAddr); |
3332 | tp->RxDescArray = NULL; | ||
3298 | err_free_tx_0: | 3333 | err_free_tx_0: |
3299 | pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, | 3334 | pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, |
3300 | tp->TxPhyAddr); | 3335 | tp->TxPhyAddr); |
3336 | tp->TxDescArray = NULL; | ||
3337 | err_pm_runtime_put: | ||
3338 | pm_runtime_put_noidle(&pdev->dev); | ||
3301 | goto out; | 3339 | goto out; |
3302 | } | 3340 | } |
3303 | 3341 | ||
@@ -4441,12 +4479,20 @@ out: | |||
4441 | return done; | 4479 | return done; |
4442 | } | 4480 | } |
4443 | 4481 | ||
4482 | /* | ||
4483 | * Warning : rtl8169_rx_interrupt() might be called : | ||
4484 | * 1) from NAPI (softirq) context | ||
4485 | * (polling = 1 : we should call netif_receive_skb()) | ||
4486 | * 2) from process context (rtl8169_reset_task()) | ||
4487 | * (polling = 0 : we must call netif_rx() instead) | ||
4488 | */ | ||
4444 | static int rtl8169_rx_interrupt(struct net_device *dev, | 4489 | static int rtl8169_rx_interrupt(struct net_device *dev, |
4445 | struct rtl8169_private *tp, | 4490 | struct rtl8169_private *tp, |
4446 | void __iomem *ioaddr, u32 budget) | 4491 | void __iomem *ioaddr, u32 budget) |
4447 | { | 4492 | { |
4448 | unsigned int cur_rx, rx_left; | 4493 | unsigned int cur_rx, rx_left; |
4449 | unsigned int delta, count; | 4494 | unsigned int delta, count; |
4495 | int polling = (budget != ~(u32)0) ? 1 : 0; | ||
4450 | 4496 | ||
4451 | cur_rx = tp->cur_rx; | 4497 | cur_rx = tp->cur_rx; |
4452 | rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; | 4498 | rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; |
@@ -4508,8 +4554,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, | |||
4508 | skb_put(skb, pkt_size); | 4554 | skb_put(skb, pkt_size); |
4509 | skb->protocol = eth_type_trans(skb, dev); | 4555 | skb->protocol = eth_type_trans(skb, dev); |
4510 | 4556 | ||
4511 | if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) | 4557 | if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { |
4512 | netif_receive_skb(skb); | 4558 | if (likely(polling)) |
4559 | netif_receive_skb(skb); | ||
4560 | else | ||
4561 | netif_rx(skb); | ||
4562 | } | ||
4513 | 4563 | ||
4514 | dev->stats.rx_bytes += pkt_size; | 4564 | dev->stats.rx_bytes += pkt_size; |
4515 | dev->stats.rx_packets++; | 4565 | dev->stats.rx_packets++; |
@@ -4704,6 +4754,8 @@ static int rtl8169_close(struct net_device *dev) | |||
4704 | struct rtl8169_private *tp = netdev_priv(dev); | 4754 | struct rtl8169_private *tp = netdev_priv(dev); |
4705 | struct pci_dev *pdev = tp->pci_dev; | 4755 | struct pci_dev *pdev = tp->pci_dev; |
4706 | 4756 | ||
4757 | pm_runtime_get_sync(&pdev->dev); | ||
4758 | |||
4707 | /* update counters before going down */ | 4759 | /* update counters before going down */ |
4708 | rtl8169_update_counters(dev); | 4760 | rtl8169_update_counters(dev); |
4709 | 4761 | ||
@@ -4718,6 +4770,8 @@ static int rtl8169_close(struct net_device *dev) | |||
4718 | tp->TxDescArray = NULL; | 4770 | tp->TxDescArray = NULL; |
4719 | tp->RxDescArray = NULL; | 4771 | tp->RxDescArray = NULL; |
4720 | 4772 | ||
4773 | pm_runtime_put_sync(&pdev->dev); | ||
4774 | |||
4721 | return 0; | 4775 | return 0; |
4722 | } | 4776 | } |
4723 | 4777 | ||
@@ -4743,12 +4797,12 @@ static void rtl_set_rx_mode(struct net_device *dev) | |||
4743 | rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; | 4797 | rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; |
4744 | mc_filter[1] = mc_filter[0] = 0xffffffff; | 4798 | mc_filter[1] = mc_filter[0] = 0xffffffff; |
4745 | } else { | 4799 | } else { |
4746 | struct dev_mc_list *mclist; | 4800 | struct netdev_hw_addr *ha; |
4747 | 4801 | ||
4748 | rx_mode = AcceptBroadcast | AcceptMyPhys; | 4802 | rx_mode = AcceptBroadcast | AcceptMyPhys; |
4749 | mc_filter[1] = mc_filter[0] = 0; | 4803 | mc_filter[1] = mc_filter[0] = 0; |
4750 | netdev_for_each_mc_addr(mclist, dev) { | 4804 | netdev_for_each_mc_addr(ha, dev) { |
4751 | int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | 4805 | int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; |
4752 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | 4806 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); |
4753 | rx_mode |= AcceptMulticast; | 4807 | rx_mode |= AcceptMulticast; |
4754 | } | 4808 | } |
@@ -4816,21 +4870,74 @@ static int rtl8169_suspend(struct device *device) | |||
4816 | return 0; | 4870 | return 0; |
4817 | } | 4871 | } |
4818 | 4872 | ||
4873 | static void __rtl8169_resume(struct net_device *dev) | ||
4874 | { | ||
4875 | netif_device_attach(dev); | ||
4876 | rtl8169_schedule_work(dev, rtl8169_reset_task); | ||
4877 | } | ||
4878 | |||
4819 | static int rtl8169_resume(struct device *device) | 4879 | static int rtl8169_resume(struct device *device) |
4820 | { | 4880 | { |
4821 | struct pci_dev *pdev = to_pci_dev(device); | 4881 | struct pci_dev *pdev = to_pci_dev(device); |
4822 | struct net_device *dev = pci_get_drvdata(pdev); | 4882 | struct net_device *dev = pci_get_drvdata(pdev); |
4823 | 4883 | ||
4824 | if (!netif_running(dev)) | 4884 | if (netif_running(dev)) |
4825 | goto out; | 4885 | __rtl8169_resume(dev); |
4826 | 4886 | ||
4827 | netif_device_attach(dev); | 4887 | return 0; |
4888 | } | ||
4889 | |||
4890 | static int rtl8169_runtime_suspend(struct device *device) | ||
4891 | { | ||
4892 | struct pci_dev *pdev = to_pci_dev(device); | ||
4893 | struct net_device *dev = pci_get_drvdata(pdev); | ||
4894 | struct rtl8169_private *tp = netdev_priv(dev); | ||
4895 | |||
4896 | if (!tp->TxDescArray) | ||
4897 | return 0; | ||
4898 | |||
4899 | spin_lock_irq(&tp->lock); | ||
4900 | tp->saved_wolopts = __rtl8169_get_wol(tp); | ||
4901 | __rtl8169_set_wol(tp, WAKE_ANY); | ||
4902 | spin_unlock_irq(&tp->lock); | ||
4903 | |||
4904 | rtl8169_net_suspend(dev); | ||
4828 | 4905 | ||
4829 | rtl8169_schedule_work(dev, rtl8169_reset_task); | ||
4830 | out: | ||
4831 | return 0; | 4906 | return 0; |
4832 | } | 4907 | } |
4833 | 4908 | ||
4909 | static int rtl8169_runtime_resume(struct device *device) | ||
4910 | { | ||
4911 | struct pci_dev *pdev = to_pci_dev(device); | ||
4912 | struct net_device *dev = pci_get_drvdata(pdev); | ||
4913 | struct rtl8169_private *tp = netdev_priv(dev); | ||
4914 | |||
4915 | if (!tp->TxDescArray) | ||
4916 | return 0; | ||
4917 | |||
4918 | spin_lock_irq(&tp->lock); | ||
4919 | __rtl8169_set_wol(tp, tp->saved_wolopts); | ||
4920 | tp->saved_wolopts = 0; | ||
4921 | spin_unlock_irq(&tp->lock); | ||
4922 | |||
4923 | __rtl8169_resume(dev); | ||
4924 | |||
4925 | return 0; | ||
4926 | } | ||
4927 | |||
4928 | static int rtl8169_runtime_idle(struct device *device) | ||
4929 | { | ||
4930 | struct pci_dev *pdev = to_pci_dev(device); | ||
4931 | struct net_device *dev = pci_get_drvdata(pdev); | ||
4932 | struct rtl8169_private *tp = netdev_priv(dev); | ||
4933 | |||
4934 | if (!tp->TxDescArray) | ||
4935 | return 0; | ||
4936 | |||
4937 | rtl8169_check_link_status(dev, tp, tp->mmio_addr); | ||
4938 | return -EBUSY; | ||
4939 | } | ||
4940 | |||
4834 | static const struct dev_pm_ops rtl8169_pm_ops = { | 4941 | static const struct dev_pm_ops rtl8169_pm_ops = { |
4835 | .suspend = rtl8169_suspend, | 4942 | .suspend = rtl8169_suspend, |
4836 | .resume = rtl8169_resume, | 4943 | .resume = rtl8169_resume, |
@@ -4838,6 +4945,9 @@ static const struct dev_pm_ops rtl8169_pm_ops = { | |||
4838 | .thaw = rtl8169_resume, | 4945 | .thaw = rtl8169_resume, |
4839 | .poweroff = rtl8169_suspend, | 4946 | .poweroff = rtl8169_suspend, |
4840 | .restore = rtl8169_resume, | 4947 | .restore = rtl8169_resume, |
4948 | .runtime_suspend = rtl8169_runtime_suspend, | ||
4949 | .runtime_resume = rtl8169_runtime_resume, | ||
4950 | .runtime_idle = rtl8169_runtime_idle, | ||
4841 | }; | 4951 | }; |
4842 | 4952 | ||
4843 | #define RTL8169_PM_OPS (&rtl8169_pm_ops) | 4953 | #define RTL8169_PM_OPS (&rtl8169_pm_ops) |