From: Zhang Qilong <zhangqilo...@huawei.com> Sent: Sunday, November 8, 2020 5:53 PM > pm_runtime_get_sync() will increment pm usage at first and it will resume the > device later. If runtime of the device has error or device is in inaccessible > state(or other error state), resume operation will fail. If we do not call put > operation to decrease the reference, it will result in reference count leak. > Moreover, this device cannot enter the idle state and always stay busy or > other > non-idle state later. So we fixed it through adding pm_runtime_put_noidle. > > Fixes: 8fff755e9f8d0 ("net: fec: Ensure clocks are enabled while using mdio > bus") > Signed-off-by: Zhang Qilong <zhangqilo...@huawei.com>
>From early discussion for the topic, Wolfram Sang wonder if such de-reference >can be better handled by pm runtime core code. https://lkml.org/lkml/2020/6/14/76 Regards, Andy > --- > drivers/net/ethernet/freescale/fec_main.c | 22 ++++++++++++++++------ > 1 file changed, 16 insertions(+), 6 deletions(-) > > diff --git a/drivers/net/ethernet/freescale/fec_main.c > b/drivers/net/ethernet/freescale/fec_main.c > index d7919555250d..6c02f885c67e 100644 > --- a/drivers/net/ethernet/freescale/fec_main.c > +++ b/drivers/net/ethernet/freescale/fec_main.c > @@ -1809,8 +1809,10 @@ static int fec_enet_mdio_read(struct mii_bus *bus, > int mii_id, int regnum) > bool is_c45 = !!(regnum & MII_ADDR_C45); > > ret = pm_runtime_get_sync(dev); > - if (ret < 0) > + if (ret < 0) { > + pm_runtime_put_noidle(dev); > return ret; > + } > > if (is_c45) { > frame_start = FEC_MMFR_ST_C45; > @@ -1868,10 +1870,12 @@ static int fec_enet_mdio_write(struct mii_bus > *bus, int mii_id, int regnum, > bool is_c45 = !!(regnum & MII_ADDR_C45); > > ret = pm_runtime_get_sync(dev); > - if (ret < 0) > + if (ret < 0) { > + pm_runtime_put_noidle(dev); > return ret; > - else > + } else { > ret = 0; > + } > > if (is_c45) { > frame_start = FEC_MMFR_ST_C45; > @@ -2276,8 +2280,10 @@ static void fec_enet_get_regs(struct net_device > *ndev, > int ret; > > ret = pm_runtime_get_sync(dev); > - if (ret < 0) > + if (ret < 0) { > + pm_runtime_put_noidle(dev); > return; > + } > > regs->version = fec_enet_register_version; > > @@ -2977,8 +2983,10 @@ fec_enet_open(struct net_device *ndev) > bool reset_again; > > ret = pm_runtime_get_sync(&fep->pdev->dev); > - if (ret < 0) > + if (ret < 0) { > + pm_runtime_put_noidle(&fep->pdev->dev); > return ret; > + } > > pinctrl_pm_select_default_state(&fep->pdev->dev); > ret = fec_enet_clk_enable(ndev, true); @@ -3771,8 +3779,10 @@ > fec_drv_remove(struct platform_device *pdev) > int ret; > > ret = pm_runtime_get_sync(&pdev->dev); > - if (ret < 0) > + if (ret < 0) { > + pm_runtime_put_noidle(&pdev->dev); > return ret; > + } > > cancel_work_sync(&fep->tx_timeout_work); > fec_ptp_stop(pdev); > -- > 2.25.4