diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:20:30 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:21:47 -0500 |
commit | d392da5207352f09030e95d9ea335a4225667ec0 (patch) | |
tree | 7d6cd1932afcad0a5619a5c504a6d93ca318187c /kernel/resource.c | |
parent | e39d5ef678045d61812c1401f04fe8edb14d6359 (diff) | |
parent | 387c31c7e5c9805b0aef8833d1731a5fe7bdea14 (diff) |
Merge v2.6.37-rc8 into powerpc/next
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index 7b36976e5dea..798e2fae2a06 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -357,6 +357,32 @@ int __weak page_is_ram(unsigned long pfn) | |||
357 | return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1; | 357 | return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1; |
358 | } | 358 | } |
359 | 359 | ||
360 | void __weak arch_remove_reservations(struct resource *avail) | ||
361 | { | ||
362 | } | ||
363 | |||
364 | static resource_size_t simple_align_resource(void *data, | ||
365 | const struct resource *avail, | ||
366 | resource_size_t size, | ||
367 | resource_size_t align) | ||
368 | { | ||
369 | return avail->start; | ||
370 | } | ||
371 | |||
372 | static void resource_clip(struct resource *res, resource_size_t min, | ||
373 | resource_size_t max) | ||
374 | { | ||
375 | if (res->start < min) | ||
376 | res->start = min; | ||
377 | if (res->end > max) | ||
378 | res->end = max; | ||
379 | } | ||
380 | |||
381 | static bool resource_contains(struct resource *res1, struct resource *res2) | ||
382 | { | ||
383 | return res1->start <= res2->start && res1->end >= res2->end; | ||
384 | } | ||
385 | |||
360 | /* | 386 | /* |
361 | * Find empty slot in the resource tree given range and alignment. | 387 | * Find empty slot in the resource tree given range and alignment. |
362 | */ | 388 | */ |
@@ -370,8 +396,9 @@ static int find_resource(struct resource *root, struct resource *new, | |||
370 | void *alignf_data) | 396 | void *alignf_data) |
371 | { | 397 | { |
372 | struct resource *this = root->child; | 398 | struct resource *this = root->child; |
373 | struct resource tmp = *new; | 399 | struct resource tmp = *new, avail, alloc; |
374 | 400 | ||
401 | tmp.flags = new->flags; | ||
375 | tmp.start = root->start; | 402 | tmp.start = root->start; |
376 | /* | 403 | /* |
377 | * Skip past an allocated resource that starts at 0, since the assignment | 404 | * Skip past an allocated resource that starts at 0, since the assignment |
@@ -386,17 +413,22 @@ static int find_resource(struct resource *root, struct resource *new, | |||
386 | tmp.end = this->start - 1; | 413 | tmp.end = this->start - 1; |
387 | else | 414 | else |
388 | tmp.end = root->end; | 415 | tmp.end = root->end; |
389 | if (tmp.start < min) | 416 | |
390 | tmp.start = min; | 417 | resource_clip(&tmp, min, max); |
391 | if (tmp.end > max) | 418 | arch_remove_reservations(&tmp); |
392 | tmp.end = max; | 419 | |
393 | tmp.start = ALIGN(tmp.start, align); | 420 | /* Check for overflow after ALIGN() */ |
394 | if (alignf) | 421 | avail = *new; |
395 | tmp.start = alignf(alignf_data, &tmp, size, align); | 422 | avail.start = ALIGN(tmp.start, align); |
396 | if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) { | 423 | avail.end = tmp.end; |
397 | new->start = tmp.start; | 424 | if (avail.start >= tmp.start) { |
398 | new->end = tmp.start + size - 1; | 425 | alloc.start = alignf(alignf_data, &avail, size, align); |
399 | return 0; | 426 | alloc.end = alloc.start + size - 1; |
427 | if (resource_contains(&avail, &alloc)) { | ||
428 | new->start = alloc.start; | ||
429 | new->end = alloc.end; | ||
430 | return 0; | ||
431 | } | ||
400 | } | 432 | } |
401 | if (!this) | 433 | if (!this) |
402 | break; | 434 | break; |
@@ -428,6 +460,9 @@ int allocate_resource(struct resource *root, struct resource *new, | |||
428 | { | 460 | { |
429 | int err; | 461 | int err; |
430 | 462 | ||
463 | if (!alignf) | ||
464 | alignf = simple_align_resource; | ||
465 | |||
431 | write_lock(&resource_lock); | 466 | write_lock(&resource_lock); |
432 | err = find_resource(root, new, size, min, max, align, alignf, alignf_data); | 467 | err = find_resource(root, new, size, min, max, align, alignf, alignf_data); |
433 | if (err >= 0 && __request_resource(root, new)) | 468 | if (err >= 0 && __request_resource(root, new)) |
@@ -453,6 +488,8 @@ static struct resource * __insert_resource(struct resource *parent, struct resou | |||
453 | 488 | ||
454 | if (first == parent) | 489 | if (first == parent) |
455 | return first; | 490 | return first; |
491 | if (WARN_ON(first == new)) /* duplicated insertion */ | ||
492 | return first; | ||
456 | 493 | ||
457 | if ((first->start > new->start) || (first->end < new->end)) | 494 | if ((first->start > new->start) || (first->end < new->end)) |
458 | break; | 495 | break; |