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: ohci: split page allocation from dma mapping

1394 OHCI PCI driver had long been the only user of dma_alloc_pages().
Although tee subsystem recently started using it, they are still a few
users of the infrequently-used function.

In the discussion for dma-mapping function, Jason Gunthorpe shows his
opinion about the design of public API for the function. According to it,
the users provide physical address to the function, then receive DMA
mapping address, regardless of the location of mapping target.

With the above aspects, this commit eliminates the use of
dma_alloc_pages() from this subsystem.

Link: https://lore.kernel.org/lkml/20250905174324.GI616306@nvidia.com/
Link: https://lore.kernel.org/r/20260110013911.19160-8-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>

+51 -26
+51 -26
drivers/firewire/ohci.c
··· 539 539 static void ar_context_release(struct ar_context *ctx) 540 540 { 541 541 struct device *dev = ctx->ohci->card.device; 542 - unsigned int i; 543 542 544 543 if (!ctx->buffer) 545 544 return; 546 545 547 - vunmap(ctx->buffer); 546 + for (int i = 0; i < AR_BUFFERS; ++i) { 547 + dma_addr_t dma_addr = page_private(ctx->pages[i]); 548 548 549 - for (i = 0; i < AR_BUFFERS; i++) { 550 - if (ctx->pages[i]) 551 - dma_free_pages(dev, PAGE_SIZE, ctx->pages[i], 552 - ar_buffer_bus(ctx, i), DMA_FROM_DEVICE); 549 + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); 550 + set_page_private(ctx->pages[i], 0); 553 551 } 552 + 553 + vunmap(ctx->buffer); 554 + ctx->buffer = NULL; 555 + 556 + release_pages(ctx->pages, AR_BUFFERS); 557 + memset(ctx->pages, 0, sizeof(ctx->pages)); 554 558 } 555 559 556 560 static void ar_context_abort(struct ar_context *ctx, const char *error_msg) ··· 849 845 { 850 846 struct device *dev = ohci->card.device; 851 847 unsigned int i; 852 - dma_addr_t dma_addr; 853 848 struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES]; 849 + void *vaddr; 854 850 struct descriptor *d; 855 851 856 852 ctx->regs = regs; 857 853 ctx->ohci = ohci; 858 854 INIT_WORK(&ctx->work, ohci_ar_context_work); 859 855 860 - for (i = 0; i < AR_BUFFERS; i++) { 861 - ctx->pages[i] = dma_alloc_pages(dev, PAGE_SIZE, &dma_addr, 862 - DMA_FROM_DEVICE, GFP_KERNEL); 863 - if (!ctx->pages[i]) 864 - goto out_of_memory; 865 - set_page_private(ctx->pages[i], dma_addr); 866 - dma_sync_single_for_device(dev, dma_addr, PAGE_SIZE, 867 - DMA_FROM_DEVICE); 856 + // Retrieve noncontiguous pages. The descriptors for 1394 OHCI AR DMA contexts have a set 857 + // of address and length per each. The reason to use pages is to construct contiguous 858 + // address range in kernel virtual address space. 859 + unsigned long nr_populated = alloc_pages_bulk(GFP_KERNEL | GFP_DMA32, AR_BUFFERS, pages); 860 + 861 + if (nr_populated != AR_BUFFERS) { 862 + release_pages(pages, nr_populated); 863 + return -ENOMEM; 868 864 } 869 865 870 - for (i = 0; i < AR_BUFFERS; i++) 871 - pages[i] = ctx->pages[i]; 866 + // Map the pages into contiguous kernel virtual addresses so that the packet data 867 + // across the pages can be referred as being contiguous, especially across the last 868 + // and first pages. 872 869 for (i = 0; i < AR_WRAPAROUND_PAGES; i++) 873 - pages[AR_BUFFERS + i] = ctx->pages[i]; 874 - ctx->buffer = vmap(pages, ARRAY_SIZE(pages), VM_MAP, PAGE_KERNEL); 875 - if (!ctx->buffer) 876 - goto out_of_memory; 870 + pages[AR_BUFFERS + i] = pages[i]; 871 + vaddr = vmap(pages, ARRAY_SIZE(pages), VM_MAP, PAGE_KERNEL); 872 + if (!vaddr) { 873 + release_pages(pages, nr_populated); 874 + return -ENOMEM; 875 + } 876 + 877 + // Retrieve DMA mapping addresses for the pages. They are not contiguous. Maintain the cache 878 + // coherency for the pages by hand. 879 + for (i = 0; i < AR_BUFFERS; i++) { 880 + // The dma_map_phys() with a physical address per page is available here, instead. 881 + dma_addr_t dma_addr = dma_map_page(dev, pages[i], 0, PAGE_SIZE, DMA_FROM_DEVICE); 882 + if (dma_mapping_error(dev, dma_addr)) 883 + break; 884 + set_page_private(pages[i], dma_addr); 885 + dma_sync_single_for_device(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); 886 + } 887 + if (i < AR_BUFFERS) { 888 + while (i-- > 0) { 889 + dma_addr_t dma_addr = page_private(pages[i]); 890 + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); 891 + } 892 + vunmap(vaddr); 893 + release_pages(pages, nr_populated); 894 + return -ENOMEM; 895 + } 896 + 897 + ctx->buffer = vaddr; 898 + memcpy(ctx->pages, pages, sizeof(ctx->pages)); 877 899 878 900 ctx->descriptors = ohci->misc_buffer + descriptors_offset; 879 901 ctx->descriptors_bus = ohci->misc_buffer_bus + descriptors_offset; ··· 916 886 } 917 887 918 888 return 0; 919 - 920 - out_of_memory: 921 - ar_context_release(ctx); 922 - 923 - return -ENOMEM; 924 889 } 925 890 926 891 static void ar_context_run(struct ar_context *ctx)