rtc: utilize new cdev_device_add helper function
authorLogan Gunthorpe <logang@deltatee.com>
Fri, 17 Mar 2017 18:48:21 +0000 (12:48 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Mar 2017 05:44:33 +0000 (06:44 +0100)
Mostly straightforward, but we had to remove the rtc_dev_add/del_device
functions as they split up the cdev_add and the device_add.

Doing this also revealed that there was likely another subtle bug:
seeing cdev_add was done after device_register, the cdev probably
was not ready before device_add when the uevent occurs. This would
race with userspace, if it tried to use the device directly after
the uevent. This is fixed just by using the new helper function.

Another weird thing is this driver would, in some error cases, call
cdev_add() without calling cdev_init. This patchset corrects this
by avoiding calling cdev_add if the devt is not set.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/rtc/class.c
drivers/rtc/rtc-core.h
drivers/rtc/rtc-dev.c

index 74fd9746aecad52cd40c7159008a274d9364fa47..5fb439897fe1acb707a8629ffdc788a59e80d544 100644 (file)
@@ -195,6 +195,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
                goto exit_ida;
        }
 
+       device_initialize(&rtc->dev);
+
        rtc->id = id;
        rtc->ops = ops;
        rtc->owner = owner;
@@ -233,14 +235,19 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 
        rtc_dev_prepare(rtc);
 
-       err = device_register(&rtc->dev);
+       err = cdev_device_add(&rtc->char_dev, &rtc->dev);
        if (err) {
+               dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
+                        rtc->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", rtc->name,
+                       MAJOR(rtc->dev.devt), rtc->id);
        }
 
-       rtc_dev_add_device(rtc);
        rtc_proc_add_device(rtc);
 
        dev_info(dev, "rtc core: registered %s as %s\n",
@@ -271,9 +278,8 @@ void rtc_device_unregister(struct rtc_device *rtc)
         * Remove innards of this RTC, then disable it, before
         * letting any rtc_class_open() users access it again
         */
-       rtc_dev_del_device(rtc);
        rtc_proc_del_device(rtc);
-       device_del(&rtc->dev);
+       cdev_device_del(&rtc->char_dev, &rtc->dev);
        rtc->ops = NULL;
        mutex_unlock(&rtc->ops_lock);
        put_device(&rtc->dev);
index a098aea197fc72dad6b0e1819c2ab739cb7dd042..7a4ed2f7c7d7dfcd531654d355d8ef4c23b082c5 100644 (file)
@@ -3,8 +3,6 @@
 extern void __init rtc_dev_init(void);
 extern void __exit rtc_dev_exit(void);
 extern void rtc_dev_prepare(struct rtc_device *rtc);
-extern void rtc_dev_add_device(struct rtc_device *rtc);
-extern void rtc_dev_del_device(struct rtc_device *rtc);
 
 #else
 
@@ -20,14 +18,6 @@ static inline void rtc_dev_prepare(struct rtc_device *rtc)
 {
 }
 
-static inline void rtc_dev_add_device(struct rtc_device *rtc)
-{
-}
-
-static inline void rtc_dev_del_device(struct rtc_device *rtc)
-{
-}
-
 #endif
 
 #ifdef CONFIG_RTC_INTF_PROC
index 6dc8f29697abfe708490005bfcb30bb291c6ef2b..e81a8711fea741b2c347f9655b2fd158db093f7d 100644 (file)
@@ -477,23 +477,6 @@ void rtc_dev_prepare(struct rtc_device *rtc)
 
        cdev_init(&rtc->char_dev, &rtc_dev_fops);
        rtc->char_dev.owner = rtc->owner;
-       rtc->char_dev.kobj.parent = &rtc->dev.kobj;
-}
-
-void rtc_dev_add_device(struct rtc_device *rtc)
-{
-       if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1))
-               dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
-                       rtc->name, MAJOR(rtc_devt), rtc->id);
-       else
-               dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name,
-                       MAJOR(rtc_devt), rtc->id);
-}
-
-void rtc_dev_del_device(struct rtc_device *rtc)
-{
-       if (rtc->dev.devt)
-               cdev_del(&rtc->char_dev);
 }
 
 void __init rtc_dev_init(void)