diff options
-rw-r--r-- | Documentation/phy.txt | 6 | ||||
-rw-r--r-- | drivers/phy/phy-core.c | 17 |
2 files changed, 22 insertions, 1 deletions
diff --git a/Documentation/phy.txt b/Documentation/phy.txt index 0103e4b15b0e..2e24b993e95f 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt | |||
@@ -84,6 +84,12 @@ The only difference between the two APIs is that devm_phy_get associates the | |||
84 | device with the PHY using devres on successful PHY get. On driver detach, | 84 | device with the PHY using devres on successful PHY get. On driver detach, |
85 | release function is invoked on the the devres data and devres data is freed. | 85 | release function is invoked on the the devres data and devres data is freed. |
86 | 86 | ||
87 | It should be noted that NULL is a valid phy reference. All phy | ||
88 | consumer calls on the NULL phy become NOPs. That is the release calls, | ||
89 | the phy_init() and phy_exit() calls, and phy_power_on() and | ||
90 | phy_power_off() calls are all NOP when applied to a NULL phy. The NULL | ||
91 | phy is useful in devices for handling optional phy devices. | ||
92 | |||
87 | 5. Releasing a reference to the PHY | 93 | 5. Releasing a reference to the PHY |
88 | 94 | ||
89 | When the controller no longer needs the PHY, it has to release the reference | 95 | When the controller no longer needs the PHY, it has to release the reference |
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 645c867c1257..a9cdeee20d91 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -162,6 +162,9 @@ int phy_init(struct phy *phy) | |||
162 | { | 162 | { |
163 | int ret; | 163 | int ret; |
164 | 164 | ||
165 | if (!phy) | ||
166 | return 0; | ||
167 | |||
165 | ret = phy_pm_runtime_get_sync(phy); | 168 | ret = phy_pm_runtime_get_sync(phy); |
166 | if (ret < 0 && ret != -ENOTSUPP) | 169 | if (ret < 0 && ret != -ENOTSUPP) |
167 | return ret; | 170 | return ret; |
@@ -187,6 +190,9 @@ int phy_exit(struct phy *phy) | |||
187 | { | 190 | { |
188 | int ret; | 191 | int ret; |
189 | 192 | ||
193 | if (!phy) | ||
194 | return 0; | ||
195 | |||
190 | ret = phy_pm_runtime_get_sync(phy); | 196 | ret = phy_pm_runtime_get_sync(phy); |
191 | if (ret < 0 && ret != -ENOTSUPP) | 197 | if (ret < 0 && ret != -ENOTSUPP) |
192 | return ret; | 198 | return ret; |
@@ -212,6 +218,9 @@ int phy_power_on(struct phy *phy) | |||
212 | { | 218 | { |
213 | int ret; | 219 | int ret; |
214 | 220 | ||
221 | if (!phy) | ||
222 | return 0; | ||
223 | |||
215 | ret = phy_pm_runtime_get_sync(phy); | 224 | ret = phy_pm_runtime_get_sync(phy); |
216 | if (ret < 0 && ret != -ENOTSUPP) | 225 | if (ret < 0 && ret != -ENOTSUPP) |
217 | return ret; | 226 | return ret; |
@@ -240,6 +249,9 @@ int phy_power_off(struct phy *phy) | |||
240 | { | 249 | { |
241 | int ret; | 250 | int ret; |
242 | 251 | ||
252 | if (!phy) | ||
253 | return 0; | ||
254 | |||
243 | mutex_lock(&phy->mutex); | 255 | mutex_lock(&phy->mutex); |
244 | if (phy->power_count == 1 && phy->ops->power_off) { | 256 | if (phy->power_count == 1 && phy->ops->power_off) { |
245 | ret = phy->ops->power_off(phy); | 257 | ret = phy->ops->power_off(phy); |
@@ -308,7 +320,7 @@ err0: | |||
308 | */ | 320 | */ |
309 | void phy_put(struct phy *phy) | 321 | void phy_put(struct phy *phy) |
310 | { | 322 | { |
311 | if (IS_ERR(phy)) | 323 | if (!phy || IS_ERR(phy)) |
312 | return; | 324 | return; |
313 | 325 | ||
314 | module_put(phy->ops->owner); | 326 | module_put(phy->ops->owner); |
@@ -328,6 +340,9 @@ void devm_phy_put(struct device *dev, struct phy *phy) | |||
328 | { | 340 | { |
329 | int r; | 341 | int r; |
330 | 342 | ||
343 | if (!phy) | ||
344 | return; | ||
345 | |||
331 | r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); | 346 | r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); |
332 | dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); | 347 | dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); |
333 | } | 348 | } |