diff options
author | Oliver Endriss <o.endriss@gmx.de> | 2006-01-09 12:32:42 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2006-01-09 12:32:42 -0500 |
commit | 66190a275246c8c5be140a224e021f8f5eb85ab6 (patch) | |
tree | 63137a5e59b5add88acd088450d659a8dc754873 /drivers/media/dvb | |
parent | da4ae5a72b2a9de351ec8f98543b7c666ec97005 (diff) |
V4L/DVB (3281): av7110 driver: improved recovery from ARM crash and crash detection
- Improved recovery from ARM crash and the way a crash is detected.
Minor white space clean-up, debug output fixed.
Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/ttpci/av7110.c | 94 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/av7110.h | 9 | ||||
-rw-r--r-- | drivers/media/dvb/ttpci/av7110_hw.c | 3 |
3 files changed, 78 insertions, 28 deletions
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index eabd4fcaf246..39b4bfa0ab7b 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -196,17 +196,15 @@ static void recover_arm(struct av7110 *av7110) | |||
196 | 196 | ||
197 | av7110_bootarm(av7110); | 197 | av7110_bootarm(av7110); |
198 | msleep(100); | 198 | msleep(100); |
199 | restart_feeds(av7110); | ||
200 | av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); | ||
201 | } | ||
202 | 199 | ||
203 | static void arm_error(struct av7110 *av7110) | 200 | init_av7110_av(av7110); |
204 | { | 201 | |
205 | dprintk(4, "%p\n",av7110); | 202 | /* card-specific recovery */ |
203 | if (av7110->recover) | ||
204 | av7110->recover(av7110); | ||
206 | 205 | ||
207 | av7110->arm_errors++; | 206 | restart_feeds(av7110); |
208 | av7110->arm_ready = 0; | 207 | av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); |
209 | recover_arm(av7110); | ||
210 | } | 208 | } |
211 | 209 | ||
212 | static void av7110_arm_sync(struct av7110 *av7110) | 210 | static void av7110_arm_sync(struct av7110 *av7110) |
@@ -246,26 +244,22 @@ static int arm_thread(void *data) | |||
246 | 244 | ||
247 | if (down_interruptible(&av7110->dcomlock)) | 245 | if (down_interruptible(&av7110->dcomlock)) |
248 | break; | 246 | break; |
249 | |||
250 | newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2); | 247 | newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2); |
251 | up(&av7110->dcomlock); | 248 | up(&av7110->dcomlock); |
252 | 249 | ||
253 | if (newloops == av7110->arm_loops) { | 250 | if (newloops == av7110->arm_loops || av7110->arm_errors > 3) { |
254 | printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", | 251 | printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", |
255 | av7110->dvb_adapter.num); | 252 | av7110->dvb_adapter.num); |
256 | 253 | ||
257 | arm_error(av7110); | 254 | recover_arm(av7110); |
258 | av7710_set_video_mode(av7110, vidmode); | ||
259 | |||
260 | init_av7110_av(av7110); | ||
261 | 255 | ||
262 | if (down_interruptible(&av7110->dcomlock)) | 256 | if (down_interruptible(&av7110->dcomlock)) |
263 | break; | 257 | break; |
264 | |||
265 | newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1; | 258 | newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1; |
266 | up(&av7110->dcomlock); | 259 | up(&av7110->dcomlock); |
267 | } | 260 | } |
268 | av7110->arm_loops = newloops; | 261 | av7110->arm_loops = newloops; |
262 | av7110->arm_errors = 0; | ||
269 | } | 263 | } |
270 | 264 | ||
271 | av7110->arm_thread = NULL; | 265 | av7110->arm_thread = NULL; |
@@ -516,10 +510,6 @@ static void gpioirq(unsigned long data) | |||
516 | iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); | 510 | iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); |
517 | 511 | ||
518 | av7110->video_size.h = h_ar & 0xfff; | 512 | av7110->video_size.h = h_ar & 0xfff; |
519 | dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", | ||
520 | av7110->video_size.w, | ||
521 | av7110->video_size.h, | ||
522 | av7110->video_size.aspect_ratio); | ||
523 | 513 | ||
524 | event.type = VIDEO_EVENT_SIZE_CHANGED; | 514 | event.type = VIDEO_EVENT_SIZE_CHANGED; |
525 | event.u.size.w = av7110->video_size.w; | 515 | event.u.size.w = av7110->video_size.w; |
@@ -541,6 +531,11 @@ static void gpioirq(unsigned long data) | |||
541 | event.u.size.aspect_ratio = VIDEO_FORMAT_4_3; | 531 | event.u.size.aspect_ratio = VIDEO_FORMAT_4_3; |
542 | av7110->videostate.video_format = VIDEO_FORMAT_4_3; | 532 | av7110->videostate.video_format = VIDEO_FORMAT_4_3; |
543 | } | 533 | } |
534 | |||
535 | dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", | ||
536 | av7110->video_size.w, av7110->video_size.h, | ||
537 | av7110->video_size.aspect_ratio); | ||
538 | |||
544 | dvb_video_add_event(av7110, &event); | 539 | dvb_video_add_event(av7110, &event); |
545 | break; | 540 | break; |
546 | } | 541 | } |
@@ -1054,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110) | |||
1054 | struct dvb_demux *dvbdmx = &av7110->demux; | 1049 | struct dvb_demux *dvbdmx = &av7110->demux; |
1055 | struct dvb_demux_feed *feed; | 1050 | struct dvb_demux_feed *feed; |
1056 | int mode; | 1051 | int mode; |
1057 | int i; | 1052 | int i, j; |
1058 | 1053 | ||
1059 | dprintk(4, "%p\n", av7110); | 1054 | dprintk(4, "%p\n", av7110); |
1060 | 1055 | ||
@@ -1062,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110) | |||
1062 | av7110->playing = 0; | 1057 | av7110->playing = 0; |
1063 | av7110->rec_mode = 0; | 1058 | av7110->rec_mode = 0; |
1064 | 1059 | ||
1065 | for (i = 0; i < dvbdmx->filternum; i++) { | 1060 | for (i = 0; i < dvbdmx->feednum; i++) { |
1066 | feed = &dvbdmx->feed[i]; | 1061 | feed = &dvbdmx->feed[i]; |
1067 | if (feed->state == DMX_STATE_GO) | 1062 | if (feed->state == DMX_STATE_GO) { |
1063 | if (feed->type == DMX_TYPE_SEC) { | ||
1064 | for (j = 0; j < dvbdmx->filternum; j++) { | ||
1065 | if (dvbdmx->filter[j].type != DMX_TYPE_SEC) | ||
1066 | continue; | ||
1067 | if (dvbdmx->filter[j].filter.parent != &feed->feed.sec) | ||
1068 | continue; | ||
1069 | if (dvbdmx->filter[j].state == DMX_STATE_GO) | ||
1070 | dvbdmx->filter[j].state = DMX_STATE_READY; | ||
1071 | } | ||
1072 | } | ||
1068 | av7110_start_feed(feed); | 1073 | av7110_start_feed(feed); |
1074 | } | ||
1069 | } | 1075 | } |
1070 | 1076 | ||
1071 | if (mode) | 1077 | if (mode) |
@@ -2121,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p | |||
2121 | struct av7110* av7110 = fe->dvb->priv; | 2127 | struct av7110* av7110 = fe->dvb->priv; |
2122 | 2128 | ||
2123 | int ret = av7110_fe_lock_fix(av7110, 0); | 2129 | int ret = av7110_fe_lock_fix(av7110, 0); |
2124 | if (!ret) | 2130 | if (!ret) { |
2131 | av7110->saved_fe_params = *params; | ||
2125 | ret = av7110->fe_set_frontend(fe, params); | 2132 | ret = av7110->fe_set_frontend(fe, params); |
2133 | } | ||
2126 | return ret; | 2134 | return ret; |
2127 | } | 2135 | } |
2128 | 2136 | ||
@@ -2164,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, | |||
2164 | struct av7110* av7110 = fe->dvb->priv; | 2172 | struct av7110* av7110 = fe->dvb->priv; |
2165 | 2173 | ||
2166 | int ret = av7110_fe_lock_fix(av7110, 0); | 2174 | int ret = av7110_fe_lock_fix(av7110, 0); |
2167 | if (!ret) | 2175 | if (!ret) { |
2176 | av7110->saved_master_cmd = *cmd; | ||
2168 | ret = av7110->fe_diseqc_send_master_cmd(fe, cmd); | 2177 | ret = av7110->fe_diseqc_send_master_cmd(fe, cmd); |
2178 | } | ||
2169 | return ret; | 2179 | return ret; |
2170 | } | 2180 | } |
2171 | 2181 | ||
@@ -2174,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_ | |||
2174 | struct av7110* av7110 = fe->dvb->priv; | 2184 | struct av7110* av7110 = fe->dvb->priv; |
2175 | 2185 | ||
2176 | int ret = av7110_fe_lock_fix(av7110, 0); | 2186 | int ret = av7110_fe_lock_fix(av7110, 0); |
2177 | if (!ret) | 2187 | if (!ret) { |
2188 | av7110->saved_minicmd = minicmd; | ||
2178 | ret = av7110->fe_diseqc_send_burst(fe, minicmd); | 2189 | ret = av7110->fe_diseqc_send_burst(fe, minicmd); |
2190 | } | ||
2179 | return ret; | 2191 | return ret; |
2180 | } | 2192 | } |
2181 | 2193 | ||
@@ -2184,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | |||
2184 | struct av7110* av7110 = fe->dvb->priv; | 2196 | struct av7110* av7110 = fe->dvb->priv; |
2185 | 2197 | ||
2186 | int ret = av7110_fe_lock_fix(av7110, 0); | 2198 | int ret = av7110_fe_lock_fix(av7110, 0); |
2187 | if (!ret) | 2199 | if (!ret) { |
2200 | av7110->saved_tone = tone; | ||
2188 | ret = av7110->fe_set_tone(fe, tone); | 2201 | ret = av7110->fe_set_tone(fe, tone); |
2202 | } | ||
2189 | return ret; | 2203 | return ret; |
2190 | } | 2204 | } |
2191 | 2205 | ||
@@ -2194,8 +2208,10 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta | |||
2194 | struct av7110* av7110 = fe->dvb->priv; | 2208 | struct av7110* av7110 = fe->dvb->priv; |
2195 | 2209 | ||
2196 | int ret = av7110_fe_lock_fix(av7110, 0); | 2210 | int ret = av7110_fe_lock_fix(av7110, 0); |
2197 | if (!ret) | 2211 | if (!ret) { |
2212 | av7110->saved_voltage = voltage; | ||
2198 | ret = av7110->fe_set_voltage(fe, voltage); | 2213 | ret = av7110->fe_set_voltage(fe, voltage); |
2214 | } | ||
2199 | return ret; | 2215 | return ret; |
2200 | } | 2216 | } |
2201 | 2217 | ||
@@ -2209,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un | |||
2209 | return ret; | 2225 | return ret; |
2210 | } | 2226 | } |
2211 | 2227 | ||
2228 | static void dvb_s_recover(struct av7110* av7110) | ||
2229 | { | ||
2230 | av7110_fe_init(av7110->fe); | ||
2231 | |||
2232 | av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage); | ||
2233 | if (av7110->saved_master_cmd.msg_len) { | ||
2234 | msleep(20); | ||
2235 | av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd); | ||
2236 | } | ||
2237 | msleep(20); | ||
2238 | av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd); | ||
2239 | msleep(20); | ||
2240 | av7110_fe_set_tone(av7110->fe, av7110->saved_tone); | ||
2241 | |||
2242 | av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params); | ||
2243 | } | ||
2244 | |||
2212 | static u8 read_pwm(struct av7110* av7110) | 2245 | static u8 read_pwm(struct av7110* av7110) |
2213 | { | 2246 | { |
2214 | u8 b = 0xff; | 2247 | u8 b = 0xff; |
@@ -2246,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110) | |||
2246 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; | 2279 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; |
2247 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; | 2280 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; |
2248 | av7110->fe->ops->set_tone = av7110_set_tone; | 2281 | av7110->fe->ops->set_tone = av7110_set_tone; |
2282 | av7110->recover = dvb_s_recover; | ||
2249 | break; | 2283 | break; |
2250 | } | 2284 | } |
2251 | 2285 | ||
@@ -2255,6 +2289,7 @@ static int frontend_init(struct av7110 *av7110) | |||
2255 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; | 2289 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; |
2256 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; | 2290 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; |
2257 | av7110->fe->ops->set_tone = av7110_set_tone; | 2291 | av7110->fe->ops->set_tone = av7110_set_tone; |
2292 | av7110->recover = dvb_s_recover; | ||
2258 | break; | 2293 | break; |
2259 | } | 2294 | } |
2260 | 2295 | ||
@@ -2264,6 +2299,7 @@ static int frontend_init(struct av7110 *av7110) | |||
2264 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; | 2299 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; |
2265 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; | 2300 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; |
2266 | av7110->fe->ops->set_tone = av7110_set_tone; | 2301 | av7110->fe->ops->set_tone = av7110_set_tone; |
2302 | av7110->recover = dvb_s_recover; | ||
2267 | break; | 2303 | break; |
2268 | } | 2304 | } |
2269 | 2305 | ||
@@ -2300,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110) | |||
2300 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; | 2336 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; |
2301 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; | 2337 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; |
2302 | av7110->fe->ops->set_tone = av7110_set_tone; | 2338 | av7110->fe->ops->set_tone = av7110_set_tone; |
2339 | av7110->recover = dvb_s_recover; | ||
2303 | } | 2340 | } |
2304 | break; | 2341 | break; |
2305 | 2342 | ||
@@ -2328,6 +2365,7 @@ static int frontend_init(struct av7110 *av7110) | |||
2328 | if (av7110->fe) { | 2365 | if (av7110->fe) { |
2329 | av7110->fe->ops->set_voltage = lnbp21_set_voltage; | 2366 | av7110->fe->ops->set_voltage = lnbp21_set_voltage; |
2330 | av7110->fe->ops->dishnetwork_send_legacy_command = NULL; | 2367 | av7110->fe->ops->dishnetwork_send_legacy_command = NULL; |
2368 | av7110->recover = dvb_s_recover; | ||
2331 | } | 2369 | } |
2332 | break; | 2370 | break; |
2333 | } | 2371 | } |
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index d5550f462062..a817664f13e0 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h | |||
@@ -246,6 +246,15 @@ struct av7110 { | |||
246 | 246 | ||
247 | struct dvb_frontend* fe; | 247 | struct dvb_frontend* fe; |
248 | fe_status_t fe_status; | 248 | fe_status_t fe_status; |
249 | |||
250 | /* crash recovery */ | ||
251 | void (*recover)(struct av7110* av7110); | ||
252 | struct dvb_frontend_parameters saved_fe_params; | ||
253 | fe_sec_voltage_t saved_voltage; | ||
254 | fe_sec_tone_mode_t saved_tone; | ||
255 | struct dvb_diseqc_master_cmd saved_master_cmd; | ||
256 | fe_sec_mini_cmd_t saved_minicmd; | ||
257 | |||
249 | int (*fe_init)(struct dvb_frontend* fe); | 258 | int (*fe_init)(struct dvb_frontend* fe); |
250 | int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status); | 259 | int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status); |
251 | int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe); | 260 | int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe); |
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 54279aaa4828..cb377452b57d 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c | |||
@@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110) | |||
230 | 230 | ||
231 | dprintk(4, "%p\n", av7110); | 231 | dprintk(4, "%p\n", av7110); |
232 | 232 | ||
233 | av7110->arm_ready = 0; | ||
234 | |||
233 | saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); | 235 | saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); |
234 | 236 | ||
235 | /* Disable DEBI and GPIO irq */ | 237 | /* Disable DEBI and GPIO irq */ |
@@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
361 | break; | 363 | break; |
362 | if (err) { | 364 | if (err) { |
363 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); | 365 | printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); |
366 | av7110->arm_errors++; | ||
364 | return -ETIMEDOUT; | 367 | return -ETIMEDOUT; |
365 | } | 368 | } |
366 | msleep(1); | 369 | msleep(1); |