aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/class.c
diff options
context:
space:
mode:
authorLogan Gunthorpe <logang@deltatee.com>2017-03-17 14:48:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-21 01:44:33 -0400
commitd5ed9177f64fe95d9de79e6504d41612d9127e8a (patch)
tree4381e84b391db399b9e986582fc81aadf5bee6e9 /drivers/rtc/class.c
parentdbef390d2eb0a7b0a6be21381a326d4e13953aba (diff)
rtc: utilize new cdev_device_add helper function
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>
Diffstat (limited to 'drivers/rtc/class.c')
-rw-r--r--drivers/rtc/class.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 74fd9746aeca..5fb439897fe1 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -195,6 +195,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
195 goto exit_ida; 195 goto exit_ida;
196 } 196 }
197 197
198 device_initialize(&rtc->dev);
199
198 rtc->id = id; 200 rtc->id = id;
199 rtc->ops = ops; 201 rtc->ops = ops;
200 rtc->owner = owner; 202 rtc->owner = owner;
@@ -233,14 +235,19 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
233 235
234 rtc_dev_prepare(rtc); 236 rtc_dev_prepare(rtc);
235 237
236 err = device_register(&rtc->dev); 238 err = cdev_device_add(&rtc->char_dev, &rtc->dev);
237 if (err) { 239 if (err) {
240 dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
241 rtc->name, MAJOR(rtc->dev.devt), rtc->id);
242
238 /* This will free both memory and the ID */ 243 /* This will free both memory and the ID */
239 put_device(&rtc->dev); 244 put_device(&rtc->dev);
240 goto exit; 245 goto exit;
246 } else {
247 dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name,
248 MAJOR(rtc->dev.devt), rtc->id);
241 } 249 }
242 250
243 rtc_dev_add_device(rtc);
244 rtc_proc_add_device(rtc); 251 rtc_proc_add_device(rtc);
245 252
246 dev_info(dev, "rtc core: registered %s as %s\n", 253 dev_info(dev, "rtc core: registered %s as %s\n",
@@ -271,9 +278,8 @@ void rtc_device_unregister(struct rtc_device *rtc)
271 * Remove innards of this RTC, then disable it, before 278 * Remove innards of this RTC, then disable it, before
272 * letting any rtc_class_open() users access it again 279 * letting any rtc_class_open() users access it again
273 */ 280 */
274 rtc_dev_del_device(rtc);
275 rtc_proc_del_device(rtc); 281 rtc_proc_del_device(rtc);
276 device_del(&rtc->dev); 282 cdev_device_del(&rtc->char_dev, &rtc->dev);
277 rtc->ops = NULL; 283 rtc->ops = NULL;
278 mutex_unlock(&rtc->ops_lock); 284 mutex_unlock(&rtc->ops_lock);
279 put_device(&rtc->dev); 285 put_device(&rtc->dev);