Commit b7a7d1c1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull DMA mapping updates from Christoph Hellwig:

 - add debugfs support for dumping dma-debug information (Corentin
   Labbe)

 - Kconfig cleanups (Andy Shevchenko and me)

 - debugfs cleanups (Greg Kroah-Hartman)

 - improve dma_map_resource and use it in the media code

 - arch_setup_dma_ops / arch_teardown_dma_ops cleanups

 - various small cleanups and improvements for the per-device coherent
   allocator

 - make the DMA mask an upper bound and don't fail "too large" dma mask
   in the remaning two architectures - this will allow big driver
   cleanups in the following merge windows

* tag 'dma-mapping-5.1' of git://git.infradead.org/users/hch/dma-mapping: (21 commits)
  Documentation/DMA-API-HOWTO: update dma_mask sections
  sparc64/pci_sun4v: allow large DMA masks
  sparc64/iommu: allow large DMA masks
  sparc64: refactor the ali DMA quirk
  ccio: allow large DMA masks
  dma-mapping: remove the DMA_MEMORY_EXCLUSIVE flag
  dma-mapping: remove dma_mark_declared_memory_occupied
  dma-mapping: move CONFIG_DMA_CMA to kernel/dma/Kconfig
  dma-mapping: improve selection of dma_declare_coherent availability
  dma-mapping: remove an incorrect __iommem annotation
  of: select OF_RESERVED_MEM automatically
  device.h: dma_mem is only needed for HAVE_GENERIC_DMA_COHERENT
  mfd/sm501: depend on HAS_DMA
  dma-mapping: add a kconfig symbol for arch_teardown_dma_ops availability
  dma-mapping: add a kconfig symbol for arch_setup_dma_ops availability
  dma-mapping: move debug configuration options to kernel/dma
  dma-debug: add dumping facility via debugfs
  dma: debug: no need to check return value of debugfs_create functions
  videobuf2: replace a layering violation with dma_map_resource
  dma-mapping: don't BUG when calling dma_map_resource on RAM
  ...
parents 065b6c4c 9eb9e96e
Loading
Loading
Loading
Loading
+41 −80
Original line number Diff line number Diff line
@@ -146,114 +146,75 @@ What about block I/O and networking buffers? The block I/O and
networking subsystems make sure that the buffers they use are valid
for you to DMA from/to.

DMA addressing limitations
DMA addressing capabilities
==========================

Does your device have any DMA addressing limitations?  For example, is
your device only capable of driving the low order 24-bits of address?
If so, you need to inform the kernel of this fact.
By default, the kernel assumes that your device can address 32-bits of DMA
addressing.  For a 64-bit capable device, this needs to be increased, and for
a device with limitations, it needs to be decreased.

By default, the kernel assumes that your device can address the full
32-bits.  For a 64-bit capable device, this needs to be increased.
And for a device with limitations, as discussed in the previous
paragraph, it needs to be decreased.
Special note about PCI: PCI-X specification requires PCI-X devices to support
64-bit addressing (DAC) for all transactions.  And at least one platform (SGI
SN2) requires 64-bit consistent allocations to operate correctly when the IO
bus is in PCI-X mode.

Special note about PCI: PCI-X specification requires PCI-X devices to
support 64-bit addressing (DAC) for all transactions.  And at least
one platform (SGI SN2) requires 64-bit consistent allocations to
operate correctly when the IO bus is in PCI-X mode.
For correct operation, you must set the DMA mask to inform the kernel about
your devices DMA addressing capabilities.

For correct operation, you must interrogate the kernel in your device
probe routine to see if the DMA controller on the machine can properly
support the DMA addressing limitation your device has.  It is good
style to do this even if your device holds the default setting,
because this shows that you did think about these issues wrt. your
device.

The query is performed via a call to dma_set_mask_and_coherent()::
This is performed via a call to dma_set_mask_and_coherent()::

	int dma_set_mask_and_coherent(struct device *dev, u64 mask);

which will query the mask for both streaming and coherent APIs together.
If you have some special requirements, then the following two separate
queries can be used instead:
which will set the mask for both streaming and coherent APIs together.  If you
have some special requirements, then the following two separate calls can be
used instead:

	The query for streaming mappings is performed via a call to
	The setup for streaming mappings is performed via a call to
	dma_set_mask()::

		int dma_set_mask(struct device *dev, u64 mask);

	The query for consistent allocations is performed via a call
	The setup for consistent allocations is performed via a call
	to dma_set_coherent_mask()::

		int dma_set_coherent_mask(struct device *dev, u64 mask);

Here, dev is a pointer to the device struct of your device, and mask
is a bit mask describing which bits of an address your device
supports.  It returns zero if your card can perform DMA properly on
the machine given the address mask you provided.  In general, the
device struct of your device is embedded in the bus-specific device
struct of your device.  For example, &pdev->dev is a pointer to the
device struct of a PCI device (pdev is a pointer to the PCI device
struct of your device).
Here, dev is a pointer to the device struct of your device, and mask is a bit
mask describing which bits of an address your device supports.  Often the
device struct of your device is embedded in the bus-specific device struct of
your device.  For example, &pdev->dev is a pointer to the device struct of a
PCI device (pdev is a pointer to the PCI device struct of your device).

If it returns non-zero, your device cannot perform DMA properly on
this platform, and attempting to do so will result in undefined
behavior.  You must either use a different mask, or not use DMA.
These calls usually return zero to indicated your device can perform DMA
properly on the machine given the address mask you provided, but they might
return an error if the mask is too small to be supportable on the given
system.  If it returns non-zero, your device cannot perform DMA properly on
this platform, and attempting to do so will result in undefined behavior.
You must not use DMA on this device unless the dma_set_mask family of
functions has returned success.

This means that in the failure case, you have three options:
This means that in the failure case, you have two options:

1) Use another DMA mask, if possible (see below).
2) Use some non-DMA mode for data transfer, if possible.
3) Ignore this device and do not initialize it.
1) Use some non-DMA mode for data transfer, if possible.
2) Ignore this device and do not initialize it.

It is recommended that your driver print a kernel KERN_WARNING message
when you end up performing either #2 or #3.  In this manner, if a user
of your driver reports that performance is bad or that the device is not
even detected, you can ask them for the kernel messages to find out
exactly why.
It is recommended that your driver print a kernel KERN_WARNING message when
setting the DMA mask fails.  In this manner, if a user of your driver reports
that performance is bad or that the device is not even detected, you can ask
them for the kernel messages to find out exactly why.

The standard 32-bit addressing device would do something like this::
The standard 64-bit addressing device would do something like this::

	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
		dev_warn(dev, "mydev: No suitable DMA available\n");
		goto ignore_this_device;
	}

Another common scenario is a 64-bit capable device.  The approach here
is to try for 64-bit addressing, but back down to a 32-bit mask that
should not fail.  The kernel may fail the 64-bit mask not because the
platform is not capable of 64-bit addressing.  Rather, it may fail in
this case simply because 32-bit addressing is done more efficiently
than 64-bit addressing.  For example, Sparc64 PCI SAC addressing is
more efficient than DAC addressing.

Here is how you would handle a 64-bit capable device which can drive
all 64-bits when accessing streaming DMA::

	int using_dac;
If the device only supports 32-bit addressing for descriptors in the
coherent allocations, but supports full 64-bits for streaming mappings
it would look like this:

	if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
		using_dac = 1;
	} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
		using_dac = 0;
	} else {
		dev_warn(dev, "mydev: No suitable DMA available\n");
		goto ignore_this_device;
	}

If a card is capable of using 64-bit consistent allocations as well,
the case would look like this::

	int using_dac, consistent_using_dac;

	if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
		using_dac = 1;
		consistent_using_dac = 1;
	} else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
		using_dac = 0;
		consistent_using_dac = 0;
	} else {
	if (dma_set_mask(dev, DMA_BIT_MASK(64))) {
		dev_warn(dev, "mydev: No suitable DMA available\n");
		goto ignore_this_device;
	}
+4 −25
Original line number Diff line number Diff line
@@ -566,8 +566,7 @@ 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, int
				    flags)
				    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.
@@ -581,12 +580,6 @@ dma_addr_t in dma_alloc_coherent()).

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

flags can be ORed together and are:

- DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions.
  Do not allow dma_alloc_coherent() to fall back to system memory when
  it's out of memory in the declared region.

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

@@ -605,23 +598,6 @@ unconditionally having removed all the required structures. It is the
driver's job to ensure that no parts of this memory region are
currently in use.

::

	void *
	dma_mark_declared_memory_occupied(struct device *dev,
					  dma_addr_t device_addr, size_t size)

This is used to occupy specific regions of the declared space
(dma_alloc_coherent() will hand out the first free region it finds).

device_addr is the *device* address of the region requested.

size is the size (and should be a page-sized multiple).

The return value will be either a pointer to the processor virtual
address of the memory, or an error (via PTR_ERR()) if any part of the
region is occupied.

Part III - Debug drivers use of the DMA-API
-------------------------------------------

@@ -696,6 +672,9 @@ dma-api/disabled This read-only file contains the character 'Y'
				happen when it runs out of memory or if it was
				disabled at boot time

dma-api/dump			This read-only file contains current DMA
				mappings.

dma-api/error_count		This file is read-only and shows the total
				numbers of errors found.

+1 −2
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ config ARC
	select ARC_TIMERS
	select ARCH_HAS_DMA_COHERENT_TO_PFN
	select ARCH_HAS_PTE_SPECIAL
	select ARCH_HAS_SETUP_DMA_OPS
	select ARCH_HAS_SYNC_DMA_FOR_CPU
	select ARCH_HAS_SYNC_DMA_FOR_DEVICE
	select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
@@ -31,7 +32,6 @@ config ARC
	select HAVE_ARCH_TRACEHOOK
	select HAVE_DEBUG_STACKOVERFLOW
	select HAVE_FUTEX_CMPXCHG if FUTEX
	select HAVE_GENERIC_DMA_COHERENT
	select HAVE_IOREMAP_PROT
	select HAVE_KERNEL_GZIP
	select HAVE_KERNEL_LZMA
@@ -45,7 +45,6 @@ config ARC
	select MODULES_USE_ELF_RELA
	select OF
	select OF_EARLY_FLATTREE
	select OF_RESERVED_MEM
	select PCI_SYSCALL if PCI
	select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING

+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ generic-y += bugs.h
generic-y += compat.h
generic-y += device.h
generic-y += div64.h
generic-y += dma-mapping.h
generic-y += emergency-restart.h
generic-y += extable.h
generic-y += ftrace.h
+0 −13
Original line number Diff line number Diff line
// SPDX-License-Identifier:  GPL-2.0
// (C) 2018 Synopsys, Inc. (www.synopsys.com)

#ifndef ASM_ARC_DMA_MAPPING_H
#define ASM_ARC_DMA_MAPPING_H

#include <asm-generic/dma-mapping.h>

void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
			const struct iommu_ops *iommu, bool coherent);
#define arch_setup_dma_ops arch_setup_dma_ops

#endif
Loading