summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/rtc/class.c14
-rw-r--r--drivers/rtc/rtc-core.h10
-rw-r--r--drivers/rtc/rtc-dev.c17
3 files changed, 10 insertions, 31 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);
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
index a098aea197fc..7a4ed2f7c7d7 100644
--- a/drivers/rtc/rtc-core.h
+++ b/drivers/rtc/rtc-core.h
@@ -3,8 +3,6 @@
3extern void __init rtc_dev_init(void); 3extern void __init rtc_dev_init(void);
4extern void __exit rtc_dev_exit(void); 4extern void __exit rtc_dev_exit(void);
5extern void rtc_dev_prepare(struct rtc_device *rtc); 5extern void rtc_dev_prepare(struct rtc_device *rtc);
6extern void rtc_dev_add_device(struct rtc_device *rtc);
7extern void rtc_dev_del_device(struct rtc_device *rtc);
8 6
9#else 7#else
10 8
@@ -20,14 +18,6 @@ static inline void rtc_dev_prepare(struct rtc_device *rtc)
20{ 18{
21} 19}
22 20
23static inline void rtc_dev_add_device(struct rtc_device *rtc)
24{
25}
26
27static inline void rtc_dev_del_device(struct rtc_device *rtc)
28{
29}
30
31#endif 21#endif
32 22
33#ifdef CONFIG_RTC_INTF_PROC 23#ifdef CONFIG_RTC_INTF_PROC
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 6dc8f29697ab..e81a8711fea7 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -477,23 +477,6 @@ void rtc_dev_prepare(struct rtc_device *rtc)
477 477
478 cdev_init(&rtc->char_dev, &rtc_dev_fops); 478 cdev_init(&rtc->char_dev, &rtc_dev_fops);
479 rtc->char_dev.owner = rtc->owner; 479 rtc->char_dev.owner = rtc->owner;
480 rtc->char_dev.kobj.parent = &rtc->dev.kobj;
481}
482
483void rtc_dev_add_device(struct rtc_device *rtc)
484{
485 if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1))
486 dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
487 rtc->name, MAJOR(rtc_devt), rtc->id);
488 else
489 dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name,
490 MAJOR(rtc_devt), rtc->id);
491}
492
493void rtc_dev_del_device(struct rtc_device *rtc)
494{
495 if (rtc->dev.devt)
496 cdev_del(&rtc->char_dev);
497} 480}
498 481
499void __init rtc_dev_init(void) 482void __init rtc_dev_init(void)