aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/resource.c
diff options
context:
space:
mode:
authorToshi Kani <toshi.kani@hpe.com>2016-03-09 14:47:04 -0500
committerDan Williams <dan.j.williams@intel.com>2016-03-09 14:07:20 -0500
commitff3cc952d3f009e6c376cc40651b87187ce364a6 (patch)
treec0b685a62ea8908bfdab98dc372bfe75fd0f291e /kernel/resource.c
parent4e0d8f7eff3fbfa3e3ac5782669c078f590dc9e2 (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.c51
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
236static int __release_resource(struct resource *old) 236static 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 */
829struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) 842struct 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 */
846int insert_resource(struct resource *parent, struct resource *new) 862int 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 */
919int 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
888static int __adjust_resource(struct resource *res, resource_size_t start, 929static int __adjust_resource(struct resource *res, resource_size_t start,
889 resource_size_t size) 930 resource_size_t size)
890{ 931{