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 16:02:59 -0500 |
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 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, | |||
570 | static void context_stop(struct context *ctx) | 570 | static 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 | ||
582 | static void | 588 | static 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 | ||
1388 | static 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 | |||
1382 | static void ohci_free_iso_context(struct fw_iso_context *base) | 1407 | static 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 | ||
1600 | static int software_reset(struct fw_ohci *ohci) | 1622 | static int software_reset(struct fw_ohci *ohci) |