Hi Hartmut, After reviewing your patch I realized that more needed to be done to get this to work properly. The core problem is that the probe function does not have a counterpart that can do a cleanup. So if the probe fails, then v4l2_device_unregister will never be called, which is a particular problem on mxb. I've made a new patch that basically reverts my original patch and instead modifies the mxb driver. I realized that mxb doesn't need to do a separate probe. Instead attach can just call probe and return an error if it fails. This way I can avoid the devinit and the cleanup is also much more straightforward. If there are no further comments, then I'll post a pull request in a few days. Tested with the mxb board. It would be nice if you can verify this with the av7110. Regards, Hans diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index fd8e1f4..7364b96 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -423,15 +423,14 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) } } -int saa7146_vv_devinit(struct saa7146_dev *dev) -{ - return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); -} -EXPORT_SYMBOL_GPL(saa7146_vv_devinit); - int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { struct saa7146_vv *vv; + int err; + + err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); + if (err) + return err; vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); if (vv == NULL) { diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index e620a3a..ad2c232 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -356,9 +356,6 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d DEB_EE((".\n")); - ret = saa7146_vv_devinit(dev); - if (ret) - return ret; hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); if (NULL == hexium) { printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index fe596a1..938a1f8 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -216,10 +216,6 @@ static int hexium_probe(struct saa7146_dev *dev) return -EFAULT; } - err = saa7146_vv_devinit(dev); - if (err) - return err; - hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); if (NULL == hexium) { printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 9f01f14..ef0c817 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -169,11 +169,7 @@ static struct saa7146_extension extension; static int mxb_probe(struct saa7146_dev *dev) { struct mxb *mxb = NULL; - int err; - err = saa7146_vv_devinit(dev); - if (err) - return err; mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); if (mxb == NULL) { DEB_D(("not enough kernel memory.\n")); @@ -699,14 +695,17 @@ static struct saa7146_ext_vv vv_data; /* this function only gets called when the probing was successful */ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { - struct mxb *mxb = (struct mxb *)dev->ext_priv; + struct mxb *mxb; DEB_EE(("dev:%p\n", dev)); - /* checking for i2c-devices can be omitted here, because we - already did this in "mxb_vl42_probe" */ - saa7146_vv_init(dev, &vv_data); + if (mxb_probe(dev)) { + saa7146_vv_release(dev); + return -1; + } + mxb = (struct mxb *)dev->ext_priv; + vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; @@ -726,6 +725,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data vv_data.ops.vidioc_default = vidioc_default; if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); + saa7146_vv_release(dev); return -1; } @@ -846,7 +846,6 @@ static struct saa7146_extension extension = { .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, - .probe = mxb_probe, .attach = mxb_attach, .detach = mxb_detach, diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index b9da1f5..4aeff96 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -188,7 +188,6 @@ void saa7146_buffer_timeout(unsigned long data); void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q, struct saa7146_buf *buf); -int saa7146_vv_devinit(struct saa7146_dev *dev); int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv); int saa7146_vv_release(struct saa7146_dev* dev); On Wednesday 03 March 2010 12:39:27 e9hack wrote: > Hi, > > changeset 14351:2eda2bcc8d6f is incomplete. If the init function is split in two function, > the deinit function shall consider this. The changes shall be apply also to av7110_init_v4l(). > > diff -r 58ae12f18e80 linux/drivers/media/common/saa7146_fops.c > --- a/linux/drivers/media/common/saa7146_fops.c Tue Mar 02 23:52:36 2010 -0300 > +++ b/linux/drivers/media/common/saa7146_fops.c Wed Mar 03 12:15:23 2010 +0100 > @@ -481,8 +481,10 @@ int saa7146_vv_release(struct saa7146_de > DEB_EE(("dev:%p\n",dev)); > > v4l2_device_unregister(&dev->v4l2_dev); > - pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, > vv->d_clipping.dma_handle); > - kfree(vv); > + if (vv) { > + pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, > vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); > + kfree(vv); > + } > dev->vv_data = NULL; > dev->vv_callback = NULL; > > diff -r 58ae12f18e80 linux/drivers/media/dvb/ttpci/av7110_v4l.c > --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c Tue Mar 02 23:52:36 2010 -0300 > +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c Wed Mar 03 12:15:23 2010 +0100 > @@ -790,12 +790,20 @@ int av7110_init_v4l(struct av7110 *av711 > vv_data = &av7110_vv_data_c; > else > vv_data = &av7110_vv_data_st; > + ret = saa7146_vv_devinit(dev); > + > + if (ret < 0) { > + ERR(("cannot init device. skipping.\n")); > + return ret; > + } > + > ret = saa7146_vv_init(dev, vv_data); > - > - if (ret) { > + if (ret < 0) { > ERR(("cannot init capture device. skipping.\n")); > + saa7146_vv_release(dev); > return ret; > } > + > vv_data->ops.vidioc_enum_input = vidioc_enum_input; > vv_data->ops.vidioc_g_input = vidioc_g_input; > vv_data->ops.vidioc_s_input = vidioc_s_input; > > Regards, > Hartmut > -- > To unsubscribe from this list: send the line "unsubscribe linux-media" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- Hans Verkuil - video4linux developer - sponsored by TANDBERG -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html