[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20201108095310.2892555-1-zhangqilong3@huawei.com>
Date: Sun, 8 Nov 2020 17:53:10 +0800
From: Zhang Qilong <zhangqilong3@...wei.com>
To: <fugang.duan@....com>, <davem@...emloft.net>, <kuba@...nel.org>
CC: <netdev@...r.kernel.org>
Subject: [PATCH] net: fec: Fix reference count leak in fec series ops
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 <zhangqilong3@...wei.com>
---
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
Powered by blists - more mailing lists