Currently, if __region_intersects() finds any overlapped but unmatched resource, it walks the descendant resource tree to check for overlapped and matched descendant resources. This is achieved using for_each_resource(), which iterates not only the descent tree, but also subsequent sibling trees in certain scenarios. While this doesn't introduce bugs, it makes code hard to be understood and potentially inefficient. So, the patch renames next_resource() to __next_resource() and modified it to return NULL after traversing all descent resources. Test shows that this avoids unnecessary resource tree walking in __region_intersects(). It appears even better to revise for_each_resource() to traverse the descendant resource tree of "_root" only. But that will cause "_root" to be evaluated twice, which I don't find a good way to eliminate. Signed-off-by: "Huang, Ying" <ying.huang@xxxxxxxxx> Cc: Dan Williams <dan.j.williams@xxxxxxxxx> Cc: David Hildenbrand <david@xxxxxxxxxx> Cc: Davidlohr Bueso <dave@xxxxxxxxxxxx> Cc: Jonathan Cameron <jonathan.cameron@xxxxxxxxxx> Cc: Alistair Popple <apopple@xxxxxxxxxx> Cc: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> Cc: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> Cc: Baoquan He <bhe@xxxxxxxxxx> Cc: Dave Jiang <dave.jiang@xxxxxxxxx> Cc: Alison Schofield <alison.schofield@xxxxxxxxx> --- kernel/resource.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index b730bd28b422..3ded4c5d4418 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -50,15 +50,28 @@ EXPORT_SYMBOL(iomem_resource); static DEFINE_RWLOCK(resource_lock); -static struct resource *next_resource(struct resource *p, bool skip_children) +static struct resource *__next_resource(struct resource *root, struct resource *p, + bool skip_children) { if (!skip_children && p->child) return p->child; - while (!p->sibling && p->parent) + while (!p->sibling && p->parent) { p = p->parent; + if (p == root) + return NULL; + } return p->sibling; } +static struct resource *next_resource(struct resource *p, bool skip_children) +{ + return __next_resource(NULL, p, skip_children); +} + +/* + * Traverse the whole resource tree (NOTE: not descendant tree under + * _root) from _root->child on. + */ #define for_each_resource(_root, _p, _skip_children) \ for ((_p) = (_root)->child; (_p); (_p) = next_resource(_p, _skip_children)) @@ -572,7 +585,7 @@ static int __region_intersects(struct resource *parent, resource_size_t start, covered = false; ostart = max(res.start, p->start); oend = min(res.end, p->end); - for_each_resource(p, dp, false) { + for (dp = p->child; dp; dp = __next_resource(p, dp, false)) { if (!resource_overlaps(dp, &res)) continue; is_type = (dp->flags & flags) == flags && -- 2.39.2