aboutsummaryrefslogtreecommitdiffstats
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
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>
-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
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c2
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/videobuf-dvb.c9
-rw-r--r--include/media/videobuf-dvb.h6
8 files changed, 65 insertions, 15 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
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index c14878f74bcc..78851526db68 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -556,7 +556,7 @@ static int dvb_register(struct cx23885_tsport *port)
556 556
557 /* register everything */ 557 /* register everything */
558 return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, 558 return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
559 &dev->pci->dev, adapter_nr); 559 &dev->pci->dev, adapter_nr, 0);
560 560
561} 561}
562 562
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 9bb7bee0da6d..0dd0ff9227fb 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -594,14 +594,9 @@ static struct stv0288_config tevii_tuner_earda_config = {
594 594
595static int dvb_register(struct cx8802_dev *dev) 595static int dvb_register(struct cx8802_dev *dev)
596{ 596{
597 //struct cx88_core *core = dev->core;
598
599 ///* init struct videobuf_dvb */
600 //fe->dvb.name = core->name;
601 //dev->ts_gen_cntrl = 0x0c;
602
603 struct cx88_core *core = dev->core; 597 struct cx88_core *core = dev->core;
604 struct videobuf_dvb_frontend *fe0, *fe1 = NULL; 598 struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
599 int mfe_shared = 0; /* bus not shared by default */
605 600
606 /* Get the first frontend */ 601 /* Get the first frontend */
607 fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); 602 fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
@@ -669,6 +664,7 @@ static int dvb_register(struct cx8802_dev *dev)
669 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); 664 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
670 if (fe1) { 665 if (fe1) {
671 dev->frontends.gate = 2; 666 dev->frontends.gate = 2;
667 mfe_shared = 1;
672 fe1->dvb.frontend = dvb_attach(cx22702_attach, 668 fe1->dvb.frontend = dvb_attach(cx22702_attach,
673 &hauppauge_hvr_config, 669 &hauppauge_hvr_config,
674 &dev->core->i2c_adap); 670 &dev->core->i2c_adap);
@@ -1013,6 +1009,7 @@ static int dvb_register(struct cx8802_dev *dev)
1013 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); 1009 fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
1014 if (fe1) { 1010 if (fe1) {
1015 dev->frontends.gate = 2; 1011 dev->frontends.gate = 2;
1012 mfe_shared = 1;
1016 fe1->dvb.frontend = dvb_attach(cx22702_attach, 1013 fe1->dvb.frontend = dvb_attach(cx22702_attach,
1017 &hauppauge_hvr_config, 1014 &hauppauge_hvr_config,
1018 &dev->core->i2c_adap); 1015 &dev->core->i2c_adap);
@@ -1110,7 +1107,7 @@ static int dvb_register(struct cx8802_dev *dev)
1110 1107
1111 /* register everything */ 1108 /* register everything */
1112 return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, 1109 return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
1113 &dev->pci->dev, adapter_nr); 1110 &dev->pci->dev, adapter_nr, mfe_shared);
1114 1111
1115frontend_detach: 1112frontend_detach:
1116 if (fe0->dvb.frontend) { 1113 if (fe0->dvb.frontend) {
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 30ae0cbe78a0..d2d238912fbf 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1395,7 +1395,7 @@ static int dvb_init(struct saa7134_dev *dev)
1395 1395
1396 /* register everything else */ 1396 /* register everything else */
1397 ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, 1397 ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
1398 &dev->pci->dev, adapter_nr); 1398 &dev->pci->dev, adapter_nr, 0);
1399 1399
1400 /* this sequence is necessary to make the tda1004x load its firmware 1400 /* this sequence is necessary to make the tda1004x load its firmware
1401 * and to enter analog mode of hybrid boards 1401 * and to enter analog mode of hybrid boards
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index a0a80e1e79e3..af0b75cda6fd 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -140,7 +140,8 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
140 struct module *module, 140 struct module *module,
141 void *adapter_priv, 141 void *adapter_priv,
142 struct device *device, 142 struct device *device,
143 short *adapter_nr) //NEW 143 short *adapter_nr,
144 int mfe_shared)
144{ 145{
145 struct list_head *list, *q; 146 struct list_head *list, *q;
146 struct videobuf_dvb_frontend *fe; 147 struct videobuf_dvb_frontend *fe;
@@ -153,7 +154,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
153 } 154 }
154 155
155 /* Bring up the adapter */ 156 /* Bring up the adapter */
156 res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr); //NEW 157 res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr, mfe_shared);
157 if (res < 0) { 158 if (res < 0) {
158 printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); 159 printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
159 goto err; 160 goto err;
@@ -181,7 +182,8 @@ int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
181 void *adapter_priv, 182 void *adapter_priv,
182 struct device *device, 183 struct device *device,
183 char *adapter_name, 184 char *adapter_name,
184 short *adapter_nr) //NEW 185 short *adapter_nr,
186 int mfe_shared)
185{ 187{
186 int result; 188 int result;
187 189
@@ -194,6 +196,7 @@ int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
194 adapter_name, result); 196 adapter_name, result);
195 } 197 }
196 fe->adapter.priv = adapter_priv; 198 fe->adapter.priv = adapter_priv;
199 fe->adapter.mfe_shared = mfe_shared;
197 200
198 return result; 201 return result;
199} 202}
diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h
index 47bc2c5e7ba9..1a401f7320b9 100644
--- a/include/media/videobuf-dvb.h
+++ b/include/media/videobuf-dvb.h
@@ -43,7 +43,8 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
43 struct module *module, 43 struct module *module,
44 void *adapter_priv, 44 void *adapter_priv,
45 struct device *device, 45 struct device *device,
46 short *adapter_nr); //NEW 46 short *adapter_nr,
47 int mfe_shared);
47 48
48void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f); 49void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f);
49 50
@@ -52,7 +53,8 @@ int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *f,
52 void *adapter_priv, 53 void *adapter_priv,
53 struct device *device, 54 struct device *device,
54 char *adapter_name, 55 char *adapter_name,
55 short *adapter_nr); //NEW 56 short *adapter_nr,
57 int mfe_shared);
56 58
57int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_dvb *dvb); 59int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_dvb *dvb);
58 60