diff mbox

[06/11] persistent_ram: Make it possible to use memory outside of bootmem

Message ID 20120512001754.GF14782@lizard
State Accepted
Commit 24c3d2f342edbc10fee9f8ab9e0a033393686543
Headers show

Commit Message

Anton Vorontsov May 12, 2012, 12:17 a.m. UTC
This includes devices' memory (e.g. framebuffers or memory mapped
EEPROMs on a local bus), as well as the normal RAM that we don't use
for the main memory.

For the normal (but unused) ram we could use kmaps, but this assumes
highmem support, so we don't bother and just use the memory via
ioremap.

As a side effect, the following hack is possible: when used together
with pstore_ram (new ramoops) module, we can limit the normal RAM region
with mem= and then point ramoops to use the rest of the memory, e.g.

	mem=128M ramoops.mem_address=0x8000000

Sure, we could just reserve the region with memblock_reserve() early in
the arch/ code, and then register a pstore_ram platform device pointing
to the reserved region. It's still a viable option if platform wants
to do so.

Also, we might want to use IO accessors in case of a real device,
but for now we don't bother (the old ramoops wasn't using it either, so
at least we don't make things worse).

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
---
 drivers/staging/android/persistent_ram.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

Comments

Colin Cross June 6, 2012, 9:10 p.m. UTC | #1
On Fri, May 11, 2012 at 5:17 PM, Anton Vorontsov
<anton.vorontsov@linaro.org> wrote:
> This includes devices' memory (e.g. framebuffers or memory mapped
> EEPROMs on a local bus), as well as the normal RAM that we don't use
> for the main memory.
>
> For the normal (but unused) ram we could use kmaps, but this assumes
> highmem support, so we don't bother and just use the memory via
> ioremap.
>
> As a side effect, the following hack is possible: when used together
> with pstore_ram (new ramoops) module, we can limit the normal RAM region
> with mem= and then point ramoops to use the rest of the memory, e.g.
>
>        mem=128M ramoops.mem_address=0x8000000
>
> Sure, we could just reserve the region with memblock_reserve() early in
> the arch/ code, and then register a pstore_ram platform device pointing
> to the reserved region. It's still a viable option if platform wants
> to do so.
>
> Also, we might want to use IO accessors in case of a real device,
> but for now we don't bother (the old ramoops wasn't using it either, so
> at least we don't make things worse).

This is long merged, but I remembered why I moved away from using
ioremap.  The current code uses atomics to track the ringbuffer
positions, which results in ldrex and strex instructions on ARM.
ldrex and strex on memory that is mapped as Device memory (which is
what ioremap maps as) is implementation defined, and is unpredictable
at the architecture level.
Anton Vorontsov June 6, 2012, 10:11 p.m. UTC | #2
On Wed, Jun 06, 2012 at 02:10:34PM -0700, Colin Cross wrote:
> On Fri, May 11, 2012 at 5:17 PM, Anton Vorontsov
> <anton.vorontsov@linaro.org> wrote:
> > This includes devices' memory (e.g. framebuffers or memory mapped
> > EEPROMs on a local bus), as well as the normal RAM that we don't use
> > for the main memory.
> >
> > For the normal (but unused) ram we could use kmaps, but this assumes
> > highmem support, so we don't bother and just use the memory via
> > ioremap.
> >
> > As a side effect, the following hack is possible: when used together
> > with pstore_ram (new ramoops) module, we can limit the normal RAM region
> > with mem= and then point ramoops to use the rest of the memory, e.g.
> >
> >        mem=128M ramoops.mem_address=0x8000000
> >
> > Sure, we could just reserve the region with memblock_reserve() early in
> > the arch/ code, and then register a pstore_ram platform device pointing
> > to the reserved region. It's still a viable option if platform wants
> > to do so.
> >
> > Also, we might want to use IO accessors in case of a real device,
> > but for now we don't bother (the old ramoops wasn't using it either, so
> > at least we don't make things worse).
> 
> This is long merged, but I remembered why I moved away from using
> ioremap.  The current code uses atomics to track the ringbuffer
> positions, which results in ldrex and strex instructions on ARM.
> ldrex and strex on memory that is mapped as Device memory (which is
> what ioremap maps as) is implementation defined, and is unpredictable
> at the architecture level.

Makes sense, thanks for sharing! Fortunately, we still map things
w/ vmap if pfn appears to be valid. :-)

Thanks,
diff mbox

Patch

diff --git a/drivers/staging/android/persistent_ram.c b/drivers/staging/android/persistent_ram.c
index ab8bff1..c16d7c2 100644
--- a/drivers/staging/android/persistent_ram.c
+++ b/drivers/staging/android/persistent_ram.c
@@ -23,6 +23,7 @@ 
 #include <linux/rslib.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <asm/page.h>
 #include "persistent_ram.h"
 
 struct persistent_ram_buffer {
@@ -349,10 +350,25 @@  static void *persistent_ram_vmap(phys_addr_t start, size_t size)
 	return vaddr;
 }
 
+static void *persistent_ram_iomap(phys_addr_t start, size_t size)
+{
+	if (!request_mem_region(start, size, "persistent_ram")) {
+		pr_err("request mem region (0x%llx@0x%llx) failed\n",
+			(unsigned long long)size, (unsigned long long)start);
+		return NULL;
+	}
+
+	return ioremap(start, size);
+}
+
 static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
 		struct persistent_ram_zone *prz)
 {
-	prz->vaddr = persistent_ram_vmap(start, size);
+	if (pfn_valid(start >> PAGE_SHIFT))
+		prz->vaddr = persistent_ram_vmap(start, size);
+	else
+		prz->vaddr = persistent_ram_iomap(start, size);
+
 	if (!prz->vaddr) {
 		pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__,
 			(unsigned long long)size, (unsigned long long)start);