diff options
author | Michael Krufky <mkrufky@linuxtv.org> | 2008-09-06 12:54:45 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:37:01 -0400 |
commit | 2a6003c20771ca16fc6386b5fd258df2f2fa8232 (patch) | |
tree | 7f577409cdb779d72b4a657e5f5fc736fde91100 /drivers/media/common | |
parent | 89fd28545c7390eb6c63d3d9e6faac78942dd1a4 (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')
-rw-r--r-- | drivers/media/common/tuners/xc5000.c | 16 |
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 | ||
52 | struct xc5000_priv { | 52 | struct 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; |