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:
@@ -277,82 +277,6 @@ static void rtc_device_get_offset(struct rtc_device *rtc)
|
|||||||
rtc->offset_secs = 0;
|
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
|
* 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);
|
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)
|
static void devm_rtc_release_device(struct device *dev, void *res)
|
||||||
{
|
{
|
||||||
struct rtc_device *rtc = *(struct rtc_device **)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);
|
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)
|
static int __init rtc_init(void)
|
||||||
{
|
{
|
||||||
rtc_class = class_create(THIS_MODULE, "rtc");
|
rtc_class = class_create(THIS_MODULE, "rtc");
|
||||||
|
|||||||
Reference in New Issue
Block a user