Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

firewire: Implement functionality to stop isochronous DMA contexts.

parent 69cdb726
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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;
	}
+1 −0
Original line number Diff line number Diff line
@@ -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;
+7 −0
Original line number Diff line number Diff line
@@ -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);
+33 −11
Original line number Diff line number Diff line
@@ -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)
+5 −0
Original line number Diff line number Diff line
@@ -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