1/*
2 *  PowerPC version derived from arch/arm/mm/consistent.c
3 *    Copyright (C) 2001 Dan Malek (dmalek@jlc.net)
4 *
5 *  Copyright (C) 2000 Russell King
6 *
7 * Consistent memory allocators.  Used for DMA devices that want to
8 * share uncached memory with the processor core.  The function return
9 * is the virtual address and 'dma_handle' is the physical address.
10 * Mostly stolen from the ARM port, with some changes for PowerPC.
11 *						-- Dan
12 *
13 * Reorganized to get rid of the arch-specific consistent_* functions
14 * and provide non-coherent implementations for the DMA API. -Matt
15 *
16 * Added in_interrupt() safe dma_alloc_coherent()/dma_free_coherent()
17 * implementation. This is pulled straight from ARM and barely
18 * modified. -Matt
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2 as
22 * published by the Free Software Foundation.
23 */
24
25#include <linux/sched.h>
26#include <linux/kernel.h>
27#include <linux/errno.h>
28#include <linux/string.h>
29#include <linux/types.h>
30#include <linux/highmem.h>
31#include <linux/dma-mapping.h>
32
33#include <asm/tlbflush.h>
34
35/*
36 * This address range defaults to a value that is safe for all
37 * platforms which currently set CONFIG_NOT_COHERENT_CACHE. It
38 * can be further configured for specific applications under
39 * the "Advanced Setup" menu. -Matt
40 */
41#define CONSISTENT_BASE	(CONFIG_CONSISTENT_START)
42#define CONSISTENT_END	(CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
43#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
44
45/*
46 * This is the page table (2MB) covering uncached, DMA consistent allocations
47 */
48static pte_t *consistent_pte;
49static DEFINE_SPINLOCK(consistent_lock);
50
51/*
52 * VM region handling support.
53 *
54 * This should become something generic, handling VM region allocations for
55 * vmalloc and similar (ioremap, module space, etc).
56 *
57 * I envisage vmalloc()'s supporting vm_struct becoming:
58 *
59 *  struct vm_struct {
60 *    struct vm_region	region;
61 *    unsigned long	flags;
62 *    struct page	**pages;
63 *    unsigned int	nr_pages;
64 *    unsigned long	phys_addr;
65 *  };
66 *
67 * get_vm_area() would then call vm_region_alloc with an appropriate
68 * struct vm_region head (eg):
69 *
70 *  struct vm_region vmalloc_head = {
71 *	.vm_list	= LIST_HEAD_INIT(vmalloc_head.vm_list),
72 *	.vm_start	= VMALLOC_START,
73 *	.vm_end		= VMALLOC_END,
74 *  };
75 *
76 * However, vmalloc_head.vm_start is variable (typically, it is dependent on
77 * the amount of RAM found at boot time.)  I would imagine that get_vm_area()
78 * would have to initialise this each time prior to calling vm_region_alloc().
79 */
80struct vm_region {
81	struct list_head	vm_list;
82	unsigned long		vm_start;
83	unsigned long		vm_end;
84};
85
86static struct vm_region consistent_head = {
87	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
88	.vm_start	= CONSISTENT_BASE,
89	.vm_end		= CONSISTENT_END,
90};
91
92static struct vm_region *
93vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
94{
95	unsigned long addr = head->vm_start, end = head->vm_end - size;
96	unsigned long flags;
97	struct vm_region *c, *new;
98
99	new = kmalloc(sizeof(struct vm_region), gfp);
100	if (!new)
101		goto out;
102
103	spin_lock_irqsave(&consistent_lock, flags);
104
105	list_for_each_entry(c, &head->vm_list, vm_list) {
106		if ((addr + size) < addr)
107			goto nospc;
108		if ((addr + size) <= c->vm_start)
109			goto found;
110		addr = c->vm_end;
111		if (addr > end)
112			goto nospc;
113	}
114
115 found:
116	/*
117	 * Insert this entry _before_ the one we found.
118	 */
119	list_add_tail(&new->vm_list, &c->vm_list);
120	new->vm_start = addr;
121	new->vm_end = addr + size;
122
123	spin_unlock_irqrestore(&consistent_lock, flags);
124	return new;
125
126 nospc:
127	spin_unlock_irqrestore(&consistent_lock, flags);
128	kfree(new);
129 out:
130	return NULL;
131}
132
133static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr)
134{
135	struct vm_region *c;
136
137	list_for_each_entry(c, &head->vm_list, vm_list) {
138		if (c->vm_start == addr)
139			goto out;
140	}
141	c = NULL;
142 out:
143	return c;
144}
145
146/*
147 * Allocate DMA-coherent memory space and return both the kernel remapped
148 * virtual and bus address for that space.
149 */
150void *
151__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
152{
153	struct page *page;
154	struct vm_region *c;
155	unsigned long order;
156	u64 mask = 0x00ffffff, limit; /* ISA default */
157
158	if (!consistent_pte) {
159		printk(KERN_ERR "%s: not initialised\n", __func__);
160		dump_stack();
161		return NULL;
162	}
163
164	size = PAGE_ALIGN(size);
165	limit = (mask + 1) & ~mask;
166	if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) {
167		printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n",
168		       size, mask);
169		return NULL;
170	}
171
172	order = get_order(size);
173
174	if (mask != 0xffffffff)
175		gfp |= GFP_DMA;
176
177	page = alloc_pages(gfp, order);
178	if (!page)
179		goto no_page;
180
181	/*
182	 * Invalidate any data that might be lurking in the
183	 * kernel direct-mapped region for device DMA.
184	 */
185	{
186		unsigned long kaddr = (unsigned long)page_address(page);
187		memset(page_address(page), 0, size);
188		flush_dcache_range(kaddr, kaddr + size);
189	}
190
191	/*
192	 * Allocate a virtual address in the consistent mapping region.
193	 */
194	c = vm_region_alloc(&consistent_head, size,
195			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
196	if (c) {
197		unsigned long vaddr = c->vm_start;
198		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
199		struct page *end = page + (1 << order);
200
201		split_page(page, order);
202
203		/*
204		 * Set the "dma handle"
205		 */
206		*handle = page_to_bus(page);
207
208		do {
209			BUG_ON(!pte_none(*pte));
210
211			SetPageReserved(page);
212			set_pte_at(&init_mm, vaddr,
213				   pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
214			page++;
215			pte++;
216			vaddr += PAGE_SIZE;
217		} while (size -= PAGE_SIZE);
218
219		/*
220		 * Free the otherwise unused pages.
221		 */
222		while (page < end) {
223			__free_page(page);
224			page++;
225		}
226
227		return (void *)c->vm_start;
228	}
229
230	if (page)
231		__free_pages(page, order);
232 no_page:
233	return NULL;
234}
235EXPORT_SYMBOL(__dma_alloc_coherent);
236
237/*
238 * free a page as defined by the above mapping.
239 */
240void __dma_free_coherent(size_t size, void *vaddr)
241{
242	struct vm_region *c;
243	unsigned long flags, addr;
244	pte_t *ptep;
245
246	size = PAGE_ALIGN(size);
247
248	spin_lock_irqsave(&consistent_lock, flags);
249
250	c = vm_region_find(&consistent_head, (unsigned long)vaddr);
251	if (!c)
252		goto no_area;
253
254	if ((c->vm_end - c->vm_start) != size) {
255		printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
256		       __func__, c->vm_end - c->vm_start, size);
257		dump_stack();
258		size = c->vm_end - c->vm_start;
259	}
260
261	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
262	addr = c->vm_start;
263	do {
264		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
265		unsigned long pfn;
266
267		ptep++;
268		addr += PAGE_SIZE;
269
270		if (!pte_none(pte) && pte_present(pte)) {
271			pfn = pte_pfn(pte);
272
273			if (pfn_valid(pfn)) {
274				struct page *page = pfn_to_page(pfn);
275				ClearPageReserved(page);
276
277				__free_page(page);
278				continue;
279			}
280		}
281
282		printk(KERN_CRIT "%s: bad page in kernel page table\n",
283		       __func__);
284	} while (size -= PAGE_SIZE);
285
286	flush_tlb_kernel_range(c->vm_start, c->vm_end);
287
288	list_del(&c->vm_list);
289
290	spin_unlock_irqrestore(&consistent_lock, flags);
291
292	kfree(c);
293	return;
294
295 no_area:
296	spin_unlock_irqrestore(&consistent_lock, flags);
297	printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
298	       __func__, vaddr);
299	dump_stack();
300}
301EXPORT_SYMBOL(__dma_free_coherent);
302
303/*
304 * Initialise the consistent memory allocation.
305 */
306static int __init dma_alloc_init(void)
307{
308	pgd_t *pgd;
309	pud_t *pud;
310	pmd_t *pmd;
311	pte_t *pte;
312	int ret = 0;
313
314	do {
315		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
316		pud = pud_alloc(&init_mm, pgd, CONSISTENT_BASE);
317		pmd = pmd_alloc(&init_mm, pud, CONSISTENT_BASE);
318		if (!pmd) {
319			printk(KERN_ERR "%s: no pmd tables\n", __func__);
320			ret = -ENOMEM;
321			break;
322		}
323		WARN_ON(!pmd_none(*pmd));
324
325		pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
326		if (!pte) {
327			printk(KERN_ERR "%s: no pte tables\n", __func__);
328			ret = -ENOMEM;
329			break;
330		}
331
332		consistent_pte = pte;
333	} while (0);
334
335	return ret;
336}
337
338core_initcall(dma_alloc_init);
339
340/*
341 * make an area consistent.
342 */
343void __dma_sync(void *vaddr, size_t size, int direction)
344{
345	unsigned long start = (unsigned long)vaddr;
346	unsigned long end   = start + size;
347
348	switch (direction) {
349	case DMA_NONE:
350		BUG();
351	case DMA_FROM_DEVICE:	/* invalidate only */
352		invalidate_dcache_range(start, end);
353		break;
354	case DMA_TO_DEVICE:		/* writeback only */
355		clean_dcache_range(start, end);
356		break;
357	case DMA_BIDIRECTIONAL:	/* writeback and invalidate */
358		flush_dcache_range(start, end);
359		break;
360	}
361}
362EXPORT_SYMBOL(__dma_sync);
363
364#ifdef CONFIG_HIGHMEM
365/*
366 * __dma_sync_page() implementation for systems using highmem.
367 * In this case, each page of a buffer must be kmapped/kunmapped
368 * in order to have a virtual address for __dma_sync(). This must
369 * not sleep so kmap_atomic()/kunmap_atomic() are used.
370 *
371 * Note: yes, it is possible and correct to have a buffer extend
372 * beyond the first page.
373 */
374static inline void __dma_sync_page_highmem(struct page *page,
375		unsigned long offset, size_t size, int direction)
376{
377	size_t seg_size = min((size_t)(PAGE_SIZE - offset), size);
378	size_t cur_size = seg_size;
379	unsigned long flags, start, seg_offset = offset;
380	int nr_segs = 1 + ((size - seg_size) + PAGE_SIZE - 1)/PAGE_SIZE;
381	int seg_nr = 0;
382
383	local_irq_save(flags);
384
385	do {
386		start = (unsigned long)kmap_atomic(page + seg_nr,
387				KM_PPC_SYNC_PAGE) + seg_offset;
388
389		/* Sync this buffer segment */
390		__dma_sync((void *)start, seg_size, direction);
391		kunmap_atomic((void *)start, KM_PPC_SYNC_PAGE);
392		seg_nr++;
393
394		/* Calculate next buffer segment size */
395		seg_size = min((size_t)PAGE_SIZE, size - cur_size);
396
397		/* Add the segment size to our running total */
398		cur_size += seg_size;
399		seg_offset = 0;
400	} while (seg_nr < nr_segs);
401
402	local_irq_restore(flags);
403}
404#endif /* CONFIG_HIGHMEM */
405
406/*
407 * __dma_sync_page makes memory consistent. identical to __dma_sync, but
408 * takes a struct page instead of a virtual address
409 */
410void __dma_sync_page(struct page *page, unsigned long offset,
411	size_t size, int direction)
412{
413#ifdef CONFIG_HIGHMEM
414	__dma_sync_page_highmem(page, offset, size, direction);
415#else
416	unsigned long start = (unsigned long)page_address(page) + offset;
417	__dma_sync((void *)start, size, direction);
418#endif
419}
420EXPORT_SYMBOL(__dma_sync_page);
421