[PATCH] IO resources: add sticky resource type

From: Yinghai Lu
Date: Wed Aug 27 2008 - 21:56:23 EST


Ingo suggested to use sticky resource type to record fixed resource.
That way we could check that BAR in the PCI init code and avoid updating
it after request_resource failed.

That way we could remove some tricky code about insert some platform
resources with late_initcall.

Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
---
include/linux/ioport.h | 3 ++
kernel/resource.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 22d2115..db53613 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -48,6 +48,8 @@ struct resource_list {
#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */
#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */

+#define IORESOURCE_STICKY 0x08000000
+
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000
@@ -109,6 +111,7 @@ extern struct resource iomem_resource;
extern int request_resource(struct resource *root, struct resource *new);
extern int release_resource(struct resource *new);
extern int insert_resource(struct resource *parent, struct resource *new);
+extern struct resource *check_sticky_resource(struct resource *bar_res);
extern int allocate_resource(struct resource *root, struct resource *new,
resource_size_t size, resource_size_t min,
resource_size_t max, resource_size_t align,
diff --git a/kernel/resource.c b/kernel/resource.c
index f5b518e..957afa7 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -586,6 +586,64 @@ int __check_region(struct resource *parent, resource_size_t start,
EXPORT_SYMBOL(__check_region);

/**
+ * check_sticky_resource
+ * @bar_res: target resource descriptor
+ *
+ * return res: identical to bar_res, or overlapping it
+ */
+struct resource *check_sticky_resource(struct resource *bar_res)
+{
+ struct resource *parent;
+ struct resource *res;
+
+ if (bar_res->flags | IORESOURCE_MEM)
+ parent = &iomem_resource;
+ else if (bar_res->flags | IORESOURCE_IO)
+ parent = &ioport_resource;
+ else
+ return NULL;
+
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (res) {
+ res->name = bar_res->name;
+ res->start = bar_res->start;
+ res->end = bar_res->end;
+ res->flags = bar_res->flags | IORESOURCE_BUSY;
+
+ write_lock(&resource_lock);
+
+ for (;;) {
+ struct resource *conflict;
+
+ conflict = __request_resource(parent, res);
+ if (!conflict) {
+ /* not found */
+ break;
+ }
+ if (conflict != parent) {
+ parent = conflict;
+ if (!(conflict->flags & IORESOURCE_STICKY))
+ continue;
+ } else {
+ parent = NULL;
+ }
+
+ kfree(res);
+ res = NULL;
+ break;
+ }
+ write_unlock(&resource_lock);
+ }
+
+ if (res) {
+ release_resource(res);
+ kfree(res);
+ }
+
+ return parent;
+}
+
+/**
* __release_region - release a previously reserved resource region
* @parent: parent resource descriptor
* @start: resource start address

----------------------->