diff options
Diffstat (limited to 'kernel/resource.c')
| -rw-r--r-- | kernel/resource.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index e1d2b8ee76d5..34d45886ee84 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | * Arbitrary resource management. | 7 | * Arbitrary resource management. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 11 | |||
| 10 | #include <linux/export.h> | 12 | #include <linux/export.h> |
| 11 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 12 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
| @@ -722,14 +724,12 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t | |||
| 722 | 724 | ||
| 723 | write_lock(&resource_lock); | 725 | write_lock(&resource_lock); |
| 724 | 726 | ||
| 727 | if (!parent) | ||
| 728 | goto skip; | ||
| 729 | |||
| 725 | if ((start < parent->start) || (end > parent->end)) | 730 | if ((start < parent->start) || (end > parent->end)) |
| 726 | goto out; | 731 | goto out; |
| 727 | 732 | ||
| 728 | for (tmp = res->child; tmp; tmp = tmp->sibling) { | ||
| 729 | if ((tmp->start < start) || (tmp->end > end)) | ||
| 730 | goto out; | ||
| 731 | } | ||
| 732 | |||
| 733 | if (res->sibling && (res->sibling->start <= end)) | 733 | if (res->sibling && (res->sibling->start <= end)) |
| 734 | goto out; | 734 | goto out; |
| 735 | 735 | ||
| @@ -741,6 +741,11 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t | |||
| 741 | goto out; | 741 | goto out; |
| 742 | } | 742 | } |
| 743 | 743 | ||
| 744 | skip: | ||
| 745 | for (tmp = res->child; tmp; tmp = tmp->sibling) | ||
| 746 | if ((tmp->start < start) || (tmp->end > end)) | ||
| 747 | goto out; | ||
| 748 | |||
| 744 | res->start = start; | 749 | res->start = start; |
| 745 | res->end = end; | 750 | res->end = end; |
| 746 | result = 0; | 751 | result = 0; |
| @@ -788,8 +793,28 @@ void __init reserve_region_with_split(struct resource *root, | |||
| 788 | resource_size_t start, resource_size_t end, | 793 | resource_size_t start, resource_size_t end, |
| 789 | const char *name) | 794 | const char *name) |
| 790 | { | 795 | { |
| 796 | int abort = 0; | ||
| 797 | |||
| 791 | write_lock(&resource_lock); | 798 | write_lock(&resource_lock); |
| 792 | __reserve_region_with_split(root, start, end, name); | 799 | if (root->start > start || root->end < end) { |
| 800 | pr_err("requested range [0x%llx-0x%llx] not in root %pr\n", | ||
| 801 | (unsigned long long)start, (unsigned long long)end, | ||
| 802 | root); | ||
| 803 | if (start > root->end || end < root->start) | ||
| 804 | abort = 1; | ||
| 805 | else { | ||
| 806 | if (end > root->end) | ||
| 807 | end = root->end; | ||
| 808 | if (start < root->start) | ||
| 809 | start = root->start; | ||
| 810 | pr_err("fixing request to [0x%llx-0x%llx]\n", | ||
| 811 | (unsigned long long)start, | ||
| 812 | (unsigned long long)end); | ||
| 813 | } | ||
| 814 | dump_stack(); | ||
| 815 | } | ||
| 816 | if (!abort) | ||
| 817 | __reserve_region_with_split(root, start, end, name); | ||
| 793 | write_unlock(&resource_lock); | 818 | write_unlock(&resource_lock); |
| 794 | } | 819 | } |
| 795 | 820 | ||
