aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-ohci.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-02-16 17:34:42 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:02:59 -0500
commitb82956685aab4a9d333714300eb8a86fed6c9ab3 (patch)
treedec07ca99cb70714ec1bb3e5c53314a7a5573e73 /drivers/firewire/fw-ohci.c
parent69cdb7268ca2e644665dae8ea26e35ce4e96679c (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.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index faa384426a12..c0ab868b9fe4 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -570,13 +570,19 @@ static void context_append(struct context *ctx,
570static void context_stop(struct context *ctx) 570static void context_stop(struct context *ctx)
571{ 571{
572 u32 reg; 572 u32 reg;
573 int i;
573 574
574 reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN); 575 reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN);
576 flush_writes(ctx->ohci);
575 577
576 reg = reg_read(ctx->ohci, control_set(ctx->regs)); 578 for (i = 0; i < 10; i++) {
577 if (reg & CONTEXT_ACTIVE) 579 reg = reg_read(ctx->ohci, control_set(ctx->regs));
578 fw_notify("Tried to stop context, but it is still active " 580 if ((reg & CONTEXT_ACTIVE) == 0)
579 "(0x%08x).\n", reg); 581 break;
582
583 fw_notify("context_stop: still active (0x%08x)\n", reg);
584 msleep(1);
585 }
580} 586}
581 587
582static void 588static void
@@ -1379,6 +1385,25 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
1379 return 0; 1385 return 0;
1380} 1386}
1381 1387
1388static int ohci_stop_iso(struct fw_iso_context *base)
1389{
1390 struct fw_ohci *ohci = fw_ohci(base->card);
1391 struct iso_context *ctx = container_of(base, struct iso_context, base);
1392 int index;
1393
1394 if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
1395 index = ctx - ohci->it_context_list;
1396 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index);
1397 } else {
1398 index = ctx - ohci->ir_context_list;
1399 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index);
1400 }
1401 flush_writes(ohci);
1402 context_stop(&ctx->context);
1403
1404 return 0;
1405}
1406
1382static void ohci_free_iso_context(struct fw_iso_context *base) 1407static void ohci_free_iso_context(struct fw_iso_context *base)
1383{ 1408{
1384 struct fw_ohci *ohci = fw_ohci(base->card); 1409 struct fw_ohci *ohci = fw_ohci(base->card);
@@ -1386,22 +1411,18 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
1386 unsigned long flags; 1411 unsigned long flags;
1387 int index; 1412 int index;
1388 1413
1414 ohci_stop_iso(base);
1415 context_release(&ctx->context);
1416
1389 spin_lock_irqsave(&ohci->lock, flags); 1417 spin_lock_irqsave(&ohci->lock, flags);
1390 1418
1391 if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { 1419 if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
1392 index = ctx - ohci->it_context_list; 1420 index = ctx - ohci->it_context_list;
1393 reg_write(ohci, OHCI1394_IsoXmitContextControlClear(index), ~0);
1394 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index);
1395 ohci->it_context_mask |= 1 << index; 1421 ohci->it_context_mask |= 1 << index;
1396 } else { 1422 } else {
1397 index = ctx - ohci->ir_context_list; 1423 index = ctx - ohci->ir_context_list;
1398 reg_write(ohci, OHCI1394_IsoRcvContextControlClear(index), ~0);
1399 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index);
1400 ohci->ir_context_mask |= 1 << index; 1424 ohci->ir_context_mask |= 1 << index;
1401 } 1425 }
1402 flush_writes(ohci);
1403
1404 context_release(&ctx->context);
1405 1426
1406 spin_unlock_irqrestore(&ohci->lock, flags); 1427 spin_unlock_irqrestore(&ohci->lock, flags);
1407} 1428}
@@ -1595,6 +1616,7 @@ static const struct fw_card_driver ohci_driver = {
1595 .free_iso_context = ohci_free_iso_context, 1616 .free_iso_context = ohci_free_iso_context,
1596 .queue_iso = ohci_queue_iso, 1617 .queue_iso = ohci_queue_iso,
1597 .start_iso = ohci_start_iso, 1618 .start_iso = ohci_start_iso,
1619 .stop_iso = ohci_stop_iso,
1598}; 1620};
1599 1621
1600static int software_reset(struct fw_ohci *ohci) 1622static int software_reset(struct fw_ohci *ohci)