diff options
| author | Jingoo Han <jg1.han@samsung.com> | 2013-04-29 19:18:27 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 21:28:21 -0400 |
| commit | 3e217b660281bbdf2db7e58725a4934b5635cb46 (patch) | |
| tree | b9e9d6d2cb27e947d2fe3f56c7b04685b7311d68 | |
| parent | 51b38c62aa89c8747c350dac2515b8899ff8f4d7 (diff) | |
rtc: add devm_rtc_device_{register,unregister}()
These functions allow the driver core to automatically clean up any
allocation made by rtc drivers. Thus it simplifies the error paths.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/rtc/class.c | 70 | ||||
| -rw-r--r-- | include/linux/rtc.h | 6 |
2 files changed, 76 insertions, 0 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 9b742d3ffb94..b72b40bd7805 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -259,6 +259,76 @@ void rtc_device_unregister(struct rtc_device *rtc) | |||
| 259 | } | 259 | } |
| 260 | EXPORT_SYMBOL_GPL(rtc_device_unregister); | 260 | EXPORT_SYMBOL_GPL(rtc_device_unregister); |
| 261 | 261 | ||
| 262 | static void devm_rtc_device_release(struct device *dev, void *res) | ||
| 263 | { | ||
| 264 | struct rtc_device *rtc = *(struct rtc_device **)res; | ||
| 265 | |||
| 266 | rtc_device_unregister(rtc); | ||
| 267 | } | ||
| 268 | |||
| 269 | static int devm_rtc_device_match(struct device *dev, void *res, void *data) | ||
| 270 | { | ||
| 271 | struct rtc **r = res; | ||
| 272 | |||
| 273 | return *r == data; | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * devm_rtc_device_register - resource managed rtc_device_register() | ||
| 278 | * @name: the name of the device | ||
| 279 | * @dev: the device to register | ||
| 280 | * @ops: the rtc operations structure | ||
| 281 | * @owner: the module owner | ||
| 282 | * | ||
| 283 | * @return a struct rtc on success, or an ERR_PTR on error | ||
| 284 | * | ||
| 285 | * Managed rtc_device_register(). The rtc_device returned from this function | ||
| 286 | * are automatically freed on driver detach. See rtc_device_register() | ||
| 287 | * for more information. | ||
| 288 | */ | ||
| 289 | |||
| 290 | struct rtc_device *devm_rtc_device_register(const char *name, | ||
| 291 | struct device *dev, | ||
| 292 | const struct rtc_class_ops *ops, | ||
| 293 | struct module *owner) | ||
| 294 | { | ||
| 295 | struct rtc_device **ptr, *rtc; | ||
| 296 | |||
| 297 | ptr = devres_alloc(devm_rtc_device_release, sizeof(*ptr), GFP_KERNEL); | ||
| 298 | if (!ptr) | ||
| 299 | return ERR_PTR(-ENOMEM); | ||
| 300 | |||
| 301 | rtc = rtc_device_register(name, dev, ops, owner); | ||
| 302 | if (!IS_ERR(rtc)) { | ||
| 303 | *ptr = rtc; | ||
| 304 | devres_add(dev, ptr); | ||
| 305 | } else { | ||
| 306 | devres_free(ptr); | ||
| 307 | } | ||
| 308 | |||
| 309 | return rtc; | ||
| 310 | } | ||
| 311 | EXPORT_SYMBOL_GPL(devm_rtc_device_register); | ||
| 312 | |||
| 313 | /** | ||
| 314 | * devm_rtc_device_unregister - resource managed devm_rtc_device_unregister() | ||
| 315 | * @dev: the device to unregister | ||
| 316 | * @rtc: the RTC class device to unregister | ||
| 317 | * | ||
| 318 | * Deallocated a rtc allocated with devm_rtc_device_register(). Normally this | ||
| 319 | * function will not need to be called and the resource management code will | ||
| 320 | * ensure that the resource is freed. | ||
| 321 | */ | ||
| 322 | void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc) | ||
| 323 | { | ||
| 324 | int rc; | ||
| 325 | |||
| 326 | rc = devres_release(dev, devm_rtc_device_release, | ||
| 327 | devm_rtc_device_match, rtc); | ||
| 328 | WARN_ON(rc); | ||
| 329 | } | ||
| 330 | EXPORT_SYMBOL_GPL(devm_rtc_device_unregister); | ||
| 331 | |||
| 262 | static int __init rtc_init(void) | 332 | static int __init rtc_init(void) |
| 263 | { | 333 | { |
| 264 | rtc_class = class_create(THIS_MODULE, "rtc"); | 334 | rtc_class = class_create(THIS_MODULE, "rtc"); |
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 580b24c8b8ca..d9557689bb8d 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h | |||
| @@ -133,7 +133,13 @@ extern struct rtc_device *rtc_device_register(const char *name, | |||
| 133 | struct device *dev, | 133 | struct device *dev, |
| 134 | const struct rtc_class_ops *ops, | 134 | const struct rtc_class_ops *ops, |
| 135 | struct module *owner); | 135 | struct module *owner); |
| 136 | extern struct rtc_device *devm_rtc_device_register(const char *name, | ||
| 137 | struct device *dev, | ||
| 138 | const struct rtc_class_ops *ops, | ||
| 139 | struct module *owner); | ||
| 136 | extern void rtc_device_unregister(struct rtc_device *rtc); | 140 | extern void rtc_device_unregister(struct rtc_device *rtc); |
| 141 | extern void devm_rtc_device_unregister(struct device *dev, | ||
| 142 | struct rtc_device *rtc); | ||
| 137 | 143 | ||
| 138 | extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); | 144 | extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); |
| 139 | extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); | 145 | extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); |
