aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/fw-device-cdev.c7
-rw-r--r--drivers/firewire/fw-device-cdev.h1
-rw-r--r--drivers/firewire/fw-iso.c7
-rw-r--r--drivers/firewire/fw-ohci.c44
-rw-r--r--drivers/firewire/fw-transaction.h5
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
517static int ioctl_stop_iso(struct client *client, void __user *arg)
518{
519 return fw_iso_context_stop(client->iso_context);
520}
521
517static int 522static int
518dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) 523dispatch_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
102struct fw_cdev_get_config_rom { 103struct 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}
157EXPORT_SYMBOL(fw_iso_context_queue); 157EXPORT_SYMBOL(fw_iso_context_queue);
158
159int
160fw_iso_context_stop(struct fw_iso_context *ctx)
161{
162 return ctx->card->driver->stop_iso(ctx);
163}
164EXPORT_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,
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)
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
386fw_iso_context_start(struct fw_iso_context *ctx, 386fw_iso_context_start(struct fw_iso_context *ctx,
387 int channel, int speed, int cycle); 387 int channel, int speed, int cycle);
388 388
389int
390fw_iso_context_stop(struct fw_iso_context *ctx);
391
389struct fw_card_driver { 392struct 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
433int 438int