mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping
Pull DMA mapping updates from Christoph Hellwig:
"A huge update this time, but a lot of that is just consolidating or
removing code:
- provide a common DMA_MAPPING_ERROR definition and avoid indirect
calls for dma_map_* error checking
- use direct calls for the DMA direct mapping case, avoiding huge
retpoline overhead for high performance workloads
- merge the swiotlb dma_map_ops into dma-direct
- provide a generic remapping DMA consistent allocator for
architectures that have devices that perform DMA that is not cache
coherent. Based on the existing arm64 implementation and also used
for csky now.
- improve the dma-debug infrastructure, including dynamic allocation
of entries (Robin Murphy)
- default to providing chaining scatterlist everywhere, with opt-outs
for the few architectures (alpha, parisc, most arm32 variants) that
can't cope with it
- misc sparc32 dma-related cleanups
- remove the dma_mark_clean arch hook used by swiotlb on ia64 and
replace it with the generic noncoherent infrastructure
- fix the return type of dma_set_max_seg_size (Niklas Söderlund)
- move the dummy dma ops for not DMA capable devices from arm64 to
common code (Robin Murphy)
- ensure dma_alloc_coherent returns zeroed memory to avoid kernel
data leaks through userspace. We already did this for most common
architectures, but this ensures we do it everywhere.
dma_zalloc_coherent has been deprecated and can hopefully be
removed after -rc1 with a coccinelle script"
* tag 'dma-mapping-4.21' of git://git.infradead.org/users/hch/dma-mapping: (73 commits)
dma-mapping: fix inverted logic in dma_supported
dma-mapping: deprecate dma_zalloc_coherent
dma-mapping: zero memory returned from dma_alloc_*
sparc/iommu: fix ->map_sg return value
sparc/io-unit: fix ->map_sg return value
arm64: default to the direct mapping in get_arch_dma_ops
PCI: Remove unused attr variable in pci_dma_configure
ia64: only select ARCH_HAS_DMA_COHERENT_TO_PFN if swiotlb is enabled
dma-mapping: bypass indirect calls for dma-direct
vmd: use the proper dma_* APIs instead of direct methods calls
dma-direct: merge swiotlb_dma_ops into the dma_direct code
dma-direct: use dma_direct_map_page to implement dma_direct_map_sg
dma-direct: improve addressability error reporting
swiotlb: remove dma_mark_clean
swiotlb: remove SWIOTLB_MAP_ERROR
ACPI / scan: Refactor _CCA enforcement
dma-mapping: factor out dummy DMA ops
dma-mapping: always build the direct mapping code
dma-mapping: move dma_cache_sync out of line
dma-mapping: move various slow path functions out of line
...
This commit is contained in:
@@ -58,15 +58,6 @@ specify the ``GFP_`` flags (see kmalloc()) for the allocation (the
|
||||
implementation may choose to ignore flags that affect the location of
|
||||
the returned memory, like GFP_DMA).
|
||||
|
||||
::
|
||||
|
||||
void *
|
||||
dma_zalloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag)
|
||||
|
||||
Wraps dma_alloc_coherent() and also zeroes the returned memory if the
|
||||
allocation attempt succeeded.
|
||||
|
||||
::
|
||||
|
||||
void
|
||||
@@ -717,12 +708,15 @@ dma-api/num_errors The number in this file shows how many
|
||||
dma-api/min_free_entries This read-only file can be read to get the
|
||||
minimum number of free dma_debug_entries the
|
||||
allocator has ever seen. If this value goes
|
||||
down to zero the code will disable itself
|
||||
because it is not longer reliable.
|
||||
down to zero the code will attempt to increase
|
||||
nr_total_entries to compensate.
|
||||
|
||||
dma-api/num_free_entries The current number of free dma_debug_entries
|
||||
in the allocator.
|
||||
|
||||
dma-api/nr_total_entries The total number of dma_debug_entries in the
|
||||
allocator, both free and used.
|
||||
|
||||
dma-api/driver-filter You can write a name of a driver into this file
|
||||
to limit the debug output to requests from that
|
||||
particular driver. Write an empty string to
|
||||
@@ -742,10 +736,15 @@ driver filter at boot time. The debug code will only print errors for that
|
||||
driver afterwards. This filter can be disabled or changed later using debugfs.
|
||||
|
||||
When the code disables itself at runtime this is most likely because it ran
|
||||
out of dma_debug_entries. These entries are preallocated at boot. The number
|
||||
of preallocated entries is defined per architecture. If it is too low for you
|
||||
boot with 'dma_debug_entries=<your_desired_number>' to overwrite the
|
||||
architectural default.
|
||||
out of dma_debug_entries and was unable to allocate more on-demand. 65536
|
||||
entries are preallocated at boot - if this is too low for you boot with
|
||||
'dma_debug_entries=<your_desired_number>' to overwrite the default. Note
|
||||
that the code allocates entries in batches, so the exact number of
|
||||
preallocated entries may be greater than the actual number requested. The
|
||||
code will print to the kernel log each time it has dynamically allocated
|
||||
as many entries as were initially preallocated. This is to indicate that a
|
||||
larger preallocation size may be appropriate, or if it happens continually
|
||||
that a driver may be leaking mappings.
|
||||
|
||||
::
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#
|
||||
# Feature name: sg-chain
|
||||
# Kconfig: ARCH_HAS_SG_CHAIN
|
||||
# description: arch supports chained scatter-gather lists
|
||||
#
|
||||
-----------------------
|
||||
| arch |status|
|
||||
-----------------------
|
||||
| alpha: | TODO |
|
||||
| arc: | ok |
|
||||
| arm: | ok |
|
||||
| arm64: | ok |
|
||||
| c6x: | TODO |
|
||||
| h8300: | TODO |
|
||||
| hexagon: | TODO |
|
||||
| ia64: | ok |
|
||||
| m68k: | TODO |
|
||||
| microblaze: | TODO |
|
||||
| mips: | TODO |
|
||||
| nds32: | TODO |
|
||||
| nios2: | TODO |
|
||||
| openrisc: | TODO |
|
||||
| parisc: | TODO |
|
||||
| powerpc: | ok |
|
||||
| riscv: | TODO |
|
||||
| s390: | ok |
|
||||
| sh: | TODO |
|
||||
| sparc: | ok |
|
||||
| um: | TODO |
|
||||
| unicore32: | TODO |
|
||||
| x86: | ok |
|
||||
| xtensa: | TODO |
|
||||
-----------------------
|
||||
@@ -209,7 +209,7 @@ IOMMU (input/output memory management unit)
|
||||
mapping with memory protection, etc.
|
||||
Kernel boot message: "PCI-DMA: Using Calgary IOMMU"
|
||||
|
||||
iommu=[<size>][,noagp][,off][,force][,noforce][,leak[=<nr_of_leak_pages>]
|
||||
iommu=[<size>][,noagp][,off][,force][,noforce]
|
||||
[,memaper[=<order>]][,merge][,fullflush][,nomerge]
|
||||
[,noaperture][,calgary]
|
||||
|
||||
@@ -228,9 +228,6 @@ IOMMU (input/output memory management unit)
|
||||
allowed Overwrite iommu off workarounds for specific chipsets.
|
||||
fullflush Flush IOMMU on each allocation (default).
|
||||
nofullflush Don't use IOMMU fullflush.
|
||||
leak Turn on simple iommu leak tracing (only when
|
||||
CONFIG_IOMMU_LEAK is on). Default number of leak pages
|
||||
is 20.
|
||||
memaper[=<order>] Allocate an own aperture over RAM with size 32MB<<order.
|
||||
(default: order=1, i.e. 64MB)
|
||||
merge Do scatter-gather (SG) merging. Implies "force"
|
||||
|
||||
@@ -5,6 +5,7 @@ config ALPHA
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select ARCH_NO_PREEMPT
|
||||
select ARCH_NO_SG_CHAIN
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
select HAVE_AOUT
|
||||
select HAVE_IDE
|
||||
@@ -202,7 +203,6 @@ config ALPHA_EIGER
|
||||
config ALPHA_JENSEN
|
||||
bool "Jensen"
|
||||
depends on BROKEN
|
||||
select DMA_DIRECT_OPS
|
||||
help
|
||||
DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
|
||||
of the first-generation Alpha systems. A number of these systems
|
||||
|
||||
@@ -7,7 +7,7 @@ extern const struct dma_map_ops alpha_pci_ops;
|
||||
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
|
||||
{
|
||||
#ifdef CONFIG_ALPHA_JENSEN
|
||||
return &dma_direct_ops;
|
||||
return NULL;
|
||||
#else
|
||||
return &alpha_pci_ops;
|
||||
#endif
|
||||
|
||||
@@ -291,7 +291,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
|
||||
use direct_map above, it now must be considered an error. */
|
||||
if (! alpha_mv.mv_pci_tbi) {
|
||||
printk_once(KERN_WARNING "pci_map_single: no HW sg\n");
|
||||
return 0;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
arena = hose->sg_pci;
|
||||
@@ -307,7 +307,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
|
||||
if (dma_ofs < 0) {
|
||||
printk(KERN_WARNING "pci_map_single failed: "
|
||||
"could not allocate dma page tables\n");
|
||||
return 0;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
paddr &= PAGE_MASK;
|
||||
@@ -443,7 +443,7 @@ static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
|
||||
gfp &= ~GFP_DMA;
|
||||
|
||||
try_again:
|
||||
cpu_addr = (void *)__get_free_pages(gfp, order);
|
||||
cpu_addr = (void *)__get_free_pages(gfp | __GFP_ZERO, order);
|
||||
if (! cpu_addr) {
|
||||
printk(KERN_INFO "pci_alloc_consistent: "
|
||||
"get_free_pages failed from %pf\n",
|
||||
@@ -455,7 +455,7 @@ try_again:
|
||||
memset(cpu_addr, 0, size);
|
||||
|
||||
*dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
|
||||
if (*dma_addrp == 0) {
|
||||
if (*dma_addrp == DMA_MAPPING_ERROR) {
|
||||
free_pages((unsigned long)cpu_addr, order);
|
||||
if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
|
||||
return NULL;
|
||||
@@ -671,7 +671,7 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
|
||||
sg->dma_address
|
||||
= pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
|
||||
sg->length, dac_allowed);
|
||||
return sg->dma_address != 0;
|
||||
return sg->dma_address != DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
start = sg;
|
||||
@@ -935,11 +935,6 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alpha_pci_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
return dma_addr == 0;
|
||||
}
|
||||
|
||||
const struct dma_map_ops alpha_pci_ops = {
|
||||
.alloc = alpha_pci_alloc_coherent,
|
||||
.free = alpha_pci_free_coherent,
|
||||
@@ -947,7 +942,6 @@ const struct dma_map_ops alpha_pci_ops = {
|
||||
.unmap_page = alpha_pci_unmap_page,
|
||||
.map_sg = alpha_pci_map_sg,
|
||||
.unmap_sg = alpha_pci_unmap_sg,
|
||||
.mapping_error = alpha_pci_mapping_error,
|
||||
.dma_supported = alpha_pci_supported,
|
||||
};
|
||||
EXPORT_SYMBOL(alpha_pci_ops);
|
||||
|
||||
@@ -13,12 +13,10 @@ config ARC
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SYNC_DMA_FOR_CPU
|
||||
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
select CLONE_BACKWARDS
|
||||
select COMMON_CLK
|
||||
select DMA_DIRECT_OPS
|
||||
select GENERIC_ATOMIC64 if !ISA_ARCV2 || !(ARC_HAS_LL64 && ARC_HAS_LLSC)
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_FIND_FIRST_BIT
|
||||
|
||||
@@ -1294,7 +1294,7 @@ void __init arc_cache_init_master(void)
|
||||
/*
|
||||
* In case of IOC (say IOC+SLC case), pointers above could still be set
|
||||
* but end up not being relevant as the first function in chain is not
|
||||
* called at all for @dma_direct_ops
|
||||
* called at all for devices using coherent DMA.
|
||||
* arch_sync_dma_for_cpu() -> dma_cache_*() -> __dma_cache_*()
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
*/
|
||||
BUG_ON(gfp & __GFP_HIGHMEM);
|
||||
|
||||
page = alloc_pages(gfp, order);
|
||||
page = alloc_pages(gfp | __GFP_ZERO, order);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ config ARM
|
||||
select ARCH_HAVE_CUSTOM_GPIO_H
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_NO_SG_CHAIN if !ARM_HAS_SG_CHAIN
|
||||
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
@@ -29,7 +30,7 @@ config ARM
|
||||
select CLONE_BACKWARDS
|
||||
select CPU_PM if (SUSPEND || CPU_IDLE)
|
||||
select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
select DMA_DIRECT_OPS if !MMU
|
||||
select DMA_REMAP if MMU
|
||||
select EDAC_SUPPORT
|
||||
select EDAC_ATOMIC_SCRUB
|
||||
select GENERIC_ALLOCATOR
|
||||
@@ -118,7 +119,6 @@ config ARM
|
||||
<http://www.arm.linux.org.uk/>.
|
||||
|
||||
config ARM_HAS_SG_CHAIN
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
bool
|
||||
|
||||
config ARM_DMA_USE_IOMMU
|
||||
|
||||
@@ -257,7 +257,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
|
||||
if (buf == NULL) {
|
||||
dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
|
||||
__func__, ptr);
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
|
||||
@@ -327,7 +327,7 @@ static dma_addr_t dmabounce_map_page(struct device *dev, struct page *page,
|
||||
|
||||
ret = needs_bounce(dev, dma_addr, size);
|
||||
if (ret < 0)
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
|
||||
if (ret == 0) {
|
||||
arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
|
||||
@@ -336,7 +336,7 @@ static dma_addr_t dmabounce_map_page(struct device *dev, struct page *page,
|
||||
|
||||
if (PageHighMem(page)) {
|
||||
dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not supported\n");
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
return map_single(dev, page_address(page) + offset, size, dir, attrs);
|
||||
@@ -453,11 +453,6 @@ static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
|
||||
return arm_dma_ops.dma_supported(dev, dma_mask);
|
||||
}
|
||||
|
||||
static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
return arm_dma_ops.mapping_error(dev, dma_addr);
|
||||
}
|
||||
|
||||
static const struct dma_map_ops dmabounce_ops = {
|
||||
.alloc = arm_dma_alloc,
|
||||
.free = arm_dma_free,
|
||||
@@ -472,7 +467,6 @@ static const struct dma_map_ops dmabounce_ops = {
|
||||
.sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
|
||||
.sync_sg_for_device = arm_dma_sync_sg_for_device,
|
||||
.dma_supported = dmabounce_dma_supported,
|
||||
.mapping_error = dmabounce_mapping_error,
|
||||
};
|
||||
|
||||
static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <linux/dma-debug.h>
|
||||
#include <linux/kref.h>
|
||||
|
||||
#define ARM_MAPPING_ERROR (~(dma_addr_t)0x0)
|
||||
|
||||
struct dma_iommu_mapping {
|
||||
/* iommu specific data */
|
||||
struct iommu_domain *domain;
|
||||
|
||||
@@ -18,7 +18,7 @@ extern const struct dma_map_ops arm_coherent_dma_ops;
|
||||
|
||||
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_MMU) ? &arm_dma_ops : &dma_direct_ops;
|
||||
return IS_ENABLED(CONFIG_MMU) ? &arm_dma_ops : NULL;
|
||||
}
|
||||
|
||||
#ifdef __arch_page_to_dma
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "dma.h"
|
||||
|
||||
/*
|
||||
* dma_direct_ops is used if
|
||||
* The generic direct mapping code is used if
|
||||
* - MMU/MPU is off
|
||||
* - cpu is v7m w/o cache support
|
||||
* - device is coherent
|
||||
@@ -209,16 +209,9 @@ const struct dma_map_ops arm_nommu_dma_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL(arm_nommu_dma_ops);
|
||||
|
||||
static const struct dma_map_ops *arm_nommu_get_dma_map_ops(bool coherent)
|
||||
{
|
||||
return coherent ? &dma_direct_ops : &arm_nommu_dma_ops;
|
||||
}
|
||||
|
||||
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
const struct iommu_ops *iommu, bool coherent)
|
||||
{
|
||||
const struct dma_map_ops *dma_ops;
|
||||
|
||||
if (IS_ENABLED(CONFIG_CPU_V7M)) {
|
||||
/*
|
||||
* Cache support for v7m is optional, so can be treated as
|
||||
@@ -234,7 +227,6 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
dev->archdata.dma_coherent = (get_cr() & CR_M) ? coherent : true;
|
||||
}
|
||||
|
||||
dma_ops = arm_nommu_get_dma_map_ops(dev->archdata.dma_coherent);
|
||||
|
||||
set_dma_ops(dev, dma_ops);
|
||||
if (!dev->archdata.dma_coherent)
|
||||
set_dma_ops(dev, &arm_nommu_dma_ops);
|
||||
}
|
||||
|
||||
@@ -179,11 +179,6 @@ static void arm_dma_sync_single_for_device(struct device *dev,
|
||||
__dma_page_cpu_to_dev(page, offset, size, dir);
|
||||
}
|
||||
|
||||
static int arm_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
return dma_addr == ARM_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
const struct dma_map_ops arm_dma_ops = {
|
||||
.alloc = arm_dma_alloc,
|
||||
.free = arm_dma_free,
|
||||
@@ -197,7 +192,6 @@ const struct dma_map_ops arm_dma_ops = {
|
||||
.sync_single_for_device = arm_dma_sync_single_for_device,
|
||||
.sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
|
||||
.sync_sg_for_device = arm_dma_sync_sg_for_device,
|
||||
.mapping_error = arm_dma_mapping_error,
|
||||
.dma_supported = arm_dma_supported,
|
||||
};
|
||||
EXPORT_SYMBOL(arm_dma_ops);
|
||||
@@ -217,7 +211,6 @@ const struct dma_map_ops arm_coherent_dma_ops = {
|
||||
.get_sgtable = arm_dma_get_sgtable,
|
||||
.map_page = arm_coherent_dma_map_page,
|
||||
.map_sg = arm_dma_map_sg,
|
||||
.mapping_error = arm_dma_mapping_error,
|
||||
.dma_supported = arm_dma_supported,
|
||||
};
|
||||
EXPORT_SYMBOL(arm_coherent_dma_ops);
|
||||
@@ -774,7 +767,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
|
||||
gfp &= ~(__GFP_COMP);
|
||||
args.gfp = gfp;
|
||||
|
||||
*handle = ARM_MAPPING_ERROR;
|
||||
*handle = DMA_MAPPING_ERROR;
|
||||
allowblock = gfpflags_allow_blocking(gfp);
|
||||
cma = allowblock ? dev_get_cma_area(dev) : false;
|
||||
|
||||
@@ -1217,7 +1210,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
|
||||
if (i == mapping->nr_bitmaps) {
|
||||
if (extend_iommu_mapping(mapping)) {
|
||||
spin_unlock_irqrestore(&mapping->lock, flags);
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
start = bitmap_find_next_zero_area(mapping->bitmaps[i],
|
||||
@@ -1225,7 +1218,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
|
||||
|
||||
if (start > mapping->bits) {
|
||||
spin_unlock_irqrestore(&mapping->lock, flags);
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
bitmap_set(mapping->bitmaps[i], start, count);
|
||||
@@ -1409,7 +1402,7 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size,
|
||||
int i;
|
||||
|
||||
dma_addr = __alloc_iova(mapping, size);
|
||||
if (dma_addr == ARM_MAPPING_ERROR)
|
||||
if (dma_addr == DMA_MAPPING_ERROR)
|
||||
return dma_addr;
|
||||
|
||||
iova = dma_addr;
|
||||
@@ -1436,7 +1429,7 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size,
|
||||
fail:
|
||||
iommu_unmap(mapping->domain, dma_addr, iova-dma_addr);
|
||||
__free_iova(mapping, dma_addr, size);
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t size)
|
||||
@@ -1497,7 +1490,7 @@ static void *__iommu_alloc_simple(struct device *dev, size_t size, gfp_t gfp,
|
||||
return NULL;
|
||||
|
||||
*handle = __iommu_create_mapping(dev, &page, size, attrs);
|
||||
if (*handle == ARM_MAPPING_ERROR)
|
||||
if (*handle == DMA_MAPPING_ERROR)
|
||||
goto err_mapping;
|
||||
|
||||
return addr;
|
||||
@@ -1525,7 +1518,7 @@ static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size,
|
||||
struct page **pages;
|
||||
void *addr = NULL;
|
||||
|
||||
*handle = ARM_MAPPING_ERROR;
|
||||
*handle = DMA_MAPPING_ERROR;
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
if (coherent_flag == COHERENT || !gfpflags_allow_blocking(gfp))
|
||||
@@ -1546,7 +1539,7 @@ static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size,
|
||||
return NULL;
|
||||
|
||||
*handle = __iommu_create_mapping(dev, pages, size, attrs);
|
||||
if (*handle == ARM_MAPPING_ERROR)
|
||||
if (*handle == DMA_MAPPING_ERROR)
|
||||
goto err_buffer;
|
||||
|
||||
if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)
|
||||
@@ -1696,10 +1689,10 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
|
||||
int prot;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
*handle = ARM_MAPPING_ERROR;
|
||||
*handle = DMA_MAPPING_ERROR;
|
||||
|
||||
iova_base = iova = __alloc_iova(mapping, size);
|
||||
if (iova == ARM_MAPPING_ERROR)
|
||||
if (iova == DMA_MAPPING_ERROR)
|
||||
return -ENOMEM;
|
||||
|
||||
for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
|
||||
@@ -1739,7 +1732,7 @@ static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
for (i = 1; i < nents; i++) {
|
||||
s = sg_next(s);
|
||||
|
||||
s->dma_address = ARM_MAPPING_ERROR;
|
||||
s->dma_address = DMA_MAPPING_ERROR;
|
||||
s->dma_length = 0;
|
||||
|
||||
if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) {
|
||||
@@ -1914,7 +1907,7 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
|
||||
int ret, prot, len = PAGE_ALIGN(size + offset);
|
||||
|
||||
dma_addr = __alloc_iova(mapping, len);
|
||||
if (dma_addr == ARM_MAPPING_ERROR)
|
||||
if (dma_addr == DMA_MAPPING_ERROR)
|
||||
return dma_addr;
|
||||
|
||||
prot = __dma_info_to_prot(dir, attrs);
|
||||
@@ -1926,7 +1919,7 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p
|
||||
return dma_addr + offset;
|
||||
fail:
|
||||
__free_iova(mapping, dma_addr, len);
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2020,7 +2013,7 @@ static dma_addr_t arm_iommu_map_resource(struct device *dev,
|
||||
size_t len = PAGE_ALIGN(size + offset);
|
||||
|
||||
dma_addr = __alloc_iova(mapping, len);
|
||||
if (dma_addr == ARM_MAPPING_ERROR)
|
||||
if (dma_addr == DMA_MAPPING_ERROR)
|
||||
return dma_addr;
|
||||
|
||||
prot = __dma_info_to_prot(dir, attrs) | IOMMU_MMIO;
|
||||
@@ -2032,7 +2025,7 @@ static dma_addr_t arm_iommu_map_resource(struct device *dev,
|
||||
return dma_addr + offset;
|
||||
fail:
|
||||
__free_iova(mapping, dma_addr, len);
|
||||
return ARM_MAPPING_ERROR;
|
||||
return DMA_MAPPING_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2105,7 +2098,6 @@ const struct dma_map_ops iommu_ops = {
|
||||
.map_resource = arm_iommu_map_resource,
|
||||
.unmap_resource = arm_iommu_unmap_resource,
|
||||
|
||||
.mapping_error = arm_dma_mapping_error,
|
||||
.dma_supported = arm_dma_supported,
|
||||
};
|
||||
|
||||
@@ -2124,7 +2116,6 @@ const struct dma_map_ops iommu_coherent_ops = {
|
||||
.map_resource = arm_iommu_map_resource,
|
||||
.unmap_resource = arm_iommu_unmap_resource,
|
||||
|
||||
.mapping_error = arm_dma_mapping_error,
|
||||
.dma_supported = arm_dma_supported,
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ config ARM64
|
||||
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SET_MEMORY
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_HAS_STRICT_MODULE_RWX
|
||||
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
|
||||
@@ -81,7 +80,7 @@ config ARM64
|
||||
select CPU_PM if (SUSPEND || CPU_IDLE)
|
||||
select CRC32
|
||||
select DCACHE_WORD_ACCESS
|
||||
select DMA_DIRECT_OPS
|
||||
select DMA_DIRECT_REMAP
|
||||
select EDAC_SUPPORT
|
||||
select FRAME_POINTER
|
||||
select GENERIC_ALLOCATOR
|
||||
|
||||
@@ -24,15 +24,9 @@
|
||||
#include <xen/xen.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
extern const struct dma_map_ops dummy_dma_ops;
|
||||
|
||||
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
|
||||
{
|
||||
/*
|
||||
* We expect no ISA devices, and all other DMA masters are expected to
|
||||
* have someone call arch_setup_dma_ops at device creation time.
|
||||
*/
|
||||
return &dummy_dma_ops;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
|
||||
@@ -33,113 +33,6 @@
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
static struct gen_pool *atomic_pool __ro_after_init;
|
||||
|
||||
#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
|
||||
static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE;
|
||||
|
||||
static int __init early_coherent_pool(char *p)
|
||||
{
|
||||
atomic_pool_size = memparse(p, &p);
|
||||
return 0;
|
||||
}
|
||||
early_param("coherent_pool", early_coherent_pool);
|
||||
|
||||
static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
|
||||
{
|
||||
unsigned long val;
|
||||
void *ptr = NULL;
|
||||
|
||||
if (!atomic_pool) {
|
||||
WARN(1, "coherent pool not initialised!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
val = gen_pool_alloc(atomic_pool, size);
|
||||
if (val) {
|
||||
phys_addr_t phys = gen_pool_virt_to_phys(atomic_pool, val);
|
||||
|
||||
*ret_page = phys_to_page(phys);
|
||||
ptr = (void *)val;
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static bool __in_atomic_pool(void *start, size_t size)
|
||||
{
|
||||
return addr_in_gen_pool(atomic_pool, (unsigned long)start, size);
|
||||
}
|
||||
|
||||
static int __free_from_pool(void *start, size_t size)
|
||||
{
|
||||
if (!__in_atomic_pool(start, size))
|
||||
return 0;
|
||||
|
||||
gen_pool_free(atomic_pool, (unsigned long)start, size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
gfp_t flags, unsigned long attrs)
|
||||
{
|
||||
struct page *page;
|
||||
void *ptr, *coherent_ptr;
|
||||
pgprot_t prot = pgprot_writecombine(PAGE_KERNEL);
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
if (!gfpflags_allow_blocking(flags)) {
|
||||
struct page *page = NULL;
|
||||
void *addr = __alloc_from_pool(size, &page, flags);
|
||||
|
||||
if (addr)
|
||||
*dma_handle = phys_to_dma(dev, page_to_phys(page));
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
ptr = dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs);
|
||||
if (!ptr)
|
||||
goto no_mem;
|
||||
|
||||
/* remove any dirty cache lines on the kernel alias */
|
||||
__dma_flush_area(ptr, size);
|
||||
|
||||
/* create a coherent mapping */
|
||||
page = virt_to_page(ptr);
|
||||
coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,
|
||||
prot, __builtin_return_address(0));
|
||||
if (!coherent_ptr)
|
||||
goto no_map;
|
||||
|
||||
return coherent_ptr;
|
||||
|
||||
no_map:
|
||||
dma_direct_free_pages(dev, size, ptr, *dma_handle, attrs);
|
||||
no_mem:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void arch_dma_free(struct device *dev, size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle, unsigned long attrs)
|
||||
{
|
||||
if (!__free_from_pool(vaddr, PAGE_ALIGN(size))) {
|
||||
void *kaddr = phys_to_virt(dma_to_phys(dev, dma_handle));
|
||||
|
||||
vunmap(vaddr);
|
||||
dma_direct_free_pages(dev, size, kaddr, dma_handle, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
|
||||
dma_addr_t dma_addr)
|
||||
{
|
||||
return __phys_to_pfn(dma_to_phys(dev, dma_addr));
|
||||
}
|
||||
|
||||
pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
|
||||
unsigned long attrs)
|
||||
{
|
||||
@@ -160,6 +53,11 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
|
||||
__dma_unmap_area(phys_to_virt(paddr), size, dir);
|
||||
}
|
||||
|
||||
void arch_dma_prep_coherent(struct page *page, size_t size)
|
||||
{
|
||||
__dma_flush_area(page_address(page), size);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOMMU_DMA
|
||||
static int __swiotlb_get_sgtable_page(struct sg_table *sgt,
|
||||
struct page *page, size_t size)
|
||||
@@ -191,167 +89,13 @@ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma,
|
||||
}
|
||||
#endif /* CONFIG_IOMMU_DMA */
|
||||
|
||||
static int __init atomic_pool_init(void)
|
||||
{
|
||||
pgprot_t prot = __pgprot(PROT_NORMAL_NC);
|
||||
unsigned long nr_pages = atomic_pool_size >> PAGE_SHIFT;
|
||||
struct page *page;
|
||||
void *addr;
|
||||
unsigned int pool_size_order = get_order(atomic_pool_size);
|
||||
|
||||
if (dev_get_cma_area(NULL))
|
||||
page = dma_alloc_from_contiguous(NULL, nr_pages,
|
||||
pool_size_order, false);
|
||||
else
|
||||
page = alloc_pages(GFP_DMA32, pool_size_order);
|
||||
|
||||
if (page) {
|
||||
int ret;
|
||||
void *page_addr = page_address(page);
|
||||
|
||||
memset(page_addr, 0, atomic_pool_size);
|
||||
__dma_flush_area(page_addr, atomic_pool_size);
|
||||
|
||||
atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
|
||||
if (!atomic_pool)
|
||||
goto free_page;
|
||||
|
||||
addr = dma_common_contiguous_remap(page, atomic_pool_size,
|
||||
VM_USERMAP, prot, atomic_pool_init);
|
||||
|
||||
if (!addr)
|
||||
goto destroy_genpool;
|
||||
|
||||
ret = gen_pool_add_virt(atomic_pool, (unsigned long)addr,
|
||||
page_to_phys(page),
|
||||
atomic_pool_size, -1);
|
||||
if (ret)
|
||||
goto remove_mapping;
|
||||
|
||||
gen_pool_set_algo(atomic_pool,
|
||||
gen_pool_first_fit_order_align,
|
||||
NULL);
|
||||
|
||||
pr_info("DMA: preallocated %zu KiB pool for atomic allocations\n",
|
||||
atomic_pool_size / 1024);
|
||||
return 0;
|
||||
}
|
||||
goto out;
|
||||
|
||||
remove_mapping:
|
||||
dma_common_free_remap(addr, atomic_pool_size, VM_USERMAP);
|
||||
destroy_genpool:
|
||||
gen_pool_destroy(atomic_pool);
|
||||
atomic_pool = NULL;
|
||||
free_page:
|
||||
if (!dma_release_from_contiguous(NULL, page, nr_pages))
|
||||
__free_pages(page, pool_size_order);
|
||||
out:
|
||||
pr_err("DMA: failed to allocate %zu KiB pool for atomic coherent allocation\n",
|
||||
atomic_pool_size / 1024);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* The following APIs are for dummy DMA ops *
|
||||
********************************************/
|
||||
|
||||
static void *__dummy_alloc(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flags,
|
||||
unsigned long attrs)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __dummy_free(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle,
|
||||
unsigned long attrs)
|
||||
{
|
||||
}
|
||||
|
||||
static int __dummy_mmap(struct device *dev,
|
||||
struct vm_area_struct *vma,
|
||||
void *cpu_addr, dma_addr_t dma_addr, size_t size,
|
||||
unsigned long attrs)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static dma_addr_t __dummy_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __dummy_unmap_page(struct device *dev, dma_addr_t dev_addr,
|
||||
size_t size, enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
}
|
||||
|
||||
static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
|
||||
int nelems, enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __dummy_unmap_sg(struct device *dev,
|
||||
struct scatterlist *sgl, int nelems,
|
||||
enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
}
|
||||
|
||||
static void __dummy_sync_single(struct device *dev,
|
||||
dma_addr_t dev_addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
}
|
||||
|
||||
static void __dummy_sync_sg(struct device *dev,
|
||||
struct scatterlist *sgl, int nelems,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
}
|
||||
|
||||
static int __dummy_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __dummy_dma_supported(struct device *hwdev, u64 mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dma_map_ops dummy_dma_ops = {
|
||||
.alloc = __dummy_alloc,
|
||||
.free = __dummy_free,
|
||||
.mmap = __dummy_mmap,
|
||||
.map_page = __dummy_map_page,
|
||||
.unmap_page = __dummy_unmap_page,
|
||||
.map_sg = __dummy_map_sg,
|
||||
.unmap_sg = __dummy_unmap_sg,
|
||||
.sync_single_for_cpu = __dummy_sync_single,
|
||||
.sync_single_for_device = __dummy_sync_single,
|
||||
.sync_sg_for_cpu = __dummy_sync_sg,
|
||||
.sync_sg_for_device = __dummy_sync_sg,
|
||||
.mapping_error = __dummy_mapping_error,
|
||||
.dma_supported = __dummy_dma_supported,
|
||||
};
|
||||
EXPORT_SYMBOL(dummy_dma_ops);
|
||||
|
||||
static int __init arm64_dma_init(void)
|
||||
{
|
||||
WARN_TAINT(ARCH_DMA_MINALIGN < cache_line_size(),
|
||||
TAINT_CPU_OUT_OF_SPEC,
|
||||
"ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)",
|
||||
ARCH_DMA_MINALIGN, cache_line_size());
|
||||
|
||||
return atomic_pool_init();
|
||||
return dma_atomic_pool_init(GFP_DMA32, __pgprot(PROT_NORMAL_NC));
|
||||
}
|
||||
arch_initcall(arm64_dma_init);
|
||||
|
||||
@@ -397,17 +141,17 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
|
||||
page = alloc_pages(gfp, get_order(size));
|
||||
addr = page ? page_address(page) : NULL;
|
||||
} else {
|
||||
addr = __alloc_from_pool(size, &page, gfp);
|
||||
addr = dma_alloc_from_pool(size, &page, gfp);
|
||||
}
|
||||
if (!addr)
|
||||
return NULL;
|
||||
|
||||
*handle = iommu_dma_map_page(dev, page, 0, iosize, ioprot);
|
||||
if (iommu_dma_mapping_error(dev, *handle)) {
|
||||
if (*handle == DMA_MAPPING_ERROR) {
|
||||
if (coherent)
|
||||
__free_pages(page, get_order(size));
|
||||
else
|
||||
__free_from_pool(addr, size);
|
||||
dma_free_from_pool(addr, size);
|
||||
addr = NULL;
|
||||
}
|
||||
} else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
|
||||
@@ -420,7 +164,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
|
||||
return NULL;
|
||||
|
||||
*handle = iommu_dma_map_page(dev, page, 0, iosize, ioprot);
|
||||
if (iommu_dma_mapping_error(dev, *handle)) {
|
||||
if (*handle == DMA_MAPPING_ERROR) {
|
||||
dma_release_from_contiguous(dev, page,
|
||||
size >> PAGE_SHIFT);
|
||||
return NULL;
|
||||
@@ -471,9 +215,9 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
|
||||
* coherent devices.
|
||||
* Hence how dodgy the below logic looks...
|
||||
*/
|
||||
if (__in_atomic_pool(cpu_addr, size)) {
|
||||
if (dma_in_atomic_pool(cpu_addr, size)) {
|
||||
iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
|
||||
__free_from_pool(cpu_addr, size);
|
||||
dma_free_from_pool(cpu_addr, size);
|
||||
} else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
|
||||
struct page *page = vmalloc_to_page(cpu_addr);
|
||||
|
||||
@@ -580,7 +324,7 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
|
||||
dma_addr_t dev_addr = iommu_dma_map_page(dev, page, offset, size, prot);
|
||||
|
||||
if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
|
||||
!iommu_dma_mapping_error(dev, dev_addr))
|
||||
dev_addr != DMA_MAPPING_ERROR)
|
||||
__dma_map_area(page_address(page) + offset, size, dir);
|
||||
|
||||
return dev_addr;
|
||||
@@ -663,7 +407,6 @@ static const struct dma_map_ops iommu_dma_ops = {
|
||||
.sync_sg_for_device = __iommu_sync_sg_for_device,
|
||||
.map_resource = iommu_dma_map_resource,
|
||||
.unmap_resource = iommu_dma_unmap_resource,
|
||||
.mapping_error = iommu_dma_mapping_error,
|
||||
};
|
||||
|
||||
static int __init __iommu_dma_init(void)
|
||||
@@ -719,9 +462,6 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
|
||||
const struct iommu_ops *iommu, bool coherent)
|
||||
{
|
||||
if (!dev->dma_ops)
|
||||
dev->dma_ops = &swiotlb_dma_ops;
|
||||
|
||||
dev->dma_coherent = coherent;
|
||||
__iommu_setup_dma_ops(dev, dma_base, size, iommu);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ config C6X
|
||||
select ARCH_HAS_SYNC_DMA_FOR_CPU
|
||||
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
|
||||
select CLKDEV_LOOKUP
|
||||
select DMA_DIRECT_OPS
|
||||
select GENERIC_ATOMIC64
|
||||
select GENERIC_IRQ_SHOW
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
|
||||
@@ -78,6 +78,7 @@ static void __free_dma_pages(u32 addr, int order)
|
||||
void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
|
||||
gfp_t gfp, unsigned long attrs)
|
||||
{
|
||||
void *ret;
|
||||
u32 paddr;
|
||||
int order;
|
||||
|
||||
@@ -94,7 +95,9 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
|
||||
if (!paddr)
|
||||
return NULL;
|
||||
|
||||
return phys_to_virt(paddr);
|
||||
ret = phys_to_virt(paddr);
|
||||
memset(ret, 0, 1 << order);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user