aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s2255drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/s2255drv.c')
-rw-r--r--drivers/media/video/s2255drv.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index e6dc7fac5b0..4dc001b0519 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -230,7 +230,7 @@ struct s2255_fmt; /*forward declaration */
struct s2255_dev {
struct video_device vdev[MAX_CHANNELS];
struct v4l2_device v4l2_dev;
- int channels; /* number of channels registered */
+ atomic_t channels; /* number of channels registered */
int frames;
struct mutex lock;
struct mutex open_lock;
@@ -276,12 +276,8 @@ struct s2255_dev {
/* dsp firmware version (f2255usb.bin) */
int dsp_fw_ver;
u16 pid; /* product id */
- struct kref kref;
};
-/* kref will be removed soon */
-#define to_s2255_dev_from_kref(d) container_of(d, struct s2255_dev, kref)
-
static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev)
{
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,
struct s2255_mode *mode);
static int s2255_board_shutdown(struct s2255_dev *dev);
static void s2255_fwload_start(struct s2255_dev *dev, int reset);
-static void s2255_destroy(struct kref *kref);
+static void s2255_destroy(struct s2255_dev *dev);
static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
u16 index, u16 value, void *buf,
s32 buf_len, int bOut);
@@ -1720,7 +1716,7 @@ static int s2255_open(struct file *file)
dprintk(1, "s2255: open called (dev=%s)\n",
video_device_node_name(vdev));
- for (i = 0; i < dev->channels; i++)
+ for (i = 0; i < MAX_CHANNELS; i++)
if (&dev->vdev[i] == vdev) {
cur_channel = i;
break;
@@ -1834,9 +1830,8 @@ static unsigned int s2255_poll(struct file *file,
return rc;
}
-static void s2255_destroy(struct kref *kref)
+static void s2255_destroy(struct s2255_dev *dev)
{
- struct s2255_dev *dev = to_s2255_dev_from_kref(kref);
/* board shutdown stops the read pipe if it is running */
s2255_board_shutdown(dev);
/* make sure firmware still not trying to load */
@@ -1936,7 +1931,9 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
static void s2255_video_device_release(struct video_device *vdev)
{
struct s2255_dev *dev = video_get_drvdata(vdev);
- kref_put(&dev->kref, s2255_destroy);
+ dprintk(4, "%s, chnls: %d \n", __func__, atomic_read(&dev->channels));
+ if (atomic_dec_and_test(&dev->channels))
+ s2255_destroy(dev);
return;
}
@@ -1965,7 +1962,8 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
dev->vidq[i].channel = i;
/* register 4 video devices */
memcpy(&dev->vdev[i], &template, sizeof(struct video_device));
- dev->vdev[i].parent = &dev->interface->dev;
+ dev->vdev[i].v4l2_dev = &dev->v4l2_dev;
+ video_set_drvdata(&dev->vdev[i], dev);
if (video_nr == -1)
ret = video_register_device(&dev->vdev[i],
VFL_TYPE_GRABBER,
@@ -1974,13 +1972,12 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
ret = video_register_device(&dev->vdev[i],
VFL_TYPE_GRABBER,
cur_nr + i);
- video_set_drvdata(&dev->vdev[i], dev);
if (ret) {
dev_err(&dev->udev->dev,
"failed to register video device!\n");
break;
}
- dev->channels++;
+ atomic_inc(&dev->channels);
v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
video_device_node_name(&dev->vdev[i]));
@@ -1990,11 +1987,11 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
S2255_MAJOR_VERSION,
S2255_MINOR_VERSION);
/* if no channels registered, return error and probe will fail*/
- if (dev->channels == 0) {
+ if (atomic_read(&dev->channels) == 0) {
v4l2_device_unregister(&dev->v4l2_dev);
return ret;
}
- if (dev->channels != MAX_CHANNELS)
+ if (atomic_read(&dev->channels) != MAX_CHANNELS)
printk(KERN_WARNING "s2255: Not all channels available.\n");
return 0;
}
@@ -2567,7 +2564,7 @@ static int s2255_probe(struct usb_interface *interface,
s2255_dev_err(&interface->dev, "out of memory\n");
return -ENOMEM;
}
- kref_init(&dev->kref);
+ atomic_set(&dev->channels, 0);
dev->pid = id->idProduct;
dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
if (!dev->fw_data)
@@ -2581,7 +2578,7 @@ static int s2255_probe(struct usb_interface *interface,
retval = -ENODEV;
goto errorUDEV;
}
- dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref,
+ dprintk(1, "dev: %p, udev %p interface %p\n", dev,
dev->udev, interface);
dev->interface = interface;
/* set up the endpoint information */
@@ -2652,9 +2649,6 @@ static int s2255_probe(struct usb_interface *interface,
goto errorBOARDINIT;
spin_lock_init(&dev->slock);
s2255_fwload_start(dev, 0);
- /* kref for each vdev. Released on video_device_release callback */
- for (i = 0; i < MAX_CHANNELS; i++)
- kref_get(&dev->kref);
/* loads v4l specific */
retval = s2255_probe_v4l(dev);
if (retval)
@@ -2688,11 +2682,15 @@ static void s2255_disconnect(struct usb_interface *interface)
{
struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
int i;
+ int channels = atomic_read(&dev->channels);
v4l2_device_unregister(&dev->v4l2_dev);
+ /*see comments in the uvc_driver.c usb disconnect function */
+ atomic_inc(&dev->channels);
/* unregister each video device. */
- for (i = 0; i < MAX_CHANNELS; i++)
+ for (i = 0; i < channels; i++) {
if (video_is_registered(&dev->vdev[i]))
video_unregister_device(&dev->vdev[i]);
+ }
/* wake up any of our timers */
atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
wake_up(&dev->fw_data->wait_fw);
@@ -2702,7 +2700,8 @@ static void s2255_disconnect(struct usb_interface *interface)
dev->vidstatus_ready[i] = 1;
wake_up(&dev->wait_vidstatus[i]);
}
- kref_put(&dev->kref, s2255_destroy);
+ if (atomic_dec_and_test(&dev->channels))
+ s2255_destroy(dev);
dev_info(&interface->dev, "%s\n", __func__);
}