mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
Resource handling: add 'insert_resource_expand_to_fit()' function
Not used anywhere yet, but this complements the existing plain 'insert_resource()' functionality with a version that can expand the resource we are adding in order to fix up any conflicts it has with existing resources. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
00aeb429a0
commit
bef69ea0dc
2 changed files with 64 additions and 25 deletions
|
@ -109,6 +109,7 @@ extern struct resource iomem_resource;
|
||||||
extern int request_resource(struct resource *root, struct resource *new);
|
extern int request_resource(struct resource *root, struct resource *new);
|
||||||
extern int release_resource(struct resource *new);
|
extern int release_resource(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 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,
|
||||||
resource_size_t max, resource_size_t align,
|
resource_size_t max, resource_size_t align,
|
||||||
|
|
|
@ -362,35 +362,21 @@ int allocate_resource(struct resource *root, struct resource *new,
|
||||||
|
|
||||||
EXPORT_SYMBOL(allocate_resource);
|
EXPORT_SYMBOL(allocate_resource);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* insert_resource - Inserts a resource in the resource tree
|
* Insert a resource into the resource tree. If successful, return NULL,
|
||||||
* @parent: parent of the new resource
|
* otherwise return the conflicting resource (compare to __request_resource())
|
||||||
* @new: new resource to insert
|
|
||||||
*
|
|
||||||
* Returns 0 on success, -EBUSY if the resource can't be inserted.
|
|
||||||
*
|
|
||||||
* This function is equivalent to request_resource when no conflict
|
|
||||||
* happens. If a conflict happens, and the conflicting resources
|
|
||||||
* entirely fit within the range of the new resource, then the new
|
|
||||||
* resource is inserted and the conflicting resources become children of
|
|
||||||
* the new resource.
|
|
||||||
*/
|
*/
|
||||||
int insert_resource(struct resource *parent, struct resource *new)
|
static struct resource * __insert_resource(struct resource *parent, struct resource *new)
|
||||||
{
|
{
|
||||||
int result;
|
|
||||||
struct resource *first, *next;
|
struct resource *first, *next;
|
||||||
|
|
||||||
write_lock(&resource_lock);
|
|
||||||
|
|
||||||
for (;; parent = first) {
|
for (;; parent = first) {
|
||||||
result = 0;
|
|
||||||
first = __request_resource(parent, new);
|
first = __request_resource(parent, new);
|
||||||
if (!first)
|
if (!first)
|
||||||
goto out;
|
return first;
|
||||||
|
|
||||||
result = -EBUSY;
|
|
||||||
if (first == parent)
|
if (first == parent)
|
||||||
goto out;
|
return first;
|
||||||
|
|
||||||
if ((first->start > new->start) || (first->end < new->end))
|
if ((first->start > new->start) || (first->end < new->end))
|
||||||
break;
|
break;
|
||||||
|
@ -401,15 +387,13 @@ int insert_resource(struct resource *parent, struct resource *new)
|
||||||
for (next = first; ; next = next->sibling) {
|
for (next = first; ; next = next->sibling) {
|
||||||
/* Partial overlap? Bad, and unfixable */
|
/* Partial overlap? Bad, and unfixable */
|
||||||
if (next->start < new->start || next->end > new->end)
|
if (next->start < new->start || next->end > new->end)
|
||||||
goto out;
|
return next;
|
||||||
if (!next->sibling)
|
if (!next->sibling)
|
||||||
break;
|
break;
|
||||||
if (next->sibling->start > new->end)
|
if (next->sibling->start > new->end)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = 0;
|
|
||||||
|
|
||||||
new->parent = parent;
|
new->parent = parent;
|
||||||
new->sibling = next->sibling;
|
new->sibling = next->sibling;
|
||||||
new->child = first;
|
new->child = first;
|
||||||
|
@ -426,10 +410,64 @@ int insert_resource(struct resource *parent, struct resource *new)
|
||||||
next = next->sibling;
|
next = next->sibling;
|
||||||
next->sibling = new;
|
next->sibling = new;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
/**
|
||||||
|
* insert_resource - Inserts a resource in the resource tree
|
||||||
|
* @parent: parent of the new resource
|
||||||
|
* @new: new resource to insert
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -EBUSY if the resource can't be inserted.
|
||||||
|
*
|
||||||
|
* This function is equivalent to request_resource when no conflict
|
||||||
|
* happens. If a conflict happens, and the conflicting resources
|
||||||
|
* entirely fit within the range of the new resource, then the new
|
||||||
|
* resource is inserted and the conflicting resources become children of
|
||||||
|
* the new resource.
|
||||||
|
*/
|
||||||
|
int insert_resource(struct resource *parent, struct resource *new)
|
||||||
|
{
|
||||||
|
struct resource *conflict;
|
||||||
|
|
||||||
|
write_lock(&resource_lock);
|
||||||
|
conflict = __insert_resource(parent, new);
|
||||||
|
write_unlock(&resource_lock);
|
||||||
|
return conflict ? -EBUSY : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert_resource_expand_to_fit - Insert a resource into the resource tree
|
||||||
|
* @parent: parent of the new resource
|
||||||
|
* @new: new resource to insert
|
||||||
|
*
|
||||||
|
* Insert a resource into the resource tree, possibly expanding it in order
|
||||||
|
* to make it encompass any conflicting resources.
|
||||||
|
*/
|
||||||
|
void insert_resource_expand_to_fit(struct resource *root, struct resource *new)
|
||||||
|
{
|
||||||
|
if (new->parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
write_lock(&resource_lock);
|
||||||
|
for (;;) {
|
||||||
|
struct resource *conflict;
|
||||||
|
|
||||||
|
conflict = __insert_resource(root, new);
|
||||||
|
if (!conflict)
|
||||||
|
break;
|
||||||
|
if (conflict == root)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Ok, expand resource to cover the conflict, then try again .. */
|
||||||
|
if (conflict->start < new->start)
|
||||||
|
new->start = conflict->start;
|
||||||
|
if (conflict->end > new->end)
|
||||||
|
new->end = conflict->end;
|
||||||
|
|
||||||
|
printk("Expanded resource %s due to conflict with %s\n", new->name, conflict->name);
|
||||||
|
}
|
||||||
write_unlock(&resource_lock);
|
write_unlock(&resource_lock);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue