From: Antti Palosaari Date: Wed, 12 Feb 2014 17:46:44 +0000 (-0300) Subject: upstream: [media] em28xx-dvb: fix PCTV 461e tuner I2C binding X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6f247e2bd5bfd68d9c3fc0ca6f54a3a8522b6422;p=platform%2Fkernel%2Flinux-3.10.git upstream: [media] em28xx-dvb: fix PCTV 461e tuner I2C binding Add missing m88ts2022 module reference counts as removing that module is not allowed when it is used by em28xx-dvb module. That same module was not unregistered correctly, fix it too. Error cases validated by returning errors from m88ds3103, m88ts2022 and a8293 probe(). Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index b762ceb..5632d85 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1406,6 +1406,7 @@ static int em28xx_dvb_init(struct em28xx *dev) { /* demod I2C adapter */ struct i2c_adapter *i2c_adapter; + struct i2c_client *client; struct i2c_board_info info; struct m88ts2022_config m88ts2022_config = { .clock = 27000000, @@ -1428,7 +1429,19 @@ static int em28xx_dvb_init(struct em28xx *dev) info.addr = 0x60; info.platform_data = &m88ts2022_config; request_module("m88ts2022"); - dvb->i2c_client_tuner = i2c_new_device(i2c_adapter, &info); + client = i2c_new_device(i2c_adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + dvb_frontend_detach(dvb->fe[0]); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + dvb_frontend_detach(dvb->fe[0]); + result = -ENODEV; + goto out_free; + } /* delegate signal strength measurement to tuner */ dvb->fe[0]->ops.read_signal_strength = @@ -1438,10 +1451,14 @@ static int em28xx_dvb_init(struct em28xx *dev) if (!dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config)) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); dvb_frontend_detach(dvb->fe[0]); result = -ENODEV; goto out_free; } + + dvb->i2c_client_tuner = client; } break; default: @@ -1503,6 +1520,7 @@ static int em28xx_dvb_fini(struct em28xx *dev) if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client = dvb->i2c_client_tuner; em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); @@ -1515,7 +1533,12 @@ static int em28xx_dvb_fini(struct em28xx *dev) prevent_sleep(&dvb->fe[1]->ops); } - i2c_release_client(dvb->i2c_client_tuner); + /* remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL;