diff options
author | Petr Vandrovec <petr@vandrovec.name> | 2007-05-06 22:14:47 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-07-09 18:07:38 -0400 |
commit | 650c12c528d3e0ac69405dd35d3bc8a7228e49f2 (patch) | |
tree | f968e1e6fea9ee93b5fc06fadbbd128a1e58a6e7 | |
parent | 883b97eaf2a3fba7628f9f78ca7dc422aaf9728b (diff) |
ieee1394: raw1394: Add ioctl() for 32bit userland on 64bit kernel
Add compat_ioctl. Although all structures are more or less same,
raw1394_iso_packets got pointer inside, and raw1394_cycle_timer got unwanted
padding in the middle. I did not add any translation for ioctls passing array
of integers around as integers seem to have same size (32 bits) on all
architectures supported by Linux.
Signed-off-by: Petr Vandrovec <petr@vandrovec.name>
Acked-by: Dan Dennedy <dan@dennedy.org>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (split into 3 patches)
-rw-r--r-- | drivers/ieee1394/raw1394.c | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 94a3b6db589c..151a48f41c8f 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -2805,6 +2805,99 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, | |||
2805 | return -EINVAL; | 2805 | return -EINVAL; |
2806 | } | 2806 | } |
2807 | 2807 | ||
2808 | #ifdef CONFIG_COMPAT | ||
2809 | struct raw1394_iso_packets32 { | ||
2810 | __u32 n_packets; | ||
2811 | compat_uptr_t infos; | ||
2812 | } __attribute__((packed)); | ||
2813 | |||
2814 | struct raw1394_cycle_timer32 { | ||
2815 | __u32 cycle_timer; | ||
2816 | __u64 local_time; | ||
2817 | } __attribute__((packed)); | ||
2818 | |||
2819 | #define RAW1394_IOC_ISO_RECV_PACKETS32 \ | ||
2820 | _IOW ('#', 0x25, struct raw1394_iso_packets32) | ||
2821 | #define RAW1394_IOC_ISO_XMIT_PACKETS32 \ | ||
2822 | _IOW ('#', 0x27, struct raw1394_iso_packets32) | ||
2823 | #define RAW1394_IOC_GET_CYCLE_TIMER32 \ | ||
2824 | _IOR ('#', 0x30, struct raw1394_cycle_timer32) | ||
2825 | |||
2826 | static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, | ||
2827 | struct raw1394_iso_packets32 __user *arg) | ||
2828 | { | ||
2829 | compat_uptr_t infos32; | ||
2830 | void *infos; | ||
2831 | long err = -EFAULT; | ||
2832 | struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets)); | ||
2833 | |||
2834 | if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) && | ||
2835 | !copy_from_user(&infos32, &arg->infos, sizeof infos32)) { | ||
2836 | infos = compat_ptr(infos32); | ||
2837 | if (!copy_to_user(&dst->infos, &infos, sizeof infos)) | ||
2838 | err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst); | ||
2839 | } | ||
2840 | return err; | ||
2841 | } | ||
2842 | |||
2843 | static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr) | ||
2844 | { | ||
2845 | struct raw1394_cycle_timer32 ct; | ||
2846 | int err; | ||
2847 | |||
2848 | err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time); | ||
2849 | if (!err) | ||
2850 | if (copy_to_user(uaddr, &ct, sizeof(ct))) | ||
2851 | err = -EFAULT; | ||
2852 | return err; | ||
2853 | } | ||
2854 | |||
2855 | static long raw1394_compat_ioctl(struct file *file, | ||
2856 | unsigned int cmd, unsigned long arg) | ||
2857 | { | ||
2858 | struct file_info *fi = file->private_data; | ||
2859 | void __user *argp = (void __user *)arg; | ||
2860 | long err; | ||
2861 | |||
2862 | lock_kernel(); | ||
2863 | switch (cmd) { | ||
2864 | /* These requests have same format as long as 'int' has same size. */ | ||
2865 | case RAW1394_IOC_ISO_RECV_INIT: | ||
2866 | case RAW1394_IOC_ISO_RECV_START: | ||
2867 | case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: | ||
2868 | case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: | ||
2869 | case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: | ||
2870 | case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: | ||
2871 | case RAW1394_IOC_ISO_RECV_FLUSH: | ||
2872 | case RAW1394_IOC_ISO_XMIT_RECV_STOP: | ||
2873 | case RAW1394_IOC_ISO_XMIT_INIT: | ||
2874 | case RAW1394_IOC_ISO_XMIT_START: | ||
2875 | case RAW1394_IOC_ISO_XMIT_SYNC: | ||
2876 | case RAW1394_IOC_ISO_GET_STATUS: | ||
2877 | case RAW1394_IOC_ISO_SHUTDOWN: | ||
2878 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: | ||
2879 | err = raw1394_ioctl(NULL, file, cmd, arg); | ||
2880 | break; | ||
2881 | /* These request have different format. */ | ||
2882 | case RAW1394_IOC_ISO_RECV_PACKETS32: | ||
2883 | err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp); | ||
2884 | break; | ||
2885 | case RAW1394_IOC_ISO_XMIT_PACKETS32: | ||
2886 | err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp); | ||
2887 | break; | ||
2888 | case RAW1394_IOC_GET_CYCLE_TIMER32: | ||
2889 | err = raw1394_read_cycle_timer32(fi, argp); | ||
2890 | break; | ||
2891 | default: | ||
2892 | err = -EINVAL; | ||
2893 | break; | ||
2894 | } | ||
2895 | unlock_kernel(); | ||
2896 | |||
2897 | return err; | ||
2898 | } | ||
2899 | #endif | ||
2900 | |||
2808 | static unsigned int raw1394_poll(struct file *file, poll_table * pt) | 2901 | static unsigned int raw1394_poll(struct file *file, poll_table * pt) |
2809 | { | 2902 | { |
2810 | struct file_info *fi = file->private_data; | 2903 | struct file_info *fi = file->private_data; |
@@ -3044,7 +3137,9 @@ static const struct file_operations raw1394_fops = { | |||
3044 | .write = raw1394_write, | 3137 | .write = raw1394_write, |
3045 | .mmap = raw1394_mmap, | 3138 | .mmap = raw1394_mmap, |
3046 | .ioctl = raw1394_ioctl, | 3139 | .ioctl = raw1394_ioctl, |
3047 | // .compat_ioctl = ... someone needs to do this | 3140 | #ifdef CONFIG_COMPAT |
3141 | .compat_ioctl = raw1394_compat_ioctl, | ||
3142 | #endif | ||
3048 | .poll = raw1394_poll, | 3143 | .poll = raw1394_poll, |
3049 | .open = raw1394_open, | 3144 | .open = raw1394_open, |
3050 | .release = raw1394_release, | 3145 | .release = raw1394_release, |