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
committerChanho Park <chanho61.park@samsung.com>2014-08-08 15:24:27 +0900
commit2eceaabd77985dbd69be1c9d0c6535f3ca151456 (patch)
tree4236b7c65d4c6ed07630f06eee5aae525d74097a /drivers/media/usb/em28xx/em28xx-dvb.c
parent0a5d22264663c8e464b943f594320dc9e391f8bd (diff)
downloadlinux-3.10-2eceaabd77985dbd69be1c9d0c6535f3ca151456.tar.gz
linux-3.10-2eceaabd77985dbd69be1c9d0c6535f3ca151456.tar.bz2
linux-3.10-2eceaabd77985dbd69be1c9d0c6535f3ca151456.zip
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 <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 b762ceb47d7..5632d85ffb1 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;