Re: SAA7146 glitch on cold boot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Oliver Endriss wrote:
> Hi,
> 
> I did some tests and I can reproduce the bug with an Activy GR card...
> 
> Andrew de Quincey wrote:
> > On Friday 07 July 2006 22:56, Oliver Endriss wrote:
> > > Andrew de Quincey wrote:
> > > > On Tuesday 04 July 2006 22:04, Oliver Endriss wrote:
> > > > > Andrew de Quincey wrote:
> > > > > > Sure, I reduced it to:
> > > > > >
> > > > > > saa7146_write(budget->dev, MC1, MASK_20);	// DMA3 off
> > > > > > saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20));	/* DMA3 on */
> > >
> > > Ok, if we cannot fix it otherwise, your patch should execute exactly
> > > these 2 lines. There should be a FIXME comment explaining why the patch
> > > has been added. I still hope that we can find the real bug. ;-)
> > 
> > Yup.
> > 
> > > > > Hm - this means that DMA3 has either not been started or is stuck.
> > > > >
> > > > > Does it make a difference if you add both lines at the end of
> > > > > start_ts_capture?
> > > >
> > > > Nope no difference. I'd already tried this by stopping+starting
> > > > dvbtraffic before I tuned... it doesn't help (I did try again tho adding
> > > > the code to the driver to make sure).
> > > >
> > > > To recap:
> > > >
> > > > 1) start dvbtraffic
> > > >
> > > > 	-- IRQs are received from the saa7146.
> 
> Hm - does your frontend deliver garbage data while not tuned?
> My card does not generate VPE interrupts here.
> 
> > > > 2) tune and lock
> > > >
> > > > 	-- The IRQs suddenly halt for no reason.
> 
> Data transfer does not start here. Strange.
> 
> > > > 3) restart dvbtraffic
> > > >
> > > > 	-- IRQs start again and everything works fine thereafter.
> 
> Confirmed.
> 
> > > > And all only the very first time DMA is started on cold boot.
> > >
> > > Very strange. I don't understand why it happens only once.
> > >
> > > Basically, it looks like an initialization problem. On the other hand,
> > > the data transfer was working and stops later.
> > >
> > > Imho this does not look like a saa7146 bug. A hw bug should show up
> > > anytime, not only once after booting.
> > >
> > > Did you check the budget->feeding stuff? At the first glance it looks
> > > strange to me that stop_ts_capture decrements budget->feeding
> > > unconditionally, while start_ts_capture checks before incrementing.
> > 
> > I don't see how that would break only on a cold boot though... I can reboot 
> > the machine as many times as I want after that and it works perfectly every 
> > time.
> 
> There might be a difference:
> The frontend might be in a different state (tuned?) during warm boot.
> 
> I'll do more testing. Stay tuned.

Please try the attached patch. It should fix your problem.

Now DMA transfers will be started if (and only if)
- frontend has lock
- feeding > 0

If it works for you I will commit it to HG.

Oliver

P.S.:
This patch might also fix some infamous video data stream broken errors
with vdr.

-- 
--------------------------------------------------------
VDR Remote Plugin available at
http://www.escape-edv.de/endriss/vdr/
--------------------------------------------------------
diff -r 1abe425b6add linux/drivers/media/dvb/ttpci/budget-av.c
--- a/linux/drivers/media/dvb/ttpci/budget-av.c	Tue Jul 18 04:06:20 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-av.c	Tue Jul 18 04:25:55 2006 +0200
@@ -1303,6 +1303,9 @@ static int budget_av_attach(struct saa71
 	budget_av->budget.dvb_adapter.priv = budget_av;
 	frontend_init(budget_av);
 	ciintf_init(budget_av);
+
+	ttpci_budget_init_hooks(&budget_av->budget);
+
 	return 0;
 }
 
diff -r 1abe425b6add linux/drivers/media/dvb/ttpci/budget-ci.c
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c	Tue Jul 18 04:06:20 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c	Tue Jul 18 04:25:55 2006 +0200
@@ -1101,6 +1101,8 @@ static int budget_ci_attach(struct saa71
 	budget_ci->budget.dvb_adapter.priv = budget_ci;
 	frontend_init(budget_ci);
 
+	ttpci_budget_init_hooks(&budget_ci->budget);
+
 	return 0;
 }
 
diff -r 1abe425b6add linux/drivers/media/dvb/ttpci/budget-core.c
--- a/linux/drivers/media/dvb/ttpci/budget-core.c	Tue Jul 18 04:06:20 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-core.c	Tue Jul 18 04:25:55 2006 +0200
@@ -63,9 +63,6 @@ static int stop_ts_capture(struct budget
 {
 	dprintk(2, "budget: %p\n", budget);
 
-	if (--budget->feeding)
-		return budget->feeding;
-
 	saa7146_write(budget->dev, MC1, MASK_20);	// DMA3 off
 	SAA7146_IER_DISABLE(budget->dev, MASK_10);
 	return 0;
@@ -77,8 +74,8 @@ static int start_ts_capture(struct budge
 
 	dprintk(2, "budget: %p\n", budget);
 
-	if (budget->feeding)
-		return ++budget->feeding;
+	if (!budget->feeding || !budget->fe_synced)
+		return 0;
 
 	saa7146_write(dev, MC1, MASK_20);	// DMA3 off
 
@@ -139,7 +136,33 @@ static int start_ts_capture(struct budge
 	SAA7146_IER_ENABLE(budget->dev, MASK_10);	/* VPE */
 	saa7146_write(dev, MC1, (MASK_04 | MASK_20));	/* DMA3 on */
 
-	return ++budget->feeding;
+	return 0;
+}
+
+static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+	int synced;
+	int ret;
+
+	if (budget->read_fe_status)
+		ret = budget->read_fe_status(fe, status);
+	else
+		ret = -EINVAL;
+
+	if (!ret) {
+	       	synced = (*status & FE_HAS_LOCK);
+		if (synced != budget->fe_synced) {
+			budget->fe_synced = synced;
+			spin_lock(&budget->feedlock);
+			if (synced)
+				start_ts_capture(budget);
+			else
+				stop_ts_capture(budget);
+			spin_unlock(&budget->feedlock);
+		}
+	}
+	return ret;
 }
 
 static void vpeirq(unsigned long data)
@@ -267,7 +290,7 @@ static int budget_start_feed(struct dvb_
 {
 	struct dvb_demux *demux = feed->demux;
 	struct budget *budget = (struct budget *) demux->priv;
-	int status;
+	int status = 0;
 
 	dprintk(2, "budget: %p\n", budget);
 
@@ -276,7 +299,8 @@ static int budget_start_feed(struct dvb_
 
 	spin_lock(&budget->feedlock);
 	feed->pusi_seen = 0; /* have a clean section start */
-	status = start_ts_capture(budget);
+	if (budget->feeding++ == 0)
+		status = start_ts_capture(budget);
 	spin_unlock(&budget->feedlock);
 	return status;
 }
@@ -285,12 +309,13 @@ static int budget_stop_feed(struct dvb_d
 {
 	struct dvb_demux *demux = feed->demux;
 	struct budget *budget = (struct budget *) demux->priv;
-	int status;
+	int status = 0;
 
 	dprintk(2, "budget: %p\n", budget);
 
 	spin_lock(&budget->feedlock);
-	status = stop_ts_capture(budget);
+	if (--budget->feeding == 0)
+		status = stop_ts_capture(budget);
 	spin_unlock(&budget->feedlock);
 	return status;
 }
@@ -470,6 +495,14 @@ err:
 	return ret;
 }
 
+void ttpci_budget_init_hooks(struct budget *budget)
+{
+	if (budget->dvb_frontend && !budget->read_fe_status) {
+		budget->read_fe_status = budget->dvb_frontend->ops.read_status;
+		budget->dvb_frontend->ops.read_status = budget_read_fe_status;
+	}
+}
+
 int ttpci_budget_deinit(struct budget *budget)
 {
 	struct saa7146_dev *dev = budget->dev;
@@ -508,11 +541,8 @@ void ttpci_budget_set_video_port(struct 
 	spin_lock(&budget->feedlock);
 	budget->video_port = video_port;
 	if (budget->feeding) {
-		int oldfeeding = budget->feeding;
-		budget->feeding = 1;
 		stop_ts_capture(budget);
 		start_ts_capture(budget);
-		budget->feeding = oldfeeding;
 	}
 	spin_unlock(&budget->feedlock);
 }
@@ -520,6 +550,7 @@ EXPORT_SYMBOL_GPL(ttpci_budget_debiread)
 EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
 EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
 EXPORT_SYMBOL_GPL(ttpci_budget_init);
+EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
 EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
 EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
 EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
diff -r 1abe425b6add linux/drivers/media/dvb/ttpci/budget-patch.c
--- a/linux/drivers/media/dvb/ttpci/budget-patch.c	Tue Jul 18 04:06:20 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget-patch.c	Tue Jul 18 04:25:55 2006 +0200
@@ -617,6 +617,8 @@ static int budget_patch_attach (struct s
 	budget->dvb_adapter.priv = budget;
 	frontend_init(budget);
 
+	ttpci_budget_init_hooks(budget);
+
 	return 0;
 }
 
diff -r 1abe425b6add linux/drivers/media/dvb/ttpci/budget.c
--- a/linux/drivers/media/dvb/ttpci/budget.c	Tue Jul 18 04:06:20 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget.c	Tue Jul 18 04:25:55 2006 +0200
@@ -470,6 +470,8 @@ static int budget_attach (struct saa7146
 
 	budget->dvb_adapter.priv = budget;
 	frontend_init(budget);
+
+	ttpci_budget_init_hooks(budget);
 
 	return 0;
 }
diff -r 1abe425b6add linux/drivers/media/dvb/ttpci/budget.h
--- a/linux/drivers/media/dvb/ttpci/budget.h	Tue Jul 18 04:06:20 2006 +0200
+++ b/linux/drivers/media/dvb/ttpci/budget.h	Tue Jul 18 04:25:55 2006 +0200
@@ -60,13 +60,6 @@ struct budget {
 	struct dmx_frontend hw_frontend;
 	struct dmx_frontend mem_frontend;
 
-	int fe_synced;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
-	struct mutex pid_mutex;
-#else
-	struct semaphore pid_mutex;
-#endif
-
 	int ci_present;
 	int video_port;
 
@@ -86,6 +79,9 @@ struct budget {
 
 	struct dvb_adapter dvb_adapter;
 	struct dvb_frontend *dvb_frontend;
+	int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
+	int fe_synced;
+
 	void *priv;
 };
 
@@ -118,6 +114,7 @@ extern int ttpci_budget_init(struct budg
 extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
 			     struct saa7146_pci_extension_data *info,
 			     struct module *owner);
+extern void ttpci_budget_init_hooks(struct budget *budget);
 extern int ttpci_budget_deinit(struct budget *budget);
 extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
 extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux