lkml.org 
[lkml]   [2003]   [Oct]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Subject[BUG][PATCH] BIOS reserved regions block iomem registration
From
Date
arch/i386/kernel/setup.c:register_memory() marks e820 memory regions -
some of which are "reserved". These "reserved" regions prevent FLASH
chip drivers from registering the memory range occupied by BIOS code:

bash-2.05# cat /proc/iomem
.
.
.
fec00000-fec003ff : reserved
fee00000-fee00fff : reserved
fff80000-ffffffff : reserved

The last range marked as "reserved" (fff80000-ffffffff) is occupied by
the FLASH chip containing the BIOS code. I'd like the MTD drivers to
register the correct ranges like this:

fec00000-fec003ff : reserved
fee00000-fee00fff : reserved
ffb00000-ffffffff : amd76xrom
fff80000-ffffffff : mtd0

That way the iomem resources will be correct and can be used to map
FLASH chip updates.

There are at least two ways to fix this problem:

1) Don't mark the BIOS reserved regions. Some BIOSes don't mark these
and the kernel works fine. This is a trivial patch of removing the
"reserved" line in setup.c:register_memory(). See
remove_reserved.patch.

2) Leave the "reserved" regions but mark them with a IORESOURCE_GUESS so
that they can be removed by a driver that knows better and is capable of
correctly using the memory range. See resource_guess_flag.patch.

Both of these patches were made on 2.4.20, but will likely apply
trivially to any 2.4.x or 2.6.


--
Thayne Harbaugh
Linux Networx
--- linux-2.4.20/arch/i386/kernel/setup.c 2002-11-28 16:53:09.000000000 -0700
+++ linux-2.4.20-bs/arch/i386/kernel/setup.c 2003-10-17 12:01:12.000000000 -0600
@@ -1047,7 +1047,6 @@
case E820_RAM: res->name = "System RAM"; break;
case E820_ACPI: res->name = "ACPI Tables"; break;
case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
- default: res->name = "reserved";
}
res->start = e820.map[i].addr;
res->end = res->start + e820.map[i].size - 1;--- linux-2.4.20/kernel/resource.c 2002-11-28 16:53:15.000000000 -0700
+++ linux-2.4.20-bs/kernel/resource.c 2003-10-16 16:17:15.000000000 -0600
@@ -70,6 +70,8 @@
unsigned long end = new->end;
struct resource *tmp, **p;

+ if (root->flags & IORESOURCE_GUESS)
+ return root;
if (end < start)
return root;
if (start < root->start)
@@ -121,6 +123,70 @@
return conflict ? -EBUSY : 0;
}

+int request_resource_remove_guess(struct resource *root, struct resource *new)
+{
+ struct resource *conflict, *sibling, *conflict_head = NULL;
+ int rc = -EBUSY;
+
+ write_lock(&resource_lock);
+ for (;;) {
+ conflict = __request_resource(root, new);
+ if (! conflict) {
+ /* success - free any IORESOURCE_GUESS resources */
+#if 0
+/* this doesn't work because the resources are alloc_bootmem_low() */
+ while (conflict_head) {
+ sibling = conflict_head->sibling;
+ kfree(conflict_head);
+ conflict_head = sibling;
+ }
+#endif
+ rc = 0;
+ break;
+ }
+ /* something is in the way - check to see what it is */
+ if (conflict->flags & IORESOURCE_GUESS) {
+ /* It's a guess that can be removed */
+ if (__release_resource(conflict)) {
+ printk(KERN_ERR __FILE__
+ " %s(): unable to remove conflict:"
+ " %s %08lx-%08lx\n",
+ __func__,
+ conflict_head->name,
+ conflict_head->start,
+ conflict_head->end);
+ break;
+ }
+ conflict->sibling = conflict_head;
+ conflict_head = conflict;
+ continue;
+ }
+ /* Can't remove the conflict */
+ break;
+ }
+
+ /* If we have anything then put it back */
+ while (conflict_head) {
+ sibling = conflict_head->sibling;
+ if ((conflict = __request_resource(root, conflict_head))) {
+ /* We hold the lock so why can't the
+ resource be replaced? */
+ printk(KERN_ERR __FILE__
+ " %s(): failed to replace resource:"
+ " %s %08lx-%08lx\n",
+ __func__,
+ conflict_head->name,
+ conflict_head->start,
+ conflict_head->end);
+ kfree(conflict);
+ }
+ conflict_head = sibling;
+ }
+
+ write_unlock(&resource_lock);
+ return rc;
+}
+
int release_resource(struct resource *old)
{
int retval;
--- linux-2.4.20/include/linux/ioport.h 2002-11-28 16:53:15.000000000 -0700
+++ linux-2.4.20-bs/include/linux/ioport.h 2003-10-16 10:15:53.000000000 -0600
@@ -42,6 +42,15 @@
#define IORESOURCE_SHADOWABLE 0x00010000
#define IORESOURCE_BUS_HAS_VGA 0x00080000

+#define IORESOURCE_GUESS 0x08000000 /* These regions are reserved
+ but it's unknown if it's
+ 100% accurate. Must not have
+ children. Can be removed by
+ request_resource_remove_guess()
+ which will also kfree() the
+ resource - handles for these
+ aren't tracked by anything. */
+
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
@@ -87,6 +96,7 @@

extern int check_resource(struct resource *root, unsigned long, unsigned long);
extern int request_resource(struct resource *root, struct resource *new);
+extern int request_resource_remove_guess(struct resource *root, struct resource *new);
extern int release_resource(struct resource *new);
extern int allocate_resource(struct resource *root, struct resource *new,
unsigned long size,
--- linux-2.4.20/kernel/ksyms.c 2003-06-18 17:04:08.000000000 -0600
+++ linux-2.4.20-bs/kernel/ksyms.c 2003-10-16 10:58:15.000000000 -0600
@@ -431,6 +431,7 @@

/* resource handling */
EXPORT_SYMBOL(request_resource);
+EXPORT_SYMBOL(request_resource_remove_guess);
EXPORT_SYMBOL(release_resource);
EXPORT_SYMBOL(allocate_resource);
EXPORT_SYMBOL(check_resource);[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2005-03-22 13:58    [W:0.060 / U:0.444 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site