diff -urp ivtv-latest/driver/ivtv-driver.c ivtv/driver/ivtv-driver.c --- ivtv-latest/driver/ivtv-driver.c 2003-11-08 22:46:13.000000000 +0100 +++ ivtv/driver/ivtv-driver.c 2003-11-16 20:29:09.000000000 +0100 @@ -207,38 +207,47 @@ int ivtv_enq_buf(struct ivtv *itv, struc return 0; } +inline void __ivtv_del_buf(struct ivtv_buffer_list *queue, + struct ivtv_buffer *buffer) { + list_del_init(&buffer->list); + queue->elements--; +} + /* called to remove the buffer returned by _peek_ functions */ void ivtv_del_buf(struct ivtv *itv, struct ivtv_buffer_list *queue, struct ivtv_buffer *buffer) { unsigned long flags; spin_lock_irqsave(&itv->lock, flags); - list_del_init(&buffer->list); - queue->elements--; + __ivtv_del_buf(queue, buffer); spin_unlock_irqrestore(&itv->lock, flags); } /* returns first item in queue, doesn't dequeue */ -struct ivtv_buffer *ivtv_deq_peek_head(struct ivtv *itv, - struct ivtv_buffer_list *queue) { +struct ivtv_buffer *__ivtv_deq_peek_head(struct ivtv_buffer_list *queue) { struct ivtv_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&itv->lock, flags); /* make sure list has something to DeQ */ if (list_empty(&queue->list)) { IVTV_DEBUG(IVTV_DEBUG_INFO,"DeQ from empty list!\n"); queue->elements = 0; - spin_unlock_irqrestore(&itv->lock, flags); return NULL; } /* grab next element of the queue */ - buf = list_entry(queue->list.next, struct ivtv_buffer, list); - + return list_entry(queue->list.next, struct ivtv_buffer, list); +} + +struct ivtv_buffer *ivtv_deq_peek_head(struct ivtv *itv, + struct ivtv_buffer_list *queue) { + unsigned long flags; + struct ivtv_buffer *buffer; + + spin_lock_irqsave(&itv->lock, flags); + buffer = __ivtv_deq_peek_head(queue); spin_unlock_irqrestore(&itv->lock, flags); - return buf; + + return buffer; } /* removes buffer from the head */ @@ -325,18 +334,19 @@ int ivtv_free_queue(struct ivtv_buffer_l /* FIXME ugly */ /* verify ivtv before continuing */ + itv = NULL; for (x = 0; x < ivtv_cards_active; x++) { - if (queue->vdev->priv == &ivtv_cards[x]) + if (queue->vdev->priv == &ivtv_cards[x]) { + itv = queue->vdev->priv; break; + } } spin_unlock_irqrestore(&ivtv_lock, flags); - if (x == ivtv_cards_active) + if (itv == NULL) return -ENODEV; - itv = queue->vdev->priv; - while ((item = ivtv_deq_buf(itv, queue))) ivtv_free_buffer(itv, item); @@ -962,10 +972,10 @@ int ivtv_stop_capture(struct ivtv_open_i if (!test_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags)) break; - IVTV_DEBUG(IVTV_DEBUG_ERR, "dma still pending!\n"); + IVTV_DEBUG(IVTV_DEBUG_INFO, "dma still pending!\n"); schedule_timeout(HZ/100); if (x++ > 100) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "dma still not cleared\n"); + IVTV_DEBUG(IVTV_DEBUG_ERR, "giving up waiting for DMA pending clear\n"); break; } } while (1); @@ -1061,15 +1071,18 @@ void ivtv_dec_timeout(unsigned long arg) /* FIXME mpg only :/ */ struct ivtv_v4l2_stream *stream = &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG]; + unsigned long flags; if (!test_bit(IVTV_F_S_DMAP, &stream->s_flags)) return; IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: lost IRQ; resetting...\n"); + spin_lock_irqsave(&itv->lock, flags); ivtv_dec_DMA_done(itv); /* kick it off again! */ set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ivtv_dec_sched_DMA(itv); + spin_unlock_irqrestore(&itv->lock, flags); } #if 0 @@ -1144,6 +1157,8 @@ void ivtv_irq_handler(int irq, void *dev return; } + spin_lock(&itv->lock); + /* ivtv_show_irq_status(itv, stat, itv->irqmask, readl(itv->reg_mem + IVTV_REG_DMASTATUS)); @@ -1154,19 +1169,11 @@ void ivtv_irq_handler(int irq, void *dev writel(combo, (itv->reg_mem + IVTV_REG_IRQSTATUS)); if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) { -#if 0 - tasklet_schedule(&itv->dma_done_tq); -#else - ivtv_DMA_done_tasklet((unsigned long) itv); -#endif + ivtv_DMA_done(itv); IVTV_DEBUG(IVTV_DEBUG_IRQ, "Processed DMA-complete\n"); } if (combo & IVTV_IRQ_ENC_START_CAP) { -#if 0 - tasklet_schedule(&itv->dma_sched_tq); -#else - ivtv_sched_DMA_tasklet((unsigned long) itv); -#endif + ivtv_sched_DMA(itv); IVTV_DEBUG(IVTV_DEBUG_IRQ, "Processed enc-startcap\n"); } if (combo & IVTV_IRQ_ENC_EOS) { @@ -1216,8 +1223,7 @@ void ivtv_irq_handler(int irq, void *dev stat, itv->irqmask, combo); } */ - - return; + spin_unlock(&itv->lock); } void ivtv_irq_dec_vsync(struct ivtv* itv) { @@ -1247,12 +1253,11 @@ void ivtv_show_debug_flags(struct ivtv * printk("\n"); } -void ivtv_DMA_done_tasklet(unsigned long arg) { +void ivtv_DMA_done(struct ivtv *itv) { u32 result; int y,stmtype=-1; struct ivtv_v4l2_stream *stream=NULL; struct ivtv_buffer *buf; - struct ivtv *itv = (struct ivtv *) arg; IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA Done tasklet\n"); @@ -1265,36 +1270,39 @@ void ivtv_DMA_done_tasklet(unsigned long if (stmtype < 0) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Got DMA-done, but not expecting one\n"); - goto debug; + ivtv_show_debug_flags(itv); + return; } stream = &itv->v4l2.streams[stmtype]; #if 0 /* Silently return if we're in an overflow state */ - if (test_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) + if (test_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "silently returning\n"); return; + } +#else + if (test_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) + IVTV_DEBUG(IVTV_DEBUG_ERR, "full but continuing\n"); #endif + /* check DMA status register */ result = readl(itv->reg_mem + IVTV_REG_DMASTATUS); - - if (result & IVTV_DMA_WRITE_ERR) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA Error. Result: 0x%08x\n", result); + if (!(result & IVTV_DMA_SUCCESS)) { + if (result & IVTV_DMA_WRITE_ERR) + IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA write error. Result=0x%08x\n", result); + if (result & IVTV_DMA_READ_ERR) + IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA read error. Result=0x%08x\n",result); return; } - if (0 == (result & IVTV_DMA_SUCCESS)) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA interrupt, but no err and no " - "success. odd %x.\n", result); - goto debug; - } - /* DMA was fine if we made it this far */ /* remove from dma_pending queue */ - while ((buf = ivtv_deq_buf(itv, &stream->dma_q))) { + while ((buf = __ivtv_deq_buf(&stream->dma_q))) { IVTV_ASSERT(buf->dma_handle != IVTV_DMA_UNMAPPED); pci_unmap_single(itv->dev, buf->dma_handle, IVTV_DMA_BUF_SIZE, PCI_DMA_TODEVICE); @@ -1306,23 +1314,18 @@ void ivtv_DMA_done_tasklet(unsigned long } } /* put in the 'done' queue */ - ivtv_enq_buf(itv, &stream->full_q, buf); + __ivtv_enq_buf(&stream->full_q, buf); } /*wake up client*/ wake_up(&stream->waitq); - return; -debug: - ivtv_show_debug_flags(itv); } +/* must hold itv->lock */ int ivtv_ignore_DMA_req(struct ivtv *itv, u32 type) { u32 data[IVTV_MBOX_MAX_DATA]; - unsigned long flags; int ret = 0; - spin_lock_irqsave(&itv->lock, flags); - set_bit(IVTV_F_S_OVERFLOW, &itv->v4l2.streams[type].s_flags); data[0] = type; @@ -1336,19 +1339,17 @@ int ivtv_ignore_DMA_req(struct ivtv *itv if (!ret) set_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags); - spin_unlock_irqrestore(&itv->lock, flags); - return 0; + return ret; } /* FIXME this function is getting too long. split it up? */ -void ivtv_sched_DMA_tasklet(unsigned long arg) { +void ivtv_sched_DMA(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; u32 type, size, offset; u32 UVsize=0, UVoffset=0, pts_stamp=0; int x, bufs_needed; int uvflag=0; - struct ivtv *itv = (struct ivtv *) arg; struct ivtv_buffer *buf; LIST_HEAD(free_list); long sequence; @@ -1431,7 +1432,7 @@ void ivtv_sched_DMA_tasklet(unsigned lon for (x = 0; x < bufs_needed; x++) { struct ivtv_v4l2_stream *st = &itv->v4l2.streams[type]; - buf = ivtv_deq_buf(itv, &st->free_q); + buf = __ivtv_deq_buf(&st->free_q); if (!buf) break; @@ -1442,22 +1443,17 @@ void ivtv_sched_DMA_tasklet(unsigned lon if (x < bufs_needed) { struct ivtv_v4l2_stream *stream = &itv->v4l2.streams[type]; - IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA buffer DeQueue failed! got %d, want %d\n", x + 1, bufs_needed); - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: free_q: %d elements\n", stream->free_q.elements); - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: dma_q: %d elements\n", stream->dma_q.elements); - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: full_q: %d elements\n", stream->full_q.elements); + IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA buffer DeQueue failed! got %d, want %d\n", x + 1, bufs_needed + 1); + IVTV_DEBUG(IVTV_DEBUG_ERR, "SCHED: free_q: %d elements\n", stream->free_q.elements); + IVTV_DEBUG(IVTV_DEBUG_ERR, "SCHED: dma_q: %d elements\n", stream->dma_q.elements); + IVTV_DEBUG(IVTV_DEBUG_ERR, "SCHED: full_q: %d elements\n", stream->full_q.elements); while (!list_empty(&free_list)) { buf = list_entry(free_list.next, struct ivtv_buffer, list); list_del_init(&buf->list); - ivtv_enq_buf(itv, &itv->v4l2.streams[type].free_q, buf); + __ivtv_enq_buf(&itv->v4l2.streams[type].free_q, buf); } /* mark overflow condition, next free will restart dma req */ set_bit(IVTV_F_S_OVERFLOW, &itv->v4l2.streams[type].s_flags); - /* FIXME: must wait a little bit, perhaps use timer to fire - * this tasklet */ -#if 1 - tasklet_schedule(&itv->dma_sched_tq); -#endif return; } @@ -1510,7 +1506,7 @@ void ivtv_sched_DMA_tasklet(unsigned lon itv->SGarray[x].dst = buf->dma_handle; /* FIXME need to add pts stuff, index, etc. */ - ivtv_enq_buf(itv, &itv->v4l2.streams[type].dma_q, buf); + __ivtv_enq_buf(&itv->v4l2.streams[type].dma_q, buf); } /* This should wrap gracefully */ @@ -1538,6 +1534,15 @@ void ivtv_sched_DMA_tasklet(unsigned lon ivtv_api_irqsafe(itv->enc_mbox, IVTV_API_SCHED_DMA_TO_HOST, 4, &data[0]); } +void ivtv_sched_DMA_tasklet(unsigned long arg) { + struct ivtv *itv = (struct ivtv *) arg; + unsigned long flags; + + spin_lock_irqsave(&itv->lock, flags); + ivtv_sched_DMA(itv); + spin_unlock_irqrestore(&itv->lock, flags); +} + /* FIXME this function does way more than it should */ static int __devinit ivtv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int retval=0; @@ -1625,7 +1630,6 @@ static int __devinit ivtv_probe(struct p itv->dec_timeout.function = ivtv_dec_timeout; itv->dec_timeout.data = (unsigned long)itv; - tasklet_init(&itv->dma_done_tq, ivtv_DMA_done_tasklet, (unsigned long) itv); tasklet_init(&itv->dma_sched_tq, ivtv_sched_DMA_tasklet, (unsigned long) itv); IVTV_DEBUG(IVTV_DEBUG_INFO, "base addr: 0x%08x\n", itv->base_addr); @@ -2001,7 +2005,7 @@ static int ivtv_YUV_fixup(struct ivtv_v4 #endif long ivtv_read(struct ivtv_open_id *id, char *ubuf, size_t count, int block) { - int x, sleepctr, datalen, retval=0; + int x, sleepctr, datalen, retval=0, freed=0; struct ivtv *itv = id->itv; size_t newcount; unsigned long tid; @@ -2113,9 +2117,7 @@ long ivtv_read(struct ivtv_open_id *id, if ((buf->buffer.bytesused == 0)) { ivtv_del_buf(itv, &st->full_q, buf); ivtv_enq_buf(itv, &st->free_q, buf); - - if (test_and_clear_bit(IVTV_F_S_OVERFLOW, &st->s_flags)) - tasklet_schedule(&itv->dma_sched_tq); + freed++; buf = ivtv_deq_peek_head(itv, &st->full_q); if (buf) { @@ -2134,7 +2136,17 @@ long ivtv_read(struct ivtv_open_id *id, } } } /* end of while */ - + + /* if we put some buffers back in the free queue, kick off dma + * scheduling if card was stopped due to overflow before */ + if (freed && test_and_clear_bit(IVTV_F_S_OVERFLOW, &st->s_flags)) { +#if 0 + tasklet_schedule(&itv->dma_sched_tq); +#else + ivtv_sched_DMA_tasklet((unsigned long) itv); +#endif + } + /*FIXME unlock */ if (retval != 0) { IVTV_DEBUG(IVTV_DEBUG_INFO, "Returning %d\n", retval); @@ -2194,6 +2206,7 @@ int ivtv_fill_dec_buffers(struct ivtv_op * deemed necessary. */ while (bytesread == 0) { DECLARE_WAITQUEUE(wait, current); + unsigned long flags; buf = NULL; add_wait_queue(&stream->waitq, &wait); @@ -2210,7 +2223,9 @@ int ivtv_fill_dec_buffers(struct ivtv_op break; } + spin_lock_irqsave(&itv->lock, flags); ivtv_dec_sched_DMA(id->itv); + spin_unlock_irqrestore(&itv->lock, flags); } while (!buf); set_current_state(TASK_RUNNING); remove_wait_queue(&stream->waitq, &wait); @@ -2280,7 +2295,6 @@ void ivtv_dec_sched_DMA(struct ivtv *itv struct ivtv_v4l2_stream *stream=NULL; u32 data[IVTV_MBOX_MAX_DATA], result; u32 mem_offset, mem_size, hw_stream_type, buffer_bytes; - unsigned long flags; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_DMA\n"); @@ -2331,7 +2345,7 @@ void ivtv_dec_sched_DMA(struct ivtv *itv while ((max > x) && (mem_size > bytes_written)) { /* send a maximum of 'max' buffers */ - buf = ivtv_deq_peek_head(itv, &stream->full_q); + buf = __ivtv_deq_peek_head(&stream->full_q); if (buf == NULL) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: No more buffers to send\n"); @@ -2371,8 +2385,8 @@ void ivtv_dec_sched_DMA(struct ivtv *itv /* buffer is empty? */ if (buf->buffer.bytesused == 0) { - ivtv_del_buf(itv, &stream->full_q, buf); - ivtv_enq_buf(itv, &stream->dma_q, buf); + __ivtv_del_buf(&stream->full_q, buf); + __ivtv_enq_buf(&stream->dma_q, buf); } x++; } @@ -2391,16 +2405,12 @@ void ivtv_dec_sched_DMA(struct ivtv *itv data[1] = bytes_written; data[2] = hw_stream_type; - /* better to mask off the DEC interrupt... */ - spin_lock_irqsave(&itv->lock, flags); - /* note that we're DMA'ing */ mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); set_bit(IVTV_F_S_DMAP, &stream->s_flags); set_bit(IVTV_F_I_BUSY, &itv->i_flags); ivtv_api_irqsafe(itv->dec_mbox, IVTV_API_DEC_DMA_FROM_HOST, 3,&data[0]); - spin_unlock_irqrestore(&itv->lock, flags); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sched DEC dma: addr: 0x%08x, array_size 0x%08x, type 0x%08x\n", @@ -2410,20 +2420,21 @@ void ivtv_dec_sched_DMA(struct ivtv *itv void ivtv_dec_DMA_done(struct ivtv *itv) { struct ivtv_v4l2_stream *stream=NULL; struct ivtv_buffer *buf; - unsigned long flags; - int y, stmtype=-1; + int y, stmtype=-1, freed=0; IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: DMA Done tasklet\n"); - spin_lock_irqsave(&itv->lock, flags); - if (!test_and_clear_bit(IVTV_F_I_BUSY, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DMAP not set\n"); - spin_unlock_irqrestore(&itv->lock, flags); - goto debug; + ivtv_show_debug_flags(itv); + return; } +#if 0 del_timer(&itv->dec_timeout); +#else + mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); +#endif for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) { if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { @@ -2432,8 +2443,6 @@ void ivtv_dec_DMA_done(struct ivtv *itv) } } - spin_unlock_irqrestore(&itv->lock, flags); - /* Handle OSD DMA */ if (test_and_clear_bit(IVTV_F_I_OSD_DMA, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "OSD: DMA Done\n"); @@ -2449,13 +2458,14 @@ void ivtv_dec_DMA_done(struct ivtv *itv) if (stmtype < 0) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: Got DMA-done, not expecting one\n"); - goto debug; + ivtv_show_debug_flags(itv); + return; } IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Stream %d dma-done\n", y); stream = &itv->v4l2.streams[y]; - while ((buf = ivtv_deq_buf(itv, &stream->dma_q)) != NULL) { + while ((buf = __ivtv_deq_buf(&stream->dma_q)) != NULL) { IVTV_ASSERT(buf->dma_handle != IVTV_DMA_UNMAPPED); pci_unmap_single(itv->dev, buf->dma_handle, IVTV_DMA_DEC_BUF_SIZE, PCI_DMA_TODEVICE); @@ -2464,18 +2474,23 @@ void ivtv_dec_DMA_done(struct ivtv *itv) buf->readpos = 0; /* put in the 'done' queue */ - ivtv_enq_buf(itv, &stream->free_q, buf); + __ivtv_enq_buf(&stream->free_q, buf); + freed++; + } - if (test_and_clear_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) - tasklet_schedule(&itv->dma_sched_tq); + /* if we put some buffers back in the free queue, kick off dma + * scheduling if card was stopped due to overflow before */ + if (freed && test_and_clear_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) { +#if 0 + tasklet_schedule(&itv->dma_sched_tq); +#else + ivtv_sched_DMA(itv); +#endif } /* wake up queue filler */ wake_up(&stream->waitq); wake_up(&itv->dec_master_w); - return; -debug: - ivtv_show_debug_flags(itv); } int ivtv_get_timing_info(struct ivtv *itv, struct ivtv_ioctl_framesync *info) { @@ -2513,6 +2528,7 @@ int ivtv_get_timing_info(struct ivtv *it ssize_t ivtv_write(struct ivtv_open_id *id, const char *ubuf, size_t count) { int bytes_written=0, ret; + unsigned long flags; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_write\n"); @@ -2529,7 +2545,9 @@ ssize_t ivtv_write(struct ivtv_open_id * } /* send it! it'll return right away if no data needed */ + spin_lock_irqsave(&id->itv->lock, flags); ivtv_dec_sched_DMA(id->itv); + spin_unlock_irqrestore(&id->itv->lock, flags); } IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: returning %d\n", bytes_written); @@ -2551,6 +2569,7 @@ unsigned int ivtv_dec_poll(struct file * /* add stream's waitq to the poll list */ poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait); +#if 0 if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; @@ -2559,6 +2578,9 @@ unsigned int ivtv_dec_poll(struct file * } up(&id->itv->sem_lock); +#else + mask |= POLLOUT | POLLWRNORM; +#endif return mask; } @@ -2569,6 +2591,7 @@ unsigned int ivtv_poll(struct file *filp /* add stream's waitq to the poll list */ poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait); +#if 0 if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; @@ -2577,6 +2600,9 @@ unsigned int ivtv_poll(struct file *filp } up(&id->itv->sem_lock); +#else + mask |= POLLIN | POLLRDNORM; +#endif return mask; } diff -urp ivtv-latest/driver/ivtv.h ivtv/driver/ivtv.h --- ivtv-latest/driver/ivtv.h 2003-11-08 22:46:13.000000000 +0100 +++ ivtv/driver/ivtv.h 2003-11-09 01:16:02.000000000 +0100 @@ -678,7 +678,7 @@ struct ivtv { /* FIXME should use part of v4l2_performace instead */ unsigned long trans_id; - struct tasklet_struct dma_sched_tq, dma_done_tq; + struct tasklet_struct dma_sched_tq; u32 enc_fw_ver, dec_fw_ver, base_addr; /*is base_addr needed? */ u32 irqmask; @@ -808,8 +808,8 @@ int ivtv_move_queue(struct ivtv *itv, st /* Hardware/IRQ */ void ivtv_irq_handler(int irq, void *dev_id, struct pt_regs *regs); -void ivtv_DMA_done_tasklet(unsigned long arg); -void ivtv_sched_DMA_tasklet(unsigned long arg); +void ivtv_DMA_done(struct ivtv *itv); +void ivtv_sched_DMA(struct ivtv *itv); void ivtv_dec_DMA_done(struct ivtv *itv); void ivtv_dec_sched_DMA(struct ivtv *itv); extern void ivtv_set_irq_mask(struct ivtv *itv, unsigned long mask);