diff options
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 0690469fcecf..e509e13cb7a7 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
@@ -1723,6 +1723,8 @@ struct ohci_iso_xmit { | |||
1723 | struct dma_prog_region prog; | 1723 | struct dma_prog_region prog; |
1724 | struct ohci1394_iso_tasklet task; | 1724 | struct ohci1394_iso_tasklet task; |
1725 | int task_active; | 1725 | int task_active; |
1726 | int last_cycle; | ||
1727 | atomic_t skips; | ||
1726 | 1728 | ||
1727 | u32 ContextControlSet; | 1729 | u32 ContextControlSet; |
1728 | u32 ContextControlClear; | 1730 | u32 ContextControlClear; |
@@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso) | |||
1759 | iso->hostdata = xmit; | 1761 | iso->hostdata = xmit; |
1760 | xmit->ohci = iso->host->hostdata; | 1762 | xmit->ohci = iso->host->hostdata; |
1761 | xmit->task_active = 0; | 1763 | xmit->task_active = 0; |
1764 | xmit->last_cycle = -1; | ||
1765 | atomic_set(&iso->skips, 0); | ||
1762 | 1766 | ||
1763 | dma_prog_region_init(&xmit->prog); | 1767 | dma_prog_region_init(&xmit->prog); |
1764 | 1768 | ||
@@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data) | |||
1856 | /* parse cycle */ | 1860 | /* parse cycle */ |
1857 | cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; | 1861 | cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; |
1858 | 1862 | ||
1863 | if (xmit->last_cycle > -1) { | ||
1864 | int cycle_diff = cycle - xmit->last_cycle; | ||
1865 | int skip; | ||
1866 | |||
1867 | /* unwrap */ | ||
1868 | if (cycle_diff < 0) { | ||
1869 | cycle_diff += 8000; | ||
1870 | if (cycle_diff < 0) | ||
1871 | PRINT(KERN_ERR, "bogus cycle diff %d\n", | ||
1872 | cycle_diff); | ||
1873 | } | ||
1874 | |||
1875 | skip = cycle_diff - 1; | ||
1876 | if (skip > 0) { | ||
1877 | DBGMSG("skipped %d cycles without packet loss", skip); | ||
1878 | atomic_add(skip, &iso->skips); | ||
1879 | } | ||
1880 | } | ||
1881 | xmit->last_cycle = cycle; | ||
1882 | |||
1859 | /* tell the subsystem the packet has gone out */ | 1883 | /* tell the subsystem the packet has gone out */ |
1860 | hpsb_iso_packet_sent(iso, cycle, event != 0x11); | 1884 | hpsb_iso_packet_sent(iso, cycle, event != 0x11); |
1861 | 1885 | ||
@@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info | |||
1943 | prev->output_last.branchAddress = cpu_to_le32( | 1967 | prev->output_last.branchAddress = cpu_to_le32( |
1944 | dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); | 1968 | dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); |
1945 | 1969 | ||
1970 | /* | ||
1971 | * Link the skip address to this descriptor itself. This causes a | ||
1972 | * context to skip a cycle whenever lost cycles or FIFO overruns occur, | ||
1973 | * without dropping the data at that point the application should then | ||
1974 | * decide whether this is an error condition or not. Some protocols | ||
1975 | * can deal with this by dropping some rate-matching padding packets. | ||
1976 | */ | ||
1977 | next->output_more_immediate.branchAddress = | ||
1978 | prev->output_last.branchAddress; | ||
1979 | |||
1946 | /* disable interrupt, unless required by the IRQ interval */ | 1980 | /* disable interrupt, unless required by the IRQ interval */ |
1947 | if (prev_i % iso->irq_interval) { | 1981 | if (prev_i % iso->irq_interval) { |
1948 | prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ | 1982 | prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ |