Commit da875fa5 authored by Zhang Qilong's avatar Zhang Qilong Committed by Jakub Kicinski

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 by replacing it with
pm_runtime_resume_and_get.

Fixes: 8fff755e ("net: fec: Ensure clocks are enabled while using mdio bus")
Signed-off-by: default avatarZhang Qilong <zhangqilong3@huawei.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent dd8088d5
...@@ -1808,7 +1808,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ...@@ -1808,7 +1808,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
int ret = 0, frame_start, frame_addr, frame_op; int ret = 0, frame_start, frame_addr, frame_op;
bool is_c45 = !!(regnum & MII_ADDR_C45); bool is_c45 = !!(regnum & MII_ADDR_C45);
ret = pm_runtime_get_sync(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1867,11 +1867,9 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ...@@ -1867,11 +1867,9 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
int ret, frame_start, frame_addr; int ret, frame_start, frame_addr;
bool is_c45 = !!(regnum & MII_ADDR_C45); bool is_c45 = !!(regnum & MII_ADDR_C45);
ret = pm_runtime_get_sync(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
else
ret = 0;
if (is_c45) { if (is_c45) {
frame_start = FEC_MMFR_ST_C45; frame_start = FEC_MMFR_ST_C45;
...@@ -2275,7 +2273,7 @@ static void fec_enet_get_regs(struct net_device *ndev, ...@@ -2275,7 +2273,7 @@ static void fec_enet_get_regs(struct net_device *ndev,
u32 i, off; u32 i, off;
int ret; int ret;
ret = pm_runtime_get_sync(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return; return;
...@@ -2976,7 +2974,7 @@ fec_enet_open(struct net_device *ndev) ...@@ -2976,7 +2974,7 @@ fec_enet_open(struct net_device *ndev)
int ret; int ret;
bool reset_again; bool reset_again;
ret = pm_runtime_get_sync(&fep->pdev->dev); ret = pm_runtime_resume_and_get(&fep->pdev->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -3770,7 +3768,7 @@ fec_drv_remove(struct platform_device *pdev) ...@@ -3770,7 +3768,7 @@ fec_drv_remove(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
int ret; int ret;
ret = pm_runtime_get_sync(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment