diff options
author | Toshi Kani <toshi.kani@hpe.com> | 2016-03-09 14:47:04 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-03-09 14:07:20 -0500 |
commit | ff3cc952d3f009e6c376cc40651b87187ce364a6 (patch) | |
tree | c0b685a62ea8908bfdab98dc372bfe75fd0f291e /kernel/resource.c | |
parent | 4e0d8f7eff3fbfa3e3ac5782669c078f590dc9e2 (diff) |
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: Toshi 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: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index 5a56e8f24058..effb6ee2c3e8 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -233,9 +233,9 @@ static struct resource * __request_resource(struct resource *root, struct resour | |||
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | static int __release_resource(struct resource *old) | 236 | static int __release_resource(struct resource *old, bool release_child) |
237 | { | 237 | { |
238 | struct resource *tmp, **p; | 238 | struct resource *tmp, **p, *chd; |
239 | 239 | ||
240 | p = &old->parent->child; | 240 | p = &old->parent->child; |
241 | for (;;) { | 241 | for (;;) { |
@@ -243,7 +243,17 @@ static int __release_resource(struct resource *old) | |||
243 | if (!tmp) | 243 | if (!tmp) |
244 | break; | 244 | break; |
245 | if (tmp == old) { | 245 | if (tmp == old) { |
246 | *p = tmp->sibling; | 246 | if (release_child || !(tmp->child)) { |
247 | *p = tmp->sibling; | ||
248 | } else { | ||
249 | for (chd = tmp->child;; chd = chd->sibling) { | ||
250 | chd->parent = tmp->parent; | ||
251 | if (!(chd->sibling)) | ||
252 | break; | ||
253 | } | ||
254 | *p = tmp->child; | ||
255 | chd->sibling = tmp->sibling; | ||
256 | } | ||
247 | old->parent = NULL; | 257 | old->parent = NULL; |
248 | return 0; | 258 | return 0; |
249 | } | 259 | } |
@@ -325,7 +335,7 @@ int release_resource(struct resource *old) | |||
325 | int retval; | 335 | int retval; |
326 | 336 | ||
327 | write_lock(&resource_lock); | 337 | write_lock(&resource_lock); |
328 | retval = __release_resource(old); | 338 | retval = __release_resource(old, true); |
329 | write_unlock(&resource_lock); | 339 | write_unlock(&resource_lock); |
330 | return retval; | 340 | return retval; |
331 | } | 341 | } |
@@ -679,7 +689,7 @@ static int reallocate_resource(struct resource *root, struct resource *old, | |||
679 | old->start = new.start; | 689 | old->start = new.start; |
680 | old->end = new.end; | 690 | old->end = new.end; |
681 | } else { | 691 | } else { |
682 | __release_resource(old); | 692 | __release_resource(old, true); |
683 | *old = new; | 693 | *old = new; |
684 | conflict = __request_resource(root, old); | 694 | conflict = __request_resource(root, old); |
685 | BUG_ON(conflict); | 695 | BUG_ON(conflict); |
@@ -825,6 +835,9 @@ static struct resource * __insert_resource(struct resource *parent, struct resou | |||
825 | * entirely fit within the range of the new resource, then the new | 835 | * entirely fit within the range of the new resource, then the new |
826 | * resource is inserted and the conflicting resources become children of | 836 | * resource is inserted and the conflicting resources become children of |
827 | * the new resource. | 837 | * the new resource. |
838 | * | ||
839 | * This function is intended for producers of resources, such as FW modules | ||
840 | * and bus drivers. | ||
828 | */ | 841 | */ |
829 | struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) | 842 | struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) |
830 | { | 843 | { |
@@ -842,6 +855,9 @@ struct resource *insert_resource_conflict(struct resource *parent, struct resour | |||
842 | * @new: new resource to insert | 855 | * @new: new resource to insert |
843 | * | 856 | * |
844 | * Returns 0 on success, -EBUSY if the resource can't be inserted. | 857 | * Returns 0 on success, -EBUSY if the resource can't be inserted. |
858 | * | ||
859 | * This function is intended for producers of resources, such as FW modules | ||
860 | * and bus drivers. | ||
845 | */ | 861 | */ |
846 | int insert_resource(struct resource *parent, struct resource *new) | 862 | int insert_resource(struct resource *parent, struct resource *new) |
847 | { | 863 | { |
@@ -885,6 +901,31 @@ void insert_resource_expand_to_fit(struct resource *root, struct resource *new) | |||
885 | write_unlock(&resource_lock); | 901 | write_unlock(&resource_lock); |
886 | } | 902 | } |
887 | 903 | ||
904 | /** | ||
905 | * remove_resource - Remove a resource in the resource tree | ||
906 | * @old: resource to remove | ||
907 | * | ||
908 | * Returns 0 on success, -EINVAL if the resource is not valid. | ||
909 | * | ||
910 | * This function removes a resource previously inserted by insert_resource() | ||
911 | * or insert_resource_conflict(), and moves the children (if any) up to | ||
912 | * where they were before. insert_resource() and insert_resource_conflict() | ||
913 | * insert a new resource, and move any conflicting resources down to the | ||
914 | * children of the new resource. | ||
915 | * | ||
916 | * insert_resource(), insert_resource_conflict() and remove_resource() are | ||
917 | * intended for producers of resources, such as FW modules and bus drivers. | ||
918 | */ | ||
919 | int remove_resource(struct resource *old) | ||
920 | { | ||
921 | int retval; | ||
922 | |||
923 | write_lock(&resource_lock); | ||
924 | retval = __release_resource(old, false); | ||
925 | write_unlock(&resource_lock); | ||
926 | return retval; | ||
927 | } | ||
928 | |||
888 | static int __adjust_resource(struct resource *res, resource_size_t start, | 929 | static int __adjust_resource(struct resource *res, resource_size_t start, |
889 | resource_size_t size) | 930 | resource_size_t size) |
890 | { | 931 | { |