diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2013-12-20 00:06:49 -0500 |
---|---|---|
committer | Kishon Vijay Abraham I <kishon@ti.com> | 2013-12-24 13:22:58 -0500 |
commit | 637d378cea0b463c466a61a6564cdd541d689af5 (patch) | |
tree | 51cb3c6ca847c33d0305547ba2b1f21d47759ff8 /drivers/phy/phy-core.c | |
parent | cedb7f89d1e1f631b7e5d920fe1ea7f742d07f79 (diff) |
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>
Diffstat (limited to 'drivers/phy/phy-core.c')
-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) | |||
167 | return ret; | 167 | return ret; |
168 | 168 | ||
169 | mutex_lock(&phy->mutex); | 169 | mutex_lock(&phy->mutex); |
170 | if (phy->init_count++ == 0 && phy->ops->init) { | 170 | if (phy->init_count == 0 && phy->ops->init) { |
171 | ret = phy->ops->init(phy); | 171 | ret = phy->ops->init(phy); |
172 | if (ret < 0) { | 172 | if (ret < 0) { |
173 | dev_err(&phy->dev, "phy init failed --> %d\n", ret); | 173 | dev_err(&phy->dev, "phy init failed --> %d\n", ret); |
174 | goto out; | 174 | goto out; |
175 | } | 175 | } |
176 | } | 176 | } |
177 | ++phy->init_count; | ||
177 | 178 | ||
178 | out: | 179 | out: |
179 | mutex_unlock(&phy->mutex); | 180 | mutex_unlock(&phy->mutex); |
@@ -191,13 +192,14 @@ int phy_exit(struct phy *phy) | |||
191 | return ret; | 192 | return ret; |
192 | 193 | ||
193 | mutex_lock(&phy->mutex); | 194 | mutex_lock(&phy->mutex); |
194 | if (--phy->init_count == 0 && phy->ops->exit) { | 195 | if (phy->init_count == 1 && phy->ops->exit) { |
195 | ret = phy->ops->exit(phy); | 196 | ret = phy->ops->exit(phy); |
196 | if (ret < 0) { | 197 | if (ret < 0) { |
197 | dev_err(&phy->dev, "phy exit failed --> %d\n", ret); | 198 | dev_err(&phy->dev, "phy exit failed --> %d\n", ret); |
198 | goto out; | 199 | goto out; |
199 | } | 200 | } |
200 | } | 201 | } |
202 | --phy->init_count; | ||
201 | 203 | ||
202 | out: | 204 | out: |
203 | mutex_unlock(&phy->mutex); | 205 | mutex_unlock(&phy->mutex); |
@@ -215,16 +217,20 @@ int phy_power_on(struct phy *phy) | |||
215 | return ret; | 217 | return ret; |
216 | 218 | ||
217 | mutex_lock(&phy->mutex); | 219 | mutex_lock(&phy->mutex); |
218 | if (phy->power_count++ == 0 && phy->ops->power_on) { | 220 | if (phy->power_count == 0 && phy->ops->power_on) { |
219 | ret = phy->ops->power_on(phy); | 221 | ret = phy->ops->power_on(phy); |
220 | if (ret < 0) { | 222 | if (ret < 0) { |
221 | dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); | 223 | dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); |
222 | goto out; | 224 | goto out; |
223 | } | 225 | } |
224 | } | 226 | } |
227 | ++phy->power_count; | ||
228 | mutex_unlock(&phy->mutex); | ||
229 | return 0; | ||
225 | 230 | ||
226 | out: | 231 | out: |
227 | mutex_unlock(&phy->mutex); | 232 | mutex_unlock(&phy->mutex); |
233 | phy_pm_runtime_put_sync(phy); | ||
228 | 234 | ||
229 | return ret; | 235 | return ret; |
230 | } | 236 | } |
@@ -235,19 +241,19 @@ int phy_power_off(struct phy *phy) | |||
235 | int ret = -ENOTSUPP; | 241 | int ret = -ENOTSUPP; |
236 | 242 | ||
237 | mutex_lock(&phy->mutex); | 243 | mutex_lock(&phy->mutex); |
238 | if (--phy->power_count == 0 && phy->ops->power_off) { | 244 | if (phy->power_count == 1 && phy->ops->power_off) { |
239 | ret = phy->ops->power_off(phy); | 245 | ret = phy->ops->power_off(phy); |
240 | if (ret < 0) { | 246 | if (ret < 0) { |
241 | dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret); | 247 | dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret); |
242 | goto out; | 248 | mutex_unlock(&phy->mutex); |
249 | return ret; | ||
243 | } | 250 | } |
244 | } | 251 | } |
245 | 252 | --phy->power_count; | |
246 | out: | ||
247 | mutex_unlock(&phy->mutex); | 253 | mutex_unlock(&phy->mutex); |
248 | phy_pm_runtime_put(phy); | 254 | phy_pm_runtime_put(phy); |
249 | 255 | ||
250 | return ret; | 256 | return 0; |
251 | } | 257 | } |
252 | EXPORT_SYMBOL_GPL(phy_power_off); | 258 | EXPORT_SYMBOL_GPL(phy_power_off); |
253 | 259 | ||