From c91adaddb0740c5a436084c85bedfe07b6d0c157 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 10 Jan 2026 10:39:04 +0900 Subject: firewire: core: move private function declaration from public header to internal header The fw_iso_buffer_lookup function is used by core module only, thus no need to describe its prototype in kernel internal header. Link: https://lore.kernel.org/r/20260110013911.19160-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- include/linux/firewire.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 6143b7d28eac..aa84421b58ac 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -533,7 +533,6 @@ struct fw_iso_buffer { int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, int page_count, enum dma_data_direction direction); void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); -size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed); struct fw_iso_context; typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, -- cgit v1.2.3 From ef6bdffbb88d86c8a2906fc8a13ae90eb5a6b64e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 10 Jan 2026 10:39:08 +0900 Subject: firewire: core: stop using page private to store DMA mapping address There is a long discussion about the use of private field in page structure between Linux kernel developers. This commit stop using page private to store DMA mapping address for isochronous context, to prepare for mm future change. Link: https://lore.kernel.org/r/20260110013911.19160-6-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- drivers/firewire/core-cdev.c | 5 +---- drivers/firewire/core-iso.c | 48 +++++++++++++++++++++++--------------------- drivers/firewire/ohci.c | 24 +++++++++++----------- include/linux/firewire.h | 2 +- 4 files changed, 39 insertions(+), 40 deletions(-) (limited to 'include/linux') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2b8a878c8aae..bb4d0f938f5b 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -67,7 +67,6 @@ struct client { u64 iso_closure; struct fw_iso_buffer buffer; unsigned long vm_start; - bool buffer_is_mapped; struct list_head phy_receiver_link; u64 phy_receiver_closure; @@ -1098,7 +1097,7 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) } // The DMA mapping operation is available if the buffer is already allocated by // mmap(2) system call. If not, it is delegated to the system call. - if (!client->buffer_is_mapped) { + if (client->buffer.pages && !client->buffer.dma_addrs) { ret = fw_iso_buffer_map_dma(&client->buffer, client->device->card, iso_dma_direction(context)); if (ret < 0) { @@ -1106,7 +1105,6 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) return ret; } - client->buffer_is_mapped = true; } client->iso_closure = a->closure; client->iso_context = context; @@ -1837,7 +1835,6 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) iso_dma_direction(client->iso_context)); if (ret < 0) goto fail; - client->buffer_is_mapped = true; } } diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index f2e35ac7a476..3f36243ec0c1 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -55,25 +55,32 @@ int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count) int fw_iso_buffer_map_dma(struct fw_iso_buffer *buffer, struct fw_card *card, enum dma_data_direction direction) { - dma_addr_t address; + dma_addr_t *dma_addrs __free(kfree) = kcalloc(buffer->page_count, sizeof(dma_addrs[0]), + GFP_KERNEL); int i; - buffer->direction = direction; + if (!dma_addrs) + return -ENOMEM; // Retrieve DMA mapping addresses for the pages. They are not contiguous. Maintain the cache // coherency for the pages by hand. for (i = 0; i < buffer->page_count; i++) { // The dma_map_phys() with a physical address per page is available here, instead. - address = dma_map_page(card->device, buffer->pages[i], - 0, PAGE_SIZE, direction); - if (dma_mapping_error(card->device, address)) + dma_addr_t dma_addr = dma_map_page(card->device, buffer->pages[i], 0, PAGE_SIZE, + direction); + if (dma_mapping_error(card->device, dma_addr)) break; - set_page_private(buffer->pages[i], address); + dma_addrs[i] = dma_addr; } - buffer->page_count_mapped = i; - if (i < buffer->page_count) + if (i < buffer->page_count) { + while (i-- > 0) + dma_unmap_page(card->device, dma_addrs[i], PAGE_SIZE, buffer->direction); return -ENOMEM; + } + + buffer->direction = direction; + buffer->dma_addrs = no_free_ptr(dma_addrs); return 0; } @@ -98,13 +105,13 @@ EXPORT_SYMBOL(fw_iso_buffer_init); void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card) { - int i; - dma_addr_t address; - - for (i = 0; i < buffer->page_count_mapped; i++) { - address = page_private(buffer->pages[i]); - dma_unmap_page(card->device, address, - PAGE_SIZE, buffer->direction); + if (buffer->dma_addrs) { + for (int i = 0; i < buffer->page_count; ++i) { + dma_addr_t dma_addr = buffer->dma_addrs[i]; + dma_unmap_page(card->device, dma_addr, PAGE_SIZE, buffer->direction); + } + kfree(buffer->dma_addrs); + buffer->dma_addrs = NULL; } if (buffer->pages) { @@ -114,20 +121,15 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, } buffer->page_count = 0; - buffer->page_count_mapped = 0; } EXPORT_SYMBOL(fw_iso_buffer_destroy); /* Convert DMA address to offset into virtually contiguous buffer. */ size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed) { - size_t i; - dma_addr_t address; - ssize_t offset; - - for (i = 0; i < buffer->page_count; i++) { - address = page_private(buffer->pages[i]); - offset = (ssize_t)completed - (ssize_t)address; + for (int i = 0; i < buffer->page_count; i++) { + dma_addr_t dma_addr = buffer->dma_addrs[i]; + ssize_t offset = (ssize_t)completed - (ssize_t)dma_addr; if (offset > 0 && offset <= PAGE_SIZE) return (i << PAGE_SHIFT) + offset; } diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index e3e78dc42530..68a336577d36 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -3184,7 +3184,7 @@ static int queue_iso_transmit(struct iso_context *ctx, struct descriptor *d, *last, *pd; struct fw_iso_packet *p; __le32 *header; - dma_addr_t d_bus, page_bus; + dma_addr_t d_bus; u32 z, header_z, payload_z, irq; u32 payload_index, payload_end_index, next_page_index; int page, end_page, i, length, offset; @@ -3254,11 +3254,11 @@ static int queue_iso_transmit(struct iso_context *ctx, min(next_page_index, payload_end_index) - payload_index; pd[i].req_count = cpu_to_le16(length); - page_bus = page_private(buffer->pages[page]); - pd[i].data_address = cpu_to_le32(page_bus + offset); + dma_addr_t dma_addr = buffer->dma_addrs[i]; + pd[i].data_address = cpu_to_le32(dma_addr + offset); dma_sync_single_range_for_device(ctx->context.ohci->card.device, - page_bus, offset, length, + dma_addr, offset, length, DMA_TO_DEVICE); payload_index += length; @@ -3287,7 +3287,7 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx, { struct device *device = ctx->context.ohci->card.device; struct descriptor *d, *pd; - dma_addr_t d_bus, page_bus; + dma_addr_t d_bus; u32 z, header_z, rest; int i, j, length; int page, offset, packet_count, header_size, payload_per_buffer; @@ -3337,10 +3337,10 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx, pd->res_count = pd->req_count; pd->transfer_status = 0; - page_bus = page_private(buffer->pages[page]); - pd->data_address = cpu_to_le32(page_bus + offset); + dma_addr_t dma_addr = buffer->dma_addrs[page]; + pd->data_address = cpu_to_le32(dma_addr + offset); - dma_sync_single_range_for_device(device, page_bus, + dma_sync_single_range_for_device(device, dma_addr, offset, length, DMA_FROM_DEVICE); @@ -3367,7 +3367,7 @@ static int queue_iso_buffer_fill(struct iso_context *ctx, unsigned long payload) { struct descriptor *d; - dma_addr_t d_bus, page_bus; + dma_addr_t d_bus; int page, offset, rest, z, i, length; page = payload >> PAGE_SHIFT; @@ -3400,11 +3400,11 @@ static int queue_iso_buffer_fill(struct iso_context *ctx, d->res_count = d->req_count; d->transfer_status = 0; - page_bus = page_private(buffer->pages[page]); - d->data_address = cpu_to_le32(page_bus + offset); + dma_addr_t dma_addr = buffer->dma_addrs[page]; + d->data_address = cpu_to_le32(dma_addr + offset); dma_sync_single_range_for_device(ctx->context.ohci->card.device, - page_bus, offset, length, + dma_addr, offset, length, DMA_FROM_DEVICE); rest -= length; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index aa84421b58ac..09c8484f7430 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -526,8 +526,8 @@ struct fw_iso_packet { struct fw_iso_buffer { enum dma_data_direction direction; struct page **pages; + dma_addr_t *dma_addrs; int page_count; - int page_count_mapped; }; int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, -- cgit v1.2.3 From 6b67470dce11cfaa09915cca8a5a807d3daf0b87 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 17 Jan 2026 23:28:14 +0900 Subject: firewire: core: add function variants for isochronous context creation The fw_iso_callback union was added by a commit ebe4560ed5c ("firewire: Remove function callback casts") to remove function pointer cast. That change affected the cdev layer of the core code, but it is more convenient for fw_iso_context_create() to accept the union directly. This commit renames and changes the existing function to take the union argument, and add static inline wrapper functions as variants. Link: https://lore.kernel.org/r/20260117142823.440811-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- drivers/firewire/core-cdev.c | 28 +++------------------------- drivers/firewire/core-iso.c | 9 ++++----- drivers/firewire/core.h | 9 +++++++++ include/linux/firewire.h | 14 +++++++++++--- 4 files changed, 27 insertions(+), 33 deletions(-) (limited to 'include/linux') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index bb4d0f938f5b..c26bea253208 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1026,25 +1026,10 @@ static enum dma_data_direction iso_dma_direction(struct fw_iso_context *context) return DMA_FROM_DEVICE; } -static struct fw_iso_context *fw_iso_mc_context_create(struct fw_card *card, - fw_iso_mc_callback_t callback, - void *callback_data) -{ - struct fw_iso_context *ctx; - - ctx = fw_iso_context_create(card, FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL, - 0, 0, 0, NULL, callback_data); - if (!IS_ERR(ctx)) - ctx->callback.mc = callback; - - return ctx; -} - static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) { struct fw_cdev_create_iso_context *a = &arg->create_iso_context; struct fw_iso_context *context; - union fw_iso_callback cb; int ret; BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT || @@ -1056,20 +1041,15 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) case FW_ISO_CONTEXT_TRANSMIT: if (a->speed > SCODE_3200 || a->channel > 63) return -EINVAL; - - cb.sc = iso_callback; break; case FW_ISO_CONTEXT_RECEIVE: if (a->header_size < 4 || (a->header_size & 3) || a->channel > 63) return -EINVAL; - - cb.sc = iso_callback; break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: - cb.mc = iso_mc_callback; break; default: @@ -1077,12 +1057,10 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) } if (a->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) - context = fw_iso_mc_context_create(client->device->card, cb.mc, - client); + context = fw_iso_mc_context_create(client->device->card, iso_mc_callback, client); else - context = fw_iso_context_create(client->device->card, a->type, - a->channel, a->speed, - a->header_size, cb.sc, client); + context = fw_iso_context_create(client->device->card, a->type, a->channel, a->speed, + a->header_size, iso_callback, client); if (IS_ERR(context)) return PTR_ERR(context); if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW) diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 3f36243ec0c1..d9b8896c8ce1 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -137,9 +137,8 @@ size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed) return 0; } -struct fw_iso_context *fw_iso_context_create(struct fw_card *card, - int type, int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data) +struct fw_iso_context *__fw_iso_context_create(struct fw_card *card, int type, int channel, + int speed, size_t header_size, union fw_iso_callback callback, void *callback_data) { struct fw_iso_context *ctx; @@ -153,7 +152,7 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, ctx->channel = channel; ctx->speed = speed; ctx->header_size = header_size; - ctx->callback.sc = callback; + ctx->callback = callback; ctx->callback_data = callback_data; trace_isoc_outbound_allocate(ctx, channel, speed); @@ -162,7 +161,7 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, return ctx; } -EXPORT_SYMBOL(fw_iso_context_create); +EXPORT_SYMBOL(__fw_iso_context_create); void fw_iso_context_destroy(struct fw_iso_context *ctx) { diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 26868f007131..e0ae948605e1 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -173,6 +173,15 @@ static inline void fw_iso_context_init_work(struct fw_iso_context *ctx, work_fun INIT_WORK(&ctx->work, func); } +static inline struct fw_iso_context *fw_iso_mc_context_create(struct fw_card *card, + fw_iso_mc_callback_t callback, void *callback_data) +{ + union fw_iso_callback cb = { .mc = callback }; + + return __fw_iso_context_create(card, FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL, 0, 0, 0, cb, + callback_data); +} + /* -topology */ diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 09c8484f7430..68161b8a8a58 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -558,9 +558,8 @@ struct fw_iso_context { void *callback_data; }; -struct fw_iso_context *fw_iso_context_create(struct fw_card *card, - int type, int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data); +struct fw_iso_context *__fw_iso_context_create(struct fw_card *card, int type, int channel, + int speed, size_t header_size, union fw_iso_callback callback, void *callback_data); int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels); int fw_iso_context_queue(struct fw_iso_context *ctx, struct fw_iso_packet *packet, @@ -569,6 +568,15 @@ int fw_iso_context_queue(struct fw_iso_context *ctx, void fw_iso_context_queue_flush(struct fw_iso_context *ctx); int fw_iso_context_flush_completions(struct fw_iso_context *ctx); +static inline struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, + int channel, int speed, size_t header_size, fw_iso_callback_t callback, + void *callback_data) +{ + union fw_iso_callback cb = { .sc = callback }; + + return __fw_iso_context_create(card, type, channel, speed, header_size, cb, callback_data); +} + /** * fw_iso_context_schedule_flush_completions() - schedule work item to process isochronous context. * @ctx: the isochronous context -- cgit v1.2.3 From 090ac6520044d0d02e039d76aaa22f4c9751837f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 17 Jan 2026 23:28:18 +0900 Subject: firewire: core: add flags member for isochronous context structure This is minor code refactoring to add a flag member to the isochronous context structure. At present, it is used only for the option to drop packets when the context header overflows. Link: https://lore.kernel.org/r/20260117142823.440811-6-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- drivers/firewire/core-cdev.c | 2 +- drivers/firewire/core-iso.c | 1 + drivers/firewire/ohci.c | 4 ++-- include/linux/firewire.h | 6 +++++- 4 files changed, 9 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index c26bea253208..9e964fdd175c 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1064,7 +1064,7 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) if (IS_ERR(context)) return PTR_ERR(context); if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW) - context->drop_overflow_headers = true; + context->flags |= FW_ISO_CONTEXT_FLAG_DROP_OVERFLOW_HEADERS; // We only support one context at this time. scoped_guard(mutex, &client->iso_context_mutex) { diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index d9b8896c8ce1..fbbd14d21ca4 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -151,6 +151,7 @@ struct fw_iso_context *__fw_iso_context_create(struct fw_card *card, int type, i ctx->type = type; ctx->channel = channel; ctx->speed = speed; + ctx->flags = 0; ctx->header_size = header_size; ctx->callback = callback; ctx->callback_data = callback_data; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6760c8d12637..8bba70b65ad7 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2756,7 +2756,7 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr) u32 *ctx_hdr; if (ctx->sc.header_length + ctx->base.header_size > PAGE_SIZE) { - if (ctx->base.drop_overflow_headers) + if (ctx->base.flags & FW_ISO_CONTEXT_FLAG_DROP_OVERFLOW_HEADERS) return; flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW); } @@ -2925,7 +2925,7 @@ static int handle_it_packet(struct context *context, sync_it_packet_for_cpu(context, d); if (ctx->sc.header_length + 4 > PAGE_SIZE) { - if (ctx->base.drop_overflow_headers) + if (ctx->base.flags & FW_ISO_CONTEXT_FLAG_DROP_OVERFLOW_HEADERS) return 1; flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW); } diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 68161b8a8a58..71d5cc8f28ce 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -546,13 +546,17 @@ union fw_iso_callback { fw_iso_mc_callback_t mc; }; +enum fw_iso_context_flag { + FW_ISO_CONTEXT_FLAG_DROP_OVERFLOW_HEADERS = BIT(0), +}; + struct fw_iso_context { struct fw_card *card; struct work_struct work; int type; int channel; int speed; - bool drop_overflow_headers; + int flags; size_t header_size; union fw_iso_callback callback; void *callback_data; -- cgit v1.2.3 From 9bf71acd65bf190a0ef1bc885a0a664f91beff03 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 17 Jan 2026 23:28:20 +0900 Subject: firewire: core: provide isoc header buffer size outside card driver For single-channel isochronous contexts, the header storage size is hard-coded to PAGE_SIZE. which is inconvenient for protocol implementations requiring more space. This commit refactors the code to obtain the header storage size outside the 1394 OHCI driver. Link: https://lore.kernel.org/r/20260117142823.440811-8-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- drivers/firewire/core-card.c | 4 ++-- drivers/firewire/core-iso.c | 8 +++++--- drivers/firewire/core.h | 6 +++--- drivers/firewire/ohci.c | 10 +++++----- include/linux/firewire.h | 7 +++++-- 5 files changed, 20 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 0462d7b9e547..a754c6366b97 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -704,8 +704,8 @@ static int dummy_enable_phys_dma(struct fw_card *card, return -ENODEV; } -static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card, - int type, int channel, size_t header_size) +static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card, int type, + int channel, size_t header_size, size_t header_storage_size) { return ERR_PTR(-ENODEV); } diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index fbbd14d21ca4..3190b2ca1298 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -138,12 +138,13 @@ size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed) } struct fw_iso_context *__fw_iso_context_create(struct fw_card *card, int type, int channel, - int speed, size_t header_size, union fw_iso_callback callback, void *callback_data) + int speed, size_t header_size, size_t header_storage_size, + union fw_iso_callback callback, void *callback_data) { struct fw_iso_context *ctx; - ctx = card->driver->allocate_iso_context(card, - type, channel, header_size); + ctx = card->driver->allocate_iso_context(card, type, channel, header_size, + header_storage_size); if (IS_ERR(ctx)) return ctx; @@ -153,6 +154,7 @@ struct fw_iso_context *__fw_iso_context_create(struct fw_card *card, int type, i ctx->speed = speed; ctx->flags = 0; ctx->header_size = header_size; + ctx->header_storage_size = header_storage_size; ctx->callback = callback; ctx->callback_data = callback_data; diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index e0ae948605e1..8b49d7480c37 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -100,8 +100,8 @@ struct fw_card_driver { void (*write_csr)(struct fw_card *card, int csr_offset, u32 value); struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, - int type, int channel, size_t header_size); + (*allocate_iso_context)(struct fw_card *card, int type, int channel, size_t header_size, + size_t header_storage_size); void (*free_iso_context)(struct fw_iso_context *ctx); int (*start_iso)(struct fw_iso_context *ctx, @@ -178,7 +178,7 @@ static inline struct fw_iso_context *fw_iso_mc_context_create(struct fw_card *ca { union fw_iso_callback cb = { .mc = callback }; - return __fw_iso_context_create(card, FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL, 0, 0, 0, cb, + return __fw_iso_context_create(card, FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL, 0, 0, 0, 0, cb, callback_data); } diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 888c43940999..1c868c1e4a49 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2755,7 +2755,7 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr) { u32 *ctx_hdr; - if (ctx->sc.header_length + ctx->base.header_size > PAGE_SIZE) { + if (ctx->sc.header_length + ctx->base.header_size > ctx->base.header_storage_size) { if (ctx->base.flags & FW_ISO_CONTEXT_FLAG_DROP_OVERFLOW_HEADERS) return; flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW); @@ -2924,7 +2924,7 @@ static int handle_it_packet(struct context *context, sync_it_packet_for_cpu(context, d); - if (ctx->sc.header_length + 4 > PAGE_SIZE) { + if (ctx->sc.header_length + 4 > ctx->base.header_storage_size) { if (ctx->base.flags & FW_ISO_CONTEXT_FLAG_DROP_OVERFLOW_HEADERS) return 1; flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_HEADER_OVERFLOW); @@ -2954,8 +2954,8 @@ static void set_multichannel_mask(struct fw_ohci *ohci, u64 channels) ohci->mc_channels = channels; } -static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, - int type, int channel, size_t header_size) +static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, int type, int channel, + size_t header_size, size_t header_storage_size) { struct fw_ohci *ohci = fw_ohci(card); void *header __free(kvfree) = NULL; @@ -3016,7 +3016,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, if (type != FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) { ctx->sc.header_length = 0; - header = kvmalloc(PAGE_SIZE, GFP_KERNEL); + header = kvmalloc(header_storage_size, GFP_KERNEL); if (!header) { ret = -ENOMEM; goto out; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 71d5cc8f28ce..8bf568471588 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -558,12 +558,14 @@ struct fw_iso_context { int speed; int flags; size_t header_size; + size_t header_storage_size; union fw_iso_callback callback; void *callback_data; }; struct fw_iso_context *__fw_iso_context_create(struct fw_card *card, int type, int channel, - int speed, size_t header_size, union fw_iso_callback callback, void *callback_data); + int speed, size_t header_size, size_t header_storage_size, + union fw_iso_callback callback, void *callback_data); int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels); int fw_iso_context_queue(struct fw_iso_context *ctx, struct fw_iso_packet *packet, @@ -578,7 +580,8 @@ static inline struct fw_iso_context *fw_iso_context_create(struct fw_card *card, { union fw_iso_callback cb = { .sc = callback }; - return __fw_iso_context_create(card, type, channel, speed, header_size, cb, callback_data); + return __fw_iso_context_create(card, type, channel, speed, header_size, PAGE_SIZE, cb, + callback_data); } /** -- cgit v1.2.3 From e5f1291b6f3f85559ed124316f814c013262b44e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 17 Jan 2026 23:28:21 +0900 Subject: firewire: core: add fw_iso_context_create() variant with header storage size This commit adds a new variant of fw_iso_context_create() that allows specifying the size of the isochronous context header storage at allocation time. Link: https://lore.kernel.org/r/20260117142823.440811-9-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- include/linux/firewire.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/linux') diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 8bf568471588..986d712e4d94 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -584,6 +584,16 @@ static inline struct fw_iso_context *fw_iso_context_create(struct fw_card *card, callback_data); } +static inline struct fw_iso_context *fw_iso_context_create_with_header_storage_size( + struct fw_card *card, int type, int channel, int speed, size_t header_size, + size_t header_storage_size, fw_iso_callback_t callback, void *callback_data) +{ + union fw_iso_callback cb = { .sc = callback }; + + return __fw_iso_context_create(card, type, channel, speed, header_size, header_storage_size, + cb, callback_data); +} + /** * fw_iso_context_schedule_flush_completions() - schedule work item to process isochronous context. * @ctx: the isochronous context -- cgit v1.2.3