Commit 6594690b authored by Darron Broad's avatar Darron Broad Committed by Mauro Carvalho Chehab

V4L/DVB (9264): MFE: bugfix: multi-frontend mutual exclusion parallel open

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.
Signed-off-by: default avatarDarron Broad <darron@kewl.org>
Signed-off-by: default avatarSteven Toth <stoth@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5c310b13
...@@ -1710,39 +1710,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) ...@@ -1710,39 +1710,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_adapter *adapter = fe->dvb; struct dvb_adapter *adapter = fe->dvb;
struct dvb_device *mfedev;
struct dvb_frontend *mfe;
struct dvb_frontend_private *mfepriv;
int mferetry;
int ret; int ret;
dprintk ("%s\n", __func__); dprintk ("%s\n", __func__);
if (adapter->mfe_shared) { if (adapter->mfe_shared) {
mutex_lock (&adapter->mfe_lock); mutex_lock (&adapter->mfe_lock);
if (adapter->mfe_dvbdev != dvbdev) {
if (adapter->mfe_dvbdev) { if (adapter->mfe_dvbdev == NULL)
mfedev = adapter->mfe_dvbdev; adapter->mfe_dvbdev = dvbdev;
mfe = mfedev->priv;
mfepriv = mfe->frontend_priv; else if (adapter->mfe_dvbdev != dvbdev) {
mutex_unlock (&adapter->mfe_lock); struct dvb_device
mferetry = (dvb_mfe_wait_time << 1); *mfedev = adapter->mfe_dvbdev;
while (mferetry-- && (mfedev->users != -1 || mfepriv->thread != NULL)) { struct dvb_frontend
if(msleep_interruptible(500)) { *mfe = mfedev->priv;
if(signal_pending(current)) struct dvb_frontend_private
return -EINTR; *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; mfedev = adapter->mfe_dvbdev;
mfe = mfedev->priv; mfe = mfedev->priv;
mfepriv = mfe->frontend_priv; mfepriv = mfe->frontend_priv;
if (mfedev->users != -1 || mfepriv->thread != NULL) { if (mfedev->users != -1 ||
ret = -EBUSY; mfepriv->thread != NULL) {
goto err0; mutex_unlock (&adapter->mfe_lock);
return -EBUSY;
} }
adapter->mfe_dvbdev = dvbdev;
} }
adapter->mfe_dvbdev = dvbdev;
} }
} }
......
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