xref: /openbmc/linux/kernel/dma/mapping.c (revision 58b0440663ec11372befb8ead0ee7099d8878590)
1cf65a0f6SChristoph Hellwig // SPDX-License-Identifier: GPL-2.0
2cf65a0f6SChristoph Hellwig /*
3cf65a0f6SChristoph Hellwig  * arch-independent dma-mapping routines
4cf65a0f6SChristoph Hellwig  *
5cf65a0f6SChristoph Hellwig  * Copyright (c) 2006  SUSE Linux Products GmbH
6cf65a0f6SChristoph Hellwig  * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
7cf65a0f6SChristoph Hellwig  */
8cf65a0f6SChristoph Hellwig 
9cf65a0f6SChristoph Hellwig #include <linux/acpi.h>
10*58b04406SChristoph Hellwig #include <linux/dma-noncoherent.h>
11cf65a0f6SChristoph Hellwig #include <linux/export.h>
12cf65a0f6SChristoph Hellwig #include <linux/gfp.h>
13cf65a0f6SChristoph Hellwig #include <linux/of_device.h>
14cf65a0f6SChristoph Hellwig #include <linux/slab.h>
15cf65a0f6SChristoph Hellwig #include <linux/vmalloc.h>
16cf65a0f6SChristoph Hellwig 
17cf65a0f6SChristoph Hellwig /*
18cf65a0f6SChristoph Hellwig  * Managed DMA API
19cf65a0f6SChristoph Hellwig  */
20cf65a0f6SChristoph Hellwig struct dma_devres {
21cf65a0f6SChristoph Hellwig 	size_t		size;
22cf65a0f6SChristoph Hellwig 	void		*vaddr;
23cf65a0f6SChristoph Hellwig 	dma_addr_t	dma_handle;
24cf65a0f6SChristoph Hellwig 	unsigned long	attrs;
25cf65a0f6SChristoph Hellwig };
26cf65a0f6SChristoph Hellwig 
27cf65a0f6SChristoph Hellwig static void dmam_release(struct device *dev, void *res)
28cf65a0f6SChristoph Hellwig {
29cf65a0f6SChristoph Hellwig 	struct dma_devres *this = res;
30cf65a0f6SChristoph Hellwig 
31cf65a0f6SChristoph Hellwig 	dma_free_attrs(dev, this->size, this->vaddr, this->dma_handle,
32cf65a0f6SChristoph Hellwig 			this->attrs);
33cf65a0f6SChristoph Hellwig }
34cf65a0f6SChristoph Hellwig 
35cf65a0f6SChristoph Hellwig static int dmam_match(struct device *dev, void *res, void *match_data)
36cf65a0f6SChristoph Hellwig {
37cf65a0f6SChristoph Hellwig 	struct dma_devres *this = res, *match = match_data;
38cf65a0f6SChristoph Hellwig 
39cf65a0f6SChristoph Hellwig 	if (this->vaddr == match->vaddr) {
40cf65a0f6SChristoph Hellwig 		WARN_ON(this->size != match->size ||
41cf65a0f6SChristoph Hellwig 			this->dma_handle != match->dma_handle);
42cf65a0f6SChristoph Hellwig 		return 1;
43cf65a0f6SChristoph Hellwig 	}
44cf65a0f6SChristoph Hellwig 	return 0;
45cf65a0f6SChristoph Hellwig }
46cf65a0f6SChristoph Hellwig 
47cf65a0f6SChristoph Hellwig /**
48cf65a0f6SChristoph Hellwig  * dmam_alloc_coherent - Managed dma_alloc_coherent()
49cf65a0f6SChristoph Hellwig  * @dev: Device to allocate coherent memory for
50cf65a0f6SChristoph Hellwig  * @size: Size of allocation
51cf65a0f6SChristoph Hellwig  * @dma_handle: Out argument for allocated DMA handle
52cf65a0f6SChristoph Hellwig  * @gfp: Allocation flags
53cf65a0f6SChristoph Hellwig  *
54cf65a0f6SChristoph Hellwig  * Managed dma_alloc_coherent().  Memory allocated using this function
55cf65a0f6SChristoph Hellwig  * will be automatically released on driver detach.
56cf65a0f6SChristoph Hellwig  *
57cf65a0f6SChristoph Hellwig  * RETURNS:
58cf65a0f6SChristoph Hellwig  * Pointer to allocated memory on success, NULL on failure.
59cf65a0f6SChristoph Hellwig  */
60cf65a0f6SChristoph Hellwig void *dmam_alloc_coherent(struct device *dev, size_t size,
61cf65a0f6SChristoph Hellwig 			   dma_addr_t *dma_handle, gfp_t gfp)
62cf65a0f6SChristoph Hellwig {
63cf65a0f6SChristoph Hellwig 	struct dma_devres *dr;
64cf65a0f6SChristoph Hellwig 	void *vaddr;
65cf65a0f6SChristoph Hellwig 
66cf65a0f6SChristoph Hellwig 	dr = devres_alloc(dmam_release, sizeof(*dr), gfp);
67cf65a0f6SChristoph Hellwig 	if (!dr)
68cf65a0f6SChristoph Hellwig 		return NULL;
69cf65a0f6SChristoph Hellwig 
70cf65a0f6SChristoph Hellwig 	vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp);
71cf65a0f6SChristoph Hellwig 	if (!vaddr) {
72cf65a0f6SChristoph Hellwig 		devres_free(dr);
73cf65a0f6SChristoph Hellwig 		return NULL;
74cf65a0f6SChristoph Hellwig 	}
75cf65a0f6SChristoph Hellwig 
76cf65a0f6SChristoph Hellwig 	dr->vaddr = vaddr;
77cf65a0f6SChristoph Hellwig 	dr->dma_handle = *dma_handle;
78cf65a0f6SChristoph Hellwig 	dr->size = size;
79cf65a0f6SChristoph Hellwig 
80cf65a0f6SChristoph Hellwig 	devres_add(dev, dr);
81cf65a0f6SChristoph Hellwig 
82cf65a0f6SChristoph Hellwig 	return vaddr;
83cf65a0f6SChristoph Hellwig }
84cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dmam_alloc_coherent);
85cf65a0f6SChristoph Hellwig 
86cf65a0f6SChristoph Hellwig /**
87cf65a0f6SChristoph Hellwig  * dmam_free_coherent - Managed dma_free_coherent()
88cf65a0f6SChristoph Hellwig  * @dev: Device to free coherent memory for
89cf65a0f6SChristoph Hellwig  * @size: Size of allocation
90cf65a0f6SChristoph Hellwig  * @vaddr: Virtual address of the memory to free
91cf65a0f6SChristoph Hellwig  * @dma_handle: DMA handle of the memory to free
92cf65a0f6SChristoph Hellwig  *
93cf65a0f6SChristoph Hellwig  * Managed dma_free_coherent().
94cf65a0f6SChristoph Hellwig  */
95cf65a0f6SChristoph Hellwig void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
96cf65a0f6SChristoph Hellwig 			dma_addr_t dma_handle)
97cf65a0f6SChristoph Hellwig {
98cf65a0f6SChristoph Hellwig 	struct dma_devres match_data = { size, vaddr, dma_handle };
99cf65a0f6SChristoph Hellwig 
100cf65a0f6SChristoph Hellwig 	dma_free_coherent(dev, size, vaddr, dma_handle);
101cf65a0f6SChristoph Hellwig 	WARN_ON(devres_destroy(dev, dmam_release, dmam_match, &match_data));
102cf65a0f6SChristoph Hellwig }
103cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dmam_free_coherent);
104cf65a0f6SChristoph Hellwig 
105cf65a0f6SChristoph Hellwig /**
106cf65a0f6SChristoph Hellwig  * dmam_alloc_attrs - Managed dma_alloc_attrs()
107cf65a0f6SChristoph Hellwig  * @dev: Device to allocate non_coherent memory for
108cf65a0f6SChristoph Hellwig  * @size: Size of allocation
109cf65a0f6SChristoph Hellwig  * @dma_handle: Out argument for allocated DMA handle
110cf65a0f6SChristoph Hellwig  * @gfp: Allocation flags
111cf65a0f6SChristoph Hellwig  * @attrs: Flags in the DMA_ATTR_* namespace.
112cf65a0f6SChristoph Hellwig  *
113cf65a0f6SChristoph Hellwig  * Managed dma_alloc_attrs().  Memory allocated using this function will be
114cf65a0f6SChristoph Hellwig  * automatically released on driver detach.
115cf65a0f6SChristoph Hellwig  *
116cf65a0f6SChristoph Hellwig  * RETURNS:
117cf65a0f6SChristoph Hellwig  * Pointer to allocated memory on success, NULL on failure.
118cf65a0f6SChristoph Hellwig  */
119cf65a0f6SChristoph Hellwig void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
120cf65a0f6SChristoph Hellwig 		gfp_t gfp, unsigned long attrs)
121cf65a0f6SChristoph Hellwig {
122cf65a0f6SChristoph Hellwig 	struct dma_devres *dr;
123cf65a0f6SChristoph Hellwig 	void *vaddr;
124cf65a0f6SChristoph Hellwig 
125cf65a0f6SChristoph Hellwig 	dr = devres_alloc(dmam_release, sizeof(*dr), gfp);
126cf65a0f6SChristoph Hellwig 	if (!dr)
127cf65a0f6SChristoph Hellwig 		return NULL;
128cf65a0f6SChristoph Hellwig 
129cf65a0f6SChristoph Hellwig 	vaddr = dma_alloc_attrs(dev, size, dma_handle, gfp, attrs);
130cf65a0f6SChristoph Hellwig 	if (!vaddr) {
131cf65a0f6SChristoph Hellwig 		devres_free(dr);
132cf65a0f6SChristoph Hellwig 		return NULL;
133cf65a0f6SChristoph Hellwig 	}
134cf65a0f6SChristoph Hellwig 
135cf65a0f6SChristoph Hellwig 	dr->vaddr = vaddr;
136cf65a0f6SChristoph Hellwig 	dr->dma_handle = *dma_handle;
137cf65a0f6SChristoph Hellwig 	dr->size = size;
138cf65a0f6SChristoph Hellwig 	dr->attrs = attrs;
139cf65a0f6SChristoph Hellwig 
140cf65a0f6SChristoph Hellwig 	devres_add(dev, dr);
141cf65a0f6SChristoph Hellwig 
142cf65a0f6SChristoph Hellwig 	return vaddr;
143cf65a0f6SChristoph Hellwig }
144cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dmam_alloc_attrs);
145cf65a0f6SChristoph Hellwig 
146cf65a0f6SChristoph Hellwig #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
147cf65a0f6SChristoph Hellwig 
148cf65a0f6SChristoph Hellwig static void dmam_coherent_decl_release(struct device *dev, void *res)
149cf65a0f6SChristoph Hellwig {
150cf65a0f6SChristoph Hellwig 	dma_release_declared_memory(dev);
151cf65a0f6SChristoph Hellwig }
152cf65a0f6SChristoph Hellwig 
153cf65a0f6SChristoph Hellwig /**
154cf65a0f6SChristoph Hellwig  * dmam_declare_coherent_memory - Managed dma_declare_coherent_memory()
155cf65a0f6SChristoph Hellwig  * @dev: Device to declare coherent memory for
156cf65a0f6SChristoph Hellwig  * @phys_addr: Physical address of coherent memory to be declared
157cf65a0f6SChristoph Hellwig  * @device_addr: Device address of coherent memory to be declared
158cf65a0f6SChristoph Hellwig  * @size: Size of coherent memory to be declared
159cf65a0f6SChristoph Hellwig  * @flags: Flags
160cf65a0f6SChristoph Hellwig  *
161cf65a0f6SChristoph Hellwig  * Managed dma_declare_coherent_memory().
162cf65a0f6SChristoph Hellwig  *
163cf65a0f6SChristoph Hellwig  * RETURNS:
164cf65a0f6SChristoph Hellwig  * 0 on success, -errno on failure.
165cf65a0f6SChristoph Hellwig  */
166cf65a0f6SChristoph Hellwig int dmam_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
167cf65a0f6SChristoph Hellwig 				 dma_addr_t device_addr, size_t size, int flags)
168cf65a0f6SChristoph Hellwig {
169cf65a0f6SChristoph Hellwig 	void *res;
170cf65a0f6SChristoph Hellwig 	int rc;
171cf65a0f6SChristoph Hellwig 
172cf65a0f6SChristoph Hellwig 	res = devres_alloc(dmam_coherent_decl_release, 0, GFP_KERNEL);
173cf65a0f6SChristoph Hellwig 	if (!res)
174cf65a0f6SChristoph Hellwig 		return -ENOMEM;
175cf65a0f6SChristoph Hellwig 
176cf65a0f6SChristoph Hellwig 	rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size,
177cf65a0f6SChristoph Hellwig 					 flags);
178cf65a0f6SChristoph Hellwig 	if (!rc)
179cf65a0f6SChristoph Hellwig 		devres_add(dev, res);
180cf65a0f6SChristoph Hellwig 	else
181cf65a0f6SChristoph Hellwig 		devres_free(res);
182cf65a0f6SChristoph Hellwig 
183cf65a0f6SChristoph Hellwig 	return rc;
184cf65a0f6SChristoph Hellwig }
185cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dmam_declare_coherent_memory);
186cf65a0f6SChristoph Hellwig 
187cf65a0f6SChristoph Hellwig /**
188cf65a0f6SChristoph Hellwig  * dmam_release_declared_memory - Managed dma_release_declared_memory().
189cf65a0f6SChristoph Hellwig  * @dev: Device to release declared coherent memory for
190cf65a0f6SChristoph Hellwig  *
191cf65a0f6SChristoph Hellwig  * Managed dmam_release_declared_memory().
192cf65a0f6SChristoph Hellwig  */
193cf65a0f6SChristoph Hellwig void dmam_release_declared_memory(struct device *dev)
194cf65a0f6SChristoph Hellwig {
195cf65a0f6SChristoph Hellwig 	WARN_ON(devres_destroy(dev, dmam_coherent_decl_release, NULL, NULL));
196cf65a0f6SChristoph Hellwig }
197cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dmam_release_declared_memory);
198cf65a0f6SChristoph Hellwig 
199cf65a0f6SChristoph Hellwig #endif
200cf65a0f6SChristoph Hellwig 
201cf65a0f6SChristoph Hellwig /*
202cf65a0f6SChristoph Hellwig  * Create scatter-list for the already allocated DMA buffer.
203cf65a0f6SChristoph Hellwig  */
204cf65a0f6SChristoph Hellwig int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
205cf65a0f6SChristoph Hellwig 		 void *cpu_addr, dma_addr_t handle, size_t size)
206cf65a0f6SChristoph Hellwig {
207cf65a0f6SChristoph Hellwig 	struct page *page = virt_to_page(cpu_addr);
208cf65a0f6SChristoph Hellwig 	int ret;
209cf65a0f6SChristoph Hellwig 
210cf65a0f6SChristoph Hellwig 	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
211cf65a0f6SChristoph Hellwig 	if (unlikely(ret))
212cf65a0f6SChristoph Hellwig 		return ret;
213cf65a0f6SChristoph Hellwig 
214cf65a0f6SChristoph Hellwig 	sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
215cf65a0f6SChristoph Hellwig 	return 0;
216cf65a0f6SChristoph Hellwig }
217cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dma_common_get_sgtable);
218cf65a0f6SChristoph Hellwig 
219cf65a0f6SChristoph Hellwig /*
220cf65a0f6SChristoph Hellwig  * Create userspace mapping for the DMA-coherent memory.
221cf65a0f6SChristoph Hellwig  */
222cf65a0f6SChristoph Hellwig int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
223*58b04406SChristoph Hellwig 		void *cpu_addr, dma_addr_t dma_addr, size_t size,
224*58b04406SChristoph Hellwig 		unsigned long attrs)
225cf65a0f6SChristoph Hellwig {
226cf65a0f6SChristoph Hellwig #ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
227cf65a0f6SChristoph Hellwig 	unsigned long user_count = vma_pages(vma);
228cf65a0f6SChristoph Hellwig 	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
229cf65a0f6SChristoph Hellwig 	unsigned long off = vma->vm_pgoff;
230*58b04406SChristoph Hellwig 	unsigned long pfn;
231*58b04406SChristoph Hellwig 	int ret = -ENXIO;
232cf65a0f6SChristoph Hellwig 
233*58b04406SChristoph Hellwig 	vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
234cf65a0f6SChristoph Hellwig 
235cf65a0f6SChristoph Hellwig 	if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
236cf65a0f6SChristoph Hellwig 		return ret;
237cf65a0f6SChristoph Hellwig 
238*58b04406SChristoph Hellwig 	if (off >= count || user_count > count - off)
239*58b04406SChristoph Hellwig 		return -ENXIO;
240cf65a0f6SChristoph Hellwig 
241*58b04406SChristoph Hellwig 	if (!dev_is_dma_coherent(dev)) {
242*58b04406SChristoph Hellwig 		if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
243*58b04406SChristoph Hellwig 			return -ENXIO;
244*58b04406SChristoph Hellwig 		pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
245*58b04406SChristoph Hellwig 	} else {
246*58b04406SChristoph Hellwig 		pfn = page_to_pfn(virt_to_page(cpu_addr));
247*58b04406SChristoph Hellwig 	}
248*58b04406SChristoph Hellwig 
249*58b04406SChristoph Hellwig 	return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
250*58b04406SChristoph Hellwig 			user_count << PAGE_SHIFT, vma->vm_page_prot);
251*58b04406SChristoph Hellwig #else
252*58b04406SChristoph Hellwig 	return -ENXIO;
253*58b04406SChristoph Hellwig #endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
254cf65a0f6SChristoph Hellwig }
255cf65a0f6SChristoph Hellwig EXPORT_SYMBOL(dma_common_mmap);
256cf65a0f6SChristoph Hellwig 
257cf65a0f6SChristoph Hellwig #ifdef CONFIG_MMU
258cf65a0f6SChristoph Hellwig static struct vm_struct *__dma_common_pages_remap(struct page **pages,
259cf65a0f6SChristoph Hellwig 			size_t size, unsigned long vm_flags, pgprot_t prot,
260cf65a0f6SChristoph Hellwig 			const void *caller)
261cf65a0f6SChristoph Hellwig {
262cf65a0f6SChristoph Hellwig 	struct vm_struct *area;
263cf65a0f6SChristoph Hellwig 
264cf65a0f6SChristoph Hellwig 	area = get_vm_area_caller(size, vm_flags, caller);
265cf65a0f6SChristoph Hellwig 	if (!area)
266cf65a0f6SChristoph Hellwig 		return NULL;
267cf65a0f6SChristoph Hellwig 
268cf65a0f6SChristoph Hellwig 	if (map_vm_area(area, prot, pages)) {
269cf65a0f6SChristoph Hellwig 		vunmap(area->addr);
270cf65a0f6SChristoph Hellwig 		return NULL;
271cf65a0f6SChristoph Hellwig 	}
272cf65a0f6SChristoph Hellwig 
273cf65a0f6SChristoph Hellwig 	return area;
274cf65a0f6SChristoph Hellwig }
275cf65a0f6SChristoph Hellwig 
276cf65a0f6SChristoph Hellwig /*
277cf65a0f6SChristoph Hellwig  * remaps an array of PAGE_SIZE pages into another vm_area
278cf65a0f6SChristoph Hellwig  * Cannot be used in non-sleeping contexts
279cf65a0f6SChristoph Hellwig  */
280cf65a0f6SChristoph Hellwig void *dma_common_pages_remap(struct page **pages, size_t size,
281cf65a0f6SChristoph Hellwig 			unsigned long vm_flags, pgprot_t prot,
282cf65a0f6SChristoph Hellwig 			const void *caller)
283cf65a0f6SChristoph Hellwig {
284cf65a0f6SChristoph Hellwig 	struct vm_struct *area;
285cf65a0f6SChristoph Hellwig 
286cf65a0f6SChristoph Hellwig 	area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller);
287cf65a0f6SChristoph Hellwig 	if (!area)
288cf65a0f6SChristoph Hellwig 		return NULL;
289cf65a0f6SChristoph Hellwig 
290cf65a0f6SChristoph Hellwig 	area->pages = pages;
291cf65a0f6SChristoph Hellwig 
292cf65a0f6SChristoph Hellwig 	return area->addr;
293cf65a0f6SChristoph Hellwig }
294cf65a0f6SChristoph Hellwig 
295cf65a0f6SChristoph Hellwig /*
296cf65a0f6SChristoph Hellwig  * remaps an allocated contiguous region into another vm_area.
297cf65a0f6SChristoph Hellwig  * Cannot be used in non-sleeping contexts
298cf65a0f6SChristoph Hellwig  */
299cf65a0f6SChristoph Hellwig 
300cf65a0f6SChristoph Hellwig void *dma_common_contiguous_remap(struct page *page, size_t size,
301cf65a0f6SChristoph Hellwig 			unsigned long vm_flags,
302cf65a0f6SChristoph Hellwig 			pgprot_t prot, const void *caller)
303cf65a0f6SChristoph Hellwig {
304cf65a0f6SChristoph Hellwig 	int i;
305cf65a0f6SChristoph Hellwig 	struct page **pages;
306cf65a0f6SChristoph Hellwig 	struct vm_struct *area;
307cf65a0f6SChristoph Hellwig 
308cf65a0f6SChristoph Hellwig 	pages = kmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL);
309cf65a0f6SChristoph Hellwig 	if (!pages)
310cf65a0f6SChristoph Hellwig 		return NULL;
311cf65a0f6SChristoph Hellwig 
312cf65a0f6SChristoph Hellwig 	for (i = 0; i < (size >> PAGE_SHIFT); i++)
313cf65a0f6SChristoph Hellwig 		pages[i] = nth_page(page, i);
314cf65a0f6SChristoph Hellwig 
315cf65a0f6SChristoph Hellwig 	area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller);
316cf65a0f6SChristoph Hellwig 
317cf65a0f6SChristoph Hellwig 	kfree(pages);
318cf65a0f6SChristoph Hellwig 
319cf65a0f6SChristoph Hellwig 	if (!area)
320cf65a0f6SChristoph Hellwig 		return NULL;
321cf65a0f6SChristoph Hellwig 	return area->addr;
322cf65a0f6SChristoph Hellwig }
323cf65a0f6SChristoph Hellwig 
324cf65a0f6SChristoph Hellwig /*
325cf65a0f6SChristoph Hellwig  * unmaps a range previously mapped by dma_common_*_remap
326cf65a0f6SChristoph Hellwig  */
327cf65a0f6SChristoph Hellwig void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags)
328cf65a0f6SChristoph Hellwig {
329cf65a0f6SChristoph Hellwig 	struct vm_struct *area = find_vm_area(cpu_addr);
330cf65a0f6SChristoph Hellwig 
331cf65a0f6SChristoph Hellwig 	if (!area || (area->flags & vm_flags) != vm_flags) {
332cf65a0f6SChristoph Hellwig 		WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
333cf65a0f6SChristoph Hellwig 		return;
334cf65a0f6SChristoph Hellwig 	}
335cf65a0f6SChristoph Hellwig 
336cf65a0f6SChristoph Hellwig 	unmap_kernel_range((unsigned long)cpu_addr, PAGE_ALIGN(size));
337cf65a0f6SChristoph Hellwig 	vunmap(cpu_addr);
338cf65a0f6SChristoph Hellwig }
339cf65a0f6SChristoph Hellwig #endif
340