[media] rtl28xxu: change module unregister order
authorAntti Palosaari <crope@iki.fi>
Tue, 2 Dec 2014 14:23:49 +0000 (11:23 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 27 Jan 2015 12:57:58 +0000 (10:57 -0200)
We must unregister frontend first and after that driver itself. That
order went wrong after demod drivers were switched to kernel I2C
drivers, causing crashes.

Tested-by: Benjamin Larsson <benjamin@southpole.se>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/usb/dvb-usb-v2/rtl28xxu.c

index 21657341ce35d2b88965d81af078a8c34b679adb..705c6c30acb733d0ca6b484388a59aeaf5e8e253 100644 (file)
@@ -917,6 +917,31 @@ err:
        return ret;
 }
 
+static int rtl2832u_frontend_detach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct rtl28xxu_priv *priv = d_to_priv(d);
+       struct i2c_client *client;
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       /* remove I2C slave demod */
+       client = priv->i2c_client_slave_demod;
+       if (client) {
+               module_put(client->dev.driver->owner);
+               i2c_unregister_device(client);
+       }
+
+       /* remove I2C demod */
+       client = priv->i2c_client_demod;
+       if (client) {
+               module_put(client->dev.driver->owner);
+               i2c_unregister_device(client);
+       }
+
+       return 0;
+}
+
 static struct qt1010_config rtl28xxu_qt1010_config = {
        .i2c_address = 0x62, /* 0xc4 */
 };
@@ -1151,6 +1176,24 @@ err:
        return ret;
 }
 
+static int rtl2832u_tuner_detach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct rtl28xxu_priv *priv = d_to_priv(d);
+       struct i2c_client *client;
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       /* remove I2C tuner */
+       client = priv->i2c_client_tuner;
+       if (client) {
+               module_put(client->dev.driver->owner);
+               i2c_unregister_device(client);
+       }
+
+       return 0;
+}
+
 static int rtl28xxu_init(struct dvb_usb_device *d)
 {
        int ret;
@@ -1185,37 +1228,6 @@ err:
        return ret;
 }
 
-static void rtl28xxu_exit(struct dvb_usb_device *d)
-{
-       struct rtl28xxu_priv *priv = d->priv;
-       struct i2c_client *client;
-
-       dev_dbg(&d->udev->dev, "%s:\n", __func__);
-
-       /* remove I2C tuner */
-       client = priv->i2c_client_tuner;
-       if (client) {
-               module_put(client->dev.driver->owner);
-               i2c_unregister_device(client);
-       }
-
-       /* remove I2C slave demod */
-       client = priv->i2c_client_slave_demod;
-       if (client) {
-               module_put(client->dev.driver->owner);
-               i2c_unregister_device(client);
-       }
-
-       /* remove I2C demod */
-       client = priv->i2c_client_demod;
-       if (client) {
-               module_put(client->dev.driver->owner);
-               i2c_unregister_device(client);
-       }
-
-       return;
-}
-
 static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        int ret;
@@ -1597,9 +1609,10 @@ static const struct dvb_usb_device_properties rtl2832u_props = {
        .i2c_algo = &rtl28xxu_i2c_algo,
        .read_config = rtl2832u_read_config,
        .frontend_attach = rtl2832u_frontend_attach,
+       .frontend_detach = rtl2832u_frontend_detach,
        .tuner_attach = rtl2832u_tuner_attach,
+       .tuner_detach = rtl2832u_tuner_detach,
        .init = rtl28xxu_init,
-       .exit = rtl28xxu_exit,
        .get_rc_config = rtl2832u_get_rc_config,
 
        .num_adapters = 1,