From: Christoph Hellwig This patch implements generic handling of RTC_IRQP_READ32, RTC_IRQP_SET32, RTC_EPOCH_READ32 and RTC_EPOCH_SET32 in fs/compat_ioctl.c. It's based on the x86_64 code which needed a little massaging to be endian-clean. parisc used COMPAT_IOCTL or generic w_long handlers for these whichce is wrong and can't work because the ioctls encode sizeof(unsigned long) in their ioctl number. parisc also duplicated COMPAT_IOCTL entries for other rtc ioctls which I remove in this patch, too. Signed-off-by: Christoph Hellwig Acked-by: Matthew Wilcox Acked-by: "David S. Miller" Signed-off-by: Andrew Morton --- arch/parisc/kernel/ioctl32.c | 19 ---------------- arch/x86_64/ia32/ia32_ioctl.c | 47 ------------------------------------------ fs/compat_ioctl.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 66 deletions(-) diff -puN arch/parisc/kernel/ioctl32.c~move-rtc-compat-ioctl-handling-to-fs-compat_ioctlc arch/parisc/kernel/ioctl32.c --- devel/arch/parisc/kernel/ioctl32.c~move-rtc-compat-ioctl-handling-to-fs-compat_ioctlc 2005-12-22 05:09:36.000000000 -0800 +++ devel-akpm/arch/parisc/kernel/ioctl32.c 2005-12-22 05:09:36.000000000 -0800 @@ -36,25 +36,6 @@ HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc) -#if defined(CONFIG_GEN_RTC) -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */ -COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */ -COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */ -COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */ -HANDLE_IOCTL(RTC_IRQP_READ, w_long) -COMPATIBLE_IOCTL(RTC_IRQP_SET) -HANDLE_IOCTL(RTC_EPOCH_READ, w_long) -COMPATIBLE_IOCTL(RTC_EPOCH_SET) -#endif - IOCTL_TABLE_END int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/x86_64/ia32/ia32_ioctl.c~move-rtc-compat-ioctl-handling-to-fs-compat_ioctlc arch/x86_64/ia32/ia32_ioctl.c --- devel/arch/x86_64/ia32/ia32_ioctl.c~move-rtc-compat-ioctl-handling-to-fs-compat_ioctlc 2005-12-22 05:09:36.000000000 -0800 +++ devel-akpm/arch/x86_64/ia32/ia32_ioctl.c 2005-12-22 05:09:36.000000000 -0800 @@ -16,45 +16,6 @@ #define CODE #include "compat_ioctl.c" - -#define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */ -#define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */ -#define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */ -#define RTC_EPOCH_SET32 _IOW('p', 0x0e, unsigned) /* Set epoch */ - -static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg) -{ - unsigned long val; - mm_segment_t oldfs = get_fs(); - int ret; - - switch (cmd) { - case RTC_IRQP_READ32: - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, RTC_IRQP_READ, (unsigned long)&val); - set_fs(oldfs); - if (!ret) - ret = put_user(val, (unsigned int __user *) arg); - return ret; - - case RTC_IRQP_SET32: - cmd = RTC_IRQP_SET; - break; - - case RTC_EPOCH_READ32: - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, RTC_EPOCH_READ, (unsigned long) &val); - set_fs(oldfs); - if (!ret) - ret = put_user(val, (unsigned int __user *) arg); - return ret; - - case RTC_EPOCH_SET32: - cmd = RTC_EPOCH_SET; - break; - } - return sys_ioctl(fd,cmd,arg); -} #define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) }, @@ -64,14 +25,6 @@ struct ioctl_trans ioctl_start[] = { #include #define DECLARES #include "compat_ioctl.c" - -/* And these ioctls need translation */ -/* realtime device */ -HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl) -HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) -HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl) -HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl) -HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl) /* take care of sizeof(sizeof()) breakage */ }; diff -puN fs/compat_ioctl.c~move-rtc-compat-ioctl-handling-to-fs-compat_ioctlc fs/compat_ioctl.c --- devel/fs/compat_ioctl.c~move-rtc-compat-ioctl-handling-to-fs-compat_ioctlc 2005-12-22 05:09:36.000000000 -0800 +++ devel-akpm/fs/compat_ioctl.c 2005-12-22 05:09:36.000000000 -0800 @@ -2749,6 +2749,49 @@ static int old_bridge_ioctl(unsigned int return -EINVAL; } +#define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) +#define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) +#define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) +#define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) + +static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg) +{ + mm_segment_t oldfs = get_fs(); + compat_ulong_t val32; + unsigned long kval; + int ret; + + switch (cmd) { + case RTC_IRQP_READ32: + case RTC_EPOCH_READ32: + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, (cmd == RTC_IRQP_READ32) ? + RTC_IRQP_READ : RTC_EPOCH_READ, + (unsigned long)&kval); + set_fs(oldfs); + if (ret) + return ret; + val32 = kval; + return put_user(val32, (unsigned int __user *)arg); + case RTC_IRQP_SET32: + case RTC_EPOCH_SET32: + ret = get_user(val32, (unsigned int __user *)arg); + if (ret) + return ret; + kval = val32; + + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, (cmd == RTC_IRQP_SET32) ? + RTC_IRQP_SET : RTC_EPOCH_SET, + (unsigned long)&kval); + set_fs(oldfs); + return ret; + default: + /* unreached */ + return -ENOIOCTLCMD; + } +} + #if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE) struct ncp_ioctl_request_32 { u32 function; @@ -3155,6 +3198,10 @@ HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl) HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) +HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) +HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl) +HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl) +HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl) #if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE) HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) _