aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common/tuners
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2008-09-06 12:54:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:01 -0400
commit2a6003c20771ca16fc6386b5fd258df2f2fa8232 (patch)
tree7f577409cdb779d72b4a657e5f5fc736fde91100 /drivers/media/common/tuners
parent89fd28545c7390eb6c63d3d9e6faac78942dd1a4 (diff)
V4L/DVB (8950): xc5000: prevent an OOPS if analog driver is unloaded while digital is in use
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>
Diffstat (limited to 'drivers/media/common/tuners')
-rw-r--r--drivers/media/common/tuners/xc5000.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index 1850f7b7d961..72efc656ad0d 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -50,17 +50,17 @@ static LIST_HEAD(hybrid_tuner_instance_list);
50#define XC5000_DEFAULT_FIRMWARE_SIZE 12332 50#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
51 51
52struct xc5000_priv { 52struct xc5000_priv {
53 struct xc5000_config *cfg;
54
55 struct tuner_i2c_props i2c_props; 53 struct tuner_i2c_props i2c_props;
56 struct list_head hybrid_tuner_instance_list; 54 struct list_head hybrid_tuner_instance_list;
57 55
56 u32 if_khz;
58 u32 freq_hz; 57 u32 freq_hz;
59 u32 bandwidth; 58 u32 bandwidth;
60 u8 video_standard; 59 u8 video_standard;
61 u8 rf_mode; 60 u8 rf_mode;
62 61
63 void *devptr; 62 void *devptr;
63 int (*tuner_callback) (void *priv, int command, int arg);
64}; 64};
65 65
66/* Misc Defines */ 66/* Misc Defines */
@@ -233,9 +233,8 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
233 233
234 dprintk(1, "%s()\n", __func__); 234 dprintk(1, "%s()\n", __func__);
235 235
236 if (priv->cfg->tuner_callback) { 236 if (priv->tuner_callback) {
237 ret = priv->cfg->tuner_callback(priv->devptr, 237 ret = priv->tuner_callback(priv->devptr, XC5000_TUNER_RESET, 0);
238 XC5000_TUNER_RESET, 0);
239 if (ret) 238 if (ret)
240 printk(KERN_ERR "xc5000: reset failed\n"); 239 printk(KERN_ERR "xc5000: reset failed\n");
241 } else 240 } else
@@ -692,10 +691,10 @@ static int xc5000_set_params(struct dvb_frontend *fe,
692 return -EREMOTEIO; 691 return -EREMOTEIO;
693 } 692 }
694 693
695 ret = xc_set_IF_frequency(priv, priv->cfg->if_khz); 694 ret = xc_set_IF_frequency(priv, priv->if_khz);
696 if (ret != XC_RESULT_SUCCESS) { 695 if (ret != XC_RESULT_SUCCESS) {
697 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", 696 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
698 priv->cfg->if_khz); 697 priv->if_khz);
699 return -EIO; 698 return -EIO;
700 } 699 }
701 700
@@ -972,9 +971,10 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
972 break; 971 break;
973 case 1: 972 case 1:
974 /* new tuner instance */ 973 /* new tuner instance */
975 priv->cfg = cfg;
976 priv->bandwidth = BANDWIDTH_6_MHZ; 974 priv->bandwidth = BANDWIDTH_6_MHZ;
977 priv->devptr = devptr; 975 priv->devptr = devptr;
976 priv->if_khz = cfg->if_khz;
977 priv->tuner_callback = cfg->tuner_callback;
978 978
979 fe->tuner_priv = priv; 979 fe->tuner_priv = priv;
980 break; 980 break;