diff options
Diffstat (limited to 'drivers/char/efirtc.c')
-rw-r--r-- | drivers/char/efirtc.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 49233f589874..67fbd7aab5db 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | 30 | ||
31 | #include <linux/smp_lock.h> | ||
31 | #include <linux/types.h> | 32 | #include <linux/types.h> |
32 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
33 | #include <linux/miscdevice.h> | 34 | #include <linux/miscdevice.h> |
@@ -36,8 +37,9 @@ | |||
36 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
37 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
38 | #include <linux/efi.h> | 39 | #include <linux/efi.h> |
40 | #include <linux/smp_lock.h> | ||
41 | #include <linux/uaccess.h> | ||
39 | 42 | ||
40 | #include <asm/uaccess.h> | ||
41 | #include <asm/system.h> | 43 | #include <asm/system.h> |
42 | 44 | ||
43 | #define EFI_RTC_VERSION "0.4" | 45 | #define EFI_RTC_VERSION "0.4" |
@@ -50,8 +52,8 @@ | |||
50 | 52 | ||
51 | static DEFINE_SPINLOCK(efi_rtc_lock); | 53 | static DEFINE_SPINLOCK(efi_rtc_lock); |
52 | 54 | ||
53 | static int efi_rtc_ioctl(struct inode *inode, struct file *file, | 55 | static long efi_rtc_ioctl(struct file *file, unsigned int cmd, |
54 | unsigned int cmd, unsigned long arg); | 56 | unsigned long arg); |
55 | 57 | ||
56 | #define is_leap(year) \ | 58 | #define is_leap(year) \ |
57 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | 59 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) |
@@ -145,9 +147,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | |||
145 | } | 147 | } |
146 | } | 148 | } |
147 | 149 | ||
148 | static int | 150 | static long efi_rtc_ioctl(struct file *file, unsigned int cmd, |
149 | efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 151 | unsigned long arg) |
150 | unsigned long arg) | ||
151 | { | 152 | { |
152 | 153 | ||
153 | efi_status_t status; | 154 | efi_status_t status; |
@@ -174,13 +175,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
174 | return -EINVAL; | 175 | return -EINVAL; |
175 | 176 | ||
176 | case RTC_RD_TIME: | 177 | case RTC_RD_TIME: |
177 | 178 | lock_kernel(); | |
178 | spin_lock_irqsave(&efi_rtc_lock, flags); | 179 | spin_lock_irqsave(&efi_rtc_lock, flags); |
179 | 180 | ||
180 | status = efi.get_time(&eft, &cap); | 181 | status = efi.get_time(&eft, &cap); |
181 | 182 | ||
182 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 183 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
183 | 184 | unlock_kernel(); | |
184 | if (status != EFI_SUCCESS) { | 185 | if (status != EFI_SUCCESS) { |
185 | /* should never happen */ | 186 | /* should never happen */ |
186 | printk(KERN_ERR "efitime: can't read time\n"); | 187 | printk(KERN_ERR "efitime: can't read time\n"); |
@@ -202,11 +203,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
202 | 203 | ||
203 | convert_to_efi_time(&wtime, &eft); | 204 | convert_to_efi_time(&wtime, &eft); |
204 | 205 | ||
206 | lock_kernel(); | ||
205 | spin_lock_irqsave(&efi_rtc_lock, flags); | 207 | spin_lock_irqsave(&efi_rtc_lock, flags); |
206 | 208 | ||
207 | status = efi.set_time(&eft); | 209 | status = efi.set_time(&eft); |
208 | 210 | ||
209 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 211 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
212 | unlock_kernel(); | ||
210 | 213 | ||
211 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 214 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
212 | 215 | ||
@@ -222,6 +225,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
222 | 225 | ||
223 | convert_to_efi_time(&wtime, &eft); | 226 | convert_to_efi_time(&wtime, &eft); |
224 | 227 | ||
228 | lock_kernel(); | ||
225 | spin_lock_irqsave(&efi_rtc_lock, flags); | 229 | spin_lock_irqsave(&efi_rtc_lock, flags); |
226 | /* | 230 | /* |
227 | * XXX Fixme: | 231 | * XXX Fixme: |
@@ -232,16 +236,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
232 | status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); | 236 | status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); |
233 | 237 | ||
234 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 238 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
239 | unlock_kernel(); | ||
235 | 240 | ||
236 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 241 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
237 | 242 | ||
238 | case RTC_WKALM_RD: | 243 | case RTC_WKALM_RD: |
239 | 244 | ||
245 | lock_kernel(); | ||
240 | spin_lock_irqsave(&efi_rtc_lock, flags); | 246 | spin_lock_irqsave(&efi_rtc_lock, flags); |
241 | 247 | ||
242 | status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); | 248 | status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); |
243 | 249 | ||
244 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 250 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
251 | unlock_kernel(); | ||
245 | 252 | ||
246 | if (status != EFI_SUCCESS) return -EINVAL; | 253 | if (status != EFI_SUCCESS) return -EINVAL; |
247 | 254 | ||
@@ -255,7 +262,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
255 | return copy_to_user(&ewp->time, &wtime, | 262 | return copy_to_user(&ewp->time, &wtime, |
256 | sizeof(struct rtc_time)) ? -EFAULT : 0; | 263 | sizeof(struct rtc_time)) ? -EFAULT : 0; |
257 | } | 264 | } |
258 | return -EINVAL; | 265 | return -ENOTTY; |
259 | } | 266 | } |
260 | 267 | ||
261 | /* | 268 | /* |
@@ -264,19 +271,18 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
264 | * up things on a close. | 271 | * up things on a close. |
265 | */ | 272 | */ |
266 | 273 | ||
267 | static int | 274 | static int efi_rtc_open(struct inode *inode, struct file *file) |
268 | efi_rtc_open(struct inode *inode, struct file *file) | ||
269 | { | 275 | { |
270 | /* | 276 | /* |
271 | * nothing special to do here | 277 | * nothing special to do here |
272 | * We do accept multiple open files at the same time as we | 278 | * We do accept multiple open files at the same time as we |
273 | * synchronize on the per call operation. | 279 | * synchronize on the per call operation. |
274 | */ | 280 | */ |
281 | cycle_kernel_lock(); | ||
275 | return 0; | 282 | return 0; |
276 | } | 283 | } |
277 | 284 | ||
278 | static int | 285 | static int efi_rtc_close(struct inode *inode, struct file *file) |
279 | efi_rtc_close(struct inode *inode, struct file *file) | ||
280 | { | 286 | { |
281 | return 0; | 287 | return 0; |
282 | } | 288 | } |
@@ -287,13 +293,12 @@ efi_rtc_close(struct inode *inode, struct file *file) | |||
287 | 293 | ||
288 | static const struct file_operations efi_rtc_fops = { | 294 | static const struct file_operations efi_rtc_fops = { |
289 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
290 | .ioctl = efi_rtc_ioctl, | 296 | .unlocked_ioctl = efi_rtc_ioctl, |
291 | .open = efi_rtc_open, | 297 | .open = efi_rtc_open, |
292 | .release = efi_rtc_close, | 298 | .release = efi_rtc_close, |
293 | }; | 299 | }; |
294 | 300 | ||
295 | static struct miscdevice efi_rtc_dev= | 301 | static struct miscdevice efi_rtc_dev= { |
296 | { | ||
297 | EFI_RTC_MINOR, | 302 | EFI_RTC_MINOR, |
298 | "efirtc", | 303 | "efirtc", |
299 | &efi_rtc_fops | 304 | &efi_rtc_fops |