diff options
Diffstat (limited to 'drivers/ieee1394/raw1394.c')
-rw-r--r-- | drivers/ieee1394/raw1394.c | 230 |
1 files changed, 127 insertions, 103 deletions
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index c7833bb37ae1..9f19ac492106 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
35 | #include <linux/poll.h> | 35 | #include <linux/poll.h> |
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/mutex.h> | ||
37 | #include <linux/init.h> | 38 | #include <linux/init.h> |
38 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
39 | #include <linux/vmalloc.h> | 40 | #include <linux/vmalloc.h> |
@@ -2267,6 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, | |||
2267 | return -EFAULT; | 2268 | return -EFAULT; |
2268 | } | 2269 | } |
2269 | 2270 | ||
2271 | mutex_lock(&fi->state_mutex); | ||
2272 | |||
2270 | switch (fi->state) { | 2273 | switch (fi->state) { |
2271 | case opened: | 2274 | case opened: |
2272 | retval = state_opened(fi, req); | 2275 | retval = state_opened(fi, req); |
@@ -2281,6 +2284,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, | |||
2281 | break; | 2284 | break; |
2282 | } | 2285 | } |
2283 | 2286 | ||
2287 | mutex_unlock(&fi->state_mutex); | ||
2288 | |||
2284 | if (retval < 0) { | 2289 | if (retval < 0) { |
2285 | free_pending_request(req); | 2290 | free_pending_request(req); |
2286 | } else { | 2291 | } else { |
@@ -2541,109 +2546,120 @@ static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr) | |||
2541 | static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) | 2546 | static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) |
2542 | { | 2547 | { |
2543 | struct file_info *fi = file->private_data; | 2548 | struct file_info *fi = file->private_data; |
2549 | int ret; | ||
2550 | |||
2551 | mutex_lock(&fi->state_mutex); | ||
2544 | 2552 | ||
2545 | if (fi->iso_state == RAW1394_ISO_INACTIVE) | 2553 | if (fi->iso_state == RAW1394_ISO_INACTIVE) |
2546 | return -EINVAL; | 2554 | ret = -EINVAL; |
2555 | else | ||
2556 | ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma); | ||
2557 | |||
2558 | mutex_unlock(&fi->state_mutex); | ||
2547 | 2559 | ||
2548 | return dma_region_mmap(&fi->iso_handle->data_buf, file, vma); | 2560 | return ret; |
2549 | } | 2561 | } |
2550 | 2562 | ||
2551 | /* ioctl is only used for rawiso operations */ | 2563 | static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd, |
2552 | static long do_raw1394_ioctl(struct file *file, unsigned int cmd, | 2564 | void __user *argp) |
2553 | unsigned long arg) | 2565 | { |
2566 | switch (cmd) { | ||
2567 | case RAW1394_IOC_ISO_XMIT_INIT: | ||
2568 | return raw1394_iso_xmit_init(fi, argp); | ||
2569 | case RAW1394_IOC_ISO_RECV_INIT: | ||
2570 | return raw1394_iso_recv_init(fi, argp); | ||
2571 | default: | ||
2572 | return -EINVAL; | ||
2573 | } | ||
2574 | } | ||
2575 | |||
2576 | static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd, | ||
2577 | unsigned long arg) | ||
2554 | { | 2578 | { |
2555 | struct file_info *fi = file->private_data; | ||
2556 | void __user *argp = (void __user *)arg; | 2579 | void __user *argp = (void __user *)arg; |
2557 | 2580 | ||
2558 | switch (fi->iso_state) { | 2581 | switch (cmd) { |
2559 | case RAW1394_ISO_INACTIVE: | 2582 | case RAW1394_IOC_ISO_RECV_START:{ |
2560 | switch (cmd) { | 2583 | int args[3]; |
2561 | case RAW1394_IOC_ISO_XMIT_INIT: | 2584 | |
2562 | return raw1394_iso_xmit_init(fi, argp); | 2585 | if (copy_from_user(&args[0], argp, sizeof(args))) |
2563 | case RAW1394_IOC_ISO_RECV_INIT: | 2586 | return -EFAULT; |
2564 | return raw1394_iso_recv_init(fi, argp); | 2587 | return hpsb_iso_recv_start(fi->iso_handle, |
2565 | default: | 2588 | args[0], args[1], args[2]); |
2566 | break; | ||
2567 | } | 2589 | } |
2568 | break; | 2590 | case RAW1394_IOC_ISO_XMIT_RECV_STOP: |
2569 | case RAW1394_ISO_RECV: | 2591 | hpsb_iso_stop(fi->iso_handle); |
2570 | switch (cmd) { | 2592 | return 0; |
2571 | case RAW1394_IOC_ISO_RECV_START:{ | 2593 | case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: |
2572 | /* copy args from user-space */ | 2594 | return hpsb_iso_recv_listen_channel(fi->iso_handle, arg); |
2573 | int args[3]; | 2595 | case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: |
2574 | if (copy_from_user | 2596 | return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg); |
2575 | (&args[0], argp, sizeof(args))) | 2597 | case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{ |
2576 | return -EFAULT; | 2598 | u64 mask; |
2577 | return hpsb_iso_recv_start(fi->iso_handle, | 2599 | |
2578 | args[0], args[1], | 2600 | if (copy_from_user(&mask, argp, sizeof(mask))) |
2579 | args[2]); | 2601 | return -EFAULT; |
2580 | } | 2602 | return hpsb_iso_recv_set_channel_mask(fi->iso_handle, |
2581 | case RAW1394_IOC_ISO_XMIT_RECV_STOP: | 2603 | mask); |
2582 | hpsb_iso_stop(fi->iso_handle); | ||
2583 | return 0; | ||
2584 | case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: | ||
2585 | return hpsb_iso_recv_listen_channel(fi->iso_handle, | ||
2586 | arg); | ||
2587 | case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: | ||
2588 | return hpsb_iso_recv_unlisten_channel(fi->iso_handle, | ||
2589 | arg); | ||
2590 | case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{ | ||
2591 | /* copy the u64 from user-space */ | ||
2592 | u64 mask; | ||
2593 | if (copy_from_user(&mask, argp, sizeof(mask))) | ||
2594 | return -EFAULT; | ||
2595 | return hpsb_iso_recv_set_channel_mask(fi-> | ||
2596 | iso_handle, | ||
2597 | mask); | ||
2598 | } | ||
2599 | case RAW1394_IOC_ISO_GET_STATUS: | ||
2600 | return raw1394_iso_get_status(fi, argp); | ||
2601 | case RAW1394_IOC_ISO_RECV_PACKETS: | ||
2602 | return raw1394_iso_recv_packets(fi, argp); | ||
2603 | case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: | ||
2604 | return hpsb_iso_recv_release_packets(fi->iso_handle, | ||
2605 | arg); | ||
2606 | case RAW1394_IOC_ISO_RECV_FLUSH: | ||
2607 | return hpsb_iso_recv_flush(fi->iso_handle); | ||
2608 | case RAW1394_IOC_ISO_SHUTDOWN: | ||
2609 | raw1394_iso_shutdown(fi); | ||
2610 | return 0; | ||
2611 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: | ||
2612 | queue_rawiso_event(fi); | ||
2613 | return 0; | ||
2614 | } | 2604 | } |
2615 | break; | 2605 | case RAW1394_IOC_ISO_GET_STATUS: |
2616 | case RAW1394_ISO_XMIT: | 2606 | return raw1394_iso_get_status(fi, argp); |
2617 | switch (cmd) { | 2607 | case RAW1394_IOC_ISO_RECV_PACKETS: |
2618 | case RAW1394_IOC_ISO_XMIT_START:{ | 2608 | return raw1394_iso_recv_packets(fi, argp); |
2619 | /* copy two ints from user-space */ | 2609 | case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: |
2620 | int args[2]; | 2610 | return hpsb_iso_recv_release_packets(fi->iso_handle, arg); |
2621 | if (copy_from_user | 2611 | case RAW1394_IOC_ISO_RECV_FLUSH: |
2622 | (&args[0], argp, sizeof(args))) | 2612 | return hpsb_iso_recv_flush(fi->iso_handle); |
2623 | return -EFAULT; | 2613 | case RAW1394_IOC_ISO_SHUTDOWN: |
2624 | return hpsb_iso_xmit_start(fi->iso_handle, | 2614 | raw1394_iso_shutdown(fi); |
2625 | args[0], args[1]); | 2615 | return 0; |
2626 | } | 2616 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: |
2627 | case RAW1394_IOC_ISO_XMIT_SYNC: | 2617 | queue_rawiso_event(fi); |
2628 | return hpsb_iso_xmit_sync(fi->iso_handle); | 2618 | return 0; |
2629 | case RAW1394_IOC_ISO_XMIT_RECV_STOP: | 2619 | default: |
2630 | hpsb_iso_stop(fi->iso_handle); | 2620 | return -EINVAL; |
2631 | return 0; | 2621 | } |
2632 | case RAW1394_IOC_ISO_GET_STATUS: | 2622 | } |
2633 | return raw1394_iso_get_status(fi, argp); | 2623 | |
2634 | case RAW1394_IOC_ISO_XMIT_PACKETS: | 2624 | static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd, |
2635 | return raw1394_iso_send_packets(fi, argp); | 2625 | void __user *argp) |
2636 | case RAW1394_IOC_ISO_SHUTDOWN: | 2626 | { |
2637 | raw1394_iso_shutdown(fi); | 2627 | switch (cmd) { |
2638 | return 0; | 2628 | case RAW1394_IOC_ISO_XMIT_START:{ |
2639 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: | 2629 | int args[2]; |
2640 | queue_rawiso_event(fi); | 2630 | |
2641 | return 0; | 2631 | if (copy_from_user(&args[0], argp, sizeof(args))) |
2632 | return -EFAULT; | ||
2633 | return hpsb_iso_xmit_start(fi->iso_handle, | ||
2634 | args[0], args[1]); | ||
2642 | } | 2635 | } |
2643 | break; | 2636 | case RAW1394_IOC_ISO_XMIT_SYNC: |
2637 | return hpsb_iso_xmit_sync(fi->iso_handle); | ||
2638 | case RAW1394_IOC_ISO_XMIT_RECV_STOP: | ||
2639 | hpsb_iso_stop(fi->iso_handle); | ||
2640 | return 0; | ||
2641 | case RAW1394_IOC_ISO_GET_STATUS: | ||
2642 | return raw1394_iso_get_status(fi, argp); | ||
2643 | case RAW1394_IOC_ISO_XMIT_PACKETS: | ||
2644 | return raw1394_iso_send_packets(fi, argp); | ||
2645 | case RAW1394_IOC_ISO_SHUTDOWN: | ||
2646 | raw1394_iso_shutdown(fi); | ||
2647 | return 0; | ||
2648 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: | ||
2649 | queue_rawiso_event(fi); | ||
2650 | return 0; | ||
2644 | default: | 2651 | default: |
2645 | break; | 2652 | return -EINVAL; |
2646 | } | 2653 | } |
2654 | } | ||
2655 | |||
2656 | /* ioctl is only used for rawiso operations */ | ||
2657 | static long raw1394_ioctl(struct file *file, unsigned int cmd, | ||
2658 | unsigned long arg) | ||
2659 | { | ||
2660 | struct file_info *fi = file->private_data; | ||
2661 | void __user *argp = (void __user *)arg; | ||
2662 | long ret; | ||
2647 | 2663 | ||
2648 | /* state-independent commands */ | 2664 | /* state-independent commands */ |
2649 | switch(cmd) { | 2665 | switch(cmd) { |
@@ -2653,16 +2669,25 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd, | |||
2653 | break; | 2669 | break; |
2654 | } | 2670 | } |
2655 | 2671 | ||
2656 | return -EINVAL; | 2672 | mutex_lock(&fi->state_mutex); |
2657 | } | 2673 | |
2674 | switch (fi->iso_state) { | ||
2675 | case RAW1394_ISO_INACTIVE: | ||
2676 | ret = raw1394_ioctl_inactive(fi, cmd, argp); | ||
2677 | break; | ||
2678 | case RAW1394_ISO_RECV: | ||
2679 | ret = raw1394_ioctl_recv(fi, cmd, arg); | ||
2680 | break; | ||
2681 | case RAW1394_ISO_XMIT: | ||
2682 | ret = raw1394_ioctl_xmit(fi, cmd, argp); | ||
2683 | break; | ||
2684 | default: | ||
2685 | ret = -EINVAL; | ||
2686 | break; | ||
2687 | } | ||
2688 | |||
2689 | mutex_unlock(&fi->state_mutex); | ||
2658 | 2690 | ||
2659 | static long raw1394_ioctl(struct file *file, unsigned int cmd, | ||
2660 | unsigned long arg) | ||
2661 | { | ||
2662 | long ret; | ||
2663 | lock_kernel(); | ||
2664 | ret = do_raw1394_ioctl(file, cmd, arg); | ||
2665 | unlock_kernel(); | ||
2666 | return ret; | 2691 | return ret; |
2667 | } | 2692 | } |
2668 | 2693 | ||
@@ -2700,7 +2725,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, | |||
2700 | !copy_from_user(&infos32, &arg->infos, sizeof infos32)) { | 2725 | !copy_from_user(&infos32, &arg->infos, sizeof infos32)) { |
2701 | infos = compat_ptr(infos32); | 2726 | infos = compat_ptr(infos32); |
2702 | if (!copy_to_user(&dst->infos, &infos, sizeof infos)) | 2727 | if (!copy_to_user(&dst->infos, &infos, sizeof infos)) |
2703 | err = do_raw1394_ioctl(file, cmd, (unsigned long)dst); | 2728 | err = raw1394_ioctl(file, cmd, (unsigned long)dst); |
2704 | } | 2729 | } |
2705 | return err; | 2730 | return err; |
2706 | } | 2731 | } |
@@ -2724,7 +2749,6 @@ static long raw1394_compat_ioctl(struct file *file, | |||
2724 | void __user *argp = (void __user *)arg; | 2749 | void __user *argp = (void __user *)arg; |
2725 | long err; | 2750 | long err; |
2726 | 2751 | ||
2727 | lock_kernel(); | ||
2728 | switch (cmd) { | 2752 | switch (cmd) { |
2729 | /* These requests have same format as long as 'int' has same size. */ | 2753 | /* These requests have same format as long as 'int' has same size. */ |
2730 | case RAW1394_IOC_ISO_RECV_INIT: | 2754 | case RAW1394_IOC_ISO_RECV_INIT: |
@@ -2741,7 +2765,7 @@ static long raw1394_compat_ioctl(struct file *file, | |||
2741 | case RAW1394_IOC_ISO_GET_STATUS: | 2765 | case RAW1394_IOC_ISO_GET_STATUS: |
2742 | case RAW1394_IOC_ISO_SHUTDOWN: | 2766 | case RAW1394_IOC_ISO_SHUTDOWN: |
2743 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: | 2767 | case RAW1394_IOC_ISO_QUEUE_ACTIVITY: |
2744 | err = do_raw1394_ioctl(file, cmd, arg); | 2768 | err = raw1394_ioctl(file, cmd, arg); |
2745 | break; | 2769 | break; |
2746 | /* These request have different format. */ | 2770 | /* These request have different format. */ |
2747 | case RAW1394_IOC_ISO_RECV_PACKETS32: | 2771 | case RAW1394_IOC_ISO_RECV_PACKETS32: |
@@ -2757,7 +2781,6 @@ static long raw1394_compat_ioctl(struct file *file, | |||
2757 | err = -EINVAL; | 2781 | err = -EINVAL; |
2758 | break; | 2782 | break; |
2759 | } | 2783 | } |
2760 | unlock_kernel(); | ||
2761 | 2784 | ||
2762 | return err; | 2785 | return err; |
2763 | } | 2786 | } |
@@ -2791,6 +2814,7 @@ static int raw1394_open(struct inode *inode, struct file *file) | |||
2791 | fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ | 2814 | fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ |
2792 | 2815 | ||
2793 | INIT_LIST_HEAD(&fi->list); | 2816 | INIT_LIST_HEAD(&fi->list); |
2817 | mutex_init(&fi->state_mutex); | ||
2794 | fi->state = opened; | 2818 | fi->state = opened; |
2795 | INIT_LIST_HEAD(&fi->req_pending); | 2819 | INIT_LIST_HEAD(&fi->req_pending); |
2796 | INIT_LIST_HEAD(&fi->req_complete); | 2820 | INIT_LIST_HEAD(&fi->req_complete); |