linux-mips
[Top] [All Lists]

patch / rfc

To: "'linux-mips@linux-mips.org'" <linux-mips@linux-mips.org>
Subject: patch / rfc
From: Pete Popov <ppopov@embeddedalley.com>
Date: Thu, 25 Aug 2005 14:51:21 -0700
Organization: Embedded Alley Solutions, Inc
Original-recipient: rfc822;linux-mips@linux-mips.org
Reply-to: ppopov@embeddedalley.com
Sender: linux-mips-bounce@linux-mips.org
This is an experimental (though tested) patch for early ioremap support
on mips, before mem_init runs. Something like this is only needed on
certain SoCs that have all of their I/O on high addresses such that they
can't me ioremapped through kseg1.

I think the CONFIG_64 stuff needs to removed since we don't need it. The
patch was tested on a MIPS32 CPU only. Some of the significant changes:

- trap_init() became early_trap_init() since too much stuff happens
there that is needed to support early ioremap. The old trap_init() is
now empty.

- added plat_setup_late() call. All ports would need to add that call,
or at least a placeholder. Early ioremap is possible only at that point.
However, most of the code in each plat_setup() can be moved to
plat_setup_late()

diff -Naur --exclude=CVS linux-2.6-orig/arch/mips/kernel/setup.c 
linux-2.6-dev/arch/mips/kernel/setup.c
--- linux-2.6-orig/arch/mips/kernel/setup.c     2005-08-24 17:12:31.000000000 
-0700
+++ linux-2.6-dev/arch/mips/kernel/setup.c      2005-08-25 10:56:40.000000000 
-0700
@@ -42,7 +42,10 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/io.h>
 
+int init_bootmem_done;
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
 EXPORT_SYMBOL(cpu_data);
@@ -417,6 +420,8 @@
 
        /* Reserve the bootmap memory.  */
        reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
+
+       init_bootmem_done = 1;
 #endif /* CONFIG_SGI_IP27 */
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -511,7 +516,23 @@
 #undef MAXMEM
 #undef MAXMEM_PFN
 
+void __init early_ioremap_init(void)
+{
+#ifdef CONFIG_64BIT
+       ioremap_base = (VMALLOC_START + PTRS_PER_PGD * PTRS_PER_PMD * 
PTRS_PER_PTE * PAGE_SIZE);
+#else
+#ifdef CONFIG_HIGHMEM
+       ioremap_base = (PKMAP_BASE-2*PAGE_SIZE);
+#else
+       ioremap_base = (FIXADDR_START-2*PAGE_SIZE);
+#endif
+#endif /* CONFIG_64BIT */
+
+       ioremap_bot = ioremap_base;
+}
+
 extern void plat_setup(void);
+extern void plat_setup_late(void);
 
 void __init setup_arch(char **cmdline_p)
 {
@@ -540,6 +561,11 @@
        sparse_init();
        paging_init();
        resource_init();
+
+       early_trap_init();
+       early_ioremap_init();
+
+       plat_setup_late();      /* safe to do early ioremap */
 }
 
 int __init fpu_disable(char *s)
diff -Naur --exclude=CVS linux-2.6-orig/arch/mips/kernel/traps.c 
linux-2.6-dev/arch/mips/kernel/traps.c
--- linux-2.6-orig/arch/mips/kernel/traps.c     2005-08-24 17:12:32.000000000 
-0700
+++ linux-2.6-dev/arch/mips/kernel/traps.c      2005-08-25 00:39:39.000000000 
-0700
@@ -1239,6 +1238,10 @@
 
 void __init trap_init(void)
 {
+}
+
+void __init early_trap_init(void)
+{
        extern char except_vec3_generic, except_vec3_r4000;
        extern char except_vec4;
        unsigned long i;
diff -Naur --exclude=CVS linux-2.6-orig/arch/mips/mm/init.c 
linux-2.6-dev/arch/mips/mm/init.c
--- linux-2.6-orig/arch/mips/mm/init.c  2005-08-10 18:15:55.000000000 -0700
+++ linux-2.6-dev/arch/mips/mm/init.c   2005-08-25 00:39:40.000000000 -0700
@@ -47,6 +47,8 @@
  * don't have to care about aliases on other CPUs.
  */
 unsigned long empty_zero_page, zero_page_mask;
+int mem_init_done;
+extern int init_bootmem_done;
 
 /*
  * Not static inline because used by IP27 special magic initialization code
@@ -200,6 +202,17 @@
        return 0;
 }
 
+void __init *early_get_page(void)
+{
+       void *p;
+       if (init_bootmem_done) {
+               p = alloc_bootmem_pages(PAGE_SIZE);
+       } else {
+               p = NULL;
+       }
+       return p;
+}
+
 void __init mem_init(void)
 {
        unsigned long codesize, reservedpages, datasize, initsize;
@@ -258,6 +271,8 @@
               datasize >> 10,
               initsize >> 10,
               (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+
+       mem_init_done = 1;
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
diff -Naur --exclude=CVS linux-2.6-orig/arch/mips/mm/ioremap.c 
linux-2.6-dev/arch/mips/mm/ioremap.c
--- linux-2.6-orig/arch/mips/mm/ioremap.c       2005-08-10 18:15:55.000000000 
-0700
+++ linux-2.6-dev/arch/mips/mm/ioremap.c        2005-08-25 13:35:25.045624752 
-0700
@@ -15,6 +15,8 @@
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 
+extern int mem_init_done;
+
 static inline void remap_area_pte(pte_t * pte, unsigned long address,
        phys_t size, phys_t phys_addr, unsigned long flags)
 {
@@ -141,8 +143,9 @@
 
        /*
         * Don't allow anybody to remap normal RAM that we're using..
+        * mem_init() sets high_memory so only do the check after that.
         */
-       if (phys_addr < virt_to_phys(high_memory)) {
+       if (mem_init_done && (phys_addr < virt_to_phys(high_memory))) {
                char *t_addr, *t_end;
                struct page *page;
 
@@ -164,12 +167,18 @@
        /*
         * Ok, go for it..
         */
-       area = get_vm_area(size, VM_IOREMAP);
-       if (!area)
-               return NULL;
-       addr = area->addr;
+       if (mem_init_done) {
+               area = get_vm_area(size, VM_IOREMAP);
+               if (!area)
+                       return NULL;
+               addr = area->addr;
+       }
+       else {
+               addr = (void *)(ioremap_bot -= size);
+       }
        if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
-               vunmap(addr);
+               if (mem_init_done)
+                       vunmap(addr);
                return NULL;
        }
 
@@ -185,13 +194,15 @@
        if (IS_KSEG1(addr))
                return;
 
-       p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
-       if (!p) {
-               printk(KERN_ERR "iounmap: bad address %p\n", addr);
-               return;
-       }
+       if ((unsigned long) addr < ioremap_bot) {
+               p = remove_vm_area((void *) (PAGE_MASK & (unsigned long 
__force) addr));
+               if (!p) {
+                       printk(KERN_ERR "iounmap: bad address %p\n", addr);
+                       return;
+               }
 
-        kfree(p);
+               kfree(p);
+       }
 }
 
 EXPORT_SYMBOL(__ioremap);
diff -Naur --exclude=CVS linux-2.6-orig/arch/mips/mm/pgtable-32.c 
linux-2.6-dev/arch/mips/mm/pgtable-32.c
--- linux-2.6-orig/arch/mips/mm/pgtable-32.c    2005-08-10 18:15:56.000000000 
-0700
+++ linux-2.6-dev/arch/mips/mm/pgtable-32.c     2005-08-23 00:46:14.000000000 
-0700
@@ -13,6 +13,9 @@
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
 
+unsigned long ioremap_base;
+unsigned long ioremap_bot;
+
 void pgd_init(unsigned long page)
 {
        unsigned long *p = (unsigned long *) page;
diff -Naur --exclude=CVS linux-2.6-orig/include/asm-mips/io.h 
linux-2.6-dev/include/asm-mips/io.h
--- linux-2.6-orig/include/asm-mips/io.h        2005-08-10 18:22:04.000000000 
-0700
+++ linux-2.6-dev/include/asm-mips/io.h 2005-08-25 13:35:31.000000000 -0700
@@ -637,4 +637,6 @@
  */
 #define xlate_dev_kmem_ptr(p)  p
 
+extern void early_ioremap_init(void);
+
 #endif /* _ASM_IO_H */
diff -Naur --exclude=CVS linux-2.6-orig/include/asm-mips/pgalloc.h 
linux-2.6-dev/include/asm-mips/pgalloc.h
--- linux-2.6-orig/include/asm-mips/pgalloc.h   2005-08-10 18:22:02.000000000 
-0700
+++ linux-2.6-dev/include/asm-mips/pgalloc.h    2005-08-25 01:49:04.000000000 
-0700
@@ -67,8 +67,17 @@
        unsigned long address)
 {
        pte_t *pte;
+       extern int mem_init_done;
+       extern void *early_get_page(void);
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 
PTE_ORDER);
+       if (mem_init_done) {
+               pte = (pte_t *) 
__get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, PTE_ORDER);
+       } else {
+               pte = (pte_t *)early_get_page();
+               if (pte) {
+                       clear_page(pte);
+               }
+       }
 
        return pte;
 }
diff -Naur --exclude=CVS linux-2.6-orig/include/asm-mips/pgtable-32.h 
linux-2.6-dev/include/asm-mips/pgtable-32.h
--- linux-2.6-orig/include/asm-mips/pgtable-32.h        2005-08-25 
13:02:30.000000000 -0700
+++ linux-2.6-dev/include/asm-mips/pgtable-32.h 2005-08-25 01:49:04.000000000 
-0700
@@ -19,6 +19,8 @@
 
 #include <asm-generic/pgtable-nopmd.h>
 
+extern unsigned long ioremap_bot, ioremap_base;
+
 /*
  * - add_wired_entry() add a fixed TLB entry, and move wired register
  */
@@ -74,13 +76,9 @@
 #define USER_PTRS_PER_PGD      (0x80000000UL/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS     0
 
-#define VMALLOC_START     MAP_BASE
+#define VMALLOC_START  MAP_BASE
 
-#ifdef CONFIG_HIGHMEM
-# define VMALLOC_END   (PKMAP_BASE-2*PAGE_SIZE)
-#else
-# define VMALLOC_END   (FIXADDR_START-2*PAGE_SIZE)
-#endif
+#define VMALLOC_END    ioremap_bot
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
 #define pte_ERROR(e) \
diff -Naur --exclude=CVS linux-2.6-orig/include/asm-mips/traps.h 
linux-2.6-dev/include/asm-mips/traps.h
--- linux-2.6-orig/include/asm-mips/traps.h     2005-08-10 18:22:04.000000000 
-0700
+++ linux-2.6-dev/include/asm-mips/traps.h      2005-08-25 10:56:01.000000000 
-0700
@@ -24,4 +24,6 @@
 extern void (*board_nmi_handler_setup)(void);
 extern void (*board_ejtag_handler_setup)(void);
 
+extern void early_trap_init(void);
+
 #endif /* _ASM_TRAPS_H */



<Prev in Thread] Current Thread [Next in Thread>