summaryrefslogtreecommitdiff
path: root/drivers/media/usb/em28xx/em28xx-dvb.c
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2014-02-12 14:46:44 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-02-24 10:28:52 -0300
commit425f53aaf76cce77b3bedd8ed4902bc94ed254ff (patch)
treef32866f213cfdf65ac2778b58942241226939a73 /drivers/media/usb/em28xx/em28xx-dvb.c
parent37e59f876bc710d67a30b660826a5e83e07101ce (diff)
downloadlinux-425f53aaf76cce77b3bedd8ed4902bc94ed254ff.tar.gz
linux-425f53aaf76cce77b3bedd8ed4902bc94ed254ff.tar.xz
[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 <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-dvb.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index a0a669e81362..defac240eec0 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1374,6 +1374,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,
@@ -1396,7 +1397,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 =
@@ -1406,10 +1419,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:
@@ -1471,6 +1488,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);
@@ -1483,7 +1501,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;