diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-02-16 17:34:42 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 22:02:59 +0100 |
commit | b82956685aab4a9d333714300eb8a86fed6c9ab3 (patch) | |
tree | dec07ca99cb70714ec1bb3e5c53314a7a5573e73 /drivers/firewire/fw-ohci.c | |
parent | 69cdb7268ca2e644665dae8ea26e35ce4e96679c (diff) |
firewire: Implement functionality to stop isochronous DMA contexts.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-ohci.c')
-rw-r--r-- | drivers/firewire/fw-ohci.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index faa384426a1..c0ab868b9fe 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -570,13 +570,19 @@ static void context_append(struct context *ctx, static void context_stop(struct context *ctx) { u32 reg; + int i; reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN); + flush_writes(ctx->ohci); - reg = reg_read(ctx->ohci, control_set(ctx->regs)); - if (reg & CONTEXT_ACTIVE) - fw_notify("Tried to stop context, but it is still active " - "(0x%08x).\n", reg); + for (i = 0; i < 10; i++) { + reg = reg_read(ctx->ohci, control_set(ctx->regs)); + if ((reg & CONTEXT_ACTIVE) == 0) + break; + + fw_notify("context_stop: still active (0x%08x)\n", reg); + msleep(1); + } } static void @@ -1379,6 +1385,25 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) return 0; } +static int ohci_stop_iso(struct fw_iso_context *base) +{ + struct fw_ohci *ohci = fw_ohci(base->card); + struct iso_context *ctx = container_of(base, struct iso_context, base); + int index; + + if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { + index = ctx - ohci->it_context_list; + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); + } else { + index = ctx - ohci->ir_context_list; + reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); + } + flush_writes(ohci); + context_stop(&ctx->context); + + return 0; +} + static void ohci_free_iso_context(struct fw_iso_context *base) { struct fw_ohci *ohci = fw_ohci(base->card); @@ -1386,22 +1411,18 @@ static void ohci_free_iso_context(struct fw_iso_context *base) unsigned long flags; int index; + ohci_stop_iso(base); + context_release(&ctx->context); + spin_lock_irqsave(&ohci->lock, flags); if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { index = ctx - ohci->it_context_list; - reg_write(ohci, OHCI1394_IsoXmitContextControlClear(index), ~0); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); ohci->it_context_mask |= 1 << index; } else { index = ctx - ohci->ir_context_list; - reg_write(ohci, OHCI1394_IsoRcvContextControlClear(index), ~0); - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); ohci->ir_context_mask |= 1 << index; } - flush_writes(ohci); - - context_release(&ctx->context); spin_unlock_irqrestore(&ohci->lock, flags); } @@ -1595,6 +1616,7 @@ static const struct fw_card_driver ohci_driver = { .free_iso_context = ohci_free_iso_context, .queue_iso = ohci_queue_iso, .start_iso = ohci_start_iso, + .stop_iso = ohci_stop_iso, }; static int software_reset(struct fw_ohci *ohci) |