Loading drivers/firewire/fw-device-cdev.c +17 −8 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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 { Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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; Loading drivers/firewire/fw-device-cdev.h +2 −0 Original line number Diff line number Diff line Loading @@ -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) Loading drivers/firewire/fw-ohci.c +34 −15 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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); Loading drivers/firewire/fw-transaction.h +4 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
drivers/firewire/fw-device-cdev.c +17 −8 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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 { Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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; Loading
drivers/firewire/fw-device-cdev.h +2 −0 Original line number Diff line number Diff line Loading @@ -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) Loading
drivers/firewire/fw-ohci.c +34 −15 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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); Loading
drivers/firewire/fw-transaction.h +4 −1 Original line number Diff line number Diff line Loading @@ -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 Loading