Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] dvb: flexcop: woraround irq stop problem

The flexcop chip often stops generating interrupts after some hours of
operation. Apparently this can be fixed by resetting register block 0x300 at
each channel change (this is not detailed in the flexcop data books).

This patch also restructures DMA handling and adds a bit of debug code for the
irq problem in case it still happens for someone.

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Patrick Boettcher and committed by
Linus Torvalds
64221be7 2819639b

+284 -106
+5 -1
drivers/media/dvb/b2c2/flexcop-common.h
··· 108 108 int flexcop_device_initialize(struct flexcop_device*); 109 109 void flexcop_device_exit(struct flexcop_device *fc); 110 110 111 + void flexcop_reset_block_300(struct flexcop_device *fc); 112 + 111 113 /* from flexcop-dma.c */ 112 114 int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size); 113 115 void flexcop_dma_free(struct flexcop_dma *dma); ··· 117 115 int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); 118 116 int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); 119 117 int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); 120 - int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index); 118 + int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); 119 + int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); 121 120 int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); 122 121 int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets); 123 122 ··· 154 151 /* from flexcop-misc.c */ 155 152 void flexcop_determine_revision(struct flexcop_device *fc); 156 153 void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix); 154 + void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num); 157 155 158 156 /* from flexcop-hw-filter.c */ 159 157 int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff);
+121 -64
drivers/media/dvb/b2c2/flexcop-dma.c
··· 37 37 } 38 38 EXPORT_SYMBOL(flexcop_dma_free); 39 39 40 - int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 40 + int flexcop_dma_config(struct flexcop_device *fc, 41 + struct flexcop_dma *dma, 42 + flexcop_dma_index_t dma_idx) 41 43 { 42 - flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 44 + flexcop_ibi_value v0x0,v0x4,v0xc; 45 + v0x0.raw = v0x4.raw = v0xc.raw = 0; 43 46 44 - if (no & FC_DMA_1) 45 - v.ctrl_208.DMA1_Timer_Enable_sig = onoff; 47 + v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; 48 + v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; 49 + v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; 46 50 47 - if (no & FC_DMA_2) 48 - v.ctrl_208.DMA2_Timer_Enable_sig = onoff; 51 + if ((dma_idx & FC_DMA_1) == dma_idx) { 52 + fc->write_ibi_reg(fc,dma1_000,v0x0); 53 + fc->write_ibi_reg(fc,dma1_004,v0x4); 54 + fc->write_ibi_reg(fc,dma1_00c,v0xc); 55 + } else if ((dma_idx & FC_DMA_2) == dma_idx) { 56 + fc->write_ibi_reg(fc,dma2_010,v0x0); 57 + fc->write_ibi_reg(fc,dma2_014,v0x4); 58 + fc->write_ibi_reg(fc,dma2_01c,v0xc); 59 + } else { 60 + err("either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call."); 61 + return -EINVAL; 62 + } 49 63 50 - fc->write_ibi_reg(fc,ctrl_208,v); 51 64 return 0; 52 65 } 53 - EXPORT_SYMBOL(flexcop_dma_control_timer_irq); 66 + EXPORT_SYMBOL(flexcop_dma_config); 54 67 55 - int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 68 + /* start the DMA transfers, but not the DMA IRQs */ 69 + int flexcop_dma_xfer_control(struct flexcop_device *fc, 70 + flexcop_dma_index_t dma_idx, 71 + flexcop_dma_addr_index_t index, 72 + int onoff) 73 + { 74 + flexcop_ibi_value v0x0,v0xc; 75 + flexcop_ibi_register r0x0,r0xc; 76 + 77 + if ((dma_idx & FC_DMA_1) == dma_idx) { 78 + r0x0 = dma1_000; 79 + r0xc = dma1_00c; 80 + } else if ((dma_idx & FC_DMA_2) == dma_idx) { 81 + r0x0 = dma2_010; 82 + r0xc = dma2_01c; 83 + } else { 84 + err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call."); 85 + return -EINVAL; 86 + } 87 + 88 + v0x0 = fc->read_ibi_reg(fc,r0x0); 89 + v0xc = fc->read_ibi_reg(fc,r0xc); 90 + 91 + deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw); 92 + deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw); 93 + 94 + if (index & FC_DMA_SUBADDR_0) 95 + v0x0.dma_0x0.dma_0start = onoff; 96 + 97 + if (index & FC_DMA_SUBADDR_1) 98 + v0xc.dma_0xc.dma_1start = onoff; 99 + 100 + fc->write_ibi_reg(fc,r0x0,v0x0); 101 + fc->write_ibi_reg(fc,r0xc,v0xc); 102 + 103 + deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw); 104 + deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw); 105 + return 0; 106 + } 107 + EXPORT_SYMBOL(flexcop_dma_xfer_control); 108 + 109 + static int flexcop_dma_remap(struct flexcop_device *fc, 110 + flexcop_dma_index_t dma_idx, 111 + int onoff) 112 + { 113 + flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; 114 + flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 115 + deb_info("%s\n",__FUNCTION__); 116 + v.dma_0xc.remap_enable = onoff; 117 + fc->write_ibi_reg(fc,r,v); 118 + return 0; 119 + } 120 + 121 + int flexcop_dma_control_size_irq(struct flexcop_device *fc, 122 + flexcop_dma_index_t no, 123 + int onoff) 56 124 { 57 125 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 58 126 ··· 135 67 } 136 68 EXPORT_SYMBOL(flexcop_dma_control_size_irq); 137 69 138 - int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 70 + int flexcop_dma_control_timer_irq(struct flexcop_device *fc, 71 + flexcop_dma_index_t no, 72 + int onoff) 139 73 { 140 74 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 141 75 76 + if (no & FC_DMA_1) 77 + v.ctrl_208.DMA1_Timer_Enable_sig = onoff; 78 + 79 + if (no & FC_DMA_2) 80 + v.ctrl_208.DMA2_Timer_Enable_sig = onoff; 81 + 82 + fc->write_ibi_reg(fc,ctrl_208,v); 83 + return 0; 84 + } 85 + EXPORT_SYMBOL(flexcop_dma_control_timer_irq); 86 + 87 + /* 1 cycles = 1.97 msec */ 88 + int flexcop_dma_config_timer(struct flexcop_device *fc, 89 + flexcop_dma_index_t dma_idx, 90 + u8 cycles) 91 + { 92 + flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 93 + flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 94 + 95 + flexcop_dma_remap(fc,dma_idx,0); 96 + 97 + deb_info("%s\n",__FUNCTION__); 98 + v.dma_0x4_write.dmatimer = cycles; 99 + fc->write_ibi_reg(fc,r,v); 100 + return 0; 101 + } 102 + EXPORT_SYMBOL(flexcop_dma_config_timer); 103 + 104 + /* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */ 105 + int flexcop_dma_control_packet_irq(struct flexcop_device *fc, 106 + flexcop_dma_index_t no, 107 + int onoff) 108 + { 109 + flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 110 + 111 + deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); 142 112 if (no & FC_DMA_1) 143 113 v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff; 144 114 ··· 184 78 v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff; 185 79 186 80 fc->write_ibi_reg(fc,ctrl_208,v); 81 + deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); 82 + 187 83 return 0; 188 84 } 189 85 EXPORT_SYMBOL(flexcop_dma_control_packet_irq); 190 86 191 - int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index) 192 - { 193 - 194 - flexcop_ibi_value v0x0,v0x4,v0xc; 195 - v0x0.raw = v0x4.raw = v0xc.raw = 0; 196 - 197 - v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; 198 - v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; 199 - v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; 200 - 201 - if (index & FC_DMA_SUBADDR_0) 202 - v0x0.dma_0x0.dma_0start = 1; 203 - 204 - if (index & FC_DMA_SUBADDR_1) 205 - v0xc.dma_0xc.dma_1start = 1; 206 - 207 - if (dma_idx & FC_DMA_1) { 208 - fc->write_ibi_reg(fc,dma1_000,v0x0); 209 - fc->write_ibi_reg(fc,dma1_004,v0x4); 210 - fc->write_ibi_reg(fc,dma1_00c,v0xc); 211 - } else { /* (dma_idx & FC_DMA_2) */ 212 - fc->write_ibi_reg(fc,dma2_010,v0x0); 213 - fc->write_ibi_reg(fc,dma2_014,v0x4); 214 - fc->write_ibi_reg(fc,dma2_01c,v0xc); 215 - } 216 - 217 - return 0; 218 - } 219 - EXPORT_SYMBOL(flexcop_dma_config); 220 - 221 - static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, int onoff) 222 - { 223 - flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; 224 - flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 225 - v.dma_0xc.remap_enable = onoff; 226 - fc->write_ibi_reg(fc,r,v); 227 - return 0; 228 - } 229 - 230 - /* 1 cycles = 1.97 msec */ 231 - int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles) 232 - { 233 - flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 234 - flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 235 - 236 - flexcop_dma_remap(fc,dma_idx,0); 237 - 238 - v.dma_0x4_write.dmatimer = cycles >> 1; 239 - fc->write_ibi_reg(fc,r,v); 240 - return 0; 241 - } 242 - EXPORT_SYMBOL(flexcop_dma_config_timer); 243 - 244 - int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets) 87 + int flexcop_dma_config_packet_count(struct flexcop_device *fc, 88 + flexcop_dma_index_t dma_idx, 89 + u8 packets) 245 90 { 246 91 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 247 92 flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+10 -2
drivers/media/dvb/b2c2/flexcop-hw-filter.c
··· 10 10 static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) 11 11 { 12 12 flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff); 13 + 14 + deb_ts("rcv_data is now: '%s'\n",onoff ? "on" : "off"); 13 15 } 14 16 15 17 void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) ··· 153 151 { 154 152 int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32; 155 153 156 - fc->feedcount += onoff ? 1 : -1; 154 + fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */ 157 155 if (dvbdmxfeed->index >= max_pid_filter) 158 156 fc->extra_feedcount += onoff ? 1 : -1; 159 157 ··· 180 178 /* if it was the first or last feed request change the stream-status */ 181 179 if (fc->feedcount == onoff) { 182 180 flexcop_rcv_data_ctrl(fc,onoff); 183 - if (fc->stream_control) 181 + if (fc->stream_control) /* device specific stream control */ 184 182 fc->stream_control(fc,onoff); 183 + 184 + /* feeding stopped -> reset the flexcop filter*/ 185 + if (onoff == 0) { 186 + flexcop_reset_block_300(fc); 187 + flexcop_hw_filter_init(fc); 188 + } 185 189 } 186 190 187 191 return 0;
+12
drivers/media/dvb/b2c2/flexcop-misc.c
··· 65 65 flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type], 66 66 flexcop_revision_names[fc->rev],suffix); 67 67 } 68 + 69 + void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num) 70 + { 71 + flexcop_ibi_value v; 72 + int i; 73 + for (i = 0; i < num; i++) { 74 + v = fc->read_ibi_reg(fc,reg+4*i); 75 + deb_rdump("0x%03x: %08x, ",reg+4*i, v.raw); 76 + } 77 + deb_rdump("\n"); 78 + } 79 + EXPORT_SYMBOL(flexcop_dump_reg);
+87 -35
drivers/media/dvb/b2c2/flexcop-pci.c
··· 13 13 module_param(enable_pid_filtering, int, 0444); 14 14 MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); 15 15 16 + static int irq_chk_intv; 17 + module_param(irq_chk_intv, int, 0644); 18 + MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging)."); 19 + 16 20 #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG 17 21 #define dprintk(level,args...) \ 18 22 do { if ((debug & level)) printk(args); } while (0) ··· 30 26 #define deb_reg(args...) dprintk(0x02,args) 31 27 #define deb_ts(args...) dprintk(0x04,args) 32 28 #define deb_irq(args...) dprintk(0x08,args) 29 + #define deb_chk(args...) dprintk(0x10,args) 33 30 34 31 static int debug = 0; 35 32 module_param(debug, int, 0644); ··· 60 55 int count; 61 56 62 57 spinlock_t irq_lock; 58 + 59 + unsigned long last_irq; 60 + 61 + struct work_struct irq_check_work; 63 62 64 63 struct flexcop_device *fc_dev; 65 64 }; ··· 97 88 return 0; 98 89 } 99 90 91 + static void flexcop_pci_irq_check_work(void *data) 92 + { 93 + struct flexcop_pci *fc_pci = data; 94 + struct flexcop_device *fc = fc_pci->fc_dev; 95 + 96 + flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); 97 + 98 + flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); 99 + 100 + if (v.sram_dest_reg_714.net_ovflow_error) 101 + deb_chk("sram net_ovflow_error\n"); 102 + if (v.sram_dest_reg_714.media_ovflow_error) 103 + deb_chk("sram media_ovflow_error\n"); 104 + if (v.sram_dest_reg_714.cai_ovflow_error) 105 + deb_chk("sram cai_ovflow_error\n"); 106 + if (v.sram_dest_reg_714.cai_ovflow_error) 107 + deb_chk("sram cai_ovflow_error\n"); 108 + 109 + schedule_delayed_work(&fc_pci->irq_check_work, 110 + msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); 111 + } 112 + 100 113 /* When PID filtering is turned on, we use the timer IRQ, because small amounts 101 114 * of data need to be passed to the user space instantly as well. When PID 102 115 * filtering is turned off, we use the page-change-IRQ */ 103 - static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs) 116 + static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) 104 117 { 105 118 struct flexcop_pci *fc_pci = dev_id; 106 119 struct flexcop_device *fc = fc_pci->fc_dev; 107 - flexcop_ibi_value v = fc->read_ibi_reg(fc,irq_20c); 120 + flexcop_ibi_value v; 108 121 irqreturn_t ret = IRQ_HANDLED; 109 122 110 123 spin_lock_irq(&fc_pci->irq_lock); 124 + 125 + v = fc->read_ibi_reg(fc,irq_20c); 126 + 127 + /* errors */ 128 + if (v.irq_20c.Data_receiver_error) 129 + deb_chk("data receiver error\n"); 130 + if (v.irq_20c.Continuity_error_flag) 131 + deb_chk("Contunuity error flag is set\n"); 132 + if (v.irq_20c.LLC_SNAP_FLAG_set) 133 + deb_chk("LLC_SNAP_FLAG_set is set\n"); 134 + if (v.irq_20c.Transport_Error) 135 + deb_chk("Transport error\n"); 136 + 137 + if ((fc_pci->count % 1000) == 0) 138 + deb_chk("%d valid irq took place so far\n",fc_pci->count); 111 139 112 140 if (v.irq_20c.DMA1_IRQ_Status == 1) { 113 141 if (fc_pci->active_dma1_addr == 0) ··· 161 115 fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; 162 116 u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; 163 117 164 - deb_irq("irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ", 165 - v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); 118 + deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ", 119 + jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); 120 + fc_pci->last_irq = jiffies; 166 121 167 122 /* buffer end was reached, restarted from the beginning 168 123 * pass the data from last_cur_pos to the buffer end to the demux ··· 174 127 fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, 175 128 (fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos); 176 129 fc_pci->last_dma1_cur_pos = 0; 177 - fc_pci->count = 0; 178 130 } 179 131 180 132 if (cur_pos > fc_pci->last_dma1_cur_pos) { ··· 185 139 deb_irq("\n"); 186 140 187 141 fc_pci->last_dma1_cur_pos = cur_pos; 188 - } else 142 + fc_pci->count++; 143 + } else { 144 + deb_irq("isr for flexcop called, apparently without reason (%08x)\n",v.raw); 189 145 ret = IRQ_NONE; 146 + } 190 147 191 148 spin_unlock_irq(&fc_pci->irq_lock); 192 - 193 - /* packet count would be ideal for hw filtering, but it isn't working. Either 194 - * the data book is wrong, or I'm unable to read it correctly */ 195 - 196 - /* if (v.irq_20c.DMA1_Size_IRQ_Status == 1) { packet counter */ 197 149 198 150 return ret; 199 151 } ··· 200 156 { 201 157 struct flexcop_pci *fc_pci = fc->bus_specific; 202 158 if (onoff) { 203 - flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1); 204 - flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1); 205 - flexcop_dma_config_timer(fc,FC_DMA_1,1); 159 + flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1); 160 + flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2); 206 161 207 - if (fc_pci->fc_dev->pid_filtering) { 208 - fc_pci->last_dma1_cur_pos = 0; 209 - flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); 210 - } else { 211 - fc_pci->active_dma1_addr = 0; 212 - flexcop_dma_control_size_irq(fc,FC_DMA_1,1); 213 - } 162 + flexcop_dma_config_timer(fc,FC_DMA_1,0); 214 163 215 - /* flexcop_dma_config_packet_count(fc,FC_DMA_1,0xc0); 216 - flexcop_dma_control_packet_irq(fc,FC_DMA_1,1); */ 164 + flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,1); 165 + deb_irq("DMA xfer enabled\n"); 217 166 218 - deb_irq("irqs enabled\n"); 167 + fc_pci->last_dma1_cur_pos = 0; 168 + flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); 169 + deb_irq("IRQ enabled\n"); 170 + 171 + // fc_pci->active_dma1_addr = 0; 172 + // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); 173 + 174 + if (irq_chk_intv > 0) 175 + schedule_delayed_work(&fc_pci->irq_check_work, 176 + msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); 219 177 } else { 220 - if (fc_pci->fc_dev->pid_filtering) 221 - flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); 222 - else 223 - flexcop_dma_control_size_irq(fc,FC_DMA_1,0); 178 + if (irq_chk_intv > 0) 179 + cancel_delayed_work(&fc_pci->irq_check_work); 224 180 225 - // flexcop_dma_control_packet_irq(fc,FC_DMA_1,0); 226 - deb_irq("irqs disabled\n"); 181 + flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); 182 + deb_irq("IRQ disabled\n"); 183 + 184 + // flexcop_dma_control_size_irq(fc,FC_DMA_1,0); 185 + 186 + flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,0); 187 + deb_irq("DMA xfer disabled\n"); 227 188 } 228 189 229 190 return 0; ··· 247 198 flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); 248 199 249 200 fc_pci->init_state |= FC_PCI_DMA_INIT; 201 + 250 202 goto success; 251 203 dma1_free: 252 204 flexcop_dma_free(&fc_pci->dma[0]); ··· 294 244 295 245 pci_set_drvdata(fc_pci->pdev, fc_pci); 296 246 297 - if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_irq, 247 + if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr, 298 248 SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0) 299 249 goto err_pci_iounmap; 300 250 ··· 374 324 if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) 375 325 goto err_fc_exit; 376 326 327 + INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci); 328 + 377 329 goto success; 378 330 err_fc_exit: 379 331 flexcop_device_exit(fc); ··· 402 350 403 351 static struct pci_device_id flexcop_pci_tbl[] = { 404 352 { PCI_DEVICE(0x13d0, 0x2103) }, 405 - /* { PCI_DEVICE(0x13d0, 0x2200) }, PCI FlexCopIII ? */ 353 + /* { PCI_DEVICE(0x13d0, 0x2200) }, ? */ 406 354 { }, 407 355 }; 408 356 409 357 MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl); 410 358 411 359 static struct pci_driver flexcop_pci_driver = { 412 - .name = "Technisat/B2C2 FlexCop II/IIb/III PCI", 360 + .name = "Technisat/B2C2 FlexCop II/IIb PCI", 413 361 .id_table = flexcop_pci_tbl, 414 - .probe = flexcop_pci_probe, 415 - .remove = flexcop_pci_remove, 362 + .probe = flexcop_pci_probe, 363 + .remove = flexcop_pci_remove, 416 364 }; 417 365 418 366 static int __init flexcop_pci_module_init(void)
+32 -2
drivers/media/dvb/b2c2/flexcop.c
··· 46 46 47 47 int b2c2_flexcop_debug; 48 48 module_param_named(debug, b2c2_flexcop_debug, int, 0644); 49 - MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram (|-able))." DEBSTATUS); 49 + MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS); 50 50 #undef DEBSTATUS 51 51 52 52 /* global zero for ibi values */ ··· 173 173 fc->write_ibi_reg(fc,ctrl_208,ibi_zero); 174 174 175 175 v210.raw = 0; 176 - v210.sw_reset_210.reset_blocks = 0xff; 176 + v210.sw_reset_210.reset_block_000 = 1; 177 + v210.sw_reset_210.reset_block_100 = 1; 178 + v210.sw_reset_210.reset_block_200 = 1; 179 + v210.sw_reset_210.reset_block_300 = 1; 180 + v210.sw_reset_210.reset_block_400 = 1; 181 + v210.sw_reset_210.reset_block_500 = 1; 182 + v210.sw_reset_210.reset_block_600 = 1; 183 + v210.sw_reset_210.reset_block_700 = 1; 177 184 v210.sw_reset_210.Block_reset_enable = 0xb2; 185 + 186 + v210.sw_reset_210.Special_controls = 0xc259; 187 + 178 188 fc->write_ibi_reg(fc,sw_reset_210,v210); 189 + msleep(1); 179 190 180 191 /* reset the periphical devices */ 181 192 ··· 196 185 v204.misc_204.Per_reset_sig = 1; 197 186 fc->write_ibi_reg(fc,misc_204,v204); 198 187 } 188 + 189 + void flexcop_reset_block_300(struct flexcop_device *fc) 190 + { 191 + flexcop_ibi_value v208_save = fc->read_ibi_reg(fc,ctrl_208), 192 + v210 = fc->read_ibi_reg(fc,sw_reset_210); 193 + 194 + deb_rdump("208: %08x, 210: %08x\n",v208_save.raw,v210.raw); 195 + 196 + fc->write_ibi_reg(fc,ctrl_208,ibi_zero); 197 + 198 + v210.sw_reset_210.reset_block_300 = 1; 199 + v210.sw_reset_210.Block_reset_enable = 0xb2; 200 + 201 + fc->write_ibi_reg(fc,sw_reset_210,v210); 202 + msleep(1); 203 + 204 + fc->write_ibi_reg(fc,ctrl_208,v208_save); 205 + } 206 + EXPORT_SYMBOL(flexcop_reset_block_300); 199 207 200 208 struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) 201 209 {
+1
drivers/media/dvb/b2c2/flexcop.h
··· 26 26 #define deb_i2c(args...) dprintk(0x04,args) 27 27 #define deb_ts(args...) dprintk(0x08,args) 28 28 #define deb_sram(args...) dprintk(0x10,args) 29 + #define deb_rdump(args...) dprintk(0x20,args) 29 30 30 31 #endif
+8 -1
drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
··· 152 152 struct { 153 153 u32 Special_controls :16; 154 154 u32 Block_reset_enable : 8; 155 - u32 reset_blocks : 8; 155 + u32 reset_block_700 : 1; 156 + u32 reset_block_600 : 1; 157 + u32 reset_block_500 : 1; 158 + u32 reset_block_400 : 1; 159 + u32 reset_block_300 : 1; 160 + u32 reset_block_200 : 1; 161 + u32 reset_block_100 : 1; 162 + u32 reset_block_000 : 1; 156 163 } sw_reset_210; 157 164 158 165 struct {
+8 -1
drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
··· 150 150 } irq_20c; 151 151 152 152 struct { 153 - u32 reset_blocks : 8; 153 + u32 reset_block_000 : 1; 154 + u32 reset_block_100 : 1; 155 + u32 reset_block_200 : 1; 156 + u32 reset_block_300 : 1; 157 + u32 reset_block_400 : 1; 158 + u32 reset_block_500 : 1; 159 + u32 reset_block_600 : 1; 160 + u32 reset_block_700 : 1; 154 161 u32 Block_reset_enable : 8; 155 162 u32 Special_controls :16; 156 163 } sw_reset_210;