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.
Signed-off-by: Timur Tabi <[email protected]>
---
My other patch, "Add alloc_pages_exact() and free_pages_exact()", must be
applied first, otherwise drivers/video/fsl-diu-fb.c will not compile.
drivers/video/fsl-diu-fb.c | 59 +++++++++++++++----------------------------
1 files changed, 21 insertions(+), 38 deletions(-)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 0a27853..d15d265 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -279,58 +279,41 @@ static struct diu_hw dr = {
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
- * very large memory (more than 4MB). We don't want to allocate all memory
- * in rheap since small memory allocation/deallocation will fragment the
- * rheap and make the furture large allocation fail.
+/**
+ * fsl_diu_alloc - allocate memory for the DIU
+ * @size: number of bytes to allocate
+ * @param: returned physical address of memory
+ *
+ * This function allocates a physically-contiguous block of memory.
*/
-
-void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
+static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
{
void *virt;
- pr_debug("size=%lu\n", size);
+ pr_debug("size=%u\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) {
*phys = virt_to_phys(virt);
- pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys);
- return virt;
- }
- 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("virt=%p, phys=%llx\n", virt, (uint64_t) *phys);
}
- pr_debug("rh virt=%p phys=%lx\n", virt, *phys);
-
return virt;
}
-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=%u\n", virt, size);
- if (!p)
- return;
-
- 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));
- }
+ if (virt && size)
+ free_pages_exact(virt, size);
}
static int fsl_diu_enable_panel(struct fb_info *info)
--
1.5.5
On Tue, 24 Jun 2008 11:44:13 -0500
Timur Tabi <[email protected]> wrote:
> 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.
>
> Signed-off-by: Timur Tabi <[email protected]>
> ---
>
> My other patch, "Add alloc_pages_exact() and free_pages_exact()", must be
> applied first, otherwise drivers/video/fsl-diu-fb.c will not compile.
>
> drivers/video/fsl-diu-fb.c | 59 +++++++++++++++----------------------------
> 1 files changed, 21 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> index 0a27853..d15d265 100644
> --- a/drivers/video/fsl-diu-fb.c
> +++ b/drivers/video/fsl-diu-fb.c
> @@ -279,58 +279,41 @@ static struct diu_hw dr = {
>
> 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
> - * very large memory (more than 4MB). We don't want to allocate all memory
> - * in rheap since small memory allocation/deallocation will fragment the
> - * rheap and make the furture large allocation fail.
> +/**
> + * fsl_diu_alloc - allocate memory for the DIU
> + * @size: number of bytes to allocate
> + * @param: returned physical address of memory
> + *
> + * This function allocates a physically-contiguous block of memory.
> */
> -
> -void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
> +static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
> {
> void *virt;
>
> - pr_debug("size=%lu\n", size);
> + pr_debug("size=%u\n", size);
Nope, this will generate warnings on some architectures.
The way to print a size_t is with %zu or %zd. I guess the latter is for
ssize_t.
> - virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size));
> + virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
> if (virt) {
> *phys = virt_to_phys(virt);
> - pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys);
> - return virt;
> - }
> - 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("virt=%p, phys=%llx\n", virt, (uint64_t) *phys);
This is also incorrect. We cannot pass u64 or uint64_t into printk at
all. We do not know what type the architectures uses to implement
them. It should be cast to a known type. In this case `unsigned long
long'.
On Jun 30, 2008, at 4:24 PM, Andrew Morton wrote:
> This is also incorrect. We cannot pass u64 or uint64_t into printk at
> all. We do not know what type the architectures uses to implement
> them. It should be cast to a known type. In this case `unsigned long
> long'.
Ok, I'll fix these, but I'm on vacation now and won't get to it for
another 10 days.