diff options
author | Toshi Kani <toshi.kani@hpe.com> | 2016-01-26 15:57:29 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-01-30 03:49:59 -0500 |
commit | 3f33647c41962401272bb60dce67e6094d14dbf2 (patch) | |
tree | 084429f03c621440e3b870c306d508b65d183a6d /kernel/resource.c | |
parent | 1c29f25bf5d6c557017f619b638c619cbbf798c4 (diff) |
resource: Add walk_iomem_res_desc()
Add a new interface, walk_iomem_res_desc(), which walks through
the iomem table by identifying a target with @flags and @desc.
This interface provides the same functionality as
walk_iomem_res(), but does not use strcmp() to @name for better
efficiency.
walk_iomem_res() is deprecated and will be removed in a later
patch.
Requested-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
[ Fixup comments. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Jakub Sitnicki <jsitnicki@gmail.com>
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Toshi Kani <toshi.kani@hp.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-mm <linux-mm@kvack.org>
Link: http://lkml.kernel.org/r/1453841853-11383-14-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index 0041cedc47d6..37ed2fcb8246 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -333,14 +333,15 @@ int release_resource(struct resource *old) | |||
333 | EXPORT_SYMBOL(release_resource); | 333 | EXPORT_SYMBOL(release_resource); |
334 | 334 | ||
335 | /* | 335 | /* |
336 | * Finds the lowest iomem reosurce exists with-in [res->start.res->end) | 336 | * Finds the lowest iomem resource existing within [res->start.res->end). |
337 | * the caller must specify res->start, res->end, res->flags and "name". | 337 | * The caller must specify res->start, res->end, res->flags, and optionally |
338 | * If found, returns 0, res is overwritten, if not found, returns -1. | 338 | * desc and "name". If found, returns 0, res is overwritten, if not found, |
339 | * This walks through whole tree and not just first level children | 339 | * returns -1. |
340 | * until and unless first_level_children_only is true. | 340 | * This function walks the whole tree and not just first level children until |
341 | * and unless first_level_children_only is true. | ||
341 | */ | 342 | */ |
342 | static int find_next_iomem_res(struct resource *res, char *name, | 343 | static int find_next_iomem_res(struct resource *res, unsigned long desc, |
343 | bool first_level_children_only) | 344 | char *name, bool first_level_children_only) |
344 | { | 345 | { |
345 | resource_size_t start, end; | 346 | resource_size_t start, end; |
346 | struct resource *p; | 347 | struct resource *p; |
@@ -360,6 +361,8 @@ static int find_next_iomem_res(struct resource *res, char *name, | |||
360 | for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) { | 361 | for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) { |
361 | if ((p->flags & res->flags) != res->flags) | 362 | if ((p->flags & res->flags) != res->flags) |
362 | continue; | 363 | continue; |
364 | if ((desc != IORES_DESC_NONE) && (desc != p->desc)) | ||
365 | continue; | ||
363 | if (name && strcmp(p->name, name)) | 366 | if (name && strcmp(p->name, name)) |
364 | continue; | 367 | continue; |
365 | if (p->start > end) { | 368 | if (p->start > end) { |
@@ -385,12 +388,55 @@ static int find_next_iomem_res(struct resource *res, char *name, | |||
385 | * Walks through iomem resources and calls func() with matching resource | 388 | * Walks through iomem resources and calls func() with matching resource |
386 | * ranges. This walks through whole tree and not just first level children. | 389 | * ranges. This walks through whole tree and not just first level children. |
387 | * All the memory ranges which overlap start,end and also match flags and | 390 | * All the memory ranges which overlap start,end and also match flags and |
391 | * desc are valid candidates. | ||
392 | * | ||
393 | * @desc: I/O resource descriptor. Use IORES_DESC_NONE to skip @desc check. | ||
394 | * @flags: I/O resource flags | ||
395 | * @start: start addr | ||
396 | * @end: end addr | ||
397 | * | ||
398 | * NOTE: For a new descriptor search, define a new IORES_DESC in | ||
399 | * <linux/ioport.h> and set it in 'desc' of a target resource entry. | ||
400 | */ | ||
401 | int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, | ||
402 | u64 end, void *arg, int (*func)(u64, u64, void *)) | ||
403 | { | ||
404 | struct resource res; | ||
405 | u64 orig_end; | ||
406 | int ret = -1; | ||
407 | |||
408 | res.start = start; | ||
409 | res.end = end; | ||
410 | res.flags = flags; | ||
411 | orig_end = res.end; | ||
412 | |||
413 | while ((res.start < res.end) && | ||
414 | (!find_next_iomem_res(&res, desc, NULL, false))) { | ||
415 | |||
416 | ret = (*func)(res.start, res.end, arg); | ||
417 | if (ret) | ||
418 | break; | ||
419 | |||
420 | res.start = res.end + 1; | ||
421 | res.end = orig_end; | ||
422 | } | ||
423 | |||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * Walks through iomem resources and calls @func with matching resource | ||
429 | * ranges. This walks the whole tree and not just first level children. | ||
430 | * All the memory ranges which overlap start,end and also match flags and | ||
388 | * name are valid candidates. | 431 | * name are valid candidates. |
389 | * | 432 | * |
390 | * @name: name of resource | 433 | * @name: name of resource |
391 | * @flags: resource flags | 434 | * @flags: resource flags |
392 | * @start: start addr | 435 | * @start: start addr |
393 | * @end: end addr | 436 | * @end: end addr |
437 | * | ||
438 | * NOTE: This function is deprecated and should not be used in new code. | ||
439 | * Use walk_iomem_res_desc(), instead. | ||
394 | */ | 440 | */ |
395 | int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, | 441 | int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, |
396 | void *arg, int (*func)(u64, u64, void *)) | 442 | void *arg, int (*func)(u64, u64, void *)) |
@@ -404,7 +450,7 @@ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, | |||
404 | res.flags = flags; | 450 | res.flags = flags; |
405 | orig_end = res.end; | 451 | orig_end = res.end; |
406 | while ((res.start < res.end) && | 452 | while ((res.start < res.end) && |
407 | (!find_next_iomem_res(&res, name, false))) { | 453 | (!find_next_iomem_res(&res, IORES_DESC_NONE, name, false))) { |
408 | ret = (*func)(res.start, res.end, arg); | 454 | ret = (*func)(res.start, res.end, arg); |
409 | if (ret) | 455 | if (ret) |
410 | break; | 456 | break; |
@@ -433,7 +479,7 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, | |||
433 | res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; | 479 | res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; |
434 | orig_end = res.end; | 480 | orig_end = res.end; |
435 | while ((res.start < res.end) && | 481 | while ((res.start < res.end) && |
436 | (!find_next_iomem_res(&res, NULL, true))) { | 482 | (!find_next_iomem_res(&res, IORES_DESC_NONE, NULL, true))) { |
437 | ret = (*func)(res.start, res.end, arg); | 483 | ret = (*func)(res.start, res.end, arg); |
438 | if (ret) | 484 | if (ret) |
439 | break; | 485 | break; |
@@ -463,7 +509,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | |||
463 | res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; | 509 | res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; |
464 | orig_end = res.end; | 510 | orig_end = res.end; |
465 | while ((res.start < res.end) && | 511 | while ((res.start < res.end) && |
466 | (find_next_iomem_res(&res, NULL, true) >= 0)) { | 512 | (find_next_iomem_res(&res, IORES_DESC_NONE, NULL, true) >= 0)) { |
467 | pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; | 513 | pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; |
468 | end_pfn = (res.end + 1) >> PAGE_SHIFT; | 514 | end_pfn = (res.end + 1) >> PAGE_SHIFT; |
469 | if (end_pfn > pfn) | 515 | if (end_pfn > pfn) |