Fabian Förg wrote:
> Hello,
> 
> I realized that only one read access is possible to devices that use the 
> cx88 driver.
> In my case it is a Hauppauge WinTV Nova-S-Plus DVB-S card.
> You can reproduce it with the following test:
> Launch femon concurrently two or more times. Only one femon is able to 
> read from the card.
> Oliver Endriss confirmed that bug after looking in cx88-dvb.c.
> Usually, only one write access but an arbitrary amount of read accesses 
> should be allowed.

Basically it's a bug in dvb_frontend.
ts_bus_ctrl() should only be called by
- the first open
- the last release
call.

Please try the attached patch.

@all:
Ok?

CU
Oliver

-- 
----------------------------------------------------------------
VDR Remote Plugin 0.3.9: http://www.escape-edv.de/endriss/vdr/
----------------------------------------------------------------
diff -r abb4c177bf6c linux/drivers/media/dvb/dvb-core/dvb_frontend.c
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c	Wed Aug 22 00:46:48 2007 +0200
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c	Thu Aug 23 01:13:49 2007 +0200
@@ -1061,18 +1061,15 @@ static int dvb_frontend_open(struct inod
 
 	dprintk ("%s\n", __FUNCTION__);
 
+	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
+		if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
+			return ret;
+	}
+
 	if ((ret = dvb_generic_open (inode, file)) < 0)
-		return ret;
-
-	if (fe->ops.ts_bus_ctrl) {
-		if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) {
-			dvb_generic_release (inode, file);
-			return ret;
-		}
-	}
+		goto err1;
 
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-
 		/* normal tune mode when opened R/W */
 		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
 		fepriv->tone = -1;
@@ -1080,13 +1077,20 @@ static int dvb_frontend_open(struct inod
 
 		ret = dvb_frontend_start (fe);
 		if (ret)
-			dvb_generic_release (inode, file);
+			goto err2;
 
 		/*  empty event queue */
 		fepriv->events.eventr = fepriv->events.eventw = 0;
 	}
 
 	return ret;
+
+err2:
+	dvb_generic_release(inode, file);
+err1:
+	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
+		fe->ops.ts_bus_ctrl(fe, 0);
+	return ret;
 }
 
 static int dvb_frontend_release(struct inode *inode, struct file *file)
@@ -1101,16 +1105,18 @@ static int dvb_frontend_release(struct i
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
 		fepriv->release_jiffies = jiffies;
 
-	if (fe->ops.ts_bus_ctrl)
-		fe->ops.ts_bus_ctrl (fe, 0);
-
 	ret = dvb_generic_release (inode, file);
 
-	if (dvbdev->users==-1 && fepriv->exit==1) {
-		fops_put(file->f_op);
-		file->f_op = NULL;
-		wake_up(&dvbdev->wait_queue);
-	}
+	if (dvbdev->users == -1) {
+		if (fepriv->exit == 1) {
+			fops_put(file->f_op);
+			file->f_op = NULL;
+			wake_up(&dvbdev->wait_queue);
+		}
+		if (fe->ops.ts_bus_ctrl)
+			fe->ops.ts_bus_ctrl(fe, 0);
+	}
+
 	return ret;
 }
 
_______________________________________________
linux-dvb mailing list
linux-dvb@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

Reply via email to