X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fieee1394%2Fdv1394.c;h=85c2d4ca0def60087a1b11120b98538e1da0f240;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=ecf6830b3b51e33350e6a580608b3280394c93d8;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index ecf6830b3..85c2d4ca0 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 @@ -108,7 +108,6 @@ #include #include #include -#include #include #include @@ -123,15 +122,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 +158,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 +1096,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 +1266,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; @@ -1540,26 +1534,29 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count /*** 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) @@ -1783,19 +1780,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; @@ -2165,7 +2159,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, @@ -2208,14 +2205,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 */ @@ -2268,37 +2263,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); } @@ -2333,9 +2305,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) @@ -2349,9 +2320,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); @@ -2507,15 +2478,16 @@ 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 __user *)arg, sizeof(dv32))) @@ -2531,28 +2503,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) { @@ -2574,6 +2543,29 @@ static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned 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 */ @@ -2586,25 +2578,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) @@ -2620,39 +2596,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);