mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
69cdb7268c
commit
b82956685a
|
@ -514,6 +514,11 @@ static int ioctl_start_iso(struct client *client, void __user *arg)
|
|||
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
|
||||
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);
|
||||
case FW_CDEV_IOC_START_ISO:
|
||||
return ioctl_start_iso(client, arg);
|
||||
case FW_CDEV_IOC_STOP_ISO:
|
||||
return ioctl_stop_iso(client, arg);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ struct fw_cdev_event_iso_interrupt {
|
|||
#define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04)
|
||||
#define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05)
|
||||
#define FW_CDEV_IOC_START_ISO _IO('#', 0x06)
|
||||
#define FW_CDEV_IOC_STOP_ISO _IO('#', 0x07)
|
||||
|
||||
struct fw_cdev_get_config_rom {
|
||||
__u32 length;
|
||||
|
|
|
@ -155,3 +155,10 @@ fw_iso_context_queue(struct fw_iso_context *ctx,
|
|||
return card->driver->queue_iso(ctx, packet, buffer, payload);
|
||||
}
|
||||
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,
|
|||
static void context_stop(struct context *ctx)
|
||||
{
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN);
|
||||
flush_writes(ctx->ohci);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
reg = reg_read(ctx->ohci, control_set(ctx->regs));
|
||||
if (reg & CONTEXT_ACTIVE)
|
||||
fw_notify("Tried to stop context, but it is still active "
|
||||
"(0x%08x).\n", reg);
|
||||
if ((reg & CONTEXT_ACTIVE) == 0)
|
||||
break;
|
||||
|
||||
fw_notify("context_stop: still active (0x%08x)\n", reg);
|
||||
msleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1379,6 +1385,25 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
|
|||
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)
|
||||
{
|
||||
struct fw_ohci *ohci = fw_ohci(base->card);
|
||||
|
@ -1386,22 +1411,18 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
|
|||
unsigned long flags;
|
||||
int index;
|
||||
|
||||
ohci_stop_iso(base);
|
||||
context_release(&ctx->context);
|
||||
|
||||
spin_lock_irqsave(&ohci->lock, flags);
|
||||
|
||||
if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
|
||||
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;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
flush_writes(ohci);
|
||||
|
||||
context_release(&ctx->context);
|
||||
|
||||
spin_unlock_irqrestore(&ohci->lock, flags);
|
||||
}
|
||||
|
@ -1595,6 +1616,7 @@ static const struct fw_card_driver ohci_driver = {
|
|||
.free_iso_context = ohci_free_iso_context,
|
||||
.queue_iso = ohci_queue_iso,
|
||||
.start_iso = ohci_start_iso,
|
||||
.stop_iso = ohci_stop_iso,
|
||||
};
|
||||
|
||||
static int software_reset(struct fw_ohci *ohci)
|
||||
|
|
|
@ -386,6 +386,9 @@ int
|
|||
fw_iso_context_start(struct fw_iso_context *ctx,
|
||||
int channel, int speed, int cycle);
|
||||
|
||||
int
|
||||
fw_iso_context_stop(struct fw_iso_context *ctx);
|
||||
|
||||
struct fw_card_driver {
|
||||
const char *name;
|
||||
|
||||
|
@ -428,6 +431,8 @@ struct fw_card_driver {
|
|||
struct fw_iso_packet *packet,
|
||||
struct fw_iso_buffer *buffer,
|
||||
unsigned long payload);
|
||||
|
||||
int (*stop_iso)(struct fw_iso_context *ctx);
|
||||
};
|
||||
|
||||
int
|
||||
|
|
Loading…
Reference in New Issue