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 | |
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>
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 7 | ||||
-rw-r--r-- | drivers/firewire/fw-device-cdev.h | 1 | ||||
-rw-r--r-- | drivers/firewire/fw-iso.c | 7 | ||||
-rw-r--r-- | drivers/firewire/fw-ohci.c | 44 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 5 |
5 files changed, 53 insertions, 11 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index b738c997ef39..1ce33d4f91a3 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c | |||
@@ -514,6 +514,11 @@ static int ioctl_start_iso(struct client *client, void __user *arg) | |||
514 | request.speed, request.cycle); | 514 | request.speed, request.cycle); |
515 | } | 515 | } |
516 | 516 | ||
517 | static int ioctl_stop_iso(struct client *client, void __user *arg) | ||
518 | { | ||
519 | return fw_iso_context_stop(client->iso_context); | ||
520 | } | ||
521 | |||
517 | static int | 522 | static int |
518 | dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) | 523 | dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) |
519 | { | 524 | { |
@@ -532,6 +537,8 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) | |||
532 | return ioctl_queue_iso(client, arg); | 537 | return ioctl_queue_iso(client, arg); |
533 | case FW_CDEV_IOC_START_ISO: | 538 | case FW_CDEV_IOC_START_ISO: |
534 | return ioctl_start_iso(client, arg); | 539 | return ioctl_start_iso(client, arg); |
540 | case FW_CDEV_IOC_STOP_ISO: | ||
541 | return ioctl_stop_iso(client, arg); | ||
535 | default: | 542 | default: |
536 | return -EINVAL; | 543 | return -EINVAL; |
537 | } | 544 | } |
diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index ac91ce501bfe..257dc872f46d 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h | |||
@@ -98,6 +98,7 @@ struct fw_cdev_event_iso_interrupt { | |||
98 | #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04) | 98 | #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04) |
99 | #define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05) | 99 | #define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05) |
100 | #define FW_CDEV_IOC_START_ISO _IO('#', 0x06) | 100 | #define FW_CDEV_IOC_START_ISO _IO('#', 0x06) |
101 | #define FW_CDEV_IOC_STOP_ISO _IO('#', 0x07) | ||
101 | 102 | ||
102 | struct fw_cdev_get_config_rom { | 103 | struct fw_cdev_get_config_rom { |
103 | __u32 length; | 104 | __u32 length; |
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index d84792fe619a..1605e1157237 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c | |||
@@ -155,3 +155,10 @@ fw_iso_context_queue(struct fw_iso_context *ctx, | |||
155 | return card->driver->queue_iso(ctx, packet, buffer, payload); | 155 | return card->driver->queue_iso(ctx, packet, buffer, payload); |
156 | } | 156 | } |
157 | EXPORT_SYMBOL(fw_iso_context_queue); | 157 | EXPORT_SYMBOL(fw_iso_context_queue); |
158 | |||
159 | int | ||
160 | fw_iso_context_stop(struct fw_iso_context *ctx) | ||
161 | { | ||
162 | return ctx->card->driver->stop_iso(ctx); | ||
163 | } | ||
164 | EXPORT_SYMBOL(fw_iso_context_stop); | ||
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) |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 9ccbed80cebb..b2a0a030c0fd 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -386,6 +386,9 @@ int | |||
386 | fw_iso_context_start(struct fw_iso_context *ctx, | 386 | fw_iso_context_start(struct fw_iso_context *ctx, |
387 | int channel, int speed, int cycle); | 387 | int channel, int speed, int cycle); |
388 | 388 | ||
389 | int | ||
390 | fw_iso_context_stop(struct fw_iso_context *ctx); | ||
391 | |||
389 | struct fw_card_driver { | 392 | struct fw_card_driver { |
390 | const char *name; | 393 | const char *name; |
391 | 394 | ||
@@ -428,6 +431,8 @@ struct fw_card_driver { | |||
428 | struct fw_iso_packet *packet, | 431 | struct fw_iso_packet *packet, |
429 | struct fw_iso_buffer *buffer, | 432 | struct fw_iso_buffer *buffer, |
430 | unsigned long payload); | 433 | unsigned long payload); |
434 | |||
435 | int (*stop_iso)(struct fw_iso_context *ctx); | ||
431 | }; | 436 | }; |
432 | 437 | ||
433 | int | 438 | int |