forked from Minki/linux
rtc: class: reimplement devm_rtc_device_register
Implement devm_rtc_device_register using devm_rtc_allocate_device and __rtc_register_device so there is only one path left to register rtc devices. Also mark it as deprecated so new drivers will hopefully use devm_rtc_allocate_device and rtc_register_device that are less race prone and allow avoiding the 2038, 2070, 2100 and 2106 bugs properly. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
parent
9a03201170
commit
a269441493
@ -277,82 +277,6 @@ static void rtc_device_get_offset(struct rtc_device *rtc)
|
||||
rtc->offset_secs = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtc_device_register - register w/ RTC class
|
||||
* @dev: the device to register
|
||||
*
|
||||
* rtc_device_unregister() must be called when the class device is no
|
||||
* longer needed.
|
||||
*
|
||||
* Returns the pointer to the new struct class device.
|
||||
*/
|
||||
static struct rtc_device *rtc_device_register(const char *name,
|
||||
struct device *dev,
|
||||
const struct rtc_class_ops *ops,
|
||||
struct module *owner)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
struct rtc_wkalrm alrm;
|
||||
int id, err;
|
||||
|
||||
id = rtc_device_get_id(dev);
|
||||
if (id < 0) {
|
||||
err = id;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rtc = rtc_allocate_device();
|
||||
if (!rtc) {
|
||||
err = -ENOMEM;
|
||||
goto exit_ida;
|
||||
}
|
||||
|
||||
rtc->id = id;
|
||||
rtc->ops = ops;
|
||||
rtc->owner = owner;
|
||||
rtc->dev.parent = dev;
|
||||
|
||||
dev_set_name(&rtc->dev, "rtc%d", id);
|
||||
|
||||
rtc_device_get_offset(rtc);
|
||||
|
||||
/* Check to see if there is an ALARM already set in hw */
|
||||
err = __rtc_read_alarm(rtc, &alrm);
|
||||
|
||||
if (!err && !rtc_valid_tm(&alrm.time))
|
||||
rtc_initialize_alarm(rtc, &alrm);
|
||||
|
||||
rtc_dev_prepare(rtc);
|
||||
|
||||
err = cdev_device_add(&rtc->char_dev, &rtc->dev);
|
||||
if (err) {
|
||||
dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
|
||||
name, MAJOR(rtc->dev.devt), rtc->id);
|
||||
|
||||
/* This will free both memory and the ID */
|
||||
put_device(&rtc->dev);
|
||||
goto exit;
|
||||
} else {
|
||||
dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", name,
|
||||
MAJOR(rtc->dev.devt), rtc->id);
|
||||
}
|
||||
|
||||
rtc_proc_add_device(rtc);
|
||||
|
||||
dev_info(dev, "rtc core: registered %s as %s\n",
|
||||
name, dev_name(&rtc->dev));
|
||||
|
||||
return rtc;
|
||||
|
||||
exit_ida:
|
||||
ida_simple_remove(&rtc_ida, id);
|
||||
|
||||
exit:
|
||||
dev_err(dev, "rtc core: unable to register %s, err = %d\n",
|
||||
name, err);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* rtc_device_unregister - removes the previously registered RTC class device
|
||||
*
|
||||
@ -372,51 +296,6 @@ static void rtc_device_unregister(struct rtc_device *rtc)
|
||||
put_device(&rtc->dev);
|
||||
}
|
||||
|
||||
static void devm_rtc_device_release(struct device *dev, void *res)
|
||||
{
|
||||
struct rtc_device *rtc = *(struct rtc_device **)res;
|
||||
|
||||
rtc_nvmem_unregister(rtc);
|
||||
rtc_device_unregister(rtc);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_rtc_device_register - resource managed rtc_device_register()
|
||||
* @dev: the device to register
|
||||
* @name: the name of the device
|
||||
* @ops: the rtc operations structure
|
||||
* @owner: the module owner
|
||||
*
|
||||
* @return a struct rtc on success, or an ERR_PTR on error
|
||||
*
|
||||
* Managed rtc_device_register(). The rtc_device returned from this function
|
||||
* are automatically freed on driver detach. See rtc_device_register()
|
||||
* for more information.
|
||||
*/
|
||||
|
||||
struct rtc_device *devm_rtc_device_register(struct device *dev,
|
||||
const char *name,
|
||||
const struct rtc_class_ops *ops,
|
||||
struct module *owner)
|
||||
{
|
||||
struct rtc_device **ptr, *rtc;
|
||||
|
||||
ptr = devres_alloc(devm_rtc_device_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rtc = rtc_device_register(name, dev, ops, owner);
|
||||
if (!IS_ERR(rtc)) {
|
||||
*ptr = rtc;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
}
|
||||
|
||||
return rtc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_rtc_device_register);
|
||||
|
||||
static void devm_rtc_release_device(struct device *dev, void *res)
|
||||
{
|
||||
struct rtc_device *rtc = *(struct rtc_device **)res;
|
||||
@ -503,6 +382,42 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__rtc_register_device);
|
||||
|
||||
/**
|
||||
* devm_rtc_device_register - resource managed rtc_device_register()
|
||||
* @dev: the device to register
|
||||
* @name: the name of the device (unused)
|
||||
* @ops: the rtc operations structure
|
||||
* @owner: the module owner
|
||||
*
|
||||
* @return a struct rtc on success, or an ERR_PTR on error
|
||||
*
|
||||
* Managed rtc_device_register(). The rtc_device returned from this function
|
||||
* are automatically freed on driver detach.
|
||||
* This function is deprecated, use devm_rtc_allocate_device and
|
||||
* rtc_register_device instead
|
||||
*/
|
||||
struct rtc_device *devm_rtc_device_register(struct device *dev,
|
||||
const char *name,
|
||||
const struct rtc_class_ops *ops,
|
||||
struct module *owner)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
int err;
|
||||
|
||||
rtc = devm_rtc_allocate_device(dev);
|
||||
if (IS_ERR(rtc))
|
||||
return rtc;
|
||||
|
||||
rtc->ops = ops;
|
||||
|
||||
err = __rtc_register_device(owner, rtc);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
return rtc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_rtc_device_register);
|
||||
|
||||
static int __init rtc_init(void)
|
||||
{
|
||||
rtc_class = class_create(THIS_MODULE, "rtc");
|
||||
|
Loading…
Reference in New Issue
Block a user