mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
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>
This commit is contained in:
parent
da4ae5a72b
commit
66190a2752
@ -196,19 +196,17 @@ static void recover_arm(struct av7110 *av7110)
|
||||
|
||||
av7110_bootarm(av7110);
|
||||
msleep(100);
|
||||
|
||||
init_av7110_av(av7110);
|
||||
|
||||
/* card-specific recovery */
|
||||
if (av7110->recover)
|
||||
av7110->recover(av7110);
|
||||
|
||||
restart_feeds(av7110);
|
||||
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
|
||||
}
|
||||
|
||||
static void arm_error(struct av7110 *av7110)
|
||||
{
|
||||
dprintk(4, "%p\n",av7110);
|
||||
|
||||
av7110->arm_errors++;
|
||||
av7110->arm_ready = 0;
|
||||
recover_arm(av7110);
|
||||
}
|
||||
|
||||
static void av7110_arm_sync(struct av7110 *av7110)
|
||||
{
|
||||
av7110->arm_rmmod = 1;
|
||||
@ -246,26 +244,22 @@ static int arm_thread(void *data)
|
||||
|
||||
if (down_interruptible(&av7110->dcomlock))
|
||||
break;
|
||||
|
||||
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
|
||||
up(&av7110->dcomlock);
|
||||
|
||||
if (newloops == av7110->arm_loops) {
|
||||
if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
|
||||
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
|
||||
av7110->dvb_adapter.num);
|
||||
|
||||
arm_error(av7110);
|
||||
av7710_set_video_mode(av7110, vidmode);
|
||||
|
||||
init_av7110_av(av7110);
|
||||
recover_arm(av7110);
|
||||
|
||||
if (down_interruptible(&av7110->dcomlock))
|
||||
break;
|
||||
|
||||
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
|
||||
up(&av7110->dcomlock);
|
||||
}
|
||||
av7110->arm_loops = newloops;
|
||||
av7110->arm_errors = 0;
|
||||
}
|
||||
|
||||
av7110->arm_thread = NULL;
|
||||
@ -516,10 +510,6 @@ static void gpioirq(unsigned long data)
|
||||
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
|
||||
|
||||
av7110->video_size.h = h_ar & 0xfff;
|
||||
dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
|
||||
av7110->video_size.w,
|
||||
av7110->video_size.h,
|
||||
av7110->video_size.aspect_ratio);
|
||||
|
||||
event.type = VIDEO_EVENT_SIZE_CHANGED;
|
||||
event.u.size.w = av7110->video_size.w;
|
||||
@ -541,6 +531,11 @@ static void gpioirq(unsigned long data)
|
||||
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
|
||||
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
|
||||
}
|
||||
|
||||
dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
|
||||
av7110->video_size.w, av7110->video_size.h,
|
||||
av7110->video_size.aspect_ratio);
|
||||
|
||||
dvb_video_add_event(av7110, &event);
|
||||
break;
|
||||
}
|
||||
@ -1054,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110)
|
||||
struct dvb_demux *dvbdmx = &av7110->demux;
|
||||
struct dvb_demux_feed *feed;
|
||||
int mode;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
dprintk(4, "%p\n", av7110);
|
||||
|
||||
@ -1062,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110)
|
||||
av7110->playing = 0;
|
||||
av7110->rec_mode = 0;
|
||||
|
||||
for (i = 0; i < dvbdmx->filternum; i++) {
|
||||
for (i = 0; i < dvbdmx->feednum; i++) {
|
||||
feed = &dvbdmx->feed[i];
|
||||
if (feed->state == DMX_STATE_GO)
|
||||
if (feed->state == DMX_STATE_GO) {
|
||||
if (feed->type == DMX_TYPE_SEC) {
|
||||
for (j = 0; j < dvbdmx->filternum; j++) {
|
||||
if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
|
||||
continue;
|
||||
if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
|
||||
continue;
|
||||
if (dvbdmx->filter[j].state == DMX_STATE_GO)
|
||||
dvbdmx->filter[j].state = DMX_STATE_READY;
|
||||
}
|
||||
}
|
||||
av7110_start_feed(feed);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode)
|
||||
@ -2121,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p
|
||||
struct av7110* av7110 = fe->dvb->priv;
|
||||
|
||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
av7110->saved_fe_params = *params;
|
||||
ret = av7110->fe_set_frontend(fe, params);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2164,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
|
||||
struct av7110* av7110 = fe->dvb->priv;
|
||||
|
||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
av7110->saved_master_cmd = *cmd;
|
||||
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2174,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
|
||||
struct av7110* av7110 = fe->dvb->priv;
|
||||
|
||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
av7110->saved_minicmd = minicmd;
|
||||
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2184,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
struct av7110* av7110 = fe->dvb->priv;
|
||||
|
||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
av7110->saved_tone = tone;
|
||||
ret = av7110->fe_set_tone(fe, tone);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2194,8 +2208,10 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta
|
||||
struct av7110* av7110 = fe->dvb->priv;
|
||||
|
||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
av7110->saved_voltage = voltage;
|
||||
ret = av7110->fe_set_voltage(fe, voltage);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2209,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dvb_s_recover(struct av7110* av7110)
|
||||
{
|
||||
av7110_fe_init(av7110->fe);
|
||||
|
||||
av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
|
||||
if (av7110->saved_master_cmd.msg_len) {
|
||||
msleep(20);
|
||||
av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
|
||||
}
|
||||
msleep(20);
|
||||
av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
|
||||
msleep(20);
|
||||
av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
|
||||
|
||||
av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
|
||||
}
|
||||
|
||||
static u8 read_pwm(struct av7110* av7110)
|
||||
{
|
||||
u8 b = 0xff;
|
||||
@ -2246,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110)
|
||||
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||
av7110->recover = dvb_s_recover;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2255,6 +2289,7 @@ static int frontend_init(struct av7110 *av7110)
|
||||
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||
av7110->recover = dvb_s_recover;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2264,6 +2299,7 @@ static int frontend_init(struct av7110 *av7110)
|
||||
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||
av7110->recover = dvb_s_recover;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2300,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110)
|
||||
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||
av7110->recover = dvb_s_recover;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2328,6 +2365,7 @@ static int frontend_init(struct av7110 *av7110)
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops->set_voltage = lnbp21_set_voltage;
|
||||
av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
|
||||
av7110->recover = dvb_s_recover;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -246,6 +246,15 @@ struct av7110 {
|
||||
|
||||
struct dvb_frontend* fe;
|
||||
fe_status_t fe_status;
|
||||
|
||||
/* crash recovery */
|
||||
void (*recover)(struct av7110* av7110);
|
||||
struct dvb_frontend_parameters saved_fe_params;
|
||||
fe_sec_voltage_t saved_voltage;
|
||||
fe_sec_tone_mode_t saved_tone;
|
||||
struct dvb_diseqc_master_cmd saved_master_cmd;
|
||||
fe_sec_mini_cmd_t saved_minicmd;
|
||||
|
||||
int (*fe_init)(struct dvb_frontend* fe);
|
||||
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
|
||||
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
|
||||
|
@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110)
|
||||
|
||||
dprintk(4, "%p\n", av7110);
|
||||
|
||||
av7110->arm_ready = 0;
|
||||
|
||||
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
|
||||
|
||||
/* Disable DEBI and GPIO irq */
|
||||
@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
|
||||
break;
|
||||
if (err) {
|
||||
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
|
||||
av7110->arm_errors++;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(1);
|
||||
|
Loading…
Reference in New Issue
Block a user