aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorDarron Broad <darron@kewl.org>2008-10-11 10:44:05 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-17 16:24:15 -0400
commit59b1842da1c6f33ad2e8da82d3dfb3445751d964 (patch)
tree9a57bcf44df5d76ad845995dcfd5f49e20c68240 /drivers/media/dvb
parent2f3af9e64de44743a860fd1eee966222a7accc54 (diff)
V4L/DVB (9227): MFE: Add multi-frontend mutual exclusion
This add frontend R/W mutual exclusion. Prior to this point in time it was possible to open both frontends simultaneously which an MFE card cannot support. In order to stop this, a delayed open is performed which has the following function: - Return EBUSY after a configurable amount of time if a frontend is unavailable due to the other being in use. - Only allow opening of a frontend if the kernel thread of the other has stopped. This solution was chosen to allow switching between frontends to work as seamlessly as possible. When both frontends are actually opened simultaneously then one will only open, but if quick switching is performed between one of many then the new open will succeed in a clean fashion rather than interrupting a kernel thread. Signed-off-by: Darron Broad <darron@kewl.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c43
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h4
3 files changed, 49 insertions, 1 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 26671757c70b..62696f865576 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -47,6 +47,7 @@ static int dvb_shutdown_timeout;
47static int dvb_force_auto_inversion; 47static int dvb_force_auto_inversion;
48static int dvb_override_tune_delay; 48static int dvb_override_tune_delay;
49static int dvb_powerdown_on_sleep = 1; 49static int dvb_powerdown_on_sleep = 1;
50static int dvb_mfe_wait_time = 5;
50 51
51module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); 52module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
52MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); 53MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
@@ -58,6 +59,8 @@ module_param(dvb_override_tune_delay, int, 0644);
58MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); 59MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
59module_param(dvb_powerdown_on_sleep, int, 0644); 60module_param(dvb_powerdown_on_sleep, int, 0644);
60MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); 61MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
62module_param(dvb_mfe_wait_time, int, 0644);
63MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
61 64
62#define dprintk if (dvb_frontend_debug) printk 65#define dprintk if (dvb_frontend_debug) printk
63 66
@@ -1706,13 +1709,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
1706 struct dvb_device *dvbdev = file->private_data; 1709 struct dvb_device *dvbdev = file->private_data;
1707 struct dvb_frontend *fe = dvbdev->priv; 1710 struct dvb_frontend *fe = dvbdev->priv;
1708 struct dvb_frontend_private *fepriv = fe->frontend_priv; 1711 struct dvb_frontend_private *fepriv = fe->frontend_priv;
1712 struct dvb_adapter *adapter = fe->dvb;
1713 struct dvb_device *mfedev;
1714 struct dvb_frontend *mfe;
1715 struct dvb_frontend_private *mfepriv;
1716 int mferetry;
1709 int ret; 1717 int ret;
1710 1718
1711 dprintk ("%s\n", __func__); 1719 dprintk ("%s\n", __func__);
1712 1720
1721 if (adapter->mfe_shared) {
1722 mutex_lock (&adapter->mfe_lock);
1723 if (adapter->mfe_dvbdev != dvbdev) {
1724 if (adapter->mfe_dvbdev) {
1725 mfedev = adapter->mfe_dvbdev;
1726 mfe = mfedev->priv;
1727 mfepriv = mfe->frontend_priv;
1728 mutex_unlock (&adapter->mfe_lock);
1729 mferetry = (dvb_mfe_wait_time << 1);
1730 while (mferetry-- && (mfedev->users != -1 || mfepriv->thread != NULL)) {
1731 if(msleep_interruptible(500)) {
1732 if(signal_pending(current))
1733 return -EINTR;
1734 }
1735 }
1736 mutex_lock (&adapter->mfe_lock);
1737 mfedev = adapter->mfe_dvbdev;
1738 mfe = mfedev->priv;
1739 mfepriv = mfe->frontend_priv;
1740 if (mfedev->users != -1 || mfepriv->thread != NULL) {
1741 ret = -EBUSY;
1742 goto err0;
1743 }
1744 }
1745 adapter->mfe_dvbdev = dvbdev;
1746 }
1747 }
1748
1713 if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { 1749 if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
1714 if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) 1750 if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
1715 return ret; 1751 goto err0;
1716 } 1752 }
1717 1753
1718 if ((ret = dvb_generic_open (inode, file)) < 0) 1754 if ((ret = dvb_generic_open (inode, file)) < 0)
@@ -1732,6 +1768,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
1732 fepriv->events.eventr = fepriv->events.eventw = 0; 1768 fepriv->events.eventr = fepriv->events.eventw = 0;
1733 } 1769 }
1734 1770
1771 if (adapter->mfe_shared)
1772 mutex_unlock (&adapter->mfe_lock);
1735 return ret; 1773 return ret;
1736 1774
1737err2: 1775err2:
@@ -1739,6 +1777,9 @@ err2:
1739err1: 1777err1:
1740 if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) 1778 if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
1741 fe->ops.ts_bus_ctrl(fe, 0); 1779 fe->ops.ts_bus_ctrl(fe, 0);
1780err0:
1781 if (adapter->mfe_shared)
1782 mutex_unlock (&adapter->mfe_lock);
1742 return ret; 1783 return ret;
1743} 1784}
1744 1785
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 665776d72a48..a113744a56cc 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -326,6 +326,9 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
326 adap->name = name; 326 adap->name = name;
327 adap->module = module; 327 adap->module = module;
328 adap->device = device; 328 adap->device = device;
329 adap->mfe_shared = 0;
330 adap->mfe_dvbdev = NULL;
331 mutex_init (&adap->mfe_lock);
329 332
330 list_add_tail (&adap->list_head, &dvb_adapter_list); 333 list_add_tail (&adap->list_head, &dvb_adapter_list);
331 334
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 89d12dc477a7..574e336bac35 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -62,6 +62,10 @@ struct dvb_adapter {
62 struct device *device; 62 struct device *device;
63 63
64 struct module *module; 64 struct module *module;
65
66 int mfe_shared; /* indicates mutually exclusive frontends */
67 struct dvb_device *mfe_dvbdev; /* frontend device in use */
68 struct mutex mfe_lock; /* access lock for thread creation */
65}; 69};
66 70
67 71