From c0e1a168c8871c030502120b0f02fda348e14db7 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Thu, 8 Jun 2006 00:01:19 -0500 Subject: Remove last bits of V4L1 dependant code From: Mike Isely With the removal of the V4L1 API, we also lose the functionality provided by the video_get_drvdata() and video_set_drvdata() functions. These functions had made it possible for a driver to stuff a pointer to its own context inside the V4L device handle context - a useful ability. However now that's going away, so the driver is on its own to find its context when called into from a more generic context (e.g. the open() entrypoint). The changes in this patch implement a global context mapping array, an array index back-reference per instance, and a new global mutex to protect the entire thing. The array is indexed by the minor device id of the V4L device inode. All this fun is present to work around what used to be roughly 4 lines of code. Sigh... Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 71 +++++++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index f4284f927..78cdd01c8 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -22,8 +22,6 @@ #include "compat.h" #include -#include - #include "pvrusb2-context.h" #include "pvrusb2-hdw.h" #include "pvrusb2.h" @@ -37,10 +35,21 @@ struct pvr2_v4l2_dev; struct pvr2_v4l2_fh; struct pvr2_v4l2; +/* V4L no longer provide the ability to set / get a private context pointer + (i.e. video_get_drvdata / video_set_drvdata), which means we have to + concoct our own context locating mechanism. Supposedly this is intended + to simplify driver implementation. It's not clear to me how that can + possibly be true. Our solution here is to maintain a lookup table of + our context instances, indexed by the minor device number of the V4L + device. See pvr2_v4l2_open() for some implications of this approach. */ +static struct pvr2_v4l2_dev *devices[256]; +static DEFINE_MUTEX(device_lock); + struct pvr2_v4l2_dev { struct pvr2_v4l2 *v4lp; struct video_device *vdev; struct pvr2_context_stream *stream; + int ctxt_idx; enum pvr2_config config; }; @@ -641,6 +650,12 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) pvr2_trace(PVR2_TRACE_INIT, "unregistering device video%d [%s]", dip->vdev->minor,pvr2_config_get_name(dip->config)); + if (dip->ctxt_idx >= 0) { + mutex_lock(&device_lock); + devices[dip->ctxt_idx] = NULL; + dip->ctxt_idx = -1; + mutex_unlock(&device_lock); + } video_unregister_device(dip->vdev); } @@ -727,12 +742,43 @@ int pvr2_v4l2_release(struct inode *inode, struct file *file) int pvr2_v4l2_open(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct pvr2_v4l2_dev *dip = - (struct pvr2_v4l2_dev *)video_get_drvdata(vdev); + struct pvr2_v4l2_dev *dip = 0; /* Our own context pointer */ struct pvr2_v4l2_fh *fhp; - struct pvr2_v4l2 *vp = dip->v4lp; - struct pvr2_hdw *hdw = vp->channel.hdw; + struct pvr2_v4l2 *vp; + struct pvr2_hdw *hdw; + + mutex_lock(&device_lock); + /* MCI 7-Jun-2006 Even though we're just doing what amounts to an + atomic read of the device mapping array here, we still need the + mutex. The problem is that there is a tiny race possible when + we register the device. We can't update the device mapping + array until after the device has been registered, owing to the + fact that we can't know the minor device number until after the + registration succeeds. And if another thread tries to open the + device in the window of time after registration but before the + map is updated, then it will get back an erroneous null pointer + and the open will result in a spurious failure. The only way to + prevent that is to (a) be inside the mutex here before we access + the array, and (b) cover the entire registration process later + on with this same mutex. Thus if we get inside the mutex here, + then we can be assured that the registration process actually + completed correctly. This is an unhappy complication from the + use of global data in a driver that lives in a preemptible + environment. It sure would be nice if the video device itself + had a means for storing and retrieving a local context pointer. + Oh wait. It did. But now it's gone. Silly me. */ + { + unsigned int midx = iminor(file->f_dentry->d_inode); + if (midx < sizeof(devices)/sizeof(devices[0])) { + dip = devices[midx]; + } + } + mutex_unlock(&device_lock); + + if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */ + + vp = dip->v4lp; + hdw = vp->channel.hdw; pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open"); @@ -980,7 +1026,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, dip->vdev->dev = &usbdev->dev; #endif dip->vdev->release = video_device_release; - video_set_drvdata(dip->vdev,dip); + mutex_lock(&device_lock); mindevnum = -1; unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); @@ -995,6 +1041,14 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, "registered device video%d [%s]", dip->vdev->minor,pvr2_config_get_name(dip->config)); } + + if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) && + (devices[dip->vdev->minor] == NULL)) { + dip->ctxt_idx = dip->vdev->minor; + devices[dip->ctxt_idx] = dip; + } + mutex_unlock(&device_lock); + pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, dip->vdev->minor); } @@ -1007,6 +1061,7 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) vp = kmalloc(sizeof(*vp),GFP_KERNEL); if (!vp) return vp; memset(vp,0,sizeof(*vp)); + vp->video_dev.ctxt_idx = -1; pvr2_channel_init(&vp->channel,mnp); pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); -- cgit v1.2.3 From 49e6c586ba2502f5cdce194081b3b9cfb590efec Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 11 Jun 2006 17:14:35 -0300 Subject: Fix cinergyt2_poll() to allow non-blocking IO on frontend From: Dyks, Axel (XL) cinergyt2_poll()" shouldn't return (POLLIN | POLLRDNORM | POLLPRI) when there are no pending events. User space programs that do non-bocking IO using "select()" and/or "poll()" would otherwise produce high system load. Signed-off-by: Axel Dyks Acked-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/cinergyT2/cinergyT2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c index 8dbba1ca7..0fb56a66a 100644 --- a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -561,15 +561,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct { struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; + unsigned int mask = 0; if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; poll_wait(file, &cinergyt2->poll_wq, wait); + if (cinergyt2->pending_fe_events != 0) + mask |= (POLLIN | POLLRDNORM | POLLPRI); + mutex_unlock(&cinergyt2->sem); - return (POLLIN | POLLRDNORM | POLLPRI); + return mask; } -- cgit v1.2.3 From 3a43601e74870844d9420353be082c2a5a1fc56e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 11 Jun 2006 18:05:10 -0300 Subject: pvrusb2 is now a V4L2 driver. Fixed Kconfig. From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 207efa6c0..4a7f88484 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" - depends on VIDEO_V4L1 && USB && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM -- cgit v1.2.3