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

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

firewire: Acummulate received iso headers and send them back to user space.

parent 500be725
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -383,20 +383,24 @@ static int ioctl_send_response(struct client *client, void __user *arg)
}

static void
iso_callback(struct fw_iso_context *context, int status, u32 cycle, void *data)
iso_callback(struct fw_iso_context *context, u32 cycle,
	     size_t header_length, void *header, void *data)
{
	struct client *client = data;
	struct iso_interrupt *interrupt;

	interrupt = kzalloc(sizeof *interrupt, GFP_ATOMIC);
	interrupt = kzalloc(sizeof *interrupt + header_length, GFP_ATOMIC);
	if (interrupt == NULL)
		return;

	interrupt->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
	interrupt->interrupt.closure   = 0;
	interrupt->interrupt.cycle     = cycle;
	interrupt->interrupt.header_length = header_length;
	memcpy(interrupt->interrupt.header, header, header_length);
	queue_event(client, &interrupt->event,
		    &interrupt->interrupt, sizeof interrupt->interrupt, NULL, 0);
		    &interrupt->interrupt,
		    sizeof interrupt->interrupt + header_length, NULL, 0);
}

static int ioctl_create_iso_context(struct client *client, void __user *arg)
@@ -423,6 +427,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg)
{
	struct fw_cdev_queue_iso request;
	struct fw_cdev_iso_packet __user *p, *end, *next;
	struct fw_iso_context *ctx = client->iso_context;
	unsigned long payload, payload_end, header_length;
	int count;
	struct {
@@ -430,7 +435,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg)
		u8 header[256];
	} u;

	if (client->iso_context == NULL)
	if (ctx == NULL)
		return -EINVAL;
	if (copy_from_user(&request, arg, sizeof request))
		return -EFAULT;
@@ -461,13 +466,17 @@ static int ioctl_queue_iso(struct client *client, void __user *arg)
		if (__copy_from_user(&u.packet, p, sizeof *p))
			return -EFAULT;

		if (client->iso_context->type == FW_ISO_CONTEXT_TRANSMIT) {
		if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
			header_length = u.packet.header_length;
		} else {
			/* We require that header_length is a multiple of
			 * the fixed header size, ctx->header_size */
			if (u.packet.header_length % client->iso_context->header_size != 0)
			if (ctx->header_size == 0) {
				if (u.packet.header_length > 0)
					return -EINVAL;
			} else if (u.packet.header_length % ctx->header_size != 0) {
				return -EINVAL;
			}
			header_length = 0;
		}

@@ -484,8 +493,8 @@ static int ioctl_queue_iso(struct client *client, void __user *arg)
		if (payload + u.packet.payload_length > payload_end)
			return -EINVAL;

		if (fw_iso_context_queue(client->iso_context,
					 &u.packet, &client->buffer, payload))
		if (fw_iso_context_queue(ctx, &u.packet,
					 &client->buffer, payload))
			break;

		p = next;
+2 −0
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ struct fw_cdev_event_iso_interrupt {
	__u32 type;
	__u32 cycle;
	__u64 closure;
	__u32 header_length;	/* Length in bytes of following headers. */
	__u32 header[0];
};

#define FW_CDEV_IOC_GET_CONFIG_ROM	_IOR('#', 0x00, struct fw_cdev_get_config_rom)
+34 −15
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ struct at_context {
struct iso_context {
	struct fw_iso_context base;
	struct context context;
	void *header;
	size_t header_length;
};

#define CONFIG_ROM_SIZE 1024
@@ -1273,16 +1275,23 @@ static int handle_ir_packet(struct context *context,
	struct iso_context *ctx =
		container_of(context, struct iso_context, context);
	struct db_descriptor *db = (struct db_descriptor *) d;
	size_t header_length;
 
	if (db->first_res_count > 0 && db->second_res_count > 0)
		/* This descriptor isn't done yet, stop iteration. */
		return 0;

	if (le16_to_cpu(db->control) & descriptor_irq_always)
		/* FIXME: we should pass payload address here. */
		ctx->base.callback(&ctx->base,
				   0, 0,
	header_length = db->first_req_count - db->first_res_count;
	if (ctx->header_length + header_length <= PAGE_SIZE)
		memcpy(ctx->header + ctx->header_length, db + 1, header_length);
	ctx->header_length += header_length;

	if (le16_to_cpu(db->control) & descriptor_irq_always) {
		ctx->base.callback(&ctx->base, 0,
				   ctx->header_length, ctx->header,
				   ctx->base.callback_data);
		ctx->header_length = 0;
	}

	return 1;
}
@@ -1301,9 +1310,8 @@ static int handle_it_packet(struct context *context,
		return 0;

	if (le16_to_cpu(last->control) & descriptor_irq_always)
		ctx->base.callback(&ctx->base,
				   0, le16_to_cpu(last->res_count),
				   ctx->base.callback_data);
		ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count),
				   0, NULL, ctx->base.callback_data);

	return 1;
}
@@ -1316,7 +1324,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type)
	descriptor_callback_t callback;
	u32 *mask, regs;
	unsigned long flags;
	int index, retval;
	int index, retval = -ENOMEM;

	if (type == FW_ISO_CONTEXT_TRANSMIT) {
		mask = &ohci->it_context_mask;
@@ -1344,16 +1352,26 @@ ohci_allocate_iso_context(struct fw_card *card, int type)
 
	ctx = &list[index];
	memset(ctx, 0, sizeof *ctx);
	ctx->header_length = 0;
	ctx->header = (void *) __get_free_page(GFP_KERNEL);
	if (ctx->header == NULL)
		goto out;

	retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE,
			      regs, callback);
	if (retval < 0) {
	if (retval < 0)
		goto out_with_header;

	return &ctx->base;

 out_with_header:
	free_page((unsigned long)ctx->header);
 out:
	spin_lock_irqsave(&ohci->lock, flags);
	*mask |= 1 << index;
	spin_unlock_irqrestore(&ohci->lock, flags);
		return ERR_PTR(retval);
	}

	return &ctx->base;
	return ERR_PTR(retval);
}

static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
@@ -1413,6 +1431,7 @@ static void ohci_free_iso_context(struct fw_iso_context *base)

	ohci_stop_iso(base);
	context_release(&ctx->context);
	free_page((unsigned long)ctx->header);

	spin_lock_irqsave(&ohci->lock, flags);

+4 −1
Original line number Diff line number Diff line
@@ -335,7 +335,10 @@ struct fw_iso_packet {
struct fw_iso_context;

typedef void (*fw_iso_callback_t) (struct fw_iso_context *context,
				   int status, u32 cycle, void *data);
				   u32 cycle,
				   size_t header_length,
				   void *header,
				   void *data);

/* An iso buffer is just a set of pages mapped for DMA in the
 * specified direction.  Since the pages are to be used for DMA, they