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

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

firewire: Implement sync and tag matching for isochronous receive.

parent 21efb3cf
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -416,6 +416,12 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg)
	if (request.channel > 63)
		return -EINVAL;

	if (request.sync > 15)
		return -EINVAL;

	if (request.tags == 0 || request.tags > 15)
		return -EINVAL;

	if (request.speed > SCODE_3200)
		return -EINVAL;

@@ -424,6 +430,8 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg)
						    request.channel,
						    request.speed,
						    request.header_size,
						    request.sync,
						    request.tags,
						    iso_callback, client);
	if (IS_ERR(client->iso_context))
		return PTR_ERR(client->iso_context);
@@ -495,7 +503,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg)
		if (__copy_from_user
		    (u.packet.header, p->header, header_length))
			return -EFAULT;
		if (u.packet.skip &&
		if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
		    u.packet.header_length + u.packet.payload_length > 0)
			return -EINVAL;
		if (payload + u.packet.payload_length > payload_end)
+8 −0
Original line number Diff line number Diff line
@@ -131,11 +131,19 @@ struct fw_cdev_allocate {
#define FW_CDEV_ISO_CONTEXT_TRANSMIT	0
#define FW_CDEV_ISO_CONTEXT_RECEIVE	1

#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15

struct fw_cdev_create_iso_context {
	__u32 type;
	__u32 header_size;
	__u32 channel;
	__u32 speed;
	__u32 sync;
	__u32 tags;
};

struct fw_cdev_iso_packet {
+6 −2
Original line number Diff line number Diff line
@@ -107,12 +107,14 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,

struct fw_iso_context *
fw_iso_context_create(struct fw_card *card, int type,
		      int channel, int speed, size_t header_size,
		      int channel, int speed,
		      int sync, int tags, size_t header_size,
		      fw_iso_callback_t callback, void *callback_data)
{
	struct fw_iso_context *ctx;

	ctx = card->driver->allocate_iso_context(card, type, header_size);
	ctx = card->driver->allocate_iso_context(card, type,
						 sync, tags, header_size);
	if (IS_ERR(ctx))
		return ctx;

@@ -120,6 +122,8 @@ fw_iso_context_create(struct fw_card *card, int type,
	ctx->type = type;
	ctx->channel = channel;
	ctx->speed = speed;
	ctx->sync = sync;
	ctx->tags = tags;
	ctx->header_size = header_size;
	ctx->callback = callback;
	ctx->callback_data = callback_data;
+30 −2
Original line number Diff line number Diff line
@@ -1337,7 +1337,8 @@ static int handle_it_packet(struct context *context,
}

static struct fw_iso_context *
ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
ohci_allocate_iso_context(struct fw_card *card, int type,
			  int sync, int tags, size_t header_size)
{
	struct fw_ohci *ohci = fw_ohci(card);
	struct iso_context *ctx, *list;
@@ -1427,7 +1428,8 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
		reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
		reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
		reg_write(ohci, context_match(ctx->context.regs),
			  0xf0000000 | ctx->base.channel);
			  (ctx->base.tags << 28) |
			  (ctx->base.sync << 8) | ctx->base.channel);
		context_run(&ctx->context, mode);
	}

@@ -1574,6 +1576,26 @@ ohci_queue_iso_transmit(struct fw_iso_context *base,
	return 0;
}
 
static int
setup_wait_descriptor(struct context *ctx)
{
	struct descriptor *d;
	dma_addr_t d_bus;

	d = context_get_descriptors(ctx, 1, &d_bus);
	if (d == NULL)
		return -ENOMEM;

	d->control = cpu_to_le16(descriptor_input_more |
				 descriptor_status |
				 descriptor_branch_always |
				 descriptor_wait);

	context_append(ctx, d, 1, 0);

	return 0;
}

static int
ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
				  struct fw_iso_packet *packet,
@@ -1591,6 +1613,9 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
	/* FIXME: Cycle lost behavior should be configurable: lose
	 * packet, retransmit or terminate.. */

	if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
		return -ENOMEM;

	p = packet;
	z = 2;

@@ -1655,6 +1680,9 @@ ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base,
	offset = payload & ~PAGE_MASK;
	rest   = packet->payload_length;

	if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
		return -ENOMEM;

	while (rest > 0) {
		d = context_get_descriptors(&ctx->context, 1, &d_bus);
		if (d == NULL)
+11 −2
Original line number Diff line number Diff line
@@ -332,6 +332,12 @@ struct fw_iso_packet {
#define FW_ISO_CONTEXT_TRANSMIT	0
#define FW_ISO_CONTEXT_RECEIVE	1

#define FW_ISO_CONTEXT_MATCH_TAG0	 1
#define FW_ISO_CONTEXT_MATCH_TAG1	 2
#define FW_ISO_CONTEXT_MATCH_TAG2	 4
#define FW_ISO_CONTEXT_MATCH_TAG3	 8
#define FW_ISO_CONTEXT_MATCH_ALL_TAGS	15

struct fw_iso_context;

typedef void (*fw_iso_callback_t) (struct fw_iso_context *context,
@@ -357,6 +363,8 @@ struct fw_iso_context {
	int type;
	int channel;
	int speed;
	int sync;
	int tags;
	size_t header_size;
	fw_iso_callback_t callback;
	void *callback_data;
@@ -374,7 +382,8 @@ fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);

struct fw_iso_context *
fw_iso_context_create(struct fw_card *card, int type,
		      int channel, int speed, size_t header_size,
		      int channel, int speed,
		      int sync, int tags, size_t header_size,
		      fw_iso_callback_t callback, void *callback_data);

void
@@ -425,7 +434,7 @@ struct fw_card_driver {
				int node_id, int generation);

	struct fw_iso_context *
	(*allocate_iso_context)(struct fw_card *card,
	(*allocate_iso_context)(struct fw_card *card, int sync, int tags,
				int type, size_t header_size);
	void (*free_iso_context)(struct fw_iso_context *ctx);