From patchwork Fri Jan 16 15:03:10 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Boettcher X-Patchwork-Id: 2825 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n0GExdQS023784 for ; Fri, 16 Jan 2009 06:59:40 -0800 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755919AbZAPPDy (ORCPT ); Fri, 16 Jan 2009 10:03:54 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755785AbZAPPDx (ORCPT ); Fri, 16 Jan 2009 10:03:53 -0500 Received: from znsun1.ifh.de ([141.34.1.16]:51085 "EHLO znsun1.ifh.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755919AbZAPPDw (ORCPT ); Fri, 16 Jan 2009 10:03:52 -0500 Received: from pub2.ifh.de (pub2.ifh.de [141.34.15.192]) by znsun1.ifh.de (8.12.11.20060614/8.12.11) with ESMTP id n0GF3Aov021952; Fri, 16 Jan 2009 16:03:10 +0100 (MET) Received: by pub2.ifh.de (Postfix, from userid 11503) id 48473301ED; Fri, 16 Jan 2009 16:03:10 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by pub2.ifh.de (Postfix) with ESMTP id 37802301D7; Fri, 16 Jan 2009 16:03:10 +0100 (CET) Date: Fri, 16 Jan 2009 16:03:10 +0100 (CET) From: Patrick Boettcher X-X-Sender: pboettch@pub2.ifh.de To: linux-dvb@linuxtv.org cc: Linux Media Mailing List Subject: RFC - Flexcop Streaming watchdog (VDSB) Message-ID: User-Agent: Alpine 1.10 (LRH 962 2008-03-14) MIME-Version: 1.0 X-Spam-Report: ALL_TRUSTED,AWL,BAYES_00 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Hi lists, For years there has been the Video Data Stream Borken-error with VDR and Technisat cards: The error occured randomly and unfrequently. A work-around for that problem was to restart VDR and let the driver reset the pid-filtering and streaming interface. In fact it turned out, that the problem is worse with setups not based on VDR and the "VDSB-error" could be really easily reproduced (I'm not sure if this applies to all generations on SkyStar2-card). I'm skipping the description of the problem here... Attached you'll find a patch which works around the hardware bug which is causing VDSB-error without needing to reload the driver. There a struct-work-watchdog looking at the number of irq-received while having PIDs active in the PID-filter. If no IRQs are received, the pid-filter-system is reset. It seems to fix the problem and so far I've not seen any false positives (like resetting the pid-filter even though streaming is working fine). Before asking to pull the patch I'd like to discuss an issue: my work-around is iterating over the pid-filter-list in the dvb_demux. I'm doing this in the struct-work-callback. In dvb_demux.c I see that this list is protected with a spinlock. When I now try to take the spinlock in the work-function I'll get a nice message saying, that I cannot do take a spinlock in a work-function. What can I do? What is the proper way to protect access to this list? Is it needed at all? thanks for you input in advance, Patrick. --- Mail: patrick.boettcher@desy.de WWW: http://www.wi-bw.tfh-wildau.de/~pboettch/ diff -r 7981bdd4e25a linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c --- a/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c Mon Jan 12 00:18:04 2009 +0000 +++ b/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c Fri Jan 16 15:46:32 2009 +0100 @@ -179,7 +179,7 @@ /* if it was the first or last feed request change the stream-status */ if (fc->feedcount == onoff) { - flexcop_rcv_data_ctrl(fc,onoff); + flexcop_rcv_data_ctrl(fc, onoff); if (fc->stream_control) /* device specific stream control */ fc->stream_control(fc,onoff); @@ -192,6 +192,7 @@ return 0; } +EXPORT_SYMBOL(flexcop_pid_feed_control); void flexcop_hw_filter_init(struct flexcop_device *fc) { diff -r 7981bdd4e25a linux/drivers/media/dvb/b2c2/flexcop-pci.c --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c Mon Jan 12 00:18:04 2009 +0000 +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c Fri Jan 16 15:46:32 2009 +0100 @@ -13,9 +13,9 @@ module_param(enable_pid_filtering, int, 0444); MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); -static int irq_chk_intv; +static int irq_chk_intv = 100; module_param(irq_chk_intv, int, 0644); -MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging)."); +MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG #define dprintk(level,args...) \ @@ -34,7 +34,7 @@ static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); +MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." DEBSTATUS); #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" @@ -58,6 +58,8 @@ int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ int count; + int count_prev; + int stream_problem; spinlock_t irq_lock; @@ -115,18 +117,47 @@ #endif struct flexcop_device *fc = fc_pci->fc_dev; - flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); + if (fc->feedcount) { + flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); - flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); + // flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); - if (v.sram_dest_reg_714.net_ovflow_error) - deb_chk("sram net_ovflow_error\n"); - if (v.sram_dest_reg_714.media_ovflow_error) - deb_chk("sram media_ovflow_error\n"); - if (v.sram_dest_reg_714.cai_ovflow_error) - deb_chk("sram cai_ovflow_error\n"); - if (v.sram_dest_reg_714.cai_ovflow_error) - deb_chk("sram cai_ovflow_error\n"); +#if 0 + deb_chk("net_ovflow_error: %d, media_ovflow_error: %d, cai_ovflow_error: %d, cao_ovflow_error: %d, sram_dma: %d, maximumfill: %d\n", + v.sram_dest_reg_714.net_ovflow_error, + v.sram_dest_reg_714.media_ovflow_error, + v.sram_dest_reg_714.cai_ovflow_error, + v.sram_dest_reg_714.cao_ovflow_error, + v.sram_dest_reg_714.ctrl_sramdma, + v.sram_dest_reg_714.ctrl_maximumfill); +#endif + + if (fc_pci->count == fc_pci->count_prev) { + deb_chk("no IRQ since the last time\n"); + if (fc_pci->stream_problem++ == 3) { + struct dvb_demux_feed *feed; + int t = 0; + + /* work-queue is atomic -> cannot + * take the demux.lock here, but is it needed? XXX + * spin_lock_irq(&fc->demux.lock); */ + list_for_each_entry(feed, &fc->demux.feed_list, list_head) { + flexcop_pid_feed_control(fc, feed, 0); + t++; + } + + list_for_each_entry(feed, &fc->demux.feed_list, list_head) { + flexcop_pid_feed_control(fc, feed, 1); + } + /* spin_unlock_irq(&fc->demux.lock); */ + + fc_pci->stream_problem = 0; + } + } else { + fc_pci->stream_problem = 0; + fc_pci->count_prev = fc_pci->count; + } + } schedule_delayed_work(&fc_pci->irq_check_work, msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); @@ -232,16 +263,12 @@ flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); deb_irq("IRQ enabled\n"); + fc_pci->count_prev = fc_pci->count; + // fc_pci->active_dma1_addr = 0; // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); - if (irq_chk_intv > 0) - schedule_delayed_work(&fc_pci->irq_check_work, - msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); } else { - if (irq_chk_intv > 0) - cancel_delayed_work(&fc_pci->irq_check_work); - flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); deb_irq("IRQ disabled\n"); @@ -315,8 +342,6 @@ IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) goto err_pci_iounmap; - - fc_pci->init_state |= FC_PCI_INIT; return ret; @@ -395,6 +420,10 @@ INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); #endif + if (irq_chk_intv > 0) + schedule_delayed_work(&fc_pci->irq_check_work, + msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); + return ret; err_fc_exit: @@ -412,6 +441,9 @@ static void flexcop_pci_remove(struct pci_dev *pdev) { struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); + + if (irq_chk_intv > 0) + cancel_delayed_work(&fc_pci->irq_check_work); flexcop_pci_dma_exit(fc_pci); flexcop_device_exit(fc_pci->fc_dev);