Thread: [Linux1394-cvslog] rev 690 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <dde...@li...> - 2002-11-18 07:23:17
|
Author: ddennedy Date: 2002-11-18 02:22:43 -0500 (Mon, 18 Nov 2002) New Revision: 690 Modified: trunk/dv1394.c Log: improved reception overrun handling between DMA, packet buffer, and frame buffer Modified: trunk/dv1394.c ============================================================================== --- trunk/dv1394.c (original) +++ trunk/dv1394.c 2002-11-18 02:22:44.000000000 -0500 @@ -53,6 +53,8 @@ via pci_alloc_consistent() DONE: + - during reception, better handling of dropped frames and continuity errors + - during reception, prevent DMA from bypassing the irq tasklets - reduce irq rate during reception (1/250 packets). - add many more internal buffers during reception with scatter/gather dma. - add dbc (continuity) checking on receive, increment status.dropped_frames @@ -760,6 +762,9 @@ int dif_sequence = p->data[1] >> 4; /* dif sequence number is in bits 4 - 7 */ int dif_block = p->data[2]; + /* sanity check */ + if (dif_sequence > 11 || dif_block > 149) return; + switch (section_type) { case 0: /* 1 Header block */ memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480); @@ -898,10 +903,6 @@ } /* next j */ - /* loop tail to head */ - if (f != NULL && f->frame_end_branch != NULL) - *(f->frame_end_branch) = cpu_to_le32(video->frames[0]->descriptor_pool_dma | 1); /* set Z=1 */ - spin_unlock_irqrestore(&video->spinlock, irq_flags); } @@ -1142,7 +1143,7 @@ struct dv1394_init init; init.api_version = DV1394_API_VERSION; - init.n_frames = 2; + init.n_frames = DV1394_MAX_FRAMES / 4; /* the following are now set via proc_fs or devfs */ init.channel = video->channel; init.format = video->pal_or_ntsc; @@ -2292,8 +2293,9 @@ spin_lock(&video->spinlock); - if( (video->ohci_ir_ctx != -1) && - (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { + if( (video->ohci_ir_ctx != -1) + && (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) + { int sof=0; /* start-of-frame flag */ struct frame *f; @@ -2301,7 +2303,12 @@ int i, dbc=0; struct DMA_descriptor_block *block = NULL; u16 xferstatus; - + + int next_i, prev_i; + struct DMA_descriptor_block *next = NULL; + dma_addr_t next_dma = 0; + struct DMA_descriptor_block *prev = NULL; + /* loop over all descriptors in all frames */ for (i = 0; i < video->n_frames*MAX_PACKETS; i++) { struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet); @@ -2338,7 +2345,12 @@ dbc = (int) (p->cip_h1 >> 24); if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) - video->dropped_frames++; + { + video->dropped_frames += video->n_clear_frames + 1; + video->first_frame = 0; + video->n_clear_frames = 0; + video->first_clear_frame = -1; + } video->continuity_counter = dbc; if (!video->first_frame) { @@ -2351,8 +2363,11 @@ frame_reset(f); /* f->state = STATE_CLEAR */ video->n_clear_frames++; if (video->n_clear_frames > video->n_frames) { - video->n_clear_frames = video->n_frames; video->dropped_frames++; + video->n_clear_frames--; + if (video->n_clear_frames < 0) + video->n_clear_frames = 0; + video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; } if (video->first_clear_frame == -1) video->first_clear_frame = video->active_frame; @@ -2388,6 +2403,29 @@ /* reset xferStatus & resCount */ block->u.in.il.q[3] = cpu_to_le32(512); + /* terminate dma chain at this (next) packet */ + next_i = video->current_packet; + f = video->frames[next_i / MAX_PACKETS]; + next = &(f->descriptor_pool[next_i % MAX_PACKETS]); + next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; + next->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ + next->u.in.il.q[2] = 0; /* disable branch */ + + /* link previous to next */ + prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); + f = video->frames[prev_i / MAX_PACKETS]; + prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); + if(prev_i % (MAX_PACKETS/2)) { + prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */ + } else { + prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ + } + prev->u.in.il.q[2] = (cpu_to_le32(next_dma) | 1); /* set Z=1 */ + wmb(); + + /* wake up DMA in case it fell asleep */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); + /* advance packet_buffer cursor */ video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * video->n_frames); @@ -2396,7 +2434,7 @@ wake = 1; /* why the hell not? */ } /* receive interrupt */ - + spin_unlock(&video->spinlock); if(wake) { |