Commit c2f60aa1 authored by Takashi Sakamoto's avatar Takashi Sakamoto
Browse files

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: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
parent a69a9e63
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -31,22 +31,18 @@
int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count)
{
	struct page **page_array __free(kfree) = kcalloc(page_count, sizeof(page_array[0]), GFP_KERNEL);
	int i;

	if (!page_array)
		return -ENOMEM;

	for (i = 0; i < page_count; ++i) {
		struct page *page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);

		if (!page)
			break;
		page_array[i] = page;
	}

	if (i < page_count) {
		while (i-- > 0)
			__free_page(page_array[i]);
	// Retrieve noncontiguous pages. The descriptors for 1394 OHCI isochronous DMA contexts
	// have a set of address and length per each, while the reason to use pages is the
	// convenience to map them into virtual address space of user process.
	unsigned long nr_populated = alloc_pages_bulk(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO,
						      page_count, page_array);
	if (nr_populated != page_count) {
		// Assuming the above call fills page_array sequentially from the beginning.
		release_pages(page_array, nr_populated);
		return -ENOMEM;
	}

@@ -64,7 +60,10 @@ int fw_iso_buffer_map_dma(struct fw_iso_buffer *buffer, struct fw_card *card,

	buffer->direction = direction;

	// 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))
@@ -109,8 +108,7 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
	}

	if (buffer->pages) {
		for (int i = 0; i < buffer->page_count; ++i)
			__free_page(buffer->pages[i]);
		release_pages(buffer->pages, buffer->page_count);
		kfree(buffer->pages);
		buffer->pages = NULL;
	}