Firstly enable ioctl in ppdev and then Keep par_timeout as timeval in
compat ioctl in order to use the 64bit time type.

Signed-off-by: Bamvor Zhang Jian <[email protected]>
---
This is my first time to try to upstream some code in kernel. Any commit
and feedback is welcome.

 drivers/char/ppdev.c       | 30 +++++++++++++++++++++++++-----
 include/uapi/linux/ppdev.h | 20 ++++++++++++++++++--
 2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index ae0b42b..9e3c101 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -69,6 +69,7 @@
 #include <linux/ppdev.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 
 #define PP_VERSION "ppdev: user-space parallel port driver"
 #define CHRDEV "ppdev"
@@ -592,9 +593,17 @@ static int pp_do_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
                atomic_sub (ret, &pp->irqc);
                return 0;
 
-       case PPSETTIME:
-               if (copy_from_user (&par_timeout, argp, sizeof(struct 
timeval))) {
-                       return -EFAULT;
+#ifdef PPSETTIME64
+       case PPSETTIME64:
+#endif /* PPSETTIME64 */
+       case PPSETTIME32:
+               if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task()) {
+                       if (compat_get_timeval(&par_timeout, compat_ptr(arg)))
+                               return -EFAULT;
+               } else {
+                       if (copy_from_user(&par_timeout, argp,
+                                               sizeof(par_timeout)))
+                               return -EFAULT;
                }
                /* Convert to jiffies, place in pp->pdev->timeout */
                if ((par_timeout.tv_sec < 0) || (par_timeout.tv_usec < 0)) {
@@ -608,13 +617,23 @@ static int pp_do_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
                pp->pdev->timeout = to_jiffies;
                return 0;
 
-       case PPGETTIME:
+#ifdef PPGETTIME64
+       case PPGETTIME64:
+#endif /* PPGETTIME64 */
+       case PPGETTIME32:
                to_jiffies = pp->pdev->timeout;
                memset(&par_timeout, 0, sizeof(par_timeout));
                par_timeout.tv_sec = to_jiffies / HZ;
                par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ);
-               if (copy_to_user (argp, &par_timeout, sizeof(struct timeval)))
                        return -EFAULT;
+               if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task()) {
+                       if (compat_put_timeval(&par_timeout, compat_ptr(arg)))
+                               return -EFAULT;
+               } else {
+                       if (copy_to_user(argp, &par_timeout,
+                                               sizeof(par_timeout)))
+                               return -EFAULT;
+               }
                return 0;
 
        default:
@@ -744,6 +763,7 @@ static const struct file_operations pp_fops = {
        .write          = pp_write,
        .poll           = pp_poll,
        .unlocked_ioctl = pp_ioctl,
+       .compat_ioctl   = pp_ioctl,
        .open           = pp_open,
        .release        = pp_release,
 };
diff --git a/include/uapi/linux/ppdev.h b/include/uapi/linux/ppdev.h
index dc18c5d..f4c8fac 100644
--- a/include/uapi/linux/ppdev.h
+++ b/include/uapi/linux/ppdev.h
@@ -74,8 +74,24 @@ struct ppdev_frob_struct {
 #define PPSETPHASE     _IOW(PP_IOCTL, 0x94, int)
 
 /* Set and get port timeout (struct timeval's) */
-#define PPGETTIME      _IOR(PP_IOCTL, 0x95, struct timeval)
-#define PPSETTIME      _IOW(PP_IOCTL, 0x96, struct timeval)
+#ifdef CONFIG_64BIT
+#define PPGETTIME      PPGETTIME64
+#define PPSETTIME      PPSETTIME64
+#define PPGETTIME64    _IOR(PP_IOCTL, 0x95, struct timeval)
+#define PPSETTIME64    _IOW(PP_IOCTL, 0x96, struct timeval)
+#define PPGETTIME32    _IOR(PP_IOCTL, 0x9c, struct compat_timeval)
+#define PPSETTIME32    _IOW(PP_IOCTL, 0x9d, struct compat_timeval)
+#elif defined(CONFIG_COMPAT_TIME)
+#define PPGETTIME      PPGETTIME32
+#define PPSETTIME      PPSETTIME32
+#define PPGETTIME32    _IOR(PP_IOCTL, 0x95, struct compat_timeval)
+#define PPSETTIME32    _IOW(PP_IOCTL, 0x96, struct compat_timeval)
+#else
+#define PPGETTIME      PPGETTIME32
+#define PPSETTIME      PPSETTIME32
+#define PPGETTIME32    _IOR(PP_IOCTL, 0x95, struct timeval)
+#define PPSETTIME32    _IOW(PP_IOCTL, 0x96, struct timeval)
+#endif /* CONFIG_64BIT */
 
 /* Get available modes (what the hardware can do) */
 #define PPGETMODES     _IOR(PP_IOCTL, 0x97, unsigned int)
-- 
2.1.4

_______________________________________________
Y2038 mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/y2038

Reply via email to