* already been canceled by the USB core. There is no need to kill the
* interrupt URB manually.
*/
-static void uvc_delete(struct uvc_device *dev)
+static void uvc_delete(struct kref *kref)
{
+ struct uvc_device *dev = container_of(kref, struct uvc_device, ref);
struct list_head *p, *n;
uvc_status_cleanup(dev);
struct uvc_streaming *stream = video_get_drvdata(vdev);
struct uvc_device *dev = stream->dev;
- /* Decrement the registered streams count and delete the device when it
- * reaches zero.
- */
- if (atomic_dec_and_test(&dev->nstreams))
- uvc_delete(dev);
+ kref_put(&dev->ref, uvc_delete);
}
/*
/* Unregistering all video devices might result in uvc_delete() being
* called from inside the loop if there's no open file handle. To avoid
- * that, increment the stream count before iterating over the streams
- * and decrement it when done.
+ * that, increment the refcount before iterating over the streams and
+ * decrement it when done.
*/
- atomic_inc(&dev->nstreams);
+ kref_get(&dev->ref);
list_for_each_entry(stream, &dev->streams, list) {
if (!video_is_registered(&stream->vdev))
uvc_debugfs_cleanup_stream(stream);
}
- /* Decrement the stream count and call uvc_delete explicitly if there
- * are no stream left.
- */
- if (atomic_dec_and_test(&dev->nstreams))
- uvc_delete(dev);
+ kref_put(&dev->ref, uvc_delete);
}
static int uvc_register_video(struct uvc_device *dev,
else
stream->chain->caps |= V4L2_CAP_VIDEO_OUTPUT;
- atomic_inc(&dev->nstreams);
+ kref_get(&dev->ref);
return 0;
}
INIT_LIST_HEAD(&dev->entities);
INIT_LIST_HEAD(&dev->chains);
INIT_LIST_HEAD(&dev->streams);
- atomic_set(&dev->nstreams, 0);
+ kref_init(&dev->ref);
atomic_set(&dev->nmappings, 0);
mutex_init(&dev->lock);