aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2016-01-06 14:11:21 -0500
committerDavid S. Miller <davem@davemloft.net>2016-01-07 14:31:27 -0500
commitbc87922ff59d364a33e9bce0febdef21a7fbd2af (patch)
treec7179d7f4969f2006e81cd7512c5d0aac8392de2
parent0071f56e46dadb88dc3ad1f8d9cf9c3ae014735d (diff)
phy: Move PHY PM operations into phy_device
The MDIO PM operations are really PHY device PM operations. So move them into phy_device. This will be needed when we support devices on the mdio bus which are not PHYs. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/mdio_bus.c83
-rw-r--r--drivers/net/phy/phy_device.c110
-rw-r--r--include/linux/mdio.h2
3 files changed, 121 insertions, 74 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index e6dddb086265..65ff8199bd09 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -561,95 +561,32 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
561} 561}
562 562
563#ifdef CONFIG_PM 563#ifdef CONFIG_PM
564
565static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
566{
567 struct device_driver *drv = phydev->mdio.dev.driver;
568 struct phy_driver *phydrv = to_phy_driver(drv);
569 struct net_device *netdev = phydev->attached_dev;
570
571 if (!drv || !phydrv->suspend)
572 return false;
573
574 /* PHY not attached? May suspend if the PHY has not already been
575 * suspended as part of a prior call to phy_disconnect() ->
576 * phy_detach() -> phy_suspend() because the parent netdev might be the
577 * MDIO bus driver and clock gated at this point.
578 */
579 if (!netdev)
580 return !phydev->suspended;
581
582 /* Don't suspend PHY if the attched netdev parent may wakeup.
583 * The parent may point to a PCI device, as in tg3 driver.
584 */
585 if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
586 return false;
587
588 /* Also don't suspend PHY if the netdev itself may wakeup. This
589 * is the case for devices w/o underlaying pwr. mgmt. aware bus,
590 * e.g. SoC devices.
591 */
592 if (device_may_wakeup(&netdev->dev))
593 return false;
594
595 return true;
596}
597
598static int mdio_bus_suspend(struct device *dev) 564static int mdio_bus_suspend(struct device *dev)
599{ 565{
600 struct phy_device *phydev = to_phy_device(dev); 566 struct mdio_device *mdio = to_mdio_device(dev);
601 567
602 /* We must stop the state machine manually, otherwise it stops out of 568 if (mdio->pm_ops && mdio->pm_ops->suspend)
603 * control, possibly with the phydev->lock held. Upon resume, netdev 569 return mdio->pm_ops->suspend(dev);
604 * may call phy routines that try to grab the same lock, and that may
605 * lead to a deadlock.
606 */
607 if (phydev->attached_dev && phydev->adjust_link)
608 phy_stop_machine(phydev);
609
610 if (!mdio_bus_phy_may_suspend(phydev))
611 return 0;
612 570
613 return phy_suspend(phydev); 571 return 0;
614} 572}
615 573
616static int mdio_bus_resume(struct device *dev) 574static int mdio_bus_resume(struct device *dev)
617{ 575{
618 struct phy_device *phydev = to_phy_device(dev); 576 struct mdio_device *mdio = to_mdio_device(dev);
619 int ret;
620
621 if (!mdio_bus_phy_may_suspend(phydev))
622 goto no_resume;
623 577
624 ret = phy_resume(phydev); 578 if (mdio->pm_ops && mdio->pm_ops->resume)
625 if (ret < 0) 579 return mdio->pm_ops->resume(dev);
626 return ret;
627
628no_resume:
629 if (phydev->attached_dev && phydev->adjust_link)
630 phy_start_machine(phydev);
631 580
632 return 0; 581 return 0;
633} 582}
634 583
635static int mdio_bus_restore(struct device *dev) 584static int mdio_bus_restore(struct device *dev)
636{ 585{
637 struct phy_device *phydev = to_phy_device(dev); 586 struct mdio_device *mdio = to_mdio_device(dev);
638 struct net_device *netdev = phydev->attached_dev;
639 int ret;
640
641 if (!netdev)
642 return 0;
643
644 ret = phy_init_hw(phydev);
645 if (ret < 0)
646 return ret;
647
648 /* The PHY needs to renegotiate. */
649 phydev->link = 0;
650 phydev->state = PHY_UP;
651 587
652 phy_start_machine(phydev); 588 if (mdio->pm_ops && mdio->pm_ops->restore)
589 return mdio->pm_ops->restore(dev);
653 590
654 return 0; 591 return 0;
655} 592}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 7a5222daff93..eb0b0ed32662 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -63,6 +63,115 @@ static struct phy_driver genphy_driver[GENPHY_DRV_MAX];
63static LIST_HEAD(phy_fixup_list); 63static LIST_HEAD(phy_fixup_list);
64static DEFINE_MUTEX(phy_fixup_lock); 64static DEFINE_MUTEX(phy_fixup_lock);
65 65
66#ifdef CONFIG_PM
67static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
68{
69 struct device_driver *drv = phydev->mdio.dev.driver;
70 struct phy_driver *phydrv = to_phy_driver(drv);
71 struct net_device *netdev = phydev->attached_dev;
72
73 if (!drv || !phydrv->suspend)
74 return false;
75
76 /* PHY not attached? May suspend if the PHY has not already been
77 * suspended as part of a prior call to phy_disconnect() ->
78 * phy_detach() -> phy_suspend() because the parent netdev might be the
79 * MDIO bus driver and clock gated at this point.
80 */
81 if (!netdev)
82 return !phydev->suspended;
83
84 /* Don't suspend PHY if the attached netdev parent may wakeup.
85 * The parent may point to a PCI device, as in tg3 driver.
86 */
87 if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
88 return false;
89
90 /* Also don't suspend PHY if the netdev itself may wakeup. This
91 * is the case for devices w/o underlaying pwr. mgmt. aware bus,
92 * e.g. SoC devices.
93 */
94 if (device_may_wakeup(&netdev->dev))
95 return false;
96
97 return true;
98}
99
100static int mdio_bus_phy_suspend(struct device *dev)
101{
102 struct phy_device *phydev = to_phy_device(dev);
103
104 /* We must stop the state machine manually, otherwise it stops out of
105 * control, possibly with the phydev->lock held. Upon resume, netdev
106 * may call phy routines that try to grab the same lock, and that may
107 * lead to a deadlock.
108 */
109 if (phydev->attached_dev && phydev->adjust_link)
110 phy_stop_machine(phydev);
111
112 if (!mdio_bus_phy_may_suspend(phydev))
113 return 0;
114
115 return phy_suspend(phydev);
116}
117
118static int mdio_bus_phy_resume(struct device *dev)
119{
120 struct phy_device *phydev = to_phy_device(dev);
121 int ret;
122
123 if (!mdio_bus_phy_may_suspend(phydev))
124 goto no_resume;
125
126 ret = phy_resume(phydev);
127 if (ret < 0)
128 return ret;
129
130no_resume:
131 if (phydev->attached_dev && phydev->adjust_link)
132 phy_start_machine(phydev);
133
134 return 0;
135}
136
137static int mdio_bus_phy_restore(struct device *dev)
138{
139 struct phy_device *phydev = to_phy_device(dev);
140 struct net_device *netdev = phydev->attached_dev;
141 int ret;
142
143 if (!netdev)
144 return 0;
145
146 ret = phy_init_hw(phydev);
147 if (ret < 0)
148 return ret;
149
150 /* The PHY needs to renegotiate. */
151 phydev->link = 0;
152 phydev->state = PHY_UP;
153
154 phy_start_machine(phydev);
155
156 return 0;
157}
158
159static const struct dev_pm_ops mdio_bus_phy_pm_ops = {
160 .suspend = mdio_bus_phy_suspend,
161 .resume = mdio_bus_phy_resume,
162 .freeze = mdio_bus_phy_suspend,
163 .thaw = mdio_bus_phy_resume,
164 .restore = mdio_bus_phy_restore,
165};
166
167#define MDIO_BUS_PHY_PM_OPS (&mdio_bus_phy_pm_ops)
168
169#else
170
171#define MDIO_BUS_PHY_PM_OPS NULL
172
173#endif /* CONFIG_PM */
174
66/** 175/**
67 * phy_register_fixup - creates a new phy_fixup and adds it to the list 176 * phy_register_fixup - creates a new phy_fixup and adds it to the list
68 * @bus_id: A string which matches phydev->mdio.dev.bus_id (or PHY_ANY_ID) 177 * @bus_id: A string which matches phydev->mdio.dev.bus_id (or PHY_ANY_ID)
@@ -165,6 +274,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
165 mdiodev->dev.parent = &bus->dev; 274 mdiodev->dev.parent = &bus->dev;
166 mdiodev->dev.bus = &mdio_bus_type; 275 mdiodev->dev.bus = &mdio_bus_type;
167 mdiodev->bus = bus; 276 mdiodev->bus = bus;
277 mdiodev->pm_ops = MDIO_BUS_PHY_PM_OPS;
168 mdiodev->addr = addr; 278 mdiodev->addr = addr;
169 mdiodev->flags = MDIO_DEVICE_FLAG_PHY; 279 mdiodev->flags = MDIO_DEVICE_FLAG_PHY;
170 280
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 8cd9579e18ea..9f844d372ed5 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -15,7 +15,7 @@ struct mii_bus;
15 15
16struct mdio_device { 16struct mdio_device {
17 struct device dev; 17 struct device dev;
18 18 const struct dev_pm_ops *pm_ops;
19 struct mii_bus *bus; 19 struct mii_bus *bus;
20 /* Bus address of the MDIO device (0-31) */ 20 /* Bus address of the MDIO device (0-31) */
21 int addr; 21 int addr;