diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 18:23:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 18:23:53 -0500 |
commit | ad56cbf0fa6c09350c738ec59a3361f2e4ab4bc7 (patch) | |
tree | 35c166dcc1c29b04cea3cdf8ff9a65fcfe9bed91 | |
parent | ab0724ffee24409a7f81afb539b2ac29090bff3e (diff) | |
parent | f4e8db31a83ad019e9ae06edb9c2f89de66bc7b7 (diff) |
Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
i2c: Encourage move to dev_pm_ops by warning on use of legacy methods
i2c: Factor out runtime suspend checks from PM operations
i2c: Unregister dummy devices last on adapter removal
-rw-r--r-- | drivers/i2c/i2c-core.c | 90 |
1 files changed, 41 insertions, 49 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index c7db6980e3a3..f0bd5bcdf563 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -196,88 +196,60 @@ static int i2c_device_pm_suspend(struct device *dev) | |||
196 | { | 196 | { |
197 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 197 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
198 | 198 | ||
199 | if (pm) { | 199 | if (pm) |
200 | if (pm_runtime_suspended(dev)) | 200 | return pm_generic_suspend(dev); |
201 | return 0; | 201 | else |
202 | else | 202 | return i2c_legacy_suspend(dev, PMSG_SUSPEND); |
203 | return pm->suspend ? pm->suspend(dev) : 0; | ||
204 | } | ||
205 | |||
206 | return i2c_legacy_suspend(dev, PMSG_SUSPEND); | ||
207 | } | 203 | } |
208 | 204 | ||
209 | static int i2c_device_pm_resume(struct device *dev) | 205 | static int i2c_device_pm_resume(struct device *dev) |
210 | { | 206 | { |
211 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 207 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
212 | int ret; | ||
213 | 208 | ||
214 | if (pm) | 209 | if (pm) |
215 | ret = pm->resume ? pm->resume(dev) : 0; | 210 | return pm_generic_resume(dev); |
216 | else | 211 | else |
217 | ret = i2c_legacy_resume(dev); | 212 | return i2c_legacy_resume(dev); |
218 | |||
219 | return ret; | ||
220 | } | 213 | } |
221 | 214 | ||
222 | static int i2c_device_pm_freeze(struct device *dev) | 215 | static int i2c_device_pm_freeze(struct device *dev) |
223 | { | 216 | { |
224 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 217 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
225 | 218 | ||
226 | if (pm) { | 219 | if (pm) |
227 | if (pm_runtime_suspended(dev)) | 220 | return pm_generic_freeze(dev); |
228 | return 0; | 221 | else |
229 | else | 222 | return i2c_legacy_suspend(dev, PMSG_FREEZE); |
230 | return pm->freeze ? pm->freeze(dev) : 0; | ||
231 | } | ||
232 | |||
233 | return i2c_legacy_suspend(dev, PMSG_FREEZE); | ||
234 | } | 223 | } |
235 | 224 | ||
236 | static int i2c_device_pm_thaw(struct device *dev) | 225 | static int i2c_device_pm_thaw(struct device *dev) |
237 | { | 226 | { |
238 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 227 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
239 | 228 | ||
240 | if (pm) { | 229 | if (pm) |
241 | if (pm_runtime_suspended(dev)) | 230 | return pm_generic_thaw(dev); |
242 | return 0; | 231 | else |
243 | else | 232 | return i2c_legacy_resume(dev); |
244 | return pm->thaw ? pm->thaw(dev) : 0; | ||
245 | } | ||
246 | |||
247 | return i2c_legacy_resume(dev); | ||
248 | } | 233 | } |
249 | 234 | ||
250 | static int i2c_device_pm_poweroff(struct device *dev) | 235 | static int i2c_device_pm_poweroff(struct device *dev) |
251 | { | 236 | { |
252 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 237 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
253 | 238 | ||
254 | if (pm) { | 239 | if (pm) |
255 | if (pm_runtime_suspended(dev)) | 240 | return pm_generic_poweroff(dev); |
256 | return 0; | 241 | else |
257 | else | 242 | return i2c_legacy_suspend(dev, PMSG_HIBERNATE); |
258 | return pm->poweroff ? pm->poweroff(dev) : 0; | ||
259 | } | ||
260 | |||
261 | return i2c_legacy_suspend(dev, PMSG_HIBERNATE); | ||
262 | } | 243 | } |
263 | 244 | ||
264 | static int i2c_device_pm_restore(struct device *dev) | 245 | static int i2c_device_pm_restore(struct device *dev) |
265 | { | 246 | { |
266 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 247 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
267 | int ret; | ||
268 | 248 | ||
269 | if (pm) | 249 | if (pm) |
270 | ret = pm->restore ? pm->restore(dev) : 0; | 250 | return pm_generic_restore(dev); |
271 | else | 251 | else |
272 | ret = i2c_legacy_resume(dev); | 252 | return i2c_legacy_resume(dev); |
273 | |||
274 | if (!ret) { | ||
275 | pm_runtime_disable(dev); | ||
276 | pm_runtime_set_active(dev); | ||
277 | pm_runtime_enable(dev); | ||
278 | } | ||
279 | |||
280 | return ret; | ||
281 | } | 253 | } |
282 | #else /* !CONFIG_PM_SLEEP */ | 254 | #else /* !CONFIG_PM_SLEEP */ |
283 | #define i2c_device_pm_suspend NULL | 255 | #define i2c_device_pm_suspend NULL |
@@ -1021,6 +993,14 @@ static int i2c_do_del_adapter(struct i2c_driver *driver, | |||
1021 | static int __unregister_client(struct device *dev, void *dummy) | 993 | static int __unregister_client(struct device *dev, void *dummy) |
1022 | { | 994 | { |
1023 | struct i2c_client *client = i2c_verify_client(dev); | 995 | struct i2c_client *client = i2c_verify_client(dev); |
996 | if (client && strcmp(client->name, "dummy")) | ||
997 | i2c_unregister_device(client); | ||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | static int __unregister_dummy(struct device *dev, void *dummy) | ||
1002 | { | ||
1003 | struct i2c_client *client = i2c_verify_client(dev); | ||
1024 | if (client) | 1004 | if (client) |
1025 | i2c_unregister_device(client); | 1005 | i2c_unregister_device(client); |
1026 | return 0; | 1006 | return 0; |
@@ -1075,8 +1055,12 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
1075 | mutex_unlock(&adap->userspace_clients_lock); | 1055 | mutex_unlock(&adap->userspace_clients_lock); |
1076 | 1056 | ||
1077 | /* Detach any active clients. This can't fail, thus we do not | 1057 | /* Detach any active clients. This can't fail, thus we do not |
1078 | checking the returned value. */ | 1058 | * check the returned value. This is a two-pass process, because |
1059 | * we can't remove the dummy devices during the first pass: they | ||
1060 | * could have been instantiated by real devices wishing to clean | ||
1061 | * them up properly, so we give them a chance to do that first. */ | ||
1079 | res = device_for_each_child(&adap->dev, NULL, __unregister_client); | 1062 | res = device_for_each_child(&adap->dev, NULL, __unregister_client); |
1063 | res = device_for_each_child(&adap->dev, NULL, __unregister_dummy); | ||
1080 | 1064 | ||
1081 | #ifdef CONFIG_I2C_COMPAT | 1065 | #ifdef CONFIG_I2C_COMPAT |
1082 | class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, | 1066 | class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, |
@@ -1140,6 +1124,14 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
1140 | if (res) | 1124 | if (res) |
1141 | return res; | 1125 | return res; |
1142 | 1126 | ||
1127 | /* Drivers should switch to dev_pm_ops instead. */ | ||
1128 | if (driver->suspend) | ||
1129 | pr_warn("i2c-core: driver [%s] using legacy suspend method\n", | ||
1130 | driver->driver.name); | ||
1131 | if (driver->resume) | ||
1132 | pr_warn("i2c-core: driver [%s] using legacy resume method\n", | ||
1133 | driver->driver.name); | ||
1134 | |||
1143 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); | 1135 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); |
1144 | 1136 | ||
1145 | INIT_LIST_HEAD(&driver->clients); | 1137 | INIT_LIST_HEAD(&driver->clients); |