VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / ppc / mm / pgtable.c
index 04c1481..c16d4cc 100644 (file)
@@ -42,6 +42,10 @@ int io_bat_index;
 #define HAVE_BATS      1
 #endif
 
+#if defined(CONFIG_FSL_BOOKE)
+#define HAVE_TLBCAM    1
+#endif
+
 extern char etext[], _stext[];
 
 #ifdef CONFIG_SMP
@@ -59,6 +63,16 @@ void setbat(int index, unsigned long virt, unsigned long phys,
 #define p_mapped_by_bats(x)    (0UL)
 #endif /* HAVE_BATS */
 
+#ifdef HAVE_TLBCAM
+extern unsigned int tlbcam_index;
+extern unsigned int num_tlbcam_entries;
+extern unsigned long v_mapped_by_tlbcam(unsigned long va);
+extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
+#else /* !HAVE_TLBCAM */
+#define v_mapped_by_tlbcam(x)  (0UL)
+#define p_mapped_by_tlbcam(x)  (0UL)
+#endif /* HAVE_TLBCAM */
+
 #ifdef CONFIG_44x
 /* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
 #define PGDIR_ORDER    1
@@ -210,6 +224,9 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
        if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
                goto out;
 
+       if ((v = p_mapped_by_tlbcam(p)))
+               goto out;
+
        if (mem_init_done) {
                struct vm_struct *area;
                area = get_vm_area(size, VM_IOREMAP);
@@ -300,6 +317,9 @@ void __init mapin_ram(void)
 /* is x a power of 2? */
 #define is_power_of_2(x)       ((x) != 0 && (((x) & ((x) - 1)) == 0))
 
+/* is x a power of 4? */
+#define is_power_of_4(x)       ((x) != 0 && (((x) & (x-1)) == 0) && (ffs(x) & 1))
+
 /*
  * Set up a mapping for a block of I/O.
  * virt, phys, size must all be page-aligned.
@@ -325,6 +345,18 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
        }
 #endif /* HAVE_BATS */
 
+#ifdef HAVE_TLBCAM
+       /*
+        * Use a CAM for this if possible...
+        */
+       if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
+           && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
+               settlbcam(tlbcam_index, virt, phys, size, flags, 0);
+               ++tlbcam_index;
+               return;
+       }
+#endif /* HAVE_TLBCAM */
+
        /* No BATs available, put it in the page tables. */
        for (i = 0; i < size; i += PAGE_SIZE)
                map_page(virt + i, phys + i, flags);