Commit b8295668 authored by Kristian Høgsberg's avatar Kristian Høgsberg Committed by Stefan Richter

firewire: Implement functionality to stop isochronous DMA contexts.

Signed-off-by: default avatarKristian Høgsberg <krh@redhat.com>
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent 69cdb726
...@@ -514,6 +514,11 @@ static int ioctl_start_iso(struct client *client, void __user *arg) ...@@ -514,6 +514,11 @@ static int ioctl_start_iso(struct client *client, void __user *arg)
request.speed, request.cycle); request.speed, request.cycle);
} }
static int ioctl_stop_iso(struct client *client, void __user *arg)
{
return fw_iso_context_stop(client->iso_context);
}
static int static int
dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
{ {
...@@ -532,6 +537,8 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) ...@@ -532,6 +537,8 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
return ioctl_queue_iso(client, arg); return ioctl_queue_iso(client, arg);
case FW_CDEV_IOC_START_ISO: case FW_CDEV_IOC_START_ISO:
return ioctl_start_iso(client, arg); return ioctl_start_iso(client, arg);
case FW_CDEV_IOC_STOP_ISO:
return ioctl_stop_iso(client, arg);
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -98,6 +98,7 @@ struct fw_cdev_event_iso_interrupt { ...@@ -98,6 +98,7 @@ struct fw_cdev_event_iso_interrupt {
#define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04) #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04)
#define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05) #define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05)
#define FW_CDEV_IOC_START_ISO _IO('#', 0x06) #define FW_CDEV_IOC_START_ISO _IO('#', 0x06)
#define FW_CDEV_IOC_STOP_ISO _IO('#', 0x07)
struct fw_cdev_get_config_rom { struct fw_cdev_get_config_rom {
__u32 length; __u32 length;
......
...@@ -155,3 +155,10 @@ fw_iso_context_queue(struct fw_iso_context *ctx, ...@@ -155,3 +155,10 @@ fw_iso_context_queue(struct fw_iso_context *ctx,
return card->driver->queue_iso(ctx, packet, buffer, payload); return card->driver->queue_iso(ctx, packet, buffer, payload);
} }
EXPORT_SYMBOL(fw_iso_context_queue); EXPORT_SYMBOL(fw_iso_context_queue);
int
fw_iso_context_stop(struct fw_iso_context *ctx)
{
return ctx->card->driver->stop_iso(ctx);
}
EXPORT_SYMBOL(fw_iso_context_stop);
...@@ -570,13 +570,19 @@ static void context_append(struct context *ctx, ...@@ -570,13 +570,19 @@ static void context_append(struct context *ctx,
static void context_stop(struct context *ctx) static void context_stop(struct context *ctx)
{ {
u32 reg; u32 reg;
int i;
reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN); reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN);
flush_writes(ctx->ohci);
reg = reg_read(ctx->ohci, control_set(ctx->regs)); for (i = 0; i < 10; i++) {
if (reg & CONTEXT_ACTIVE) reg = reg_read(ctx->ohci, control_set(ctx->regs));
fw_notify("Tried to stop context, but it is still active " if ((reg & CONTEXT_ACTIVE) == 0)
"(0x%08x).\n", reg); break;
fw_notify("context_stop: still active (0x%08x)\n", reg);
msleep(1);
}
} }
static void static void
...@@ -1379,6 +1385,25 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) ...@@ -1379,6 +1385,25 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
return 0; 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) static void ohci_free_iso_context(struct fw_iso_context *base)
{ {
struct fw_ohci *ohci = fw_ohci(base->card); struct fw_ohci *ohci = fw_ohci(base->card);
...@@ -1386,22 +1411,18 @@ static void ohci_free_iso_context(struct fw_iso_context *base) ...@@ -1386,22 +1411,18 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
unsigned long flags; unsigned long flags;
int index; int index;
ohci_stop_iso(base);
context_release(&ctx->context);
spin_lock_irqsave(&ohci->lock, flags); spin_lock_irqsave(&ohci->lock, flags);
if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
index = ctx - ohci->it_context_list; 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; ohci->it_context_mask |= 1 << index;
} else { } else {
index = ctx - ohci->ir_context_list; 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; ohci->ir_context_mask |= 1 << index;
} }
flush_writes(ohci);
context_release(&ctx->context);
spin_unlock_irqrestore(&ohci->lock, flags); spin_unlock_irqrestore(&ohci->lock, flags);
} }
...@@ -1595,6 +1616,7 @@ static const struct fw_card_driver ohci_driver = { ...@@ -1595,6 +1616,7 @@ static const struct fw_card_driver ohci_driver = {
.free_iso_context = ohci_free_iso_context, .free_iso_context = ohci_free_iso_context,
.queue_iso = ohci_queue_iso, .queue_iso = ohci_queue_iso,
.start_iso = ohci_start_iso, .start_iso = ohci_start_iso,
.stop_iso = ohci_stop_iso,
}; };
static int software_reset(struct fw_ohci *ohci) static int software_reset(struct fw_ohci *ohci)
......
...@@ -386,6 +386,9 @@ int ...@@ -386,6 +386,9 @@ int
fw_iso_context_start(struct fw_iso_context *ctx, fw_iso_context_start(struct fw_iso_context *ctx,
int channel, int speed, int cycle); int channel, int speed, int cycle);
int
fw_iso_context_stop(struct fw_iso_context *ctx);
struct fw_card_driver { struct fw_card_driver {
const char *name; const char *name;
...@@ -428,6 +431,8 @@ struct fw_card_driver { ...@@ -428,6 +431,8 @@ struct fw_card_driver {
struct fw_iso_packet *packet, struct fw_iso_packet *packet,
struct fw_iso_buffer *buffer, struct fw_iso_buffer *buffer,
unsigned long payload); unsigned long payload);
int (*stop_iso)(struct fw_iso_context *ctx);
}; };
int int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment