Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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,
+46 −5
Original line number Original line Diff line number Diff line
@@ -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)
		if (!tmp)
		if (!tmp)
			break;
			break;
		if (tmp == old) {
		if (tmp == old) {
			if (release_child || !(tmp->child)) {
				*p = tmp->sibling;
				*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)
	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,
		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
 * 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
 * @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)
	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)
{
{