summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index d779b8dd180a..9dfc96008551 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -314,13 +314,6 @@ static int dvb_register(struct cx23885_tsport *port)
struct cx23885_i2c *i2c_bus = NULL;
struct videobuf_dvb_frontend *fe0;
- printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
-
- if (videobuf_dvb_alloc_frontend(dev, &port->frontends, 1) == NULL) {
- printk(KERN_ERR "%s() failed to alloc\n", __func__);
- return -ENOMEM;
- }
-
/* Get the first frontend */
fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
if (!fe0)
@@ -560,26 +553,46 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
struct videobuf_dvb_frontend *fe0;
struct cx23885_dev *dev = port->dev;
- int err;
+ int err, i;
+
+ /* Here we need to allocate the correct number of frontends,
+ * as reflected in the cards struct. The reality is that currrently
+ * no cx23885 boards support this - yet. But, if we don't modify this
+ * code then the second frontend would never be allocated (later)
+ * and fail with error before the attach in dvb_register().
+ * Without these changes we risk an OOPS later. The changes here
+ * are for safety, and should provide a good foundation for the
+ * future addition of any multi-frontend cx23885 based boards.
+ */
+ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+ port->num_frontends);
- fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
- if (!fe0)
- err = -EINVAL;
+ for (i = 1; i <= port->num_frontends; i++) {
+ if (videobuf_dvb_alloc_frontend(dev, &port->frontends, i) == NULL) {
+ printk(KERN_ERR "%s() failed to alloc\n", __func__);
+ return -ENOMEM;
+ }
+
+ fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
+ if (!fe0)
+ err = -EINVAL;
- dprintk(1, "%s\n", __func__);
- dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
- dev->board,
- dev->name,
- dev->pci_bus,
- dev->pci_slot);
+ dprintk(1, "%s\n", __func__);
+ dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ dev->board,
+ dev->name,
+ dev->pci_bus,
+ dev->pci_slot);
- err = -ENODEV;
+ err = -ENODEV;
- /* dvb stuff */
- printk("%s: cx23885 based dvb card\n", dev->name);
- videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
+ /* dvb stuff */
+ /* We have to init the queue for each frontend on a port. */
+ printk("%s: cx23885 based dvb card\n", dev->name);
+ videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
sizeof(struct cx23885_buffer), port);
+ }
err = dvb_register(port);
if (err != 0)
printk("%s() dvb_register failed err = %d\n", __func__, err);
@@ -591,8 +604,14 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
{
struct videobuf_dvb_frontend *fe0;
+ /* FIXME: in an error condition where the we have
+ * an expected number of frontends (attach problem)
+ * then this might not clean up correctly, if 1
+ * is invalid.
+ * This comment only applies to future boards IF they
+ * implement MFE support.
+ */
fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
- /* dvb */
if(fe0->dvb.frontend)
videobuf_dvb_unregister_bus(&port->frontends);