Commit 5a32c341 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'dma-mapping-5.10' of git://git.infradead.org/users/hch/dma-mapping

Pull dma-mapping updates from Christoph Hellwig:

 - rework the non-coherent DMA allocator

 - move private definitions out of <linux/dma-mapping.h>

 - lower CMA_ALIGNMENT (Paul Cercueil)

 - remove the omap1 dma address translation in favor of the common code

 - make dma-direct aware of multiple dma offset ranges (Jim Quinlan)

 - support per-node DMA CMA areas (Barry Song)

 - increase the default seg boundary limit (Nicolin Chen)

 - misc fixes (Robin Murphy, Thomas Tai, Xu Wang)

 - various cleanups

* tag 'dma-mapping-5.10' of git://git.infradead.org/users/hch/dma-mapping: (63 commits)
  ARM/ixp4xx: add a missing include of dma-map-ops.h
  dma-direct: simplify the DMA_ATTR_NO_KERNEL_MAPPING handling
  dma-direct: factor out a dma_direct_alloc_from_pool helper
  dma-direct check for highmem pages in dma_direct_alloc_pages
  dma-mapping: merge <linux/dma-noncoherent.h> into <linux/dma-map-ops.h>
  dma-mapping: move large parts of <linux/dma-direct.h> to kernel/dma
  dma-mapping: move dma-debug.h to kernel/dma/
  dma-mapping: remove <asm/dma-contiguous.h>
  dma-mapping: merge <linux/dma-contiguous.h> into <linux/dma-map-ops.h>
  dma-contiguous: remove dma_contiguous_set_default
  dma-contiguous: remove dev_set_cma_area
  dma-contiguous: remove dma_declare_contiguous
  dma-mapping: split <linux/dma-mapping.h>
  cma: decrease CMA_ALIGNMENT lower limit to 2
  firewire-ohci: use dma_alloc_pages
  dma-iommu: implement ->alloc_noncoherent
  dma-mapping: add new {alloc,free}_noncoherent dma_map_ops methods
  dma-mapping: add a new dma_alloc_pages API
  dma-mapping: remove dma_cache_sync
  53c700: convert to dma_alloc_noncoherent
  ...
parents f065199d 2a410d09
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -597,7 +597,18 @@
			placement constraint by the physical address range of
			memory allocations. A value of 0 disables CMA
			altogether. For more information, see
			include/linux/dma-contiguous.h
			kernel/dma/contiguous.c

	cma_pernuma=nn[MG]
			[ARM64,KNL]
			Sets the size of kernel per-numa memory area for
			contiguous memory allocations. A value of 0 disables
			per-numa CMA altogether. And If this option is not
			specificed, the default value is 0.
			With per-numa CMA enabled, DMA users on node nid will
			first try to allocate buffer from the pernuma area
			which is located in node nid, if the allocation fails,
			they will fallback to the global default memory area.

	cmo_free_hint=	[PPC] Format: { yes | no }
			Specify whether pages are marked as being inactive
+36 −63
Original line number Diff line number Diff line
@@ -516,48 +516,56 @@ routines, e.g.:::
	}


Part II - Advanced dma usage
----------------------------
Part II - Non-coherent DMA allocations
--------------------------------------

Warning: These pieces of the DMA API should not be used in the
majority of cases, since they cater for unlikely corner cases that
don't belong in usual drivers.
These APIs allow to allocate pages in the kernel direct mapping that are
guaranteed to be DMA addressable.  This means that unlike dma_alloc_coherent,
virt_to_page can be called on the resulting address, and the resulting
struct page can be used for everything a struct page is suitable for.

If you don't understand how cache line coherency works between a
processor and an I/O device, you should not be using this part of the
API at all.
If you don't understand how cache line coherency works between a processor and
an I/O device, you should not be using this part of the API.

::

	void *
	dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
			gfp_t flag, unsigned long attrs)
	dma_alloc_noncoherent(struct device *dev, size_t size,
			dma_addr_t *dma_handle, enum dma_data_direction dir,
			gfp_t gfp)

Identical to dma_alloc_coherent() except that when the
DMA_ATTR_NON_CONSISTENT flags is passed in the attrs argument, the
platform will choose to return either consistent or non-consistent memory
as it sees fit.  By using this API, you are guaranteeing to the platform
that you have all the correct and necessary sync points for this memory
in the driver should it choose to return non-consistent memory.
This routine allocates a region of <size> bytes of consistent memory.  It
returns a pointer to the allocated region (in the processor's virtual address
space) or NULL if the allocation failed.  The returned memory may or may not
be in the kernels direct mapping.  Drivers must not call virt_to_page on
the returned memory region.

Note: where the platform can return consistent memory, it will
guarantee that the sync points become nops.
It also returns a <dma_handle> which may be cast to an unsigned integer the
same width as the bus and given to the device as the DMA address base of
the region.

The dir parameter specified if data is read and/or written by the device,
see dma_map_single() for details.

The gfp parameter allows the caller to specify the ``GFP_`` flags (see
kmalloc()) for the allocation, but rejects flags used to specify a memory
zone such as GFP_DMA or GFP_HIGHMEM.

Warning:  Handling non-consistent memory is a real pain.  You should
only use this API if you positively know your driver will be
required to work on one of the rare (usually non-PCI) architectures
that simply cannot make consistent memory.
Before giving the memory to the device, dma_sync_single_for_device() needs
to be called, and before reading memory written by the device,
dma_sync_single_for_cpu(), just like for streaming DMA mappings that are
reused.

::

	void
	dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
		       dma_addr_t dma_handle, unsigned long attrs)
	dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
			dma_addr_t dma_handle, enum dma_data_direction dir)

Free memory allocated by the dma_alloc_attrs().  All common
parameters must be identical to those otherwise passed to dma_free_coherent,
and the attrs argument must be identical to the attrs passed to
dma_alloc_attrs().
Free a region of memory previously allocated using dma_alloc_noncoherent().
dev, size and dma_handle and dir must all be the same as those passed into
dma_alloc_noncoherent().  cpu_addr must be the virtual address returned by
the dma_alloc_noncoherent().

::

@@ -575,41 +583,6 @@ memory or doing partial flushes.
	into the width returned by this call.  It will also always be a power
	of two for easy alignment.

::

	void
	dma_cache_sync(struct device *dev, void *vaddr, size_t size,
		       enum dma_data_direction direction)

Do a partial sync of memory that was allocated by dma_alloc_attrs() with
the DMA_ATTR_NON_CONSISTENT flag starting at virtual address vaddr and
continuing on for size.  Again, you *must* observe the cache line
boundaries when doing this.

::

	int
	dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
				    dma_addr_t device_addr, size_t size);

Declare region of memory to be handed out by dma_alloc_coherent() when
it's asked for coherent memory for this device.

phys_addr is the CPU physical address to which the memory is currently
assigned (this will be ioremapped so the CPU can access the region).

device_addr is the DMA address the device needs to be programmed
with to actually address this memory (this will be handed out as the
dma_addr_t in dma_alloc_coherent()).

size is the size of the area (must be multiples of PAGE_SIZE).

As a simplification for the platforms, only *one* such region of
memory may be declared per device.

For reasons of efficiency, most platforms choose to track the declared
region only at the granularity of a page.  For smaller allocations,
you should use the dma_pool() API.

Part III - Debug drivers use of the DMA-API
-------------------------------------------
+0 −8
Original line number Diff line number Diff line
@@ -25,14 +25,6 @@ Since it is optional for platforms to implement DMA_ATTR_WRITE_COMBINE,
those that do not will simply ignore the attribute and exhibit default
behavior.

DMA_ATTR_NON_CONSISTENT
-----------------------

DMA_ATTR_NON_CONSISTENT lets the platform to choose to return either
consistent or non-consistent memory as it sees fit.  By using this API,
you are guaranteeing to the platform that you have all the correct and
necessary sync points for this memory in the driver.

DMA_ATTR_NO_KERNEL_MAPPING
--------------------------

+1 −1
Original line number Diff line number Diff line
@@ -5216,7 +5216,7 @@ T: git git://git.infradead.org/users/hch/dma-mapping.git
F:	include/asm-generic/dma-mapping.h
F:	include/linux/dma-direct.h
F:	include/linux/dma-mapping.h
F:	include/linux/dma-noncoherent.h
F:	include/linux/dma-map-ops.h
F:	kernel/dma/
DMA-BUF HEAPS FRAMEWORK
+4 −7
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@
#include <linux/export.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
#include <linux/dma-mapping.h>
#include <linux/dma-map-ops.h>
#include <linux/iommu-helper.h>

#include <asm/io.h>
@@ -141,12 +141,7 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
	unsigned long boundary_size;

	base = arena->dma_base >> PAGE_SHIFT;
	if (dev) {
		boundary_size = dma_get_seg_boundary(dev) + 1;
		boundary_size >>= PAGE_SHIFT;
	} else {
		boundary_size = 1UL << (32 - PAGE_SHIFT);
	}
	boundary_size = dma_get_seg_boundary_nr_pages(dev, PAGE_SHIFT);

	/* Search forward for the first mask-aligned sequence of N free ptes */
	ptes = arena->ptes;
@@ -957,5 +952,7 @@ const struct dma_map_ops alpha_pci_ops = {
	.dma_supported		= alpha_pci_supported,
	.mmap			= dma_common_mmap,
	.get_sgtable		= dma_common_get_sgtable,
	.alloc_pages		= dma_common_alloc_pages,
	.free_pages		= dma_common_free_pages,
};
EXPORT_SYMBOL(alpha_pci_ops);
Loading