Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66190a27 authored by Oliver Endriss's avatar Oliver Endriss Committed by Mauro Carvalho Chehab
Browse files

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: default avatarOliver Endriss <o.endriss@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@brturbo.com.br>
parent da4ae5a7
Loading
Loading
Loading
Loading
+66 −28
Original line number Diff line number Diff line
@@ -196,17 +196,15 @@ static void recover_arm(struct av7110 *av7110)

	av7110_bootarm(av7110);
	msleep(100);
	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);
	init_av7110_av(av7110);

	av7110->arm_errors++;
	av7110->arm_ready = 0;
	recover_arm(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 av7110_arm_sync(struct av7110 *av7110)
@@ -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,11 +1057,22 @@ 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)
		av7110_av_start_play(av7110, 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;
		}
+9 −0
Original line number Diff line number Diff line
@@ -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);
+3 −0
Original line number Diff line number Diff line
@@ -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);