Commit ff3cc952 authored by Toshi Kani's avatar Toshi Kani Committed by Dan Williams

resource: Add remove_resource interface

insert_resource() and insert_resource_conflict() are called
by resource producers to insert a new resource.  When there
is any conflict, they move conflicting resources down to the
children of the new resource.  There is no destructor of these
interfaces, however.

Add remove_resource(), which removes a resource previously
inserted by insert_resource() or insert_resource_conflict(),
and moves the children up to where they were before.

__release_resource() is changed to have @release_child, so
that this function can be used for remove_resource() as well.

Also add comments to clarify that these functions are intended
for producers of resources to avoid any confusion with
request/release_resource() for consumers.
Signed-off-by: default avatarToshi Kani <toshi.kani@hpe.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 4e0d8f7e
...@@ -174,6 +174,7 @@ extern void reserve_region_with_split(struct resource *root, ...@@ -174,6 +174,7 @@ extern void reserve_region_with_split(struct resource *root,
extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new); extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);
extern int insert_resource(struct resource *parent, struct resource *new); extern int insert_resource(struct resource *parent, struct resource *new);
extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new);
extern int remove_resource(struct resource *old);
extern void arch_remove_reservations(struct resource *avail); extern void arch_remove_reservations(struct resource *avail);
extern int allocate_resource(struct resource *root, struct resource *new, extern int allocate_resource(struct resource *root, struct resource *new,
resource_size_t size, resource_size_t min, resource_size_t size, resource_size_t min,
......
...@@ -233,9 +233,9 @@ static struct resource * __request_resource(struct resource *root, struct resour ...@@ -233,9 +233,9 @@ static struct resource * __request_resource(struct resource *root, struct resour
} }
} }
static int __release_resource(struct resource *old) static int __release_resource(struct resource *old, bool release_child)
{ {
struct resource *tmp, **p; struct resource *tmp, **p, *chd;
p = &old->parent->child; p = &old->parent->child;
for (;;) { for (;;) {
...@@ -243,7 +243,17 @@ static int __release_resource(struct resource *old) ...@@ -243,7 +243,17 @@ static int __release_resource(struct resource *old)
if (!tmp) if (!tmp)
break; break;
if (tmp == old) { if (tmp == old) {
*p = tmp->sibling; if (release_child || !(tmp->child)) {
*p = tmp->sibling;
} else {
for (chd = tmp->child;; chd = chd->sibling) {
chd->parent = tmp->parent;
if (!(chd->sibling))
break;
}
*p = tmp->child;
chd->sibling = tmp->sibling;
}
old->parent = NULL; old->parent = NULL;
return 0; return 0;
} }
...@@ -325,7 +335,7 @@ int release_resource(struct resource *old) ...@@ -325,7 +335,7 @@ int release_resource(struct resource *old)
int retval; int retval;
write_lock(&resource_lock); write_lock(&resource_lock);
retval = __release_resource(old); retval = __release_resource(old, true);
write_unlock(&resource_lock); write_unlock(&resource_lock);
return retval; return retval;
} }
...@@ -679,7 +689,7 @@ static int reallocate_resource(struct resource *root, struct resource *old, ...@@ -679,7 +689,7 @@ static int reallocate_resource(struct resource *root, struct resource *old,
old->start = new.start; old->start = new.start;
old->end = new.end; old->end = new.end;
} else { } else {
__release_resource(old); __release_resource(old, true);
*old = new; *old = new;
conflict = __request_resource(root, old); conflict = __request_resource(root, old);
BUG_ON(conflict); BUG_ON(conflict);
...@@ -825,6 +835,9 @@ static struct resource * __insert_resource(struct resource *parent, struct resou ...@@ -825,6 +835,9 @@ static struct resource * __insert_resource(struct resource *parent, struct resou
* entirely fit within the range of the new resource, then the new * entirely fit within the range of the new resource, then the new
* resource is inserted and the conflicting resources become children of * resource is inserted and the conflicting resources become children of
* the new resource. * the new resource.
*
* This function is intended for producers of resources, such as FW modules
* and bus drivers.
*/ */
struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) struct resource *insert_resource_conflict(struct resource *parent, struct resource *new)
{ {
...@@ -842,6 +855,9 @@ struct resource *insert_resource_conflict(struct resource *parent, struct resour ...@@ -842,6 +855,9 @@ struct resource *insert_resource_conflict(struct resource *parent, struct resour
* @new: new resource to insert * @new: new resource to insert
* *
* Returns 0 on success, -EBUSY if the resource can't be inserted. * Returns 0 on success, -EBUSY if the resource can't be inserted.
*
* This function is intended for producers of resources, such as FW modules
* and bus drivers.
*/ */
int insert_resource(struct resource *parent, struct resource *new) int insert_resource(struct resource *parent, struct resource *new)
{ {
...@@ -885,6 +901,31 @@ void insert_resource_expand_to_fit(struct resource *root, struct resource *new) ...@@ -885,6 +901,31 @@ void insert_resource_expand_to_fit(struct resource *root, struct resource *new)
write_unlock(&resource_lock); write_unlock(&resource_lock);
} }
/**
* remove_resource - Remove a resource in the resource tree
* @old: resource to remove
*
* Returns 0 on success, -EINVAL if the resource is not valid.
*
* This function removes a resource previously inserted by insert_resource()
* or insert_resource_conflict(), and moves the children (if any) up to
* where they were before. insert_resource() and insert_resource_conflict()
* insert a new resource, and move any conflicting resources down to the
* children of the new resource.
*
* insert_resource(), insert_resource_conflict() and remove_resource() are
* intended for producers of resources, such as FW modules and bus drivers.
*/
int remove_resource(struct resource *old)
{
int retval;
write_lock(&resource_lock);
retval = __release_resource(old, false);
write_unlock(&resource_lock);
return retval;
}
static int __adjust_resource(struct resource *res, resource_size_t start, static int __adjust_resource(struct resource *res, resource_size_t start,
resource_size_t size) resource_size_t size)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment