diff options
Diffstat (limited to 'kernel/resource.c')
| -rw-r--r-- | kernel/resource.c | 46 |
1 files changed, 12 insertions, 34 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index fd5d7d574bb9..ac5f3a36923f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -533,43 +533,21 @@ static void __init __reserve_region_with_split(struct resource *root, | |||
| 533 | res->end = end; | 533 | res->end = end; |
| 534 | res->flags = IORESOURCE_BUSY; | 534 | res->flags = IORESOURCE_BUSY; |
| 535 | 535 | ||
| 536 | for (;;) { | 536 | conflict = __request_resource(parent, res); |
| 537 | conflict = __request_resource(parent, res); | 537 | if (!conflict) |
| 538 | if (!conflict) | 538 | return; |
| 539 | break; | ||
| 540 | if (conflict != parent) { | ||
| 541 | parent = conflict; | ||
| 542 | if (!(conflict->flags & IORESOURCE_BUSY)) | ||
| 543 | continue; | ||
| 544 | } | ||
| 545 | |||
| 546 | /* Uhhuh, that didn't work out.. */ | ||
| 547 | kfree(res); | ||
| 548 | res = NULL; | ||
| 549 | break; | ||
| 550 | } | ||
| 551 | |||
| 552 | if (!res) { | ||
| 553 | /* failed, split and try again */ | ||
| 554 | |||
| 555 | /* conflict covered whole area */ | ||
| 556 | if (conflict->start <= start && conflict->end >= end) | ||
| 557 | return; | ||
| 558 | 539 | ||
| 559 | if (conflict->start > start) | 540 | /* failed, split and try again */ |
| 560 | __reserve_region_with_split(root, start, conflict->start-1, name); | 541 | kfree(res); |
| 561 | if (!(conflict->flags & IORESOURCE_BUSY)) { | ||
| 562 | resource_size_t common_start, common_end; | ||
| 563 | 542 | ||
| 564 | common_start = max(conflict->start, start); | 543 | /* conflict covered whole area */ |
| 565 | common_end = min(conflict->end, end); | 544 | if (conflict->start <= start && conflict->end >= end) |
| 566 | if (common_start < common_end) | 545 | return; |
| 567 | __reserve_region_with_split(root, common_start, common_end, name); | ||
| 568 | } | ||
| 569 | if (conflict->end < end) | ||
| 570 | __reserve_region_with_split(root, conflict->end+1, end, name); | ||
| 571 | } | ||
| 572 | 546 | ||
| 547 | if (conflict->start > start) | ||
| 548 | __reserve_region_with_split(root, start, conflict->start-1, name); | ||
| 549 | if (conflict->end < end) | ||
| 550 | __reserve_region_with_split(root, conflict->end+1, end, name); | ||
| 573 | } | 551 | } |
| 574 | 552 | ||
| 575 | void __init reserve_region_with_split(struct resource *root, | 553 | void __init reserve_region_with_split(struct resource *root, |
