X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fieee1394%2Fdv1394.c;h=87532dd43374f9625d9f06693503a63c07a2758f;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=9964d6fbc5a13f2e97d499f692c49fd301c5ec1e;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 9964d6fbc..87532dd43 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -73,7 +73,7 @@ - fix all XXX showstoppers - disable IR/IT DMA interrupts on shutdown - flush pci writes to the card by issuing a read - - devfs and character device dispatching (* needs testing with Linux 2.2.x) + - character device dispatching - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!) - keep all video_cards in a list (for open() via chardev), set file->private_data = video - dv1394_poll should indicate POLLIN when receiving buffers are available @@ -83,7 +83,6 @@ */ -#include #include #include #include @@ -108,7 +107,6 @@ #include #include #include -#include #include #include @@ -123,15 +121,6 @@ #include "ohci1394.h" -#ifndef virt_to_page -#define virt_to_page(x) MAP_NR(x) -#endif - -#ifndef vmalloc_32 -#define vmalloc_32(x) vmalloc(x) -#endif - - /* DEBUG LEVELS: 0 - no debugging messages 1 - some debugging messages, but none during DMA frame transmission @@ -168,11 +157,16 @@ static inline void flush_pci_write(struct ti_ohci *ohci) static void it_tasklet_func(unsigned long data); static void ir_tasklet_func(unsigned long data); +#ifdef CONFIG_COMPAT +static long dv1394_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +#endif + /* GLOBAL DATA */ /* list of all video_cards */ static LIST_HEAD(dv1394_cards); -static spinlock_t dv1394_cards_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(dv1394_cards_lock); /* translate from a struct file* to the corresponding struct video_card* */ @@ -1101,7 +1095,6 @@ static int do_dv1394_init_default(struct video_card *video) init.api_version = DV1394_API_VERSION; init.n_frames = DV1394_MAX_FRAMES / 4; - /* the following are now set via devfs */ init.channel = video->channel; init.format = video->pal_or_ntsc; init.cip_n = video->cip_n; @@ -1272,7 +1265,7 @@ static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf) error-prone code in dv1394. */ -int dv1394_mmap(struct file *file, struct vm_area_struct *vma) +static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) { struct video_card *video = file_to_video_card(file); int retval = -EINVAL; @@ -1322,7 +1315,7 @@ static unsigned int dv1394_poll(struct file *file, struct poll_table_struct *wai static int dv1394_fasync(int fd, struct file *file, int on) { /* I just copied this code verbatim from Alan Cox's mouse driver example - (linux/Documentation/DocBook/) */ + (Documentation/DocBook/) */ struct video_card *video = file_to_video_card(file); @@ -1333,7 +1326,7 @@ static int dv1394_fasync(int fd, struct file *file, int on) return 0; } -static ssize_t dv1394_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct video_card *video = file_to_video_card(file); DECLARE_WAITQUEUE(wait, current); @@ -1430,7 +1423,7 @@ static ssize_t dv1394_write(struct file *file, const char *buffer, size_t count, } -static ssize_t dv1394_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct video_card *video = file_to_video_card(file); DECLARE_WAITQUEUE(wait, current); @@ -1540,25 +1533,29 @@ static ssize_t dv1394_read(struct file *file, char *buffer, size_t count, loff_ /*** DEVICE IOCTL INTERFACE ************************************************/ -/* I *think* the VFS serializes ioctl() for us, so we don't have to worry - about situations like having two threads in here at once... */ - -static int dv1394_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct video_card *video = file_to_video_card(file); + struct video_card *video; unsigned long flags; int ret = -EINVAL; + void __user *argp = (void __user *)arg; DECLARE_WAITQUEUE(wait, current); + lock_kernel(); + video = file_to_video_card(file); + /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) + if (down_trylock(&video->sem)) { + unlock_kernel(); return -EAGAIN; + } } else { - if (down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) { + unlock_kernel(); return -ERESTARTSYS; + } } switch(cmd) @@ -1718,10 +1715,10 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, case DV1394_IOC_INIT: { struct dv1394_init init; - if (arg == (unsigned long) NULL) { + if (!argp) { ret = do_dv1394_init_default(video); } else { - if (copy_from_user(&init, (void*)arg, sizeof(init))) { + if (copy_from_user(&init, argp, sizeof(init))) { ret = -EFAULT; goto out; } @@ -1767,7 +1764,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, spin_unlock_irqrestore(&video->spinlock, flags); - if (copy_to_user((void*)arg, &status, sizeof(status))) { + if (copy_to_user(argp, &status, sizeof(status))) { ret = -EFAULT; goto out; } @@ -1782,19 +1779,16 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, out: up(&video->sem); + unlock_kernel(); return ret; } - - /*** DEVICE FILE INTERFACE CONTINUED ***************************************/ static int dv1394_open(struct inode *inode, struct file *file) { struct video_card *video = NULL; - /* if the device was opened through devfs, then file->private_data - has already been set to video by devfs */ if (file->private_data) { video = (struct video_card*) file->private_data; @@ -2164,7 +2158,10 @@ static struct file_operations dv1394_fops= { .owner = THIS_MODULE, .poll = dv1394_poll, - .ioctl = dv1394_ioctl, + .unlocked_ioctl = dv1394_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = dv1394_compat_ioctl, +#endif .mmap = dv1394_mmap, .open = dv1394_open, .write = dv1394_write, @@ -2207,14 +2204,12 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes unsigned long flags; int i; - video = kmalloc(sizeof(struct video_card), GFP_KERNEL); + video = kzalloc(sizeof(*video), GFP_KERNEL); if (!video) { printk(KERN_ERR "dv1394: cannot allocate video_card\n"); - goto err; + return -1; } - memset(video, 0, sizeof(struct video_card)); - video->ohci = ohci; /* lower 2 bits of id indicate which of four "plugs" per host */ @@ -2267,37 +2262,14 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes list_add_tail(&video->list, &dv1394_cards); spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394*16 + video->id), - S_IFCHR|S_IRUGO|S_IWUGO, - "ieee1394/dv/host%d/%s/%s", - (video->id>>2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out")) < 0) - goto err_free; - debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id); - return 0; - - err_free: - kfree(video); - err: - return -1; } static void dv1394_un_init(struct video_card *video) { - char buf[32]; - /* obviously nobody has the driver open at this point */ do_dv1394_shutdown(video, 1); - snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out") - ); - - devfs_remove("ieee1394/%s", buf); kfree(video); } @@ -2332,9 +2304,8 @@ static void dv1394_remove_host (struct hpsb_host *host) dv1394_un_init(video); } while (video != NULL); - devfs_remove("ieee1394/dv/host%d/NTSC", id); - devfs_remove("ieee1394/dv/host%d/PAL", id); - devfs_remove("ieee1394/dv/host%d", id); + class_device_destroy(hpsb_protocol_class, + MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2))); } static void dv1394_add_host (struct hpsb_host *host) @@ -2348,9 +2319,9 @@ static void dv1394_add_host (struct hpsb_host *host) ohci = (struct ti_ohci *)host->hostdata; - devfs_mk_dir("ieee1394/dv/host%d", id); - devfs_mk_dir("ieee1394/dv/host%d/NTSC", id); - devfs_mk_dir("ieee1394/dv/host%d/PAL", id); + class_device_create(hpsb_protocol_class, NULL, MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), + NULL, "dv1394-%d", id); dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); @@ -2506,18 +2477,19 @@ struct dv1394_status32 { u32 dropped_frames; }; -static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg, - struct file *file) +/* RED-PEN: this should use compat_alloc_userspace instead */ + +static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long arg) { struct dv1394_init32 dv32; struct dv1394_init dv; mm_segment_t old_fs; int ret; - if (file->f_op->ioctl != dv1394_ioctl) + if (file->f_op->unlocked_ioctl != dv1394_ioctl) return -EFAULT; - if (copy_from_user(&dv32, (void *)arg, sizeof(dv32))) + if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32))) return -EFAULT; dv.api_version = dv32.api_version; @@ -2530,28 +2502,25 @@ static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long a old_fs = get_fs(); set_fs(KERNEL_DS); - ret = dv1394_ioctl(file->f_dentry->d_inode, file, - DV1394_IOC_INIT, (unsigned long)&dv); + ret = dv1394_ioctl(file, DV1394_IOC_INIT, (unsigned long)&dv); set_fs(old_fs); return ret; } -static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg, - struct file *file) +static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigned long arg) { struct dv1394_status32 dv32; struct dv1394_status dv; mm_segment_t old_fs; int ret; - if (file->f_op->ioctl != dv1394_ioctl) + if (file->f_op->unlocked_ioctl != dv1394_ioctl) return -EFAULT; old_fs = get_fs(); set_fs(KERNEL_DS); - ret = dv1394_ioctl(file->f_dentry->d_inode, file, - DV1394_IOC_GET_STATUS, (unsigned long)&dv); + ret = dv1394_ioctl(file, DV1394_IOC_GET_STATUS, (unsigned long)&dv); set_fs(old_fs); if (!ret) { @@ -2567,12 +2536,35 @@ static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned dv32.n_clear_frames = dv.n_clear_frames; dv32.dropped_frames = dv.dropped_frames; - if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32))) + if (copy_to_user((struct dv1394_status32 __user *)arg, &dv32, sizeof(dv32))) ret = -EFAULT; } return ret; } + + + +static long dv1394_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case DV1394_IOC_SHUTDOWN: + case DV1394_IOC_SUBMIT_FRAMES: + case DV1394_IOC_WAIT_FRAMES: + case DV1394_IOC_RECEIVE_FRAMES: + case DV1394_IOC_START_RECEIVE: + return dv1394_ioctl(file, cmd, arg); + + case DV1394_IOC32_INIT: + return handle_dv1394_init(file, cmd, arg); + case DV1394_IOC32_GET_STATUS: + return handle_dv1394_get_status(file, cmd, arg); + default: + return -ENOIOCTLCMD; + } +} + #endif /* CONFIG_COMPAT */ @@ -2585,25 +2577,9 @@ MODULE_LICENSE("GPL"); static void __exit dv1394_exit_module(void) { -#ifdef CONFIG_COMPAT - int ret; - - ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN); - ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES); - ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES); - ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES); - ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE); - ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT); - ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS); - if (ret) - printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n"); -#endif - hpsb_unregister_protocol(&dv1394_driver); - hpsb_unregister_highlevel(&dv1394_highlevel); cdev_del(&dv1394_cdev); - devfs_remove("ieee1394/dv"); } static int __init dv1394_init_module(void) @@ -2619,39 +2595,18 @@ static int __init dv1394_init_module(void) return ret; } - devfs_mk_dir("ieee1394/dv"); - hpsb_register_highlevel(&dv1394_highlevel); ret = hpsb_register_protocol(&dv1394_driver); if (ret) { printk(KERN_ERR "dv1394: failed to register protocol\n"); hpsb_unregister_highlevel(&dv1394_highlevel); - devfs_remove("ieee1394/dv"); cdev_del(&dv1394_cdev); return ret; } -#ifdef CONFIG_COMPAT - { - /* First compatible ones */ - ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL); - ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL); - ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL); - ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL); - ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL); - - /* These need to be handled by translation */ - ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init); - ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status); - if (ret) - printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n"); - } -#endif - return 0; } module_init(dv1394_init_module); module_exit(dv1394_exit_module); -MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16);