aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-dev.c58
1 files changed, 38 insertions, 20 deletions
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 0114a78b7cbb..0a870b7e5c32 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -209,7 +209,7 @@ static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
209 return (data != 0) ? (POLLIN | POLLRDNORM) : 0; 209 return (data != 0) ? (POLLIN | POLLRDNORM) : 0;
210} 210}
211 211
212static int rtc_dev_ioctl(struct inode *inode, struct file *file, 212static long rtc_dev_ioctl(struct file *file,
213 unsigned int cmd, unsigned long arg) 213 unsigned int cmd, unsigned long arg)
214{ 214{
215 int err = 0; 215 int err = 0;
@@ -219,6 +219,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
219 struct rtc_wkalrm alarm; 219 struct rtc_wkalrm alarm;
220 void __user *uarg = (void __user *) arg; 220 void __user *uarg = (void __user *) arg;
221 221
222 err = mutex_lock_interruptible(&rtc->ops_lock);
223 if (err)
224 return -EBUSY;
225
222 /* check that the calling task has appropriate permissions 226 /* check that the calling task has appropriate permissions
223 * for certain ioctls. doing this check here is useful 227 * for certain ioctls. doing this check here is useful
224 * to avoid duplicate code in each driver. 228 * to avoid duplicate code in each driver.
@@ -227,26 +231,31 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
227 case RTC_EPOCH_SET: 231 case RTC_EPOCH_SET:
228 case RTC_SET_TIME: 232 case RTC_SET_TIME:
229 if (!capable(CAP_SYS_TIME)) 233 if (!capable(CAP_SYS_TIME))
230 return -EACCES; 234 err = -EACCES;
231 break; 235 break;
232 236
233 case RTC_IRQP_SET: 237 case RTC_IRQP_SET:
234 if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) 238 if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
235 return -EACCES; 239 err = -EACCES;
236 break; 240 break;
237 241
238 case RTC_PIE_ON: 242 case RTC_PIE_ON:
239 if (rtc->irq_freq > rtc->max_user_freq && 243 if (rtc->irq_freq > rtc->max_user_freq &&
240 !capable(CAP_SYS_RESOURCE)) 244 !capable(CAP_SYS_RESOURCE))
241 return -EACCES; 245 err = -EACCES;
242 break; 246 break;
243 } 247 }
244 248
249 if (err)
250 goto done;
251
245 /* try the driver's ioctl interface */ 252 /* try the driver's ioctl interface */
246 if (ops->ioctl) { 253 if (ops->ioctl) {
247 err = ops->ioctl(rtc->dev.parent, cmd, arg); 254 err = ops->ioctl(rtc->dev.parent, cmd, arg);
248 if (err != -ENOIOCTLCMD) 255 if (err != -ENOIOCTLCMD) {
256 mutex_unlock(&rtc->ops_lock);
249 return err; 257 return err;
258 }
250 } 259 }
251 260
252 /* if the driver does not provide the ioctl interface 261 /* if the driver does not provide the ioctl interface
@@ -265,15 +274,19 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
265 274
266 switch (cmd) { 275 switch (cmd) {
267 case RTC_ALM_READ: 276 case RTC_ALM_READ:
277 mutex_unlock(&rtc->ops_lock);
278
268 err = rtc_read_alarm(rtc, &alarm); 279 err = rtc_read_alarm(rtc, &alarm);
269 if (err < 0) 280 if (err < 0)
270 return err; 281 return err;
271 282
272 if (copy_to_user(uarg, &alarm.time, sizeof(tm))) 283 if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
273 return -EFAULT; 284 err = -EFAULT;
274 break; 285 return err;
275 286
276 case RTC_ALM_SET: 287 case RTC_ALM_SET:
288 mutex_unlock(&rtc->ops_lock);
289
277 if (copy_from_user(&alarm.time, uarg, sizeof(tm))) 290 if (copy_from_user(&alarm.time, uarg, sizeof(tm)))
278 return -EFAULT; 291 return -EFAULT;
279 292
@@ -321,24 +334,26 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
321 } 334 }
322 } 335 }
323 336
324 err = rtc_set_alarm(rtc, &alarm); 337 return rtc_set_alarm(rtc, &alarm);
325 break;
326 338
327 case RTC_RD_TIME: 339 case RTC_RD_TIME:
340 mutex_unlock(&rtc->ops_lock);
341
328 err = rtc_read_time(rtc, &tm); 342 err = rtc_read_time(rtc, &tm);
329 if (err < 0) 343 if (err < 0)
330 return err; 344 return err;
331 345
332 if (copy_to_user(uarg, &tm, sizeof(tm))) 346 if (copy_to_user(uarg, &tm, sizeof(tm)))
333 return -EFAULT; 347 err = -EFAULT;
334 break; 348 return err;
335 349
336 case RTC_SET_TIME: 350 case RTC_SET_TIME:
351 mutex_unlock(&rtc->ops_lock);
352
337 if (copy_from_user(&tm, uarg, sizeof(tm))) 353 if (copy_from_user(&tm, uarg, sizeof(tm)))
338 return -EFAULT; 354 return -EFAULT;
339 355
340 err = rtc_set_time(rtc, &tm); 356 return rtc_set_time(rtc, &tm);
341 break;
342 357
343 case RTC_PIE_ON: 358 case RTC_PIE_ON:
344 err = rtc_irq_set_state(rtc, NULL, 1); 359 err = rtc_irq_set_state(rtc, NULL, 1);
@@ -376,34 +391,37 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
376 break; 391 break;
377#endif 392#endif
378 case RTC_WKALM_SET: 393 case RTC_WKALM_SET:
394 mutex_unlock(&rtc->ops_lock);
379 if (copy_from_user(&alarm, uarg, sizeof(alarm))) 395 if (copy_from_user(&alarm, uarg, sizeof(alarm)))
380 return -EFAULT; 396 return -EFAULT;
381 397
382 err = rtc_set_alarm(rtc, &alarm); 398 return rtc_set_alarm(rtc, &alarm);
383 break;
384 399
385 case RTC_WKALM_RD: 400 case RTC_WKALM_RD:
401 mutex_unlock(&rtc->ops_lock);
386 err = rtc_read_alarm(rtc, &alarm); 402 err = rtc_read_alarm(rtc, &alarm);
387 if (err < 0) 403 if (err < 0)
388 return err; 404 return err;
389 405
390 if (copy_to_user(uarg, &alarm, sizeof(alarm))) 406 if (copy_to_user(uarg, &alarm, sizeof(alarm)))
391 return -EFAULT; 407 err = -EFAULT;
392 break; 408 return err;
393 409
394#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 410#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
395 case RTC_UIE_OFF: 411 case RTC_UIE_OFF:
396 clear_uie(rtc); 412 clear_uie(rtc);
397 return 0; 413 break;
398 414
399 case RTC_UIE_ON: 415 case RTC_UIE_ON:
400 return set_uie(rtc); 416 err = set_uie(rtc);
401#endif 417#endif
402 default: 418 default:
403 err = -ENOTTY; 419 err = -ENOTTY;
404 break; 420 break;
405 } 421 }
406 422
423done:
424 mutex_unlock(&rtc->ops_lock);
407 return err; 425 return err;
408} 426}
409 427
@@ -432,7 +450,7 @@ static const struct file_operations rtc_dev_fops = {
432 .llseek = no_llseek, 450 .llseek = no_llseek,
433 .read = rtc_dev_read, 451 .read = rtc_dev_read,
434 .poll = rtc_dev_poll, 452 .poll = rtc_dev_poll,
435 .ioctl = rtc_dev_ioctl, 453 .unlocked_ioctl = rtc_dev_ioctl,
436 .open = rtc_dev_open, 454 .open = rtc_dev_open,
437 .release = rtc_dev_release, 455 .release = rtc_dev_release,
438 .fasync = rtc_dev_fasync, 456 .fasync = rtc_dev_fasync,