Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

firewire: core: use common kernel API to allocate and release a batch of pages

The pair of alloc_pages_bulk() and release_pages() are convenient to
allocate and release a batch of pages.

This commit utilizes the pair to maintain pages for isochronous DMA
context.

Link: https://lore.kernel.org/r/20260110013911.19160-5-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>

+12 -14
+12 -14
drivers/firewire/core-iso.c
··· 31 31 int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count) 32 32 { 33 33 struct page **page_array __free(kfree) = kcalloc(page_count, sizeof(page_array[0]), GFP_KERNEL); 34 - int i; 35 34 36 35 if (!page_array) 37 36 return -ENOMEM; 38 37 39 - for (i = 0; i < page_count; ++i) { 40 - struct page *page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); 41 - 42 - if (!page) 43 - break; 44 - page_array[i] = page; 45 - } 46 - 47 - if (i < page_count) { 48 - while (i-- > 0) 49 - __free_page(page_array[i]); 38 + // Retrieve noncontiguous pages. The descriptors for 1394 OHCI isochronous DMA contexts 39 + // have a set of address and length per each, while the reason to use pages is the 40 + // convenience to map them into virtual address space of user process. 41 + unsigned long nr_populated = alloc_pages_bulk(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO, 42 + page_count, page_array); 43 + if (nr_populated != page_count) { 44 + // Assuming the above call fills page_array sequentially from the beginning. 45 + release_pages(page_array, nr_populated); 50 46 return -ENOMEM; 51 47 } 52 48 ··· 60 64 61 65 buffer->direction = direction; 62 66 67 + // Retrieve DMA mapping addresses for the pages. They are not contiguous. Maintain the cache 68 + // coherency for the pages by hand. 63 69 for (i = 0; i < buffer->page_count; i++) { 70 + // The dma_map_phys() with a physical address per page is available here, instead. 64 71 address = dma_map_page(card->device, buffer->pages[i], 65 72 0, PAGE_SIZE, direction); 66 73 if (dma_mapping_error(card->device, address)) ··· 108 109 } 109 110 110 111 if (buffer->pages) { 111 - for (int i = 0; i < buffer->page_count; ++i) 112 - __free_page(buffer->pages[i]); 112 + release_pages(buffer->pages, buffer->page_count); 113 113 kfree(buffer->pages); 114 114 buffer->pages = NULL; 115 115 }