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