aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-02-17 17:56:38 +0900
committerPaul Mundt <lethal@linux-sh.org>2010-02-17 17:56:38 +0900
commitd7813bc9e8e384f5a293b05c095c799d41af3668 (patch)
tree285ef4ffef4a0da0f54cfc90ca259eaa426bc5e4
parentsh: uncached mapping helpers. (diff)
downloadlinux-dev-d7813bc9e8e384f5a293b05c095c799d41af3668.tar.xz
linux-dev-d7813bc9e8e384f5a293b05c095c799d41af3668.zip
sh: Build PMB entry links for existing contiguous multi-page mappings.
This plugs in entry sizing support for existing mappings and then builds on top of that for linking together entries that are mapping contiguous areas. This will ultimately permit us to coalesce mappings and promote head pages while reclaiming PMB slots for dynamic remapping. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/include/asm/mmu.h2
-rw-r--r--arch/sh/mm/pmb.c59
2 files changed, 30 insertions, 31 deletions
diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h
index 44c904341414..5453169bf052 100644
--- a/arch/sh/include/asm/mmu.h
+++ b/arch/sh/include/asm/mmu.h
@@ -59,6 +59,7 @@ struct pmb_entry {
unsigned long vpn;
unsigned long ppn;
unsigned long flags;
+ unsigned long size;
/*
* 0 .. NR_PMB_ENTRIES for specific entry selection, or
@@ -66,7 +67,6 @@ struct pmb_entry {
*/
int entry;
- struct pmb_entry *next;
/* Adjacent entry link for contiguous multi-entry mappings */
struct pmb_entry *link;
};
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 924f3e4b3a82..f2ad6e374b64 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -90,20 +90,15 @@ static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
pmbe->ppn = ppn;
pmbe->flags = flags;
pmbe->entry = pos;
+ pmbe->size = 0;
return pmbe;
}
static void pmb_free(struct pmb_entry *pmbe)
{
- int pos = pmbe->entry;
-
- pmbe->vpn = 0;
- pmbe->ppn = 0;
- pmbe->flags = 0;
- pmbe->entry = 0;
-
- clear_bit(pos, pmb_map);
+ clear_bit(pmbe->entry, pmb_map);
+ pmbe->entry = PMB_NO_ENTRY;
}
/*
@@ -198,6 +193,8 @@ again:
vaddr += pmb_sizes[i].size;
size -= pmb_sizes[i].size;
+ pmbe->size = pmb_sizes[i].size;
+
/*
* Link adjacent entries that span multiple PMB entries
* for easier tear-down.
@@ -273,25 +270,7 @@ static void pmb_unmap_entry(struct pmb_entry *pmbe)
} while (pmbe);
}
-static inline void
-pmb_log_mapping(unsigned long data_val, unsigned long vpn, unsigned long ppn)
-{
- unsigned int size;
- const char *sz_str;
-
- size = data_val & PMB_SZ_MASK;
-
- sz_str = (size == PMB_SZ_16M) ? " 16MB":
- (size == PMB_SZ_64M) ? " 64MB":
- (size == PMB_SZ_128M) ? "128MB":
- "512MB";
-
- pr_info("\t0x%08lx -> 0x%08lx [ %s %scached ]\n",
- vpn >> PAGE_SHIFT, ppn >> PAGE_SHIFT, sz_str,
- (data_val & PMB_C) ? "" : "un");
-}
-
-static inline unsigned int pmb_ppn_in_range(unsigned long ppn)
+static __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
{
return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
}
@@ -299,7 +278,8 @@ static inline unsigned int pmb_ppn_in_range(unsigned long ppn)
static int pmb_synchronize_mappings(void)
{
unsigned int applied = 0;
- int i;
+ struct pmb_entry *pmbp = NULL;
+ int i, j;
pr_info("PMB: boot mappings:\n");
@@ -323,6 +303,7 @@ static int pmb_synchronize_mappings(void)
unsigned long addr, data;
unsigned long addr_val, data_val;
unsigned long ppn, vpn, flags;
+ unsigned int size;
struct pmb_entry *pmbe;
addr = mk_pmb_addr(i);
@@ -366,7 +347,8 @@ static int pmb_synchronize_mappings(void)
__raw_writel(data_val, data);
}
- flags = data_val & (PMB_SZ_MASK | PMB_CACHE_MASK);
+ size = data_val & PMB_SZ_MASK;
+ flags = size | (data_val & PMB_CACHE_MASK);
pmbe = pmb_alloc(vpn, ppn, flags, i);
if (IS_ERR(pmbe)) {
@@ -374,7 +356,24 @@ static int pmb_synchronize_mappings(void)
continue;
}
- pmb_log_mapping(data_val, vpn, ppn);
+ for (j = 0; j < ARRAY_SIZE(pmb_sizes); j++)
+ if (pmb_sizes[j].flag == size)
+ pmbe->size = pmb_sizes[j].size;
+
+ /*
+ * Compare the previous entry against the current one to
+ * see if the entries span a contiguous mapping. If so,
+ * setup the entry links accordingly.
+ */
+ if (pmbp && ((pmbe->vpn == (pmbp->vpn + pmbp->size)) &&
+ (pmbe->ppn == (pmbp->ppn + pmbp->size))))
+ pmbp->link = pmbe;
+
+ pmbp = pmbe;
+
+ pr_info("\t0x%08lx -> 0x%08lx [ %ldMB %scached ]\n",
+ vpn >> PAGE_SHIFT, ppn >> PAGE_SHIFT, pmbe->size >> 20,
+ (data_val & PMB_C) ? "" : "un");
applied++;
}