diff options
Diffstat (limited to 'drivers/rtc/class.c')
-rw-r--r-- | drivers/rtc/class.c | 42 |
1 files changed, 14 insertions, 28 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 01a7df5317c1..dc4c2748bbc3 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -21,16 +21,13 @@ | |||
21 | #include "rtc-core.h" | 21 | #include "rtc-core.h" |
22 | 22 | ||
23 | 23 | ||
24 | static DEFINE_IDR(rtc_idr); | 24 | static DEFINE_IDA(rtc_ida); |
25 | static DEFINE_MUTEX(idr_lock); | ||
26 | struct class *rtc_class; | 25 | struct class *rtc_class; |
27 | 26 | ||
28 | static void rtc_device_release(struct device *dev) | 27 | static void rtc_device_release(struct device *dev) |
29 | { | 28 | { |
30 | struct rtc_device *rtc = to_rtc_device(dev); | 29 | struct rtc_device *rtc = to_rtc_device(dev); |
31 | mutex_lock(&idr_lock); | 30 | ida_simple_remove(&rtc_ida, rtc->id); |
32 | idr_remove(&rtc_idr, rtc->id); | ||
33 | mutex_unlock(&idr_lock); | ||
34 | kfree(rtc); | 31 | kfree(rtc); |
35 | } | 32 | } |
36 | 33 | ||
@@ -66,7 +63,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) | |||
66 | */ | 63 | */ |
67 | delta = timespec_sub(old_system, old_rtc); | 64 | delta = timespec_sub(old_system, old_rtc); |
68 | delta_delta = timespec_sub(delta, old_delta); | 65 | delta_delta = timespec_sub(delta, old_delta); |
69 | if (abs(delta_delta.tv_sec) >= 2) { | 66 | if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { |
70 | /* | 67 | /* |
71 | * if delta_delta is too large, assume time correction | 68 | * if delta_delta is too large, assume time correction |
72 | * has occured and set old_delta to the current delta. | 69 | * has occured and set old_delta to the current delta. |
@@ -100,9 +97,8 @@ static int rtc_resume(struct device *dev) | |||
100 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); | 97 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); |
101 | new_rtc.tv_nsec = 0; | 98 | new_rtc.tv_nsec = 0; |
102 | 99 | ||
103 | if (new_rtc.tv_sec <= old_rtc.tv_sec) { | 100 | if (new_rtc.tv_sec < old_rtc.tv_sec) { |
104 | if (new_rtc.tv_sec < old_rtc.tv_sec) | 101 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); |
105 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); | ||
106 | return 0; | 102 | return 0; |
107 | } | 103 | } |
108 | 104 | ||
@@ -119,7 +115,8 @@ static int rtc_resume(struct device *dev) | |||
119 | sleep_time = timespec_sub(sleep_time, | 115 | sleep_time = timespec_sub(sleep_time, |
120 | timespec_sub(new_system, old_system)); | 116 | timespec_sub(new_system, old_system)); |
121 | 117 | ||
122 | timekeeping_inject_sleeptime(&sleep_time); | 118 | if (sleep_time.tv_sec >= 0) |
119 | timekeeping_inject_sleeptime(&sleep_time); | ||
123 | return 0; | 120 | return 0; |
124 | } | 121 | } |
125 | 122 | ||
@@ -146,25 +143,16 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
146 | struct rtc_wkalrm alrm; | 143 | struct rtc_wkalrm alrm; |
147 | int id, err; | 144 | int id, err; |
148 | 145 | ||
149 | if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { | 146 | id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); |
150 | err = -ENOMEM; | 147 | if (id < 0) { |
148 | err = id; | ||
151 | goto exit; | 149 | goto exit; |
152 | } | 150 | } |
153 | 151 | ||
154 | |||
155 | mutex_lock(&idr_lock); | ||
156 | err = idr_get_new(&rtc_idr, NULL, &id); | ||
157 | mutex_unlock(&idr_lock); | ||
158 | |||
159 | if (err < 0) | ||
160 | goto exit; | ||
161 | |||
162 | id = id & MAX_ID_MASK; | ||
163 | |||
164 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); | 152 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); |
165 | if (rtc == NULL) { | 153 | if (rtc == NULL) { |
166 | err = -ENOMEM; | 154 | err = -ENOMEM; |
167 | goto exit_idr; | 155 | goto exit_ida; |
168 | } | 156 | } |
169 | 157 | ||
170 | rtc->id = id; | 158 | rtc->id = id; |
@@ -222,10 +210,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
222 | exit_kfree: | 210 | exit_kfree: |
223 | kfree(rtc); | 211 | kfree(rtc); |
224 | 212 | ||
225 | exit_idr: | 213 | exit_ida: |
226 | mutex_lock(&idr_lock); | 214 | ida_simple_remove(&rtc_ida, id); |
227 | idr_remove(&rtc_idr, id); | ||
228 | mutex_unlock(&idr_lock); | ||
229 | 215 | ||
230 | exit: | 216 | exit: |
231 | dev_err(dev, "rtc core: unable to register %s, err = %d\n", | 217 | dev_err(dev, "rtc core: unable to register %s, err = %d\n", |
@@ -276,7 +262,7 @@ static void __exit rtc_exit(void) | |||
276 | { | 262 | { |
277 | rtc_dev_exit(); | 263 | rtc_dev_exit(); |
278 | class_destroy(rtc_class); | 264 | class_destroy(rtc_class); |
279 | idr_destroy(&rtc_idr); | 265 | ida_destroy(&rtc_ida); |
280 | } | 266 | } |
281 | 267 | ||
282 | subsys_initcall(rtc_init); | 268 | subsys_initcall(rtc_init); |