Commit dc93a70c authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB (9973): v4l2-dev: use the release callback from device instead of cdev

Instead of relying on the cdev release callback we should rely on the
release callback from the device struct. This requires that we use
get_device/put_device to do proper refcounting. In order to do this
safely v4l2-dev.c now sets up its own file_operations that call
out to the driver's ops.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent be49e368
This diff is collapsed.
...@@ -26,6 +26,11 @@ ...@@ -26,6 +26,11 @@
struct v4l2_ioctl_callbacks; struct v4l2_ioctl_callbacks;
/* Flag to mark the video_device struct as unregistered.
Drivers can set this flag if they want to block all future
device access. It is set by video_unregister_device. */
#define V4L2_FL_UNREGISTERED (0)
/* /*
* Newer version of video_device, handled by videodev2.c * Newer version of video_device, handled by videodev2.c
* This version moves redundant code from video device code to * This version moves redundant code from video device code to
...@@ -39,15 +44,17 @@ struct video_device ...@@ -39,15 +44,17 @@ struct video_device
/* sysfs */ /* sysfs */
struct device dev; /* v4l device */ struct device dev; /* v4l device */
struct cdev cdev; /* character device */ struct cdev *cdev; /* character device */
void (*cdev_release)(struct kobject *kobj);
struct device *parent; /* device parent */ struct device *parent; /* device parent */
/* device info */ /* device info */
char name[32]; char name[32];
int vfl_type; int vfl_type;
/* 'minor' is set to -1 if the registration failed */
int minor; int minor;
u16 num; u16 num;
/* use bitops to set/clear/test flags */
unsigned long flags;
/* attribute to differentiate multiple indices on one physical device */ /* attribute to differentiate multiple indices on one physical device */
int index; int index;
...@@ -58,7 +65,7 @@ struct video_device ...@@ -58,7 +65,7 @@ struct video_device
v4l2_std_id current_norm; /* Current tvnorm */ v4l2_std_id current_norm; /* Current tvnorm */
/* callbacks */ /* callbacks */
void (*release)(struct video_device *vfd); void (*release)(struct video_device *vdev);
/* ioctl callbacks */ /* ioctl callbacks */
const struct v4l2_ioctl_ops *ioctl_ops; const struct v4l2_ioctl_ops *ioctl_ops;
...@@ -67,36 +74,41 @@ struct video_device ...@@ -67,36 +74,41 @@ struct video_device
/* dev to video-device */ /* dev to video-device */
#define to_video_device(cd) container_of(cd, struct video_device, dev) #define to_video_device(cd) container_of(cd, struct video_device, dev)
/* Register and unregister devices. Note that if video_register_device fails, /* Register video devices. Note that if video_register_device fails,
the release() callback of the video_device structure is *not* called, so the release() callback of the video_device structure is *not* called, so
the caller is responsible for freeing any data. Usually that means that the caller is responsible for freeing any data. Usually that means that
you call video_device_release() on failure. */ you call video_device_release() on failure.
int __must_check video_register_device(struct video_device *vfd, int type, int nr);
int __must_check video_register_device_index(struct video_device *vfd, Also note that vdev->minor is set to -1 if the registration failed. */
int __must_check video_register_device(struct video_device *vdev, int type, int nr);
int __must_check video_register_device_index(struct video_device *vdev,
int type, int nr, int index); int type, int nr, int index);
void video_unregister_device(struct video_device *vfd);
/* Unregister video devices. Will do nothing if vdev == NULL or
vdev->minor < 0. */
void video_unregister_device(struct video_device *vdev);
/* helper functions to alloc/release struct video_device, the /* helper functions to alloc/release struct video_device, the
latter can also be used for video_device->release(). */ latter can also be used for video_device->release(). */
struct video_device * __must_check video_device_alloc(void); struct video_device * __must_check video_device_alloc(void);
/* this release function frees the vfd pointer */ /* this release function frees the vdev pointer */
void video_device_release(struct video_device *vfd); void video_device_release(struct video_device *vdev);
/* this release function does nothing, use when the video_device is a /* this release function does nothing, use when the video_device is a
static global struct. Note that having a static video_device is static global struct. Note that having a static video_device is
a dubious construction at best. */ a dubious construction at best. */
void video_device_release_empty(struct video_device *vfd); void video_device_release_empty(struct video_device *vdev);
/* helper functions to access driver private data. */ /* helper functions to access driver private data. */
static inline void *video_get_drvdata(struct video_device *dev) static inline void *video_get_drvdata(struct video_device *vdev)
{ {
return dev_get_drvdata(&dev->dev); return dev_get_drvdata(&vdev->dev);
} }
static inline void video_set_drvdata(struct video_device *dev, void *data) static inline void video_set_drvdata(struct video_device *vdev, void *data)
{ {
dev_set_drvdata(&dev->dev, data); dev_set_drvdata(&vdev->dev, data);
} }
struct video_device *video_devdata(struct file *file); struct video_device *video_devdata(struct file *file);
...@@ -108,4 +120,9 @@ static inline void *video_drvdata(struct file *file) ...@@ -108,4 +120,9 @@ static inline void *video_drvdata(struct file *file)
return video_get_drvdata(video_devdata(file)); return video_get_drvdata(video_devdata(file));
} }
static inline int video_is_unregistered(struct video_device *vdev)
{
return test_bit(V4L2_FL_UNREGISTERED, &vdev->flags);
}
#endif /* _V4L2_DEV_H */ #endif /* _V4L2_DEV_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment