summaryrefslogtreecommitdiffstats
path: root/drivers/char/ppdev.c
diff options
context:
space:
mode:
authorBamvor Jian Zhang <bamvor.zhangjian@linaro.org>2016-01-08 02:50:48 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-02-08 18:00:04 -0500
commit3b9ab374a1e6d3cd6d16231ec6fe11fe2c49a72a (patch)
tree51358634f4bec64354891db97eef6b4ac43ebb72 /drivers/char/ppdev.c
parent468623bb835c215028947820c5c36afa409de633 (diff)
ppdev: convert to y2038 safe
The y2038 issue for ppdev is changes of timeval in the ioctl (PPSETTIME and PPGETTIME). The size of struct timeval changes from 8bytes to 16bytes due to the changes of time_t. It lead to the changes of the command of ioctl, e.g. for PPGETTIME, We have: on 32-bit (old): 0x80087095 on 32-bit (new): 0x80107095 on 64-bit : 0x80107095 This patch define these two ioctl commands to support the 32bit and 64bit time_t application at the same time. And, introduce pp_set_timeout to remove some duplicated code. Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/char/ppdev.c')
-rw-r--r--drivers/char/ppdev.c75
1 files changed, 55 insertions, 20 deletions
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index ae0b42b66e55..c03d998731ea 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -98,6 +98,13 @@ struct pp_struct {
98#define ROUND_UP(x,y) (((x)+(y)-1)/(y)) 98#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
99 99
100static DEFINE_MUTEX(pp_do_mutex); 100static DEFINE_MUTEX(pp_do_mutex);
101
102/* define fixed sized ioctl cmd for y2038 migration */
103#define PPGETTIME32 _IOR(PP_IOCTL, 0x95, s32[2])
104#define PPSETTIME32 _IOW(PP_IOCTL, 0x96, s32[2])
105#define PPGETTIME64 _IOR(PP_IOCTL, 0x95, s64[2])
106#define PPSETTIME64 _IOW(PP_IOCTL, 0x96, s64[2])
107
101static inline void pp_enable_irq (struct pp_struct *pp) 108static inline void pp_enable_irq (struct pp_struct *pp)
102{ 109{
103 struct parport *port = pp->pdev->port; 110 struct parport *port = pp->pdev->port;
@@ -322,6 +329,22 @@ static enum ieee1284_phase init_phase (int mode)
322 return IEEE1284_PH_FWD_IDLE; 329 return IEEE1284_PH_FWD_IDLE;
323} 330}
324 331
332static int pp_set_timeout(struct pardevice *pdev, long tv_sec, int tv_usec)
333{
334 long to_jiffies;
335
336 if ((tv_sec < 0) || (tv_usec < 0))
337 return -EINVAL;
338
339 to_jiffies = usecs_to_jiffies(tv_usec);
340 to_jiffies += tv_sec * HZ;
341 if (to_jiffies <= 0)
342 return -EINVAL;
343
344 pdev->timeout = to_jiffies;
345 return 0;
346}
347
325static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 348static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
326{ 349{
327 unsigned int minor = iminor(file_inode(file)); 350 unsigned int minor = iminor(file_inode(file));
@@ -495,9 +518,10 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
495 unsigned char reg; 518 unsigned char reg;
496 unsigned char mask; 519 unsigned char mask;
497 int mode; 520 int mode;
521 s32 time32[2];
522 s64 time64[2];
523 struct timespec64 ts;
498 int ret; 524 int ret;
499 struct timeval par_timeout;
500 long to_jiffies;
501 525
502 case PPRSTATUS: 526 case PPRSTATUS:
503 reg = parport_read_status (port); 527 reg = parport_read_status (port);
@@ -592,29 +616,40 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
592 atomic_sub (ret, &pp->irqc); 616 atomic_sub (ret, &pp->irqc);
593 return 0; 617 return 0;
594 618
595 case PPSETTIME: 619 case PPSETTIME32:
596 if (copy_from_user (&par_timeout, argp, sizeof(struct timeval))) { 620 if (copy_from_user(time32, argp, sizeof(time32)))
597 return -EFAULT; 621 return -EFAULT;
598 } 622
599 /* Convert to jiffies, place in pp->pdev->timeout */ 623 return pp_set_timeout(pp->pdev, time32[0], time32[1]);
600 if ((par_timeout.tv_sec < 0) || (par_timeout.tv_usec < 0)) { 624
601 return -EINVAL; 625 case PPSETTIME64:
602 } 626 if (copy_from_user(time64, argp, sizeof(time64)))
603 to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ); 627 return -EFAULT;
604 to_jiffies += par_timeout.tv_sec * (long)HZ; 628
605 if (to_jiffies <= 0) { 629 return pp_set_timeout(pp->pdev, time64[0], time64[1]);
630
631 case PPGETTIME32:
632 jiffies_to_timespec64(pp->pdev->timeout, &ts);
633 time32[0] = ts.tv_sec;
634 time32[1] = ts.tv_nsec / NSEC_PER_USEC;
635 if ((time32[0] < 0) || (time32[1] < 0))
606 return -EINVAL; 636 return -EINVAL;
607 } 637
608 pp->pdev->timeout = to_jiffies; 638 if (copy_to_user(argp, time32, sizeof(time32)))
639 return -EFAULT;
640
609 return 0; 641 return 0;
610 642
611 case PPGETTIME: 643 case PPGETTIME64:
612 to_jiffies = pp->pdev->timeout; 644 jiffies_to_timespec64(pp->pdev->timeout, &ts);
613 memset(&par_timeout, 0, sizeof(par_timeout)); 645 time64[0] = ts.tv_sec;
614 par_timeout.tv_sec = to_jiffies / HZ; 646 time64[1] = ts.tv_nsec / NSEC_PER_USEC;
615 par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); 647 if ((time64[0] < 0) || (time64[1] < 0))
616 if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) 648 return -EINVAL;
649
650 if (copy_to_user(argp, time64, sizeof(time64)))
617 return -EFAULT; 651 return -EFAULT;
652
618 return 0; 653 return 0;
619 654
620 default: 655 default: