diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-25 12:24:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-25 12:24:06 -0700 |
commit | 5f3b28781cbc030351e2fa0712602afbea592aae (patch) | |
tree | 1387cb2fcea6d4119cd7ad13c76e79c41d5ff4ac /drivers/ieee1394/ohci1394.c | |
parent | f7ce1f5e083fc099346019fb1f8d56a5452703ed (diff) | |
parent | e38649702ea64fdbbab3dd459bf8558142dd3bc4 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
ieee1394: silence defined but not used warning in non-modular builds
ieee1394: rawiso: requeue packet for transmission after skipped cycle
Diffstat (limited to 'drivers/ieee1394/ohci1394.c')
-rw-r--r-- | drivers/ieee1394/ohci1394.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 0690469fcec..e509e13cb7a 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -1723,6 +1723,8 @@ struct ohci_iso_xmit { struct dma_prog_region prog; struct ohci1394_iso_tasklet task; int task_active; + int last_cycle; + atomic_t skips; u32 ContextControlSet; u32 ContextControlClear; @@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso) iso->hostdata = xmit; xmit->ohci = iso->host->hostdata; xmit->task_active = 0; + xmit->last_cycle = -1; + atomic_set(&iso->skips, 0); dma_prog_region_init(&xmit->prog); @@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data) /* parse cycle */ cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; + if (xmit->last_cycle > -1) { + int cycle_diff = cycle - xmit->last_cycle; + int skip; + + /* unwrap */ + if (cycle_diff < 0) { + cycle_diff += 8000; + if (cycle_diff < 0) + PRINT(KERN_ERR, "bogus cycle diff %d\n", + cycle_diff); + } + + skip = cycle_diff - 1; + if (skip > 0) { + DBGMSG("skipped %d cycles without packet loss", skip); + atomic_add(skip, &iso->skips); + } + } + xmit->last_cycle = cycle; + /* tell the subsystem the packet has gone out */ hpsb_iso_packet_sent(iso, cycle, event != 0x11); @@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info prev->output_last.branchAddress = cpu_to_le32( dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); + /* + * Link the skip address to this descriptor itself. This causes a + * context to skip a cycle whenever lost cycles or FIFO overruns occur, + * without dropping the data at that point the application should then + * decide whether this is an error condition or not. Some protocols + * can deal with this by dropping some rate-matching padding packets. + */ + next->output_more_immediate.branchAddress = + prev->output_last.branchAddress; + /* disable interrupt, unless required by the IRQ interval */ if (prev_i % iso->irq_interval) { prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ |