diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2013-12-20 06:06:49 +0100 |
---|---|---|
committer | Kishon Vijay Abraham I <kishon@ti.com> | 2013-12-24 19:22:58 +0100 |
commit | 637d378cea0b463c466a61a6564cdd541d689af5 (patch) | |
tree | 51cb3c6ca847c33d0305547ba2b1f21d47759ff8 | |
parent | phy: core: properly handle failure of pm_runtime_get functions (diff) | |
download | linux-637d378cea0b463c466a61a6564cdd541d689af5.tar.xz linux-637d378cea0b463c466a61a6564cdd541d689af5.zip |
phy: phy-core: increment refcounting variables only on 'success'
Increment 'init_count' only if the 'init' callback succeeded and decrement
'init_count' only if the 'exit' callback succeded. Increment 'power_count'
only if 'power_on' callback succeded and if it failed disable the clocks using
phy_pm_runtime_put_sync(). Also decrement 'power_count' only if 'power_off'
callback succeded and if it failed do not disable the clocks.
Reported-by: George Cherian <george.cherian@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r-- | drivers/phy/phy-core.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 8797bb7d9c48..33fcbcc5561f 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -167,13 +167,14 @@ int phy_init(struct phy *phy) return ret; mutex_lock(&phy->mutex); - if (phy->init_count++ == 0 && phy->ops->init) { + if (phy->init_count == 0 && phy->ops->init) { ret = phy->ops->init(phy); if (ret < 0) { dev_err(&phy->dev, "phy init failed --> %d\n", ret); goto out; } } + ++phy->init_count; out: mutex_unlock(&phy->mutex); @@ -191,13 +192,14 @@ int phy_exit(struct phy *phy) return ret; mutex_lock(&phy->mutex); - if (--phy->init_count == 0 && phy->ops->exit) { + if (phy->init_count == 1 && phy->ops->exit) { ret = phy->ops->exit(phy); if (ret < 0) { dev_err(&phy->dev, "phy exit failed --> %d\n", ret); goto out; } } + --phy->init_count; out: mutex_unlock(&phy->mutex); @@ -215,16 +217,20 @@ int phy_power_on(struct phy *phy) return ret; mutex_lock(&phy->mutex); - if (phy->power_count++ == 0 && phy->ops->power_on) { + if (phy->power_count == 0 && phy->ops->power_on) { ret = phy->ops->power_on(phy); if (ret < 0) { dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); goto out; } } + ++phy->power_count; + mutex_unlock(&phy->mutex); + return 0; out: mutex_unlock(&phy->mutex); + phy_pm_runtime_put_sync(phy); return ret; } @@ -235,19 +241,19 @@ int phy_power_off(struct phy *phy) int ret = -ENOTSUPP; mutex_lock(&phy->mutex); - if (--phy->power_count == 0 && phy->ops->power_off) { + if (phy->power_count == 1 && phy->ops->power_off) { ret = phy->ops->power_off(phy); if (ret < 0) { dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret); - goto out; + mutex_unlock(&phy->mutex); + return ret; } } - -out: + --phy->power_count; mutex_unlock(&phy->mutex); phy_pm_runtime_put(phy); - return ret; + return 0; } EXPORT_SYMBOL_GPL(phy_power_off); |