Skip to contentSkip to conversation

Slram doesn't work

DISCUSSION B. D. Elliott 2 participants 2 messages Oct 21, 2003 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

I have an old (x86) machine that does not cache the upper half of memory. Under 2.4.x, I used "slram=slr0,64M,+64M" to reserve that half, and then used it as a swap device.

This fails on 2.6.0-test8, with an "ioremap failed" message during booting. The boot messages plus capturing the page flags in ioremap() shows the following:

...
slram: devname = slr0
slram: devstart = 64M
slram: devlength = +64M
slram: devname=slr0, devstart=0x4000000, devlength=0x4000000
.. ioremap failed: line 145 (approximately)
.. phys_addr: 04000000 t_addr: c4000000 t_end: c7ffffff page0: c10a0000 page: c10a0000 .. page-1 flags: 01000000
.. page flags: 01000080
.. page+1 flags: 01000080
.. page+2 flags: 01000080
.. page+3 flags: 01000080
.. PageReserved(page): 0
slram: ioremap failed
...

The failure occurs where "PageReserved" is checked. "page0" is the address of the first page entry for the region, which is also where it failed. ("PageReserved" is bit 11.) Apparently, "PageReserved" is no longer set when slram initialization occurs.

Signature · 1 line
B. D. Elliott   [email protected]
#1 lore raw
Quoted 24 lines · B. D. Elliott

I have an old (x86) machine that does not cache the upper half of memory. Under 2.4.x, I used "slram=slr0,64M,+64M" to reserve that half, and then used it as a swap device.

This fails on 2.6.0-test8, with an "ioremap failed" message during booting. The boot messages plus capturing the page flags in ioremap() shows the following:

...
slram: devname = slr0
slram: devstart = 64M
slram: devlength = +64M
slram: devname=slr0, devstart=0x4000000, devlength=0x4000000
.. ioremap failed: line 145 (approximately)
.. phys_addr: 04000000 t_addr: c4000000 t_end: c7ffffff page0: c10a0000 page: c10a0000 .. page-1 flags: 01000000
.. page flags: 01000080
.. page+1 flags: 01000080
.. page+2 flags: 01000080
.. page+3 flags: 01000080
.. PageReserved(page): 0
slram: ioremap failed
...

Quoted 4 lines

The failure occurs where "PageReserved" is checked. "page0" is the address of the first page entry for the region, which is also where it failed. ("PageReserved" is bit 11.) Apparently, "PageReserved" is no longer set when slram initialization occurs.

The ioremap failure occurs because the 2.6 "mem=" bootparam currently behaves slightly differently from the 2.4 one, and your slram ends up overlapping memory used by the kernel. That was noticed a few days ago, and a fix to setup.c is already queued up in 2.6.0-test8-mm1.

But when you fix that, you'll find mkswap (and any other write to it)
fails: a small change to mtdblock_writesect seems to work fine for me, but it might not be the right fix - MTD handles a lot more than just slram, I've never delved in there before, David is the maintainer, and sure to grasp the issues.

Many thanks for leading me to drivers/mtd/devices/slram.c: I'd long thought such a driver should exist, but never discovered that it does already exist. Looks like just what's needed to eliminate one of my betes noirs, arch/m68k/atari/stram.c. (Though something else I'd like to try with it, is using i386 mem above 4GB for swap: but it's not at present suitable for that, since it's using permanent ioremap space.)

Hugh

arch/i386/kernel/setup.c +4 -4
@@ -141,14 +141,14 @@ static void __init probe_roms(void)
 
 static void __init limit_regions (unsigned long long size)
 {
+	unsigned long long current_addr = 0;
 	int i;
-	unsigned long long current_size = 0;
 
 	for (i = 0; i < e820.nr_map; i++) {
 		if (e820.map[i].type == E820_RAM) {
-			current_size += e820.map[i].size;
-			if (current_size >= size) {
-				e820.map[i].size -= current_size-size;
+			current_addr = e820.map[i].addr + e820.map[i].size;
+			if (current_addr >= size) {
+				e820.map[i].size -= current_addr-size;
 				e820.nr_map = i + 1;
 				return;
 			}
drivers/mtd/mtdblock.c +1 -1
@@ -248,7 +248,7 @@ static int mtdblock_writesect(struct mtd
 			      unsigned long block, char *buf)
 {
 	struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
-	if (unlikely(!mtdblk->cache_data)) {
+	if (unlikely(!mtdblk->cache_data && mtdblk->mtd->erasesize)) {
 		mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
 		if (!mtdblk->cache_data)
 			return -EINTR;