lkml.org 
[lkml]   [2010]   [Apr]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] NOMMU: Work around the lack of vmap()/vunmap() in firmware_loading_store() [ver #2]
    Date
    Work around the lack of vmap()/vunmap() in firmware_loading_store() when
    operating in NOMMU mode. vmap() cannot be implemented as there's no virtual
    mapping available.

    Instead, in NOMMU mode, make available a function (vcoalesce()) that can
    coalesce the supplied data into one big buffer and store as the address vmap()
    would've returned.

    This can be #defined to vmap() in NOMMU mode by interested parties.

    Signed-off-by: David Howells <dhowells@redhat.com>
    ---

    drivers/base/firmware_class.c | 8 ++++++++
    include/linux/vmalloc.h | 1 +
    mm/nommu.c | 24 ++++++++++++++++++++++++
    3 files changed, 33 insertions(+), 0 deletions(-)


    diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
    index 985da11..be71e54 100644
    --- a/drivers/base/firmware_class.c
    +++ b/drivers/base/firmware_class.c
    @@ -60,6 +60,14 @@ static struct builtin_fw *__start_builtin_fw;
    static struct builtin_fw *__end_builtin_fw;
    #endif

    +/*
    + * NOMMU mode can't provide vmap() as there's no MMU to do the virtual mapping.
    + * Coalesce the data into a big buffer instead.
    + */
    +#ifndef CONFIG_MMU
    +#define vmap(pg, c, f, pr) vcoalesce(pg, c, f, pr)
    +#endif
    +
    static void
    fw_load_abort(struct firmware_priv *fw_priv)
    {
    diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
    index 227c2a5..f36a4b2 100644
    --- a/include/linux/vmalloc.h
    +++ b/include/linux/vmalloc.h
    @@ -48,6 +48,7 @@ extern void __init vmalloc_init(void);
    static inline void vmalloc_init(void)
    {
    }
    +extern void *vcoalesce(struct page **, unsigned int, unsigned long, pgprot_t);
    #endif

    extern void *vmalloc(unsigned long size);
    diff --git a/mm/nommu.c b/mm/nommu.c
    index 63fa17d..05a5c63 100644
    --- a/mm/nommu.c
    +++ b/mm/nommu.c
    @@ -405,6 +405,30 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
    EXPORT_SYMBOL(vm_insert_page);

    /*
    + * NOMMU mode can't provide vmap() as there's no MMU to do the virtual mapping.
    + * Provide a facility to coalesce the data into a big buffer instead.
    + */
    +void *vcoalesce(struct page **pages, unsigned int count,
    + unsigned long flags, pgprot_t prot)
    +{
    + unsigned int i;
    + void *new_map, *page_data;
    +
    + new_map = kmalloc(count << PAGE_SHIFT, GFP_KERNEL);
    + if (!new_map)
    + return NULL;
    +
    + for (i = 0; i < count; ++i) {
    + page_data = kmap(pages[i]);
    + memcpy(new_map + (i << PAGE_SHIFT), page_data, PAGE_SIZE);
    + kunmap(page_data);
    + }
    +
    + return new_map;
    +}
    +EXPORT_SYMBOL(vcoalesce);
    +
    +/*
    * sys_brk() for the most part doesn't need the global kernel
    * lock, except when an application is doing something nasty
    * like trying to un-brk an area that has already been mapped


    \
     
     \ /
      Last update: 2010-04-08 15:53    [W:0.046 / U:0.220 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site