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: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2008-12-19 21:28:27 -03:00 committed by Mauro Carvalho Chehab
parent be49e368fb
commit dc93a70cc7
2 changed files with 295 additions and 108 deletions

View file

@ -26,6 +26,11 @@
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
* This version moves redundant code from video device code to
@ -39,15 +44,17 @@ struct video_device
/* sysfs */
struct device dev; /* v4l device */
struct cdev cdev; /* character device */
void (*cdev_release)(struct kobject *kobj);
struct cdev *cdev; /* character device */
struct device *parent; /* device parent */
/* device info */
char name[32];
int vfl_type;
/* 'minor' is set to -1 if the registration failed */
int minor;
u16 num;
/* use bitops to set/clear/test flags */
unsigned long flags;
/* attribute to differentiate multiple indices on one physical device */
int index;
@ -58,7 +65,7 @@ struct video_device
v4l2_std_id current_norm; /* Current tvnorm */
/* callbacks */
void (*release)(struct video_device *vfd);
void (*release)(struct video_device *vdev);
/* ioctl callbacks */
const struct v4l2_ioctl_ops *ioctl_ops;
@ -67,36 +74,41 @@ struct video_device
/* dev to video-device */
#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 caller is responsible for freeing any data. Usually that means that
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,
you call video_device_release() on failure.
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);
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
latter can also be used for video_device->release(). */
struct video_device * __must_check video_device_alloc(void);
/* this release function frees the vfd pointer */
void video_device_release(struct video_device *vfd);
/* this release function frees the vdev pointer */
void video_device_release(struct video_device *vdev);
/* this release function does nothing, use when the video_device is a
static global struct. Note that having a static video_device is
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. */
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);
@ -108,4 +120,9 @@ static inline void *video_drvdata(struct file *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 */