Merge branch 'tmpreg' into devel
[safe/jmp/linux-2.6] / arch / sparc / mm / sun4c.c
index 0729305..1865253 100644 (file)
@@ -17,7 +17,9 @@
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
+#include <linux/bitmap.h>
 
+#include <asm/sections.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
@@ -31,7 +33,6 @@
 #include <asm/oplib.h>
 #include <asm/openprom.h>
 #include <asm/mmu_context.h>
-#include <asm/sun4paddr.h>
 #include <asm/highmem.h>
 #include <asm/btfixup.h>
 #include <asm/cacheflush.h>
@@ -52,15 +53,11 @@ extern int num_segmaps, num_contexts;
 
 extern unsigned long page_kernel;
 
-#ifdef CONFIG_SUN4
-#define SUN4C_VAC_SIZE sun4c_vacinfo.num_bytes
-#else
 /* That's it, we prom_halt() on sun4c if the cache size is something other than 65536.
  * So let's save some cycles and just use that everywhere except for that bootup
  * sanity check.
  */
 #define SUN4C_VAC_SIZE 65536
-#endif
 
 #define SUN4C_KERNEL_BUCKETS 32
 
@@ -245,9 +242,7 @@ void sun4c_complete_all_stores(void)
 
        _unused = sun4c_get_context();
        sun4c_set_context(_unused);
-#ifdef CONFIG_SUN_AUXIO
        _unused = get_auxio();
-#endif
 }
 
 /* Bootup utility functions. */
@@ -285,75 +280,32 @@ void __init sun4c_probe_vac(void)
 {
        sun4c_disable_vac();
 
-       if (ARCH_SUN4) {
-               switch (idprom->id_machtype) {
-
-               case (SM_SUN4|SM_4_110):
-                       sun4c_vacinfo.type = VAC_NONE;
-                       sun4c_vacinfo.num_bytes = 0;
-                       sun4c_vacinfo.linesize = 0;
-                       sun4c_vacinfo.do_hwflushes = 0;
-                       prom_printf("No VAC. Get some bucks and buy a real computer.");
-                       prom_halt();
-                       break;
-
-               case (SM_SUN4|SM_4_260):
-                       sun4c_vacinfo.type = VAC_WRITE_BACK;
-                       sun4c_vacinfo.num_bytes = 128 * 1024;
-                       sun4c_vacinfo.linesize = 16;
-                       sun4c_vacinfo.do_hwflushes = 0;
-                       break;
-
-               case (SM_SUN4|SM_4_330):
-                       sun4c_vacinfo.type = VAC_WRITE_THROUGH;
-                       sun4c_vacinfo.num_bytes = 128 * 1024;
-                       sun4c_vacinfo.linesize = 16;
-                       sun4c_vacinfo.do_hwflushes = 0;
-                       break;
-
-               case (SM_SUN4|SM_4_470):
-                       sun4c_vacinfo.type = VAC_WRITE_BACK;
-                       sun4c_vacinfo.num_bytes = 128 * 1024;
-                       sun4c_vacinfo.linesize = 32;
-                       sun4c_vacinfo.do_hwflushes = 0;
-                       break;
-
-               default:
-                       prom_printf("Cannot initialize VAC - weird sun4 model idprom->id_machtype = %d", idprom->id_machtype);
-                       prom_halt();
-               };
+       if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
+           (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
+               /* PROM on SS1 lacks this info, to be super safe we
+                * hard code it here since this arch is cast in stone.
+                */
+               sun4c_vacinfo.num_bytes = 65536;
+               sun4c_vacinfo.linesize = 16;
        } else {
-               sun4c_vacinfo.type = VAC_WRITE_THROUGH;
+               sun4c_vacinfo.num_bytes =
+                prom_getintdefault(prom_root_node, "vac-size", 65536);
+               sun4c_vacinfo.linesize =
+                prom_getintdefault(prom_root_node, "vac-linesize", 16);
+       }
+       sun4c_vacinfo.do_hwflushes =
+        prom_getintdefault(prom_root_node, "vac-hwflush", 0);
 
-               if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
-                   (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
-                       /* PROM on SS1 lacks this info, to be super safe we
-                        * hard code it here since this arch is cast in stone.
-                        */
-                       sun4c_vacinfo.num_bytes = 65536;
-                       sun4c_vacinfo.linesize = 16;
-               } else {
-                       sun4c_vacinfo.num_bytes =
-                        prom_getintdefault(prom_root_node, "vac-size", 65536);
-                       sun4c_vacinfo.linesize =
-                        prom_getintdefault(prom_root_node, "vac-linesize", 16);
-               }
+       if (sun4c_vacinfo.do_hwflushes == 0)
                sun4c_vacinfo.do_hwflushes =
-                prom_getintdefault(prom_root_node, "vac-hwflush", 0);
+                prom_getintdefault(prom_root_node, "vac_hwflush", 0);
 
-               if (sun4c_vacinfo.do_hwflushes == 0)
-                       sun4c_vacinfo.do_hwflushes =
-                        prom_getintdefault(prom_root_node, "vac_hwflush", 0);
-
-               if (sun4c_vacinfo.num_bytes != 65536) {
-                       prom_printf("WEIRD Sun4C VAC cache size, "
-                                   "tell sparclinux@vger.kernel.org");
-                       prom_halt();
-               }
+       if (sun4c_vacinfo.num_bytes != 65536) {
+               prom_printf("WEIRD Sun4C VAC cache size, "
+                           "tell sparclinux@vger.kernel.org");
+               prom_halt();
        }
 
-       sun4c_vacinfo.num_lines =
-               (sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize);
        switch (sun4c_vacinfo.linesize) {
        case 16:
                sun4c_vacinfo.log2lsize = 4;
@@ -447,49 +399,18 @@ static void __init patch_kernel_fault_handler(void)
 
 static void __init sun4c_probe_mmu(void)
 {
-       if (ARCH_SUN4) {
-               switch (idprom->id_machtype) {
-               case (SM_SUN4|SM_4_110):
-                       prom_printf("No support for 4100 yet\n");
-                       prom_halt();
-                       num_segmaps = 256;
-                       num_contexts = 8;
-                       break;
-
-               case (SM_SUN4|SM_4_260):
-                       /* should be 512 segmaps. when it get fixed */
-                       num_segmaps = 256;
-                       num_contexts = 16;
-                       break;
-
-               case (SM_SUN4|SM_4_330):
-                       num_segmaps = 256;
-                       num_contexts = 16;
-                       break;
-
-               case (SM_SUN4|SM_4_470):
-                       /* should be 1024 segmaps. when it get fixed */
-                       num_segmaps = 256;
-                       num_contexts = 64;
-                       break;
-               default:
-                       prom_printf("Invalid SUN4 model\n");
-                       prom_halt();
-               };
+       if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
+           (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
+               /* Hardcode these just to be safe, PROM on SS1 does
+               * not have this info available in the root node.
+               */
+               num_segmaps = 128;
+               num_contexts = 8;
        } else {
-               if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
-                   (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
-                       /* Hardcode these just to be safe, PROM on SS1 does
-                       * not have this info available in the root node.
-                       */
-                       num_segmaps = 128;
-                       num_contexts = 8;
-               } else {
-                       num_segmaps =
-                           prom_getintdefault(prom_root_node, "mmu-npmg", 128);
-                       num_contexts =
-                           prom_getintdefault(prom_root_node, "mmu-nctx", 0x8);
-               }
+               num_segmaps =
+                   prom_getintdefault(prom_root_node, "mmu-npmg", 128);
+               num_contexts =
+                   prom_getintdefault(prom_root_node, "mmu-nctx", 0x8);
        }
        patch_kernel_fault_handler();
 }
@@ -501,18 +422,14 @@ void __init sun4c_probe_memerr_reg(void)
        int node;
        struct linux_prom_registers regs[1];
 
-       if (ARCH_SUN4) {
-               sun4c_memerr_reg = ioremap(sun4_memreg_physaddr, PAGE_SIZE);
-       } else {
-               node = prom_getchild(prom_root_node);
-               node = prom_searchsiblings(prom_root_node, "memory-error");
-               if (!node)
-                       return;
-               if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0)
-                       return;
-               /* hmm I think regs[0].which_io is zero here anyways */
-               sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size);
-       }
+       node = prom_getchild(prom_root_node);
+       node = prom_searchsiblings(prom_root_node, "memory-error");
+       if (!node)
+               return;
+       if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0)
+               return;
+       /* hmm I think regs[0].which_io is zero here anyways */
+       sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size);
 }
 
 static inline void sun4c_init_ss2_cache_bug(void)
@@ -521,7 +438,6 @@ static inline void sun4c_init_ss2_cache_bug(void)
 
        if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
            (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
-           (idprom->id_machtype == (SM_SUN4 | SM_4_330)) ||
            (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
                /* Whee.. */
                printk("SS2 cache bug detected, uncaching trap table page\n");
@@ -532,8 +448,8 @@ static inline void sun4c_init_ss2_cache_bug(void)
 }
 
 /* Addr is always aligned on a page boundary for us already. */
-static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va,
-    unsigned long addr, int len)
+static int sun4c_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va,
+                             unsigned long addr, int len)
 {
        unsigned long page, end;
 
@@ -555,14 +471,7 @@ static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va,
        return 0;
 }
 
-static struct page *sun4c_translate_dvma(unsigned long busa)
-{
-       /* Fortunately for us, bus_addr == uncached_virt in sun4c. */
-       unsigned long pte = sun4c_get_pte(busa);
-       return pfn_to_page(pte & SUN4C_PFN_MASK);
-}
-
-static void sun4c_unmap_dma_area(unsigned long busa, int len)
+static void sun4c_unmap_dma_area(struct device *dev, unsigned long busa, int len)
 {
        /* Fortunately for us, bus_addr == uncached_virt in sun4c. */
        /* XXX Implement this */
@@ -624,11 +533,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
 {
        unsigned long vaddr;
        unsigned char pseg, ctx;
-#ifdef CONFIG_SUN4
-       /* sun4/110 and 260 have no kadb. */
-       if ((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && 
-           (idprom->id_machtype != (SM_SUN4 | SM_4_110))) {
-#endif
+
        for (vaddr = KADB_DEBUGGER_BEGVM;
             vaddr < LINUX_OPPROM_ENDVM;
             vaddr += SUN4C_REAL_PGDIR_SIZE) {
@@ -640,9 +545,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
                        fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
                }
        }
-#ifdef CONFIG_SUN4
-       }
-#endif
+
        for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
                pseg = sun4c_get_segmap(vaddr);
                mmu_entry_pool[pseg].locked = 1;
@@ -1048,14 +951,10 @@ static struct thread_info *sun4c_alloc_thread_info(void)
         * so we must flush the cache to guarantee consistency.
         */
        sun4c_flush_page(pages);
-#ifndef CONFIG_SUN4    
        sun4c_flush_page(pages + PAGE_SIZE);
-#endif
 
        sun4c_put_pte(addr, BUCKET_PTE(pages));
-#ifndef CONFIG_SUN4    
        sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE));
-#endif
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
        memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER);
@@ -1072,13 +971,11 @@ static void sun4c_free_thread_info(struct thread_info *ti)
 
        /* We are deleting a mapping, so the flush here is mandatory. */
        sun4c_flush_page(tiaddr);
-#ifndef CONFIG_SUN4    
        sun4c_flush_page(tiaddr + PAGE_SIZE);
-#endif
+
        sun4c_put_pte(tiaddr, 0);
-#ifndef CONFIG_SUN4    
        sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
-#endif
+
        sun4c_bucket[entry] = BUCKET_EMPTY;
        if (entry < sun4c_lowbucket_avail)
                sun4c_lowbucket_avail = entry;
@@ -1125,20 +1022,12 @@ static char *sun4c_lockarea(char *vaddr, unsigned long size)
        npages = (((unsigned long)vaddr & ~PAGE_MASK) +
                  size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
 
-       scan = 0;
        local_irq_save(flags);
-       for (;;) {
-               scan = find_next_zero_bit(sun4c_iobuffer_map,
-                                         iobuffer_map_size, scan);
-               if ((base = scan) + npages > iobuffer_map_size) goto abend;
-               for (;;) {
-                       if (scan >= base + npages) goto found;
-                       if (test_bit(scan, sun4c_iobuffer_map)) break;
-                       scan++;
-               }
-       }
+       base = bitmap_find_next_zero_area(sun4c_iobuffer_map, iobuffer_map_size,
+                                               0, npages, 0);
+       if (base >= iobuffer_map_size)
+               goto abend;
 
-found:
        high = ((base + npages) << PAGE_SHIFT) + sun4c_iobuffer_start;
        high = SUN4C_REAL_PGDIR_ALIGN(high);
        while (high > sun4c_iobuffer_high) {
@@ -1211,7 +1100,7 @@ static void sun4c_unlockarea(char *vaddr, unsigned long size)
  * by implication and fool the page locking code above
  * if passed to by mistake.
  */
-static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus *sbus)
+static __u32 sun4c_get_scsi_one(struct device *dev, char *bufptr, unsigned long len)
 {
        unsigned long page;
 
@@ -1223,28 +1112,28 @@ static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus
        return (__u32)sun4c_lockarea(bufptr, len);
 }
 
-static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
+static void sun4c_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
 {
        while (sz != 0) {
                --sz;
-               sg->dvma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length);
-               sg->dvma_length = sg->length;
+               sg->dma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length);
+               sg->dma_length = sg->length;
                sg = sg_next(sg);
        }
 }
 
-static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_bus *sbus)
+static void sun4c_release_scsi_one(struct device *dev, __u32 bufptr, unsigned long len)
 {
        if (bufptr < sun4c_iobuffer_start)
                return; /* On kernel stack or similar, see above */
        sun4c_unlockarea((char *)bufptr, len);
 }
 
-static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
+static void sun4c_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
 {
        while (sz != 0) {
                --sz;
-               sun4c_unlockarea((char *)sg->dvma_address, sg->length);
+               sun4c_unlockarea((char *)sg->dma_address, sg->length);
                sg = sg_next(sg);
        }
 }
@@ -1941,18 +1830,21 @@ static pte_t *sun4c_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add
        if ((pte = sun4c_pte_alloc_one_fast(mm, address)) != NULL)
                return pte;
 
-       pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
-       if (pte)
-               memset(pte, 0, PAGE_SIZE);
+       pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
        return pte;
 }
 
-static struct page *sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static pgtable_t sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       pte_t *pte = sun4c_pte_alloc_one_kernel(mm, address);
+       pte_t *pte;
+       struct page *page;
+
+       pte = sun4c_pte_alloc_one_kernel(mm, address);
        if (pte == NULL)
                return NULL;
-       return virt_to_page(pte);
+       page = virt_to_page(pte);
+       pgtable_page_ctor(page);
+       return page;
 }
 
 static inline void sun4c_free_pte_fast(pte_t *pte)
@@ -1962,8 +1854,9 @@ static inline void sun4c_free_pte_fast(pte_t *pte)
        pgtable_cache_size++;
 }
 
-static void sun4c_pte_free(struct page *pte)
+static void sun4c_pte_free(pgtable_t pte)
 {
+       pgtable_page_dtor(pte);
        sun4c_free_pte_fast(page_address(pte));
 }
 
@@ -1994,7 +1887,7 @@ static void sun4c_check_pgt_cache(int low, int high)
 /* An experiment, turn off by default for now... -DaveM */
 #define SUN4C_PRELOAD_PSEG
 
-void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
        unsigned long flags;
        int pseg;
@@ -2036,7 +1929,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
                        start += PAGE_SIZE;
                }
 #ifndef SUN4C_PRELOAD_PSEG
-               sun4c_put_pte(address, pte_val(pte));
+               sun4c_put_pte(address, pte_val(*ptep));
 #endif
                local_irq_restore(flags);
                return;
@@ -2047,12 +1940,11 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
                add_lru(entry);
        }
 
-       sun4c_put_pte(address, pte_val(pte));
+       sun4c_put_pte(address, pte_val(*ptep));
        local_irq_restore(flags);
 }
 
 extern void sparc_context_init(int);
-extern unsigned long end;
 extern unsigned long bootmem_init(unsigned long *pages_avail);
 extern unsigned long last_valid_pfn;
 
@@ -2063,7 +1955,7 @@ void __init sun4c_paging_init(void)
        extern struct resource sparc_iomap;
        unsigned long end_pfn, pages_avail;
 
-       kernel_end = (unsigned long) &end;
+       kernel_end = (unsigned long) &_end;
        kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
 
        pages_avail = 0;
@@ -2119,8 +2011,7 @@ void __init sun4c_paging_init(void)
                zones_size[ZONE_HIGHMEM] = npages;
                zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-               free_area_init_node(0, &contig_page_data, zones_size,
-                                   pfn_base, zholes_size);
+               free_area_init_node(0, zones_size, pfn_base, zholes_size);
        }
 
        cnt = 0;
@@ -2260,7 +2151,6 @@ void __init ld_mmu_sun4c(void)
 
        BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM);
        BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM);
-       BTFIXUPSET_CALL(mmu_translate_dvma, sun4c_translate_dvma, BTFIXUPCALL_NORM);
 
        BTFIXUPSET_CALL(sparc_mapiorange, sun4c_mapiorange, BTFIXUPCALL_NORM);
        BTFIXUPSET_CALL(sparc_unmapiorange, sun4c_unmapiorange, BTFIXUPCALL_NORM);