--- /dev/null
+From foo@baz Fri Nov 19 02:27:53 PM CET 2021
+From: Meng Li <Meng.Li@windriver.com>
+Date: Fri, 19 Nov 2021 10:53:54 +0800
+Subject: net: stmmac: add clocks management for gmac driver
+To: stable@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, mcoquelin.stm32@gmail.com, linux@armlinux.org.uk, andrew@lunn.ch, qiangqing.zhang@nxp.com
+Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, meng.li@windriver.com
+Message-ID: <20211119025359.30815-2-Meng.Li@windriver.com>
+
+From: Joakim Zhang <qiangqing.zhang@nxp.com>
+
+commit 5ec55823438e850c91c6b92aec93fb04ebde29e2 upstream.
+
+This patch intends to add clocks management for stmmac driver:
+
+If CONFIG_PM enabled:
+1. Keep clocks disabled after driver probed.
+2. Enable clocks when up the net device, and disable clocks when down
+the net device.
+
+If CONFIG_PM disabled:
+Keep clocks always enabled after driver probed.
+
+Note:
+1. It is fine for ethtool, since the way of implementing ethtool_ops::begin
+in stmmac is only can be accessed when interface is enabled, so the clocks
+are ticked.
+2. The MDIO bus has a different life cycle to the MAC, need ensure
+clocks are enabled when _mdio_read/write() need clocks, because these
+functions can be called while the interface it not opened.
+
+Stable backport notes:
+When run below command to remove ethernet driver on
+stratix10 platform, there will be warning trace as below:
+
+$ cd /sys/class/net/eth0/device/driver/
+$ echo ff800000.ethernet > unbind
+
+WARNING: CPU: 3 PID: 386 at drivers/clk/clk.c:810 clk_core_unprepare+0x114/0x274
+Modules linked in: sch_fq_codel
+CPU: 3 PID: 386 Comm: sh Tainted: G W 5.10.74-yocto-standard #1
+Hardware name: SoCFPGA Stratix 10 SoCDK (DT)
+pstate: 00000005 (nzcv daif -PAN -UAO -TCO BTYPE=--)
+pc : clk_core_unprepare+0x114/0x274
+lr : clk_core_unprepare+0x114/0x274
+sp : ffff800011bdbb10
+clk_core_unprepare+0x114/0x274
+ clk_unprepare+0x38/0x50
+ stmmac_remove_config_dt+0x40/0x80
+ stmmac_pltfr_remove+0x64/0x80
+ platform_drv_remove+0x38/0x60
+ ... ..
+ el0_sync_handler+0x1a4/0x1b0
+ el0_sync+0x180/0x1c0
+This issue is introduced by introducing upstream commit 8f269102baf7
+("net: stmmac: disable clocks in stmmac_remove_config_dt()")
+
+But in latest mainline kernel, there is no this issue. Because this
+patch improved clocks management for stmmac driver.
+Therefore, backport it and its fixing patches to stable kernel v5.10.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: stable@vger.kernel.org
+Signed-off-by: Meng Li <Meng.Li@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 75 ++++++++++--
+ drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 111 +++++++++++++-----
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 24 +++
+ 4 files changed, 174 insertions(+), 37 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -270,6 +270,7 @@ void stmmac_disable_eee_mode(struct stmm
+ bool stmmac_eee_init(struct stmmac_priv *priv);
+ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
+ int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size);
++int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);
+
+ #if IS_ENABLED(CONFIG_STMMAC_SELFTESTS)
+ void stmmac_selftest_run(struct net_device *dev,
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -28,6 +28,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
++#include <linux/pm_runtime.h>
+ #include <linux/prefetch.h>
+ #include <linux/pinctrl/consumer.h>
+ #ifdef CONFIG_DEBUG_FS
+@@ -113,6 +114,28 @@ static void stmmac_exit_fs(struct net_de
+
+ #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+
++int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
++{
++ int ret = 0;
++
++ if (enabled) {
++ ret = clk_prepare_enable(priv->plat->stmmac_clk);
++ if (ret)
++ return ret;
++ ret = clk_prepare_enable(priv->plat->pclk);
++ if (ret) {
++ clk_disable_unprepare(priv->plat->stmmac_clk);
++ return ret;
++ }
++ } else {
++ clk_disable_unprepare(priv->plat->stmmac_clk);
++ clk_disable_unprepare(priv->plat->pclk);
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(stmmac_bus_clks_config);
++
+ /**
+ * stmmac_verify_args - verify the driver parameters.
+ * Description: it checks the driver parameters and set a default in case of
+@@ -2792,6 +2815,12 @@ static int stmmac_open(struct net_device
+ u32 chan;
+ int ret;
+
++ ret = pm_runtime_get_sync(priv->device);
++ if (ret < 0) {
++ pm_runtime_put_noidle(priv->device);
++ return ret;
++ }
++
+ if (priv->hw->pcs != STMMAC_PCS_TBI &&
+ priv->hw->pcs != STMMAC_PCS_RTBI &&
+ priv->hw->xpcs == NULL) {
+@@ -2800,7 +2829,7 @@ static int stmmac_open(struct net_device
+ netdev_err(priv->dev,
+ "%s: Cannot attach to PHY (error: %d)\n",
+ __func__, ret);
+- return ret;
++ goto init_phy_error;
+ }
+ }
+
+@@ -2915,6 +2944,8 @@ init_error:
+ free_dma_desc_resources(priv);
+ dma_desc_error:
+ phylink_disconnect_phy(priv->phylink);
++init_phy_error:
++ pm_runtime_put(priv->device);
+ return ret;
+ }
+
+@@ -2965,6 +2996,8 @@ static int stmmac_release(struct net_dev
+
+ stmmac_release_ptp(priv);
+
++ pm_runtime_put(priv->device);
++
+ return 0;
+ }
+
+@@ -4616,6 +4649,12 @@ static int stmmac_vlan_rx_kill_vid(struc
+ bool is_double = false;
+ int ret;
+
++ ret = pm_runtime_get_sync(priv->device);
++ if (ret < 0) {
++ pm_runtime_put_noidle(priv->device);
++ return ret;
++ }
++
+ if (be16_to_cpu(proto) == ETH_P_8021AD)
+ is_double = true;
+
+@@ -4624,10 +4663,15 @@ static int stmmac_vlan_rx_kill_vid(struc
+ if (priv->hw->num_vlan) {
+ ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
+ if (ret)
+- return ret;
++ goto del_vlan_error;
+ }
+
+- return stmmac_vlan_update(priv, is_double);
++ ret = stmmac_vlan_update(priv, is_double);
++
++del_vlan_error:
++ pm_runtime_put(priv->device);
++
++ return ret;
+ }
+
+ static const struct net_device_ops stmmac_netdev_ops = {
+@@ -5066,6 +5110,10 @@ int stmmac_dvr_probe(struct device *devi
+
+ stmmac_check_pcs_mode(priv);
+
++ pm_runtime_get_noresume(device);
++ pm_runtime_set_active(device);
++ pm_runtime_enable(device);
++
+ if (priv->hw->pcs != STMMAC_PCS_TBI &&
+ priv->hw->pcs != STMMAC_PCS_RTBI) {
+ /* MDIO bus Registration */
+@@ -5103,6 +5151,11 @@ int stmmac_dvr_probe(struct device *devi
+ stmmac_init_fs(ndev);
+ #endif
+
++ /* Let pm_runtime_put() disable the clocks.
++ * If CONFIG_PM is not enabled, the clocks will stay powered.
++ */
++ pm_runtime_put(device);
++
+ return ret;
+
+ error_serdes_powerup:
+@@ -5117,6 +5170,7 @@ error_mdio_register:
+ stmmac_napi_del(ndev);
+ error_hw_init:
+ destroy_workqueue(priv->wq);
++ stmmac_bus_clks_config(priv, false);
+
+ return ret;
+ }
+@@ -5152,8 +5206,8 @@ int stmmac_dvr_remove(struct device *dev
+ phylink_destroy(priv->phylink);
+ if (priv->plat->stmmac_rst)
+ reset_control_assert(priv->plat->stmmac_rst);
+- clk_disable_unprepare(priv->plat->pclk);
+- clk_disable_unprepare(priv->plat->stmmac_clk);
++ pm_runtime_put(dev);
++ pm_runtime_disable(dev);
+ if (priv->hw->pcs != STMMAC_PCS_TBI &&
+ priv->hw->pcs != STMMAC_PCS_RTBI)
+ stmmac_mdio_unregister(ndev);
+@@ -5176,6 +5230,7 @@ int stmmac_suspend(struct device *dev)
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ u32 chan;
++ int ret;
+
+ if (!ndev || !netif_running(ndev))
+ return 0;
+@@ -5219,8 +5274,9 @@ int stmmac_suspend(struct device *dev)
+ pinctrl_pm_select_sleep_state(priv->device);
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+- clk_disable_unprepare(priv->plat->pclk);
+- clk_disable_unprepare(priv->plat->stmmac_clk);
++ ret = pm_runtime_force_suspend(dev);
++ if (ret)
++ return ret;
+ }
+ mutex_unlock(&priv->lock);
+
+@@ -5286,8 +5342,9 @@ int stmmac_resume(struct device *dev)
+ } else {
+ pinctrl_pm_select_default_state(priv->device);
+ /* enable the clk previously disabled */
+- clk_prepare_enable(priv->plat->stmmac_clk);
+- clk_prepare_enable(priv->plat->pclk);
++ ret = pm_runtime_force_resume(dev);
++ if (ret)
++ return ret;
+ if (priv->plat->clk_ptp_ref)
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ /* reset the phy so that it's ready */
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+@@ -15,6 +15,7 @@
+ #include <linux/iopoll.h>
+ #include <linux/mii.h>
+ #include <linux/of_mdio.h>
++#include <linux/pm_runtime.h>
+ #include <linux/phy.h>
+ #include <linux/property.h>
+ #include <linux/slab.h>
+@@ -87,21 +88,29 @@ static int stmmac_xgmac2_mdio_read(struc
+ u32 tmp, addr, value = MII_XGMAC_BUSY;
+ int ret;
+
++ ret = pm_runtime_get_sync(priv->device);
++ if (ret < 0) {
++ pm_runtime_put_noidle(priv->device);
++ return ret;
++ }
++
+ /* Wait until any existing MII operation is complete */
+ if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
+- !(tmp & MII_XGMAC_BUSY), 100, 10000))
+- return -EBUSY;
++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
++ ret = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ if (phyreg & MII_ADDR_C45) {
+ phyreg &= ~MII_ADDR_C45;
+
+ ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr);
+ if (ret)
+- return ret;
++ goto err_disable_clks;
+ } else {
+ ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
+ if (ret)
+- return ret;
++ goto err_disable_clks;
+
+ value |= MII_XGMAC_SADDR;
+ }
+@@ -112,8 +121,10 @@ static int stmmac_xgmac2_mdio_read(struc
+
+ /* Wait until any existing MII operation is complete */
+ if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
+- !(tmp & MII_XGMAC_BUSY), 100, 10000))
+- return -EBUSY;
++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
++ ret = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ /* Set the MII address register to read */
+ writel(addr, priv->ioaddr + mii_address);
+@@ -121,11 +132,18 @@ static int stmmac_xgmac2_mdio_read(struc
+
+ /* Wait until any existing MII operation is complete */
+ if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
+- !(tmp & MII_XGMAC_BUSY), 100, 10000))
+- return -EBUSY;
++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
++ ret = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ /* Read the data from the MII data register */
+- return readl(priv->ioaddr + mii_data) & GENMASK(15, 0);
++ ret = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0);
++
++err_disable_clks:
++ pm_runtime_put(priv->device);
++
++ return ret;
+ }
+
+ static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr,
+@@ -138,21 +156,29 @@ static int stmmac_xgmac2_mdio_write(stru
+ u32 addr, tmp, value = MII_XGMAC_BUSY;
+ int ret;
+
++ ret = pm_runtime_get_sync(priv->device);
++ if (ret < 0) {
++ pm_runtime_put_noidle(priv->device);
++ return ret;
++ }
++
+ /* Wait until any existing MII operation is complete */
+ if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
+- !(tmp & MII_XGMAC_BUSY), 100, 10000))
+- return -EBUSY;
++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
++ ret = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ if (phyreg & MII_ADDR_C45) {
+ phyreg &= ~MII_ADDR_C45;
+
+ ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr);
+ if (ret)
+- return ret;
++ goto err_disable_clks;
+ } else {
+ ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
+ if (ret)
+- return ret;
++ goto err_disable_clks;
+
+ value |= MII_XGMAC_SADDR;
+ }
+@@ -164,16 +190,23 @@ static int stmmac_xgmac2_mdio_write(stru
+
+ /* Wait until any existing MII operation is complete */
+ if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
+- !(tmp & MII_XGMAC_BUSY), 100, 10000))
+- return -EBUSY;
++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
++ ret = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ /* Set the MII address register to write */
+ writel(addr, priv->ioaddr + mii_address);
+ writel(value, priv->ioaddr + mii_data);
+
+ /* Wait until any existing MII operation is complete */
+- return readl_poll_timeout(priv->ioaddr + mii_data, tmp,
+- !(tmp & MII_XGMAC_BUSY), 100, 10000);
++ ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp,
++ !(tmp & MII_XGMAC_BUSY), 100, 10000);
++
++err_disable_clks:
++ pm_runtime_put(priv->device);
++
++ return ret;
+ }
+
+ /**
+@@ -196,6 +229,12 @@ static int stmmac_mdio_read(struct mii_b
+ int data = 0;
+ u32 v;
+
++ data = pm_runtime_get_sync(priv->device);
++ if (data < 0) {
++ pm_runtime_put_noidle(priv->device);
++ return data;
++ }
++
+ value |= (phyaddr << priv->hw->mii.addr_shift)
+ & priv->hw->mii.addr_mask;
+ value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
+@@ -216,19 +255,26 @@ static int stmmac_mdio_read(struct mii_b
+ }
+
+ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
+- 100, 10000))
+- return -EBUSY;
++ 100, 10000)) {
++ data = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ writel(data, priv->ioaddr + mii_data);
+ writel(value, priv->ioaddr + mii_address);
+
+ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
+- 100, 10000))
+- return -EBUSY;
++ 100, 10000)) {
++ data = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ /* Read the data from the MII data register */
+ data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
+
++err_disable_clks:
++ pm_runtime_put(priv->device);
++
+ return data;
+ }
+
+@@ -247,10 +293,16 @@ static int stmmac_mdio_write(struct mii_
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned int mii_address = priv->hw->mii.addr;
+ unsigned int mii_data = priv->hw->mii.data;
++ int ret, data = phydata;
+ u32 value = MII_BUSY;
+- int data = phydata;
+ u32 v;
+
++ ret = pm_runtime_get_sync(priv->device);
++ if (ret < 0) {
++ pm_runtime_put_noidle(priv->device);
++ return ret;
++ }
++
+ value |= (phyaddr << priv->hw->mii.addr_shift)
+ & priv->hw->mii.addr_mask;
+ value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
+@@ -275,16 +327,23 @@ static int stmmac_mdio_write(struct mii_
+
+ /* Wait until any existing MII operation is complete */
+ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
+- 100, 10000))
+- return -EBUSY;
++ 100, 10000)) {
++ ret = -EBUSY;
++ goto err_disable_clks;
++ }
+
+ /* Set the MII address register to write */
+ writel(data, priv->ioaddr + mii_data);
+ writel(value, priv->ioaddr + mii_address);
+
+ /* Wait until any existing MII operation is complete */
+- return readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
+- 100, 10000);
++ ret = readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
++ 100, 10000);
++
++err_disable_clks:
++ pm_runtime_put(priv->device);
++
++ return ret;
+ }
+
+ /**
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -760,10 +760,30 @@ static int stmmac_pltfr_resume(struct de
+
+ return stmmac_resume(dev);
+ }
++
++static int stmmac_runtime_suspend(struct device *dev)
++{
++ struct net_device *ndev = dev_get_drvdata(dev);
++ struct stmmac_priv *priv = netdev_priv(ndev);
++
++ stmmac_bus_clks_config(priv, false);
++
++ return 0;
++}
++
++static int stmmac_runtime_resume(struct device *dev)
++{
++ struct net_device *ndev = dev_get_drvdata(dev);
++ struct stmmac_priv *priv = netdev_priv(ndev);
++
++ return stmmac_bus_clks_config(priv, true);
++}
+ #endif /* CONFIG_PM_SLEEP */
+
+-SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend,
+- stmmac_pltfr_resume);
++const struct dev_pm_ops stmmac_pltfr_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
++ SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
++};
+ EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
+
+ MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
--- /dev/null
+From foo@baz Fri Nov 19 02:27:53 PM CET 2021
+From: Meng Li <Meng.Li@windriver.com>
+Date: Fri, 19 Nov 2021 10:53:58 +0800
+Subject: net: stmmac: fix issue where clk is being unprepared twice
+To: stable@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, mcoquelin.stm32@gmail.com, linux@armlinux.org.uk, andrew@lunn.ch, qiangqing.zhang@nxp.com
+Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, meng.li@windriver.com
+Message-ID: <20211119025359.30815-6-Meng.Li@windriver.com>
+
+From: Wong Vee Khee <vee.khee.wong@linux.intel.com>
+
+commit ab00f3e051e851a8458f0d0eb1bb426deadb6619 upstream.
+
+In the case of MDIO bus registration failure due to no external PHY
+devices is connected to the MAC, clk_disable_unprepare() is called in
+stmmac_bus_clk_config() and intel_eth_pci_probe() respectively.
+
+The second call in intel_eth_pci_probe() will caused the following:-
+
+[ 16.578605] intel-eth-pci 0000:00:1e.5: No PHY found
+[ 16.583778] intel-eth-pci 0000:00:1e.5: stmmac_dvr_probe: MDIO bus (id: 2) registration failed
+[ 16.680181] ------------[ cut here ]------------
+[ 16.684861] stmmac-0000:00:1e.5 already disabled
+[ 16.689547] WARNING: CPU: 13 PID: 2053 at drivers/clk/clk.c:952 clk_core_disable+0x96/0x1b0
+[ 16.697963] Modules linked in: dwc3 iTCO_wdt mei_hdcp iTCO_vendor_support udc_core x86_pkg_temp_thermal kvm_intel marvell10g kvm sch_fq_codel nfsd irqbypass dwmac_intel(+) stmmac uio ax88179_178a pcs_xpcs phylink uhid spi_pxa2xx_platform usbnet mei_me pcspkr tpm_crb mii i2c_i801 dw_dmac dwc3_pci thermal dw_dmac_core intel_rapl_msr libphy i2c_smbus mei tpm_tis intel_th_gth tpm_tis_core tpm intel_th_acpi intel_pmc_core intel_th i915 fuse configfs snd_hda_intel snd_intel_dspcfg snd_intel_sdw_acpi snd_hda_codec snd_hda_core snd_pcm snd_timer snd soundcore
+[ 16.746785] CPU: 13 PID: 2053 Comm: systemd-udevd Tainted: G U 5.13.0-rc3-intel-lts #76
+[ 16.756134] Hardware name: Intel Corporation Alder Lake Client Platform/AlderLake-S ADP-S DRR4 CRB, BIOS ADLIFSI1.R00.1494.B00.2012031421 12/03/2020
+[ 16.769465] RIP: 0010:clk_core_disable+0x96/0x1b0
+[ 16.774222] Code: 00 8b 05 45 96 17 01 85 c0 7f 24 48 8b 5b 30 48 85 db 74 a5 8b 43 7c 85 c0 75 93 48 8b 33 48 c7 c7 6e 32 cc b7 e8 b2 5d 52 00 <0f> 0b 5b 5d c3 65 8b 05 76 31 18 49 89 c0 48 0f a3 05 bc 92 1a 01
+[ 16.793016] RSP: 0018:ffffa44580523aa0 EFLAGS: 00010086
+[ 16.798287] RAX: 0000000000000000 RBX: ffff8d7d0eb70a00 RCX: 0000000000000000
+[ 16.805435] RDX: 0000000000000002 RSI: ffffffffb7c62d5f RDI: 00000000ffffffff
+[ 16.812610] RBP: 0000000000000287 R08: 0000000000000000 R09: ffffa445805238d0
+[ 16.819759] R10: 0000000000000001 R11: 0000000000000001 R12: ffff8d7d0eb70a00
+[ 16.826904] R13: ffff8d7d027370c8 R14: 0000000000000006 R15: ffffa44580523ad0
+[ 16.834047] FS: 00007f9882fa2600(0000) GS:ffff8d80a0940000(0000) knlGS:0000000000000000
+[ 16.842177] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 16.847966] CR2: 00007f9882bea3d8 CR3: 000000010b126001 CR4: 0000000000370ee0
+[ 16.855144] Call Trace:
+[ 16.857614] clk_core_disable_lock+0x1b/0x30
+[ 16.861941] intel_eth_pci_probe.cold+0x11d/0x136 [dwmac_intel]
+[ 16.867913] pci_device_probe+0xcf/0x150
+[ 16.871890] really_probe+0xf5/0x3e0
+[ 16.875526] driver_probe_device+0x64/0x150
+[ 16.879763] device_driver_attach+0x53/0x60
+[ 16.883998] __driver_attach+0x9f/0x150
+[ 16.887883] ? device_driver_attach+0x60/0x60
+[ 16.892288] ? device_driver_attach+0x60/0x60
+[ 16.896698] bus_for_each_dev+0x77/0xc0
+[ 16.900583] bus_add_driver+0x184/0x1f0
+[ 16.904469] driver_register+0x6c/0xc0
+[ 16.908268] ? 0xffffffffc07ae000
+[ 16.911598] do_one_initcall+0x4a/0x210
+[ 16.915489] ? kmem_cache_alloc_trace+0x305/0x4e0
+[ 16.920247] do_init_module+0x5c/0x230
+[ 16.924057] load_module+0x2894/0x2b70
+[ 16.927857] ? __do_sys_finit_module+0xb5/0x120
+[ 16.932441] __do_sys_finit_module+0xb5/0x120
+[ 16.936845] do_syscall_64+0x42/0x80
+[ 16.940476] entry_SYSCALL_64_after_hwframe+0x44/0xae
+[ 16.945586] RIP: 0033:0x7f98830e5ccd
+[ 16.949177] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 93 31 0c 00 f7 d8 64 89 01 48
+[ 16.967970] RSP: 002b:00007ffc66b60168 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
+[ 16.975583] RAX: ffffffffffffffda RBX: 000055885de35ef0 RCX: 00007f98830e5ccd
+[ 16.982725] RDX: 0000000000000000 RSI: 00007f98832541e3 RDI: 0000000000000012
+[ 16.989868] RBP: 0000000000020000 R08: 0000000000000000 R09: 0000000000000000
+[ 16.997042] R10: 0000000000000012 R11: 0000000000000246 R12: 00007f98832541e3
+[ 17.004222] R13: 0000000000000000 R14: 0000000000000000 R15: 00007ffc66b60328
+[ 17.011369] ---[ end trace df06a3dab26b988c ]---
+[ 17.016062] ------------[ cut here ]------------
+[ 17.020701] stmmac-0000:00:1e.5 already unprepared
+
+Removing the stmmac_bus_clks_config() call in stmmac_dvr_probe and let
+dwmac-intel to handle the unprepare and disable of the clk device.
+
+Fixes: 5ec55823438e ("net: stmmac: add clocks management for gmac driver")
+Cc: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: Wong Vee Khee <vee.khee.wong@linux.intel.com>
+Reviewed-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Meng Li <Meng.Li@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -5179,7 +5179,6 @@ error_mdio_register:
+ stmmac_napi_del(ndev);
+ error_hw_init:
+ destroy_workqueue(priv->wq);
+- stmmac_bus_clks_config(priv, false);
+
+ return ret;
+ }
--- /dev/null
+From foo@baz Fri Nov 19 02:27:53 PM CET 2021
+From: Meng Li <Meng.Li@windriver.com>
+Date: Fri, 19 Nov 2021 10:53:55 +0800
+Subject: net: stmmac: platform: fix build error with !CONFIG_PM_SLEEP
+To: stable@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, mcoquelin.stm32@gmail.com, linux@armlinux.org.uk, andrew@lunn.ch, qiangqing.zhang@nxp.com
+Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, meng.li@windriver.com
+Message-ID: <20211119025359.30815-3-Meng.Li@windriver.com>
+
+From: Wei Yongjun <weiyongjun1@huawei.com>
+
+commit 7ec05a6035480f3a5934b2b31222620b2e906163 upstream
+
+Get rid of the CONFIG_PM_SLEEP ifdefery to fix the build error
+and use __maybe_unused for the suspend()/resume() hooks to avoid
+build warning:
+
+drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:769:21:
+ error: 'stmmac_runtime_suspend' undeclared here (not in a function); did you mean 'stmmac_suspend'?
+ 769 | SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ | ^~~~~~~~~~~~~~~~~~~~~~
+./include/linux/pm.h:342:21: note: in definition of macro 'SET_RUNTIME_PM_OPS'
+ 342 | .runtime_suspend = suspend_fn, \
+ | ^~~~~~~~~~
+drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:769:45:
+ error: 'stmmac_runtime_resume' undeclared here (not in a function)
+ 769 | SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ | ^~~~~~~~~~~~~~~~~~~~~
+./include/linux/pm.h:343:20: note: in definition of macro 'SET_RUNTIME_PM_OPS'
+ 343 | .runtime_resume = resume_fn, \
+ | ^~~~~~~~~
+
+Fixes: 5ec55823438e ("net: stmmac: add clocks management for gmac driver")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Meng Li <Meng.Li@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -720,7 +720,6 @@ int stmmac_pltfr_remove(struct platform_
+ }
+ EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
+
+-#ifdef CONFIG_PM_SLEEP
+ /**
+ * stmmac_pltfr_suspend
+ * @dev: device pointer
+@@ -728,7 +727,7 @@ EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
+ * call the main suspend function and then, if required, on some platform, it
+ * can call an exit helper.
+ */
+-static int stmmac_pltfr_suspend(struct device *dev)
++static int __maybe_unused stmmac_pltfr_suspend(struct device *dev)
+ {
+ int ret;
+ struct net_device *ndev = dev_get_drvdata(dev);
+@@ -749,7 +748,7 @@ static int stmmac_pltfr_suspend(struct d
+ * the main resume function, on some platforms, it can call own init helper
+ * if required.
+ */
+-static int stmmac_pltfr_resume(struct device *dev)
++static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
+ {
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+@@ -761,7 +760,7 @@ static int stmmac_pltfr_resume(struct de
+ return stmmac_resume(dev);
+ }
+
+-static int stmmac_runtime_suspend(struct device *dev)
++static int __maybe_unused stmmac_runtime_suspend(struct device *dev)
+ {
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+@@ -771,14 +770,13 @@ static int stmmac_runtime_suspend(struct
+ return 0;
+ }
+
+-static int stmmac_runtime_resume(struct device *dev)
++static int __maybe_unused stmmac_runtime_resume(struct device *dev)
+ {
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+
+ return stmmac_bus_clks_config(priv, true);
+ }
+-#endif /* CONFIG_PM_SLEEP */
+
+ const struct dev_pm_ops stmmac_pltfr_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)