summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
authordarron@kewl.org <darron@kewl.org>2008-10-15 17:37:59 +0100
committerdarron@kewl.org <darron@kewl.org>2008-10-15 17:37:59 +0100
commit78057bdf11c9ba36c64c6c081eeb6bae29cd72c4 (patch)
treec395354f4f82313c372ff789085716e489a82d93 /linux/drivers/media/dvb
parente6236e8ddedbbd6189021eac4c7071fda656bcfd (diff)
downloadmediapointer-dvb-s2-78057bdf11c9ba36c64c6c081eeb6bae29cd72c4.tar.gz
mediapointer-dvb-s2-78057bdf11c9ba36c64c6c081eeb6bae29cd72c4.tar.bz2
MFE: bugfix: multi-frontend mutual exclusion parallel open
From: Darron Broad <darron@kewl.org> When moving from one frontend to another an application could spawn multiple threads opening the same new frontend and in some circumstances all of these could become delayed waiting for the previous frontend readers or previous frontend writer thread to complete. In this scenario the first thread will succeed on open to bring the new frontend online but any others will return EBUSY. This is a fault. If the first succeeds and all others are on the same frontend then they should succeed also. Priority: normal Signed-off-by: Darron Broad <darron@kewl.org> Signed-off-by: Steven Toth <stoth@linuxtv.org>
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 51fb82edc..4fb5e671f 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1825,39 +1825,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_adapter *adapter = fe->dvb;
- struct dvb_device *mfedev;
- struct dvb_frontend *mfe;
- struct dvb_frontend_private *mfepriv;
- int mferetry;
int ret;
dprintk ("%s\n", __func__);
if (adapter->mfe_shared) {
mutex_lock (&adapter->mfe_lock);
- if (adapter->mfe_dvbdev != dvbdev) {
- if (adapter->mfe_dvbdev) {
- mfedev = adapter->mfe_dvbdev;
- mfe = mfedev->priv;
- mfepriv = mfe->frontend_priv;
- mutex_unlock (&adapter->mfe_lock);
- mferetry = (dvb_mfe_wait_time << 1);
- while (mferetry-- && (mfedev->users != -1 || mfepriv->thread != NULL)) {
- if(msleep_interruptible(500)) {
- if(signal_pending(current))
- return -EINTR;
- }
+
+ if (adapter->mfe_dvbdev == NULL)
+ adapter->mfe_dvbdev = dvbdev;
+
+ else if (adapter->mfe_dvbdev != dvbdev) {
+ struct dvb_device
+ *mfedev = adapter->mfe_dvbdev;
+ struct dvb_frontend
+ *mfe = mfedev->priv;
+ struct dvb_frontend_private
+ *mfepriv = mfe->frontend_priv;
+ int mferetry = (dvb_mfe_wait_time << 1);
+
+ mutex_unlock (&adapter->mfe_lock);
+ while (mferetry-- && (mfedev->users != -1 ||
+ mfepriv->thread != NULL)) {
+ if(msleep_interruptible(500)) {
+ if(signal_pending(current))
+ return -EINTR;
}
- mutex_lock (&adapter->mfe_lock);
+ }
+
+ mutex_lock (&adapter->mfe_lock);
+ if(adapter->mfe_dvbdev != dvbdev) {
mfedev = adapter->mfe_dvbdev;
mfe = mfedev->priv;
mfepriv = mfe->frontend_priv;
- if (mfedev->users != -1 || mfepriv->thread != NULL) {
- ret = -EBUSY;
- goto err0;
+ if (mfedev->users != -1 ||
+ mfepriv->thread != NULL) {
+ mutex_unlock (&adapter->mfe_lock);
+ return -EBUSY;
}
+ adapter->mfe_dvbdev = dvbdev;
}
- adapter->mfe_dvbdev = dvbdev;
}
}