/* Module Parameters */
static int phys_dma = 1;
module_param(phys_dma, int, 0444);
-MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
+MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1).");
static void dma_trm_tasklet(unsigned long data);
static void dma_trm_reset(struct dma_trm_ctx *d);
struct dma_prog_region prog;
struct ohci1394_iso_tasklet task;
int task_active;
+ int last_cycle;
+ atomic_t skips;
u32 ContextControlSet;
u32 ContextControlClear;
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);
/* 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);
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 */
d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
if (d->buf_cpu == NULL || d->buf_bus == NULL) {
- PRINT(KERN_ERR, "Failed to allocate dma buffer");
+ PRINT(KERN_ERR, "Failed to allocate %s", "DMA buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
- PRINT(KERN_ERR, "Failed to allocate dma prg");
+ PRINT(KERN_ERR, "Failed to allocate %s", "DMA prg");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
if (d->spb == NULL) {
- PRINT(KERN_ERR, "Failed to allocate split buffer");
+ PRINT(KERN_ERR, "Failed to allocate %s", "split buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
memset(d->buf_cpu[i], 0, d->buf_size);
} else {
PRINT(KERN_ERR,
- "Failed to allocate dma buffer");
+ "Failed to allocate %s", "DMA buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
} else {
PRINT(KERN_ERR,
- "Failed to allocate dma prg");
+ "Failed to allocate %s", "DMA prg");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
- PRINT(KERN_ERR, "Failed to allocate at dma prg");
+ PRINT(KERN_ERR, "Failed to allocate %s", "AT DMA prg");
free_dma_trm_ctx(d);
return -ENOMEM;
}
memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
} else {
PRINT(KERN_ERR,
- "Failed to allocate at dma prg");
+ "Failed to allocate %s", "AT DMA prg");
free_dma_trm_ctx(d);
return -ENOMEM;
}
host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
if (!host) {
- PRINT_G(KERN_ERR, "Failed to allocate host structure");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "host structure");
goto err;
}
ohci = host->hostdata;
pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
&ohci->csr_config_rom_bus);
if (ohci->csr_config_rom_cpu == NULL) {
- PRINT_G(KERN_ERR, "Failed to allocate buffer config rom");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "buffer config rom");
goto err;
}
ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
&ohci->selfid_buf_bus);
if (ohci->selfid_buf_cpu == NULL) {
- PRINT_G(KERN_ERR, "Failed to allocate self-ID buffer");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "self-ID buffer");
goto err;
}
ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
DMA_CTX_ASYNC_REQ, 0, AR_REQ_NUM_DESC,
AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE,
OHCI1394_AsReqRcvContextBase) < 0) {
- PRINT_G(KERN_ERR, "Failed to allocate AR Req context");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Req context");
goto err;
}
/* AR DMA response context allocation */
DMA_CTX_ASYNC_RESP, 0, AR_RESP_NUM_DESC,
AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE,
OHCI1394_AsRspRcvContextBase) < 0) {
- PRINT_G(KERN_ERR, "Failed to allocate AR Resp context");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Resp context");
goto err;
}
/* AT DMA request context */
if (alloc_dma_trm_ctx(ohci, &ohci->at_req_context,
DMA_CTX_ASYNC_REQ, 0, AT_REQ_NUM_DESC,
OHCI1394_AsReqTrContextBase) < 0) {
- PRINT_G(KERN_ERR, "Failed to allocate AT Req context");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Req context");
goto err;
}
/* AT DMA response context */
if (alloc_dma_trm_ctx(ohci, &ohci->at_resp_context,
DMA_CTX_ASYNC_RESP, 1, AT_RESP_NUM_DESC,
OHCI1394_AsRspTrContextBase) < 0) {
- PRINT_G(KERN_ERR, "Failed to allocate AT Resp context");
+ PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Resp context");
goto err;
}
/* Start off with a soft reset, to clear everything to a sane
ohci = pci_get_drvdata(dev);
if (!ohci)
- return;
+ goto out;
device = get_device(&ohci->host->device);
release_mem_region(pci_resource_start(dev, 0),
OHCI1394_REGISTER_SIZE);
- ohci1394_pmac_off(dev);
-
case OHCI_INIT_ALLOC_HOST:
pci_set_drvdata(dev, NULL);
}
if (device)
put_device(device);
+out:
+ ohci1394_pmac_off(dev);
}
#ifdef CONFIG_PM