diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/s2255drv.c | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index e6dc7fac5b01..4dc001b0519a 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -230,7 +230,7 @@ struct s2255_fmt; /*forward declaration */ | |||
230 | struct s2255_dev { | 230 | struct s2255_dev { |
231 | struct video_device vdev[MAX_CHANNELS]; | 231 | struct video_device vdev[MAX_CHANNELS]; |
232 | struct v4l2_device v4l2_dev; | 232 | struct v4l2_device v4l2_dev; |
233 | int channels; /* number of channels registered */ | 233 | atomic_t channels; /* number of channels registered */ |
234 | int frames; | 234 | int frames; |
235 | struct mutex lock; | 235 | struct mutex lock; |
236 | struct mutex open_lock; | 236 | struct mutex open_lock; |
@@ -276,12 +276,8 @@ struct s2255_dev { | |||
276 | /* dsp firmware version (f2255usb.bin) */ | 276 | /* dsp firmware version (f2255usb.bin) */ |
277 | int dsp_fw_ver; | 277 | int dsp_fw_ver; |
278 | u16 pid; /* product id */ | 278 | u16 pid; /* product id */ |
279 | struct kref kref; | ||
280 | }; | 279 | }; |
281 | 280 | ||
282 | /* kref will be removed soon */ | ||
283 | #define to_s2255_dev_from_kref(d) container_of(d, struct s2255_dev, kref) | ||
284 | |||
285 | static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) | 281 | static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) |
286 | { | 282 | { |
287 | return container_of(v4l2_dev, struct s2255_dev, v4l2_dev); | 283 | return container_of(v4l2_dev, struct s2255_dev, v4l2_dev); |
@@ -372,7 +368,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
372 | struct s2255_mode *mode); | 368 | struct s2255_mode *mode); |
373 | static int s2255_board_shutdown(struct s2255_dev *dev); | 369 | static int s2255_board_shutdown(struct s2255_dev *dev); |
374 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); | 370 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); |
375 | static void s2255_destroy(struct kref *kref); | 371 | static void s2255_destroy(struct s2255_dev *dev); |
376 | static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, | 372 | static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, |
377 | u16 index, u16 value, void *buf, | 373 | u16 index, u16 value, void *buf, |
378 | s32 buf_len, int bOut); | 374 | s32 buf_len, int bOut); |
@@ -1720,7 +1716,7 @@ static int s2255_open(struct file *file) | |||
1720 | dprintk(1, "s2255: open called (dev=%s)\n", | 1716 | dprintk(1, "s2255: open called (dev=%s)\n", |
1721 | video_device_node_name(vdev)); | 1717 | video_device_node_name(vdev)); |
1722 | 1718 | ||
1723 | for (i = 0; i < dev->channels; i++) | 1719 | for (i = 0; i < MAX_CHANNELS; i++) |
1724 | if (&dev->vdev[i] == vdev) { | 1720 | if (&dev->vdev[i] == vdev) { |
1725 | cur_channel = i; | 1721 | cur_channel = i; |
1726 | break; | 1722 | break; |
@@ -1834,9 +1830,8 @@ static unsigned int s2255_poll(struct file *file, | |||
1834 | return rc; | 1830 | return rc; |
1835 | } | 1831 | } |
1836 | 1832 | ||
1837 | static void s2255_destroy(struct kref *kref) | 1833 | static void s2255_destroy(struct s2255_dev *dev) |
1838 | { | 1834 | { |
1839 | struct s2255_dev *dev = to_s2255_dev_from_kref(kref); | ||
1840 | /* board shutdown stops the read pipe if it is running */ | 1835 | /* board shutdown stops the read pipe if it is running */ |
1841 | s2255_board_shutdown(dev); | 1836 | s2255_board_shutdown(dev); |
1842 | /* make sure firmware still not trying to load */ | 1837 | /* make sure firmware still not trying to load */ |
@@ -1936,7 +1931,9 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { | |||
1936 | static void s2255_video_device_release(struct video_device *vdev) | 1931 | static void s2255_video_device_release(struct video_device *vdev) |
1937 | { | 1932 | { |
1938 | struct s2255_dev *dev = video_get_drvdata(vdev); | 1933 | struct s2255_dev *dev = video_get_drvdata(vdev); |
1939 | kref_put(&dev->kref, s2255_destroy); | 1934 | dprintk(4, "%s, chnls: %d \n", __func__, atomic_read(&dev->channels)); |
1935 | if (atomic_dec_and_test(&dev->channels)) | ||
1936 | s2255_destroy(dev); | ||
1940 | return; | 1937 | return; |
1941 | } | 1938 | } |
1942 | 1939 | ||
@@ -1965,7 +1962,8 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1965 | dev->vidq[i].channel = i; | 1962 | dev->vidq[i].channel = i; |
1966 | /* register 4 video devices */ | 1963 | /* register 4 video devices */ |
1967 | memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); | 1964 | memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); |
1968 | dev->vdev[i].parent = &dev->interface->dev; | 1965 | dev->vdev[i].v4l2_dev = &dev->v4l2_dev; |
1966 | video_set_drvdata(&dev->vdev[i], dev); | ||
1969 | if (video_nr == -1) | 1967 | if (video_nr == -1) |
1970 | ret = video_register_device(&dev->vdev[i], | 1968 | ret = video_register_device(&dev->vdev[i], |
1971 | VFL_TYPE_GRABBER, | 1969 | VFL_TYPE_GRABBER, |
@@ -1974,13 +1972,12 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1974 | ret = video_register_device(&dev->vdev[i], | 1972 | ret = video_register_device(&dev->vdev[i], |
1975 | VFL_TYPE_GRABBER, | 1973 | VFL_TYPE_GRABBER, |
1976 | cur_nr + i); | 1974 | cur_nr + i); |
1977 | video_set_drvdata(&dev->vdev[i], dev); | ||
1978 | if (ret) { | 1975 | if (ret) { |
1979 | dev_err(&dev->udev->dev, | 1976 | dev_err(&dev->udev->dev, |
1980 | "failed to register video device!\n"); | 1977 | "failed to register video device!\n"); |
1981 | break; | 1978 | break; |
1982 | } | 1979 | } |
1983 | dev->channels++; | 1980 | atomic_inc(&dev->channels); |
1984 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", | 1981 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", |
1985 | video_device_node_name(&dev->vdev[i])); | 1982 | video_device_node_name(&dev->vdev[i])); |
1986 | 1983 | ||
@@ -1990,11 +1987,11 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1990 | S2255_MAJOR_VERSION, | 1987 | S2255_MAJOR_VERSION, |
1991 | S2255_MINOR_VERSION); | 1988 | S2255_MINOR_VERSION); |
1992 | /* if no channels registered, return error and probe will fail*/ | 1989 | /* if no channels registered, return error and probe will fail*/ |
1993 | if (dev->channels == 0) { | 1990 | if (atomic_read(&dev->channels) == 0) { |
1994 | v4l2_device_unregister(&dev->v4l2_dev); | 1991 | v4l2_device_unregister(&dev->v4l2_dev); |
1995 | return ret; | 1992 | return ret; |
1996 | } | 1993 | } |
1997 | if (dev->channels != MAX_CHANNELS) | 1994 | if (atomic_read(&dev->channels) != MAX_CHANNELS) |
1998 | printk(KERN_WARNING "s2255: Not all channels available.\n"); | 1995 | printk(KERN_WARNING "s2255: Not all channels available.\n"); |
1999 | return 0; | 1996 | return 0; |
2000 | } | 1997 | } |
@@ -2567,7 +2564,7 @@ static int s2255_probe(struct usb_interface *interface, | |||
2567 | s2255_dev_err(&interface->dev, "out of memory\n"); | 2564 | s2255_dev_err(&interface->dev, "out of memory\n"); |
2568 | return -ENOMEM; | 2565 | return -ENOMEM; |
2569 | } | 2566 | } |
2570 | kref_init(&dev->kref); | 2567 | atomic_set(&dev->channels, 0); |
2571 | dev->pid = id->idProduct; | 2568 | dev->pid = id->idProduct; |
2572 | dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); | 2569 | dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); |
2573 | if (!dev->fw_data) | 2570 | if (!dev->fw_data) |
@@ -2581,7 +2578,7 @@ static int s2255_probe(struct usb_interface *interface, | |||
2581 | retval = -ENODEV; | 2578 | retval = -ENODEV; |
2582 | goto errorUDEV; | 2579 | goto errorUDEV; |
2583 | } | 2580 | } |
2584 | dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref, | 2581 | dprintk(1, "dev: %p, udev %p interface %p\n", dev, |
2585 | dev->udev, interface); | 2582 | dev->udev, interface); |
2586 | dev->interface = interface; | 2583 | dev->interface = interface; |
2587 | /* set up the endpoint information */ | 2584 | /* set up the endpoint information */ |
@@ -2652,9 +2649,6 @@ static int s2255_probe(struct usb_interface *interface, | |||
2652 | goto errorBOARDINIT; | 2649 | goto errorBOARDINIT; |
2653 | spin_lock_init(&dev->slock); | 2650 | spin_lock_init(&dev->slock); |
2654 | s2255_fwload_start(dev, 0); | 2651 | s2255_fwload_start(dev, 0); |
2655 | /* kref for each vdev. Released on video_device_release callback */ | ||
2656 | for (i = 0; i < MAX_CHANNELS; i++) | ||
2657 | kref_get(&dev->kref); | ||
2658 | /* loads v4l specific */ | 2652 | /* loads v4l specific */ |
2659 | retval = s2255_probe_v4l(dev); | 2653 | retval = s2255_probe_v4l(dev); |
2660 | if (retval) | 2654 | if (retval) |
@@ -2688,11 +2682,15 @@ static void s2255_disconnect(struct usb_interface *interface) | |||
2688 | { | 2682 | { |
2689 | struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); | 2683 | struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); |
2690 | int i; | 2684 | int i; |
2685 | int channels = atomic_read(&dev->channels); | ||
2691 | v4l2_device_unregister(&dev->v4l2_dev); | 2686 | v4l2_device_unregister(&dev->v4l2_dev); |
2687 | /*see comments in the uvc_driver.c usb disconnect function */ | ||
2688 | atomic_inc(&dev->channels); | ||
2692 | /* unregister each video device. */ | 2689 | /* unregister each video device. */ |
2693 | for (i = 0; i < MAX_CHANNELS; i++) | 2690 | for (i = 0; i < channels; i++) { |
2694 | if (video_is_registered(&dev->vdev[i])) | 2691 | if (video_is_registered(&dev->vdev[i])) |
2695 | video_unregister_device(&dev->vdev[i]); | 2692 | video_unregister_device(&dev->vdev[i]); |
2693 | } | ||
2696 | /* wake up any of our timers */ | 2694 | /* wake up any of our timers */ |
2697 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | 2695 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); |
2698 | wake_up(&dev->fw_data->wait_fw); | 2696 | wake_up(&dev->fw_data->wait_fw); |
@@ -2702,7 +2700,8 @@ static void s2255_disconnect(struct usb_interface *interface) | |||
2702 | dev->vidstatus_ready[i] = 1; | 2700 | dev->vidstatus_ready[i] = 1; |
2703 | wake_up(&dev->wait_vidstatus[i]); | 2701 | wake_up(&dev->wait_vidstatus[i]); |
2704 | } | 2702 | } |
2705 | kref_put(&dev->kref, s2255_destroy); | 2703 | if (atomic_dec_and_test(&dev->channels)) |
2704 | s2255_destroy(dev); | ||
2706 | dev_info(&interface->dev, "%s\n", __func__); | 2705 | dev_info(&interface->dev, "%s\n", __func__); |
2707 | } | 2706 | } |
2708 | 2707 | ||