fsl-diu-fb: update Freescale DIU driver to use page_alloc_exact()

Update the Freescale DIU driver to use page_alloc_exact() to allocate a
DMA buffer.  This also eliminates the rheap-based memory allocator.  We
can do this now because commit 6ccf61f9 allows us to allocate 8MB
physically- contiguous memory blocks.

[akpm@linux-foundation.org: fix printk warnings]
Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Timur Tabi 2008-07-23 21:31:39 -07:00 committed by Linus Torvalds
parent c25826a7cf
commit 6b51d51a9d
1 changed files with 22 additions and 38 deletions

View File

@ -279,58 +279,42 @@ static struct diu_hw dr = {
static struct diu_pool pool; static struct diu_pool pool;
/* To allocate memory for framebuffer. First try __get_free_pages(). If it /**
* fails, try rh_alloc. The reason is __get_free_pages() cannot allocate * fsl_diu_alloc - allocate memory for the DIU
* very large memory (more than 4MB). We don't want to allocate all memory * @size: number of bytes to allocate
* in rheap since small memory allocation/deallocation will fragment the * @param: returned physical address of memory
* rheap and make the furture large allocation fail. *
* This function allocates a physically-contiguous block of memory.
*/ */
static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
{ {
void *virt; void *virt;
pr_debug("size=%lu\n", size); pr_debug("size=%zu\n", size);
virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size)); virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
if (virt) { if (virt) {
*phys = virt_to_phys(virt); *phys = virt_to_phys(virt);
pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys); pr_debug("virt=%p phys=%llx\n", virt,
return virt; (unsigned long long)*phys);
} }
if (!diu_ops.diu_mem) {
printk(KERN_INFO "%s: no diu_mem."
" To reserve more memory, put 'diufb=15M' "
"in the command line\n", __func__);
return NULL;
}
virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU");
if (virt) {
*phys = virt_to_bus(virt);
memset(virt, 0, size);
}
pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys);
return virt; return virt;
} }
static void fsl_diu_free(void *p, unsigned long size) /**
* fsl_diu_free - release DIU memory
* @virt: pointer returned by fsl_diu_alloc()
* @size: number of bytes allocated by fsl_diu_alloc()
*
* This function releases memory allocated by fsl_diu_alloc().
*/
static void fsl_diu_free(void *virt, size_t size)
{ {
pr_debug("p=%p size=%lu\n", p, size); pr_debug("virt=%p size=%zu\n", virt, size);
if (!p) if (virt && size)
return; free_pages_exact(virt, size);
if ((p >= diu_ops.diu_mem) &&
(p < (diu_ops.diu_mem + diu_ops.diu_size))) {
pr_debug("rh\n");
rh_free(&diu_ops.diu_rh_info, (unsigned long) p);
} else {
pr_debug("dma\n");
free_pages((unsigned long)p, get_order(size));
}
} }
static int fsl_diu_enable_panel(struct fb_info *info) static int fsl_diu_enable_panel(struct fb_info *info)