V4L/DVB (8950): xc5000: prevent an OOPS if analog driver is unloaded while digital...
authorMichael Krufky <mkrufky@linuxtv.org>
Sat, 6 Sep 2008 16:54:45 +0000 (13:54 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 12 Oct 2008 11:37:01 +0000 (09:37 -0200)
Prevent an OOPS if xc5000_attach was called by tuner.ko before being called by
the DVB adapter driver. The OOPS occurs when a digital tune request is made
after tuner.ko is unloaded.

When tuner.ko is unloaded, it takes the xc5000_config structure with it.

Rather than storing a pointer to the xc5000_config structure, just store the
if_khz and tuner_callback inside the xc5000_priv internal state structure.

Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/common/tuners/xc5000.c

index 1850f7b7d9610b452367487d3f8fc31fb7f3ddef..72efc656ad0dc286f735621e10c200f8b427fb87 100644 (file)
@@ -50,17 +50,17 @@ static LIST_HEAD(hybrid_tuner_instance_list);
 #define XC5000_DEFAULT_FIRMWARE_SIZE 12332
 
 struct xc5000_priv {
-       struct xc5000_config *cfg;
-
        struct tuner_i2c_props i2c_props;
        struct list_head hybrid_tuner_instance_list;
 
+       u32 if_khz;
        u32 freq_hz;
        u32 bandwidth;
        u8  video_standard;
        u8  rf_mode;
 
        void *devptr;
+       int  (*tuner_callback) (void *priv, int command, int arg);
 };
 
 /* Misc Defines */
@@ -233,9 +233,8 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
 
        dprintk(1, "%s()\n", __func__);
 
-       if (priv->cfg->tuner_callback) {
-               ret = priv->cfg->tuner_callback(priv->devptr,
-                                               XC5000_TUNER_RESET, 0);
+       if (priv->tuner_callback) {
+               ret = priv->tuner_callback(priv->devptr, XC5000_TUNER_RESET, 0);
                if (ret)
                        printk(KERN_ERR "xc5000: reset failed\n");
        } else
@@ -692,10 +691,10 @@ static int xc5000_set_params(struct dvb_frontend *fe,
                return -EREMOTEIO;
        }
 
-       ret = xc_set_IF_frequency(priv, priv->cfg->if_khz);
+       ret = xc_set_IF_frequency(priv, priv->if_khz);
        if (ret != XC_RESULT_SUCCESS) {
                printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
-                       priv->cfg->if_khz);
+                      priv->if_khz);
                return -EIO;
        }
 
@@ -972,9 +971,10 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                break;
        case 1:
                /* new tuner instance */
-               priv->cfg = cfg;
                priv->bandwidth = BANDWIDTH_6_MHZ;
                priv->devptr = devptr;
+               priv->if_khz = cfg->if_khz;
+               priv->tuner_callback = cfg->tuner_callback;
 
                fe->tuner_priv = priv;
                break;