When running suspend/resume test on nxp ls1028 platform, there is below
warning trace
Call trace:
mdio_bus_phy_resume+0xa8/0x128
dpm_run_callback+0x4c/0x184
device_resume+0x9c/0x1f0
dpm_resume+0x114/0x340
dpm_resume_end+0x24/0x3c
suspend_devices_and_enter+0x1e0/0x810
pm_suspend+0x288/0x330
......
el0t_64_sync+0x1a0/0x1a4
---[ end trace e8da30565a047649 ]---
Because there is a commit 47ac7b2f6a1f("net: phy: Warn about incorrect
mdio_bus_phy_resume() state") to check phy state when entering resume
phase. This is only a surface phenomenon, the root cause is that enetc driver
can not co-operation with common phy code properly. According to
commit fba863b81604("net: phy: make PHY PM ops a no-op if MAC driver
manages PHY PM "). enetc also can manages PHY PM by itself. So, add
suspend/resume function to manage both mac and phy PM.
Signed-off-by: Meng Li <[email protected]>
---
.../net/ethernet/freescale/enetc/enetc_pf.c | 67 +++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c4560222318d..538a4dba42d3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -8,6 +8,7 @@
#include <linux/of_platform.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
+#include <linux/of.h>
#include <linux/pcs-lynx.h>
#include "enetc_ierb.h"
#include "enetc_pf.h"
@@ -1243,6 +1244,8 @@ static int enetc_pf_probe(struct pci_dev *pdev,
struct enetc_si *si;
struct enetc_pf *pf;
int err;
+ struct fwnode_handle *phy_fwnode;
+ struct phy_device *phy_dev;
err = enetc_pf_register_with_ierb(pdev);
if (err == -EPROBE_DEFER)
@@ -1349,6 +1352,11 @@ static int enetc_pf_probe(struct pci_dev *pdev,
enetc_tsn_pf_init(ndev, pdev);
+ phy_fwnode = fwnode_get_phy_node(of_fwnode_handle(priv->dev->of_node));
+ phy_dev = fwnode_phy_find_device(phy_fwnode);
+ if (phy_dev)
+ phy_dev->mac_managed_pm = 1;
+
return 0;
err_reg_netdev:
@@ -1405,6 +1413,62 @@ static void enetc_pf_remove(struct pci_dev *pdev)
enetc_pci_remove(pdev);
}
+static int enetc_pf_resume(struct device *dev)
+{
+ struct enetc_si *si = dev_get_drvdata(dev);
+ struct net_device *netdev = si->ndev;
+ struct enetc_ndev_priv *priv = netdev_priv(netdev);
+ struct fwnode_handle *phy_fwnode;
+ struct phy_device *phy_dev;
+
+ if (!netdev)
+ return 0;
+
+ rtnl_lock();
+
+ if (!netif_running(netdev)) {
+ rtnl_unlock();
+ return 0;
+ }
+
+ phy_fwnode = fwnode_get_phy_node(of_fwnode_handle(priv->dev->of_node));
+ phy_dev = fwnode_phy_find_device(phy_fwnode);
+ if (phy_dev)
+ phy_init_hw(phy_dev);
+ enetc_start(netdev);
+
+ rtnl_unlock();
+
+ return 0;
+}
+
+static int enetc_pf_suspend(struct device *dev)
+{
+ struct enetc_si *si = dev_get_drvdata(dev);
+ struct net_device *netdev = si->ndev;
+
+ if (!netdev)
+ return 0;
+
+ rtnl_lock();
+
+ if (!netif_running(netdev)) {
+ rtnl_unlock();
+ return 0;
+ }
+
+ enetc_stop(netdev);
+
+ rtnl_unlock();
+
+ return 0;
+}
+
+static const struct dev_pm_ops enetc_pf_pm_ops = {
+ .suspend = enetc_pf_suspend,
+ .resume = enetc_pf_resume,
+};
+
static const struct pci_device_id enetc_pf_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
{ 0, } /* End of table. */
@@ -1419,6 +1483,9 @@ static struct pci_driver enetc_pf_driver = {
#ifdef CONFIG_PCI_IOV
.sriov_configure = enetc_sriov_configure,
#endif
+ .driver = {
+ .pm = &enetc_pf_pm_ops,
+ },
};
module_pci_driver(enetc_pf_driver);
--
2.36.1
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#12442):
https://lists.yoctoproject.org/g/linux-yocto/message/12442
Mute This Topic: https://lists.yoctoproject.org/mt/98555946/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-