aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Endriss <o.endriss@gmx.de>2006-01-09 12:32:42 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 12:32:42 -0500
commit66190a275246c8c5be140a224e021f8f5eb85ab6 (patch)
tree63137a5e59b5add88acd088450d659a8dc754873
parentda4ae5a72b2a9de351ec8f98543b7c666ec97005 (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>
-rw-r--r--drivers/media/dvb/ttpci/av7110.c94
-rw-r--r--drivers/media/dvb/ttpci/av7110.h9
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c3
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
203static 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
212static void av7110_arm_sync(struct av7110 *av7110) 210static 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
2228static 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
2212static u8 read_pwm(struct av7110* av7110) 2245static 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);