X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fieee1394%2Fdv1394.c;h=59e383c7d8fd9e9e559c49f98b30113567ba6af5;hb=refs%2Fheads%2Fvserver;hp=ecf6830b3b51e33350e6a580608b3280394c93d8;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index ecf6830b3..59e383c7d 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 @@ -96,6 +95,7 @@ #include #include #include +#include #include #include #include @@ -108,30 +108,20 @@ #include #include #include -#include #include #include +#include "dv1394.h" +#include "dv1394-private.h" +#include "highlevel.h" +#include "hosts.h" #include "ieee1394.h" +#include "ieee1394_core.h" +#include "ieee1394_hotplug.h" #include "ieee1394_types.h" #include "nodemgr.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "dv1394.h" -#include "dv1394-private.h" - #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 @@ -147,13 +137,13 @@ #if DV1394_DEBUG_LEVEL >= 2 #define irq_printk( args... ) printk( args ) #else -#define irq_printk( args... ) +#define irq_printk( args... ) do {} while (0) #endif #if DV1394_DEBUG_LEVEL >= 1 #define debug_printk( args... ) printk( args) #else -#define debug_printk( args... ) +#define debug_printk( args... ) do {} while (0) #endif /* issue a dummy PCI read to force the preceding write @@ -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* */ @@ -253,7 +248,7 @@ static void frame_delete(struct frame *f) Frame_prepare() must be called OUTSIDE the video->spinlock. However, frame_prepare() must still be serialized, so - it should be called WITH the video->sem taken. + it should be called WITH the video->mtx taken. */ static void frame_prepare(struct video_card *video, unsigned int this_frame) @@ -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,13 +1266,13 @@ 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; /* serialize mmap */ - down(&video->sem); + mutex_lock(&video->mtx); if ( ! video_card_initialized(video) ) { retval = do_dv1394_init_default(video); @@ -1288,7 +1282,7 @@ int dv1394_mmap(struct file *file, struct vm_area_struct *vma) retval = dma_region_mmap(&video->dv_buf, file, vma); out: - up(&video->sem); + mutex_unlock(&video->mtx); return retval; } @@ -1344,17 +1338,17 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) + if (!mutex_trylock(&video->mtx)) return -EAGAIN; } else { - if (down_interruptible(&video->sem)) + if (mutex_lock_interruptible(&video->mtx)) return -ERESTARTSYS; } if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); if (ret) { - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } } @@ -1425,7 +1419,7 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } @@ -1441,17 +1435,17 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) + if (!mutex_trylock(&video->mtx)) return -EAGAIN; } else { - if (down_interruptible(&video->sem)) + if (mutex_lock_interruptible(&video->mtx)) return -ERESTARTSYS; } if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); if (ret) { - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } video->continuity_counter = -1; @@ -1533,18 +1527,14 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } /*** 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); unsigned long flags; @@ -1555,10 +1545,10 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) + if (!mutex_trylock(&video->mtx)) return -EAGAIN; } else { - if (down_interruptible(&video->sem)) + if (mutex_lock_interruptible(&video->mtx)) return -ERESTARTSYS; } @@ -1782,20 +1772,16 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, } out: - up(&video->sem); + mutex_unlock(&video->mtx); 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 +2151,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, @@ -2191,12 +2180,8 @@ static struct ieee1394_device_id dv1394_id_table[] = { MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); static struct hpsb_protocol_driver dv1394_driver = { - .name = "DV/1394 Driver", + .name = "dv1394", .id_table = dv1394_id_table, - .driver = { - .name = "dv1394", - .bus = &ieee1394_bus_type, - }, }; @@ -2208,14 +2193,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 */ @@ -2259,7 +2242,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes clear_bit(0, &video->open); spin_lock_init(&video->spinlock); video->dma_running = 0; - init_MUTEX(&video->sem); + mutex_init(&video->mtx); init_waitqueue_head(&video->waitq); video->fasync = NULL; @@ -2268,37 +2251,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); } @@ -2307,11 +2267,7 @@ static void dv1394_remove_host (struct hpsb_host *host) { struct video_card *video; unsigned long flags; - int id = host->id; - - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; + int id = host->id, found_ohci_card = 0; /* find the corresponding video_cards */ do { @@ -2324,6 +2280,7 @@ static void dv1394_remove_host (struct hpsb_host *host) if ((tmp_vid->id >> 2) == id) { list_del(&tmp_vid->list); video = tmp_vid; + found_ohci_card = 1; break; } } @@ -2333,9 +2290,9 @@ 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); + if (found_ohci_card) + 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 +2306,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 +2464,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 +2489,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 +2529,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,31 +2564,19 @@ 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) { int ret; + printk(KERN_WARNING + "WARNING: The dv1394 driver is unsupported and will be removed " + "from Linux soon. Use raw1394 instead.\n"); + cdev_init(&dv1394_cdev, &dv1394_fops); dv1394_cdev.owner = THIS_MODULE; kobject_set_name(&dv1394_cdev.kobj, "dv1394"); @@ -2620,39 +2586,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);