aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/media/w9968cf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/media/w9968cf.c')
-rw-r--r--drivers/usb/media/w9968cf.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index 78cd1a577d26..b57dec3782e0 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -47,6 +47,13 @@
47#include "w9968cf.h" 47#include "w9968cf.h"
48#include "w9968cf_decoder.h" 48#include "w9968cf_decoder.h"
49 49
50static struct w9968cf_vpp_t* w9968cf_vpp;
51static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait);
52
53static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */
54static DEFINE_MUTEX(w9968cf_devlist_mutex); /* semaphore for list traversal */
55
56static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */
50 57
51 58
52/**************************************************************************** 59/****************************************************************************
@@ -2418,7 +2425,7 @@ w9968cf_configure_camera(struct w9968cf_device* cam,
2418 enum w9968cf_model_id mod_id, 2425 enum w9968cf_model_id mod_id,
2419 const unsigned short dev_nr) 2426 const unsigned short dev_nr)
2420{ 2427{
2421 init_MUTEX(&cam->fileop_sem); 2428 mutex_init(&cam->fileop_mutex);
2422 init_waitqueue_head(&cam->open); 2429 init_waitqueue_head(&cam->open);
2423 spin_lock_init(&cam->urb_lock); 2430 spin_lock_init(&cam->urb_lock);
2424 spin_lock_init(&cam->flist_lock); 2431 spin_lock_init(&cam->flist_lock);
@@ -2646,7 +2653,7 @@ static void w9968cf_adjust_configuration(struct w9968cf_device* cam)
2646 --------------------------------------------------------------------------*/ 2653 --------------------------------------------------------------------------*/
2647static void w9968cf_release_resources(struct w9968cf_device* cam) 2654static void w9968cf_release_resources(struct w9968cf_device* cam)
2648{ 2655{
2649 down(&w9968cf_devlist_sem); 2656 mutex_lock(&w9968cf_devlist_mutex);
2650 2657
2651 DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor) 2658 DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor)
2652 2659
@@ -2657,7 +2664,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
2657 kfree(cam->control_buffer); 2664 kfree(cam->control_buffer);
2658 kfree(cam->data_buffer); 2665 kfree(cam->data_buffer);
2659 2666
2660 up(&w9968cf_devlist_sem); 2667 mutex_unlock(&w9968cf_devlist_mutex);
2661} 2668}
2662 2669
2663 2670
@@ -2677,14 +2684,14 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
2677 2684
2678 cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); 2685 cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
2679 2686
2680 down(&cam->dev_sem); 2687 mutex_lock(&cam->dev_mutex);
2681 2688
2682 if (cam->sensor == CC_UNKNOWN) { 2689 if (cam->sensor == CC_UNKNOWN) {
2683 DBG(2, "No supported image sensor has been detected by the " 2690 DBG(2, "No supported image sensor has been detected by the "
2684 "'ovcamchip' module for the %s (/dev/video%d). Make " 2691 "'ovcamchip' module for the %s (/dev/video%d). Make "
2685 "sure it is loaded *before* (re)connecting the camera.", 2692 "sure it is loaded *before* (re)connecting the camera.",
2686 symbolic(camlist, cam->id), cam->v4ldev->minor) 2693 symbolic(camlist, cam->id), cam->v4ldev->minor)
2687 up(&cam->dev_sem); 2694 mutex_unlock(&cam->dev_mutex);
2688 up_read(&w9968cf_disconnect); 2695 up_read(&w9968cf_disconnect);
2689 return -ENODEV; 2696 return -ENODEV;
2690 } 2697 }
@@ -2693,11 +2700,11 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
2693 DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", 2700 DBG(2, "%s (/dev/video%d) has been already occupied by '%s'",
2694 symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command) 2701 symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command)
2695 if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { 2702 if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
2696 up(&cam->dev_sem); 2703 mutex_unlock(&cam->dev_mutex);
2697 up_read(&w9968cf_disconnect); 2704 up_read(&w9968cf_disconnect);
2698 return -EWOULDBLOCK; 2705 return -EWOULDBLOCK;
2699 } 2706 }
2700 up(&cam->dev_sem); 2707 mutex_unlock(&cam->dev_mutex);
2701 err = wait_event_interruptible_exclusive(cam->open, 2708 err = wait_event_interruptible_exclusive(cam->open,
2702 cam->disconnected || 2709 cam->disconnected ||
2703 !cam->users); 2710 !cam->users);
@@ -2709,7 +2716,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
2709 up_read(&w9968cf_disconnect); 2716 up_read(&w9968cf_disconnect);
2710 return -ENODEV; 2717 return -ENODEV;
2711 } 2718 }
2712 down(&cam->dev_sem); 2719 mutex_lock(&cam->dev_mutex);
2713 } 2720 }
2714 2721
2715 DBG(5, "Opening '%s', /dev/video%d ...", 2722 DBG(5, "Opening '%s', /dev/video%d ...",
@@ -2738,7 +2745,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
2738 2745
2739 DBG(5, "Video device is open") 2746 DBG(5, "Video device is open")
2740 2747
2741 up(&cam->dev_sem); 2748 mutex_unlock(&cam->dev_mutex);
2742 up_read(&w9968cf_disconnect); 2749 up_read(&w9968cf_disconnect);
2743 2750
2744 return 0; 2751 return 0;
@@ -2746,7 +2753,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
2746deallocate_memory: 2753deallocate_memory:
2747 w9968cf_deallocate_memory(cam); 2754 w9968cf_deallocate_memory(cam);
2748 DBG(2, "Failed to open the video device") 2755 DBG(2, "Failed to open the video device")
2749 up(&cam->dev_sem); 2756 mutex_unlock(&cam->dev_mutex);
2750 up_read(&w9968cf_disconnect); 2757 up_read(&w9968cf_disconnect);
2751 return err; 2758 return err;
2752} 2759}
@@ -2758,13 +2765,13 @@ static int w9968cf_release(struct inode* inode, struct file* filp)
2758 2765
2759 cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); 2766 cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
2760 2767
2761 down(&cam->dev_sem); /* prevent disconnect() to be called */ 2768 mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
2762 2769
2763 w9968cf_stop_transfer(cam); 2770 w9968cf_stop_transfer(cam);
2764 2771
2765 if (cam->disconnected) { 2772 if (cam->disconnected) {
2766 w9968cf_release_resources(cam); 2773 w9968cf_release_resources(cam);
2767 up(&cam->dev_sem); 2774 mutex_unlock(&cam->dev_mutex);
2768 kfree(cam); 2775 kfree(cam);
2769 return 0; 2776 return 0;
2770 } 2777 }
@@ -2774,7 +2781,7 @@ static int w9968cf_release(struct inode* inode, struct file* filp)
2774 wake_up_interruptible_nr(&cam->open, 1); 2781 wake_up_interruptible_nr(&cam->open, 1);
2775 2782
2776 DBG(5, "Video device closed") 2783 DBG(5, "Video device closed")
2777 up(&cam->dev_sem); 2784 mutex_unlock(&cam->dev_mutex);
2778 return 0; 2785 return 0;
2779} 2786}
2780 2787
@@ -2791,18 +2798,18 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
2791 if (filp->f_flags & O_NONBLOCK) 2798 if (filp->f_flags & O_NONBLOCK)
2792 return -EWOULDBLOCK; 2799 return -EWOULDBLOCK;
2793 2800
2794 if (down_interruptible(&cam->fileop_sem)) 2801 if (mutex_lock_interruptible(&cam->fileop_mutex))
2795 return -ERESTARTSYS; 2802 return -ERESTARTSYS;
2796 2803
2797 if (cam->disconnected) { 2804 if (cam->disconnected) {
2798 DBG(2, "Device not present") 2805 DBG(2, "Device not present")
2799 up(&cam->fileop_sem); 2806 mutex_unlock(&cam->fileop_mutex);
2800 return -ENODEV; 2807 return -ENODEV;
2801 } 2808 }
2802 2809
2803 if (cam->misconfigured) { 2810 if (cam->misconfigured) {
2804 DBG(2, "The camera is misconfigured. Close and open it again.") 2811 DBG(2, "The camera is misconfigured. Close and open it again.")
2805 up(&cam->fileop_sem); 2812 mutex_unlock(&cam->fileop_mutex);
2806 return -EIO; 2813 return -EIO;
2807 } 2814 }
2808 2815
@@ -2817,11 +2824,11 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
2817 cam->frame[1].status == F_READY || 2824 cam->frame[1].status == F_READY ||
2818 cam->disconnected); 2825 cam->disconnected);
2819 if (err) { 2826 if (err) {
2820 up(&cam->fileop_sem); 2827 mutex_unlock(&cam->fileop_mutex);
2821 return err; 2828 return err;
2822 } 2829 }
2823 if (cam->disconnected) { 2830 if (cam->disconnected) {
2824 up(&cam->fileop_sem); 2831 mutex_unlock(&cam->fileop_mutex);
2825 return -ENODEV; 2832 return -ENODEV;
2826 } 2833 }
2827 2834
@@ -2835,7 +2842,7 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
2835 2842
2836 if (copy_to_user(buf, fr->buffer, count)) { 2843 if (copy_to_user(buf, fr->buffer, count)) {
2837 fr->status = F_UNUSED; 2844 fr->status = F_UNUSED;
2838 up(&cam->fileop_sem); 2845 mutex_unlock(&cam->fileop_mutex);
2839 return -EFAULT; 2846 return -EFAULT;
2840 } 2847 }
2841 *f_pos += count; 2848 *f_pos += count;
@@ -2844,7 +2851,7 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
2844 2851
2845 DBG(5, "%zu bytes read", count) 2852 DBG(5, "%zu bytes read", count)
2846 2853
2847 up(&cam->fileop_sem); 2854 mutex_unlock(&cam->fileop_mutex);
2848 return count; 2855 return count;
2849} 2856}
2850 2857
@@ -2898,24 +2905,24 @@ w9968cf_ioctl(struct inode* inode, struct file* filp,
2898 2905
2899 cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); 2906 cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
2900 2907
2901 if (down_interruptible(&cam->fileop_sem)) 2908 if (mutex_lock_interruptible(&cam->fileop_mutex))
2902 return -ERESTARTSYS; 2909 return -ERESTARTSYS;
2903 2910
2904 if (cam->disconnected) { 2911 if (cam->disconnected) {
2905 DBG(2, "Device not present") 2912 DBG(2, "Device not present")
2906 up(&cam->fileop_sem); 2913 mutex_unlock(&cam->fileop_mutex);
2907 return -ENODEV; 2914 return -ENODEV;
2908 } 2915 }
2909 2916
2910 if (cam->misconfigured) { 2917 if (cam->misconfigured) {
2911 DBG(2, "The camera is misconfigured. Close and open it again.") 2918 DBG(2, "The camera is misconfigured. Close and open it again.")
2912 up(&cam->fileop_sem); 2919 mutex_unlock(&cam->fileop_mutex);
2913 return -EIO; 2920 return -EIO;
2914 } 2921 }
2915 2922
2916 err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg); 2923 err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg);
2917 2924
2918 up(&cam->fileop_sem); 2925 mutex_unlock(&cam->fileop_mutex);
2919 return err; 2926 return err;
2920} 2927}
2921 2928
@@ -3502,8 +3509,8 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3502 if (!cam) 3509 if (!cam)
3503 return -ENOMEM; 3510 return -ENOMEM;
3504 3511
3505 init_MUTEX(&cam->dev_sem); 3512 mutex_init(&cam->dev_mutex);
3506 down(&cam->dev_sem); 3513 mutex_lock(&cam->dev_mutex);
3507 3514
3508 cam->usbdev = udev; 3515 cam->usbdev = udev;
3509 /* NOTE: a local copy is used to avoid possible race conditions */ 3516 /* NOTE: a local copy is used to avoid possible race conditions */
@@ -3515,10 +3522,10 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3515 simcams = W9968CF_SIMCAMS; 3522 simcams = W9968CF_SIMCAMS;
3516 3523
3517 /* How many cameras are connected ? */ 3524 /* How many cameras are connected ? */
3518 down(&w9968cf_devlist_sem); 3525 mutex_lock(&w9968cf_devlist_mutex);
3519 list_for_each(ptr, &w9968cf_dev_list) 3526 list_for_each(ptr, &w9968cf_dev_list)
3520 sc++; 3527 sc++;
3521 up(&w9968cf_devlist_sem); 3528 mutex_unlock(&w9968cf_devlist_mutex);
3522 3529
3523 if (sc >= simcams) { 3530 if (sc >= simcams) {
3524 DBG(2, "Device rejected: too many connected cameras " 3531 DBG(2, "Device rejected: too many connected cameras "
@@ -3578,9 +3585,9 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3578 w9968cf_configure_camera(cam, udev, mod_id, dev_nr); 3585 w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
3579 3586
3580 /* Add a new entry into the list of V4L registered devices */ 3587 /* Add a new entry into the list of V4L registered devices */
3581 down(&w9968cf_devlist_sem); 3588 mutex_lock(&w9968cf_devlist_mutex);
3582 list_add(&cam->v4llist, &w9968cf_dev_list); 3589 list_add(&cam->v4llist, &w9968cf_dev_list);
3583 up(&w9968cf_devlist_sem); 3590 mutex_unlock(&w9968cf_devlist_mutex);
3584 dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; 3591 dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0;
3585 3592
3586 w9968cf_turn_on_led(cam); 3593 w9968cf_turn_on_led(cam);
@@ -3588,7 +3595,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3588 w9968cf_i2c_init(cam); 3595 w9968cf_i2c_init(cam);
3589 3596
3590 usb_set_intfdata(intf, cam); 3597 usb_set_intfdata(intf, cam);
3591 up(&cam->dev_sem); 3598 mutex_unlock(&cam->dev_mutex);
3592 return 0; 3599 return 0;
3593 3600
3594fail: /* Free unused memory */ 3601fail: /* Free unused memory */
@@ -3596,7 +3603,7 @@ fail: /* Free unused memory */
3596 kfree(cam->data_buffer); 3603 kfree(cam->data_buffer);
3597 if (cam->v4ldev) 3604 if (cam->v4ldev)
3598 video_device_release(cam->v4ldev); 3605 video_device_release(cam->v4ldev);
3599 up(&cam->dev_sem); 3606 mutex_unlock(&cam->dev_mutex);
3600 kfree(cam); 3607 kfree(cam);
3601 return err; 3608 return err;
3602} 3609}
@@ -3611,7 +3618,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
3611 3618
3612 if (cam) { 3619 if (cam) {
3613 /* Prevent concurrent accesses to data */ 3620 /* Prevent concurrent accesses to data */
3614 down(&cam->dev_sem); 3621 mutex_lock(&cam->dev_mutex);
3615 3622
3616 cam->disconnected = 1; 3623 cam->disconnected = 1;
3617 3624
@@ -3630,7 +3637,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
3630 } else 3637 } else
3631 w9968cf_release_resources(cam); 3638 w9968cf_release_resources(cam);
3632 3639
3633 up(&cam->dev_sem); 3640 mutex_unlock(&cam->dev_mutex);
3634 3641
3635 if (!cam->users) 3642 if (!cam->users)
3636 kfree(cam); 3643 kfree(cam);