aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/resource.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2010-12-16 12:38:41 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-12-17 13:00:59 -0500
commitc0f5ac5426f7fd82b23dd5c6a1e633b290294a08 (patch)
treee271f4e49d7d32a4637d958b619b3b0836f7079c /kernel/resource.c
parent6db45b76eaa08133187f2cb44d496de7e9503aa8 (diff)
Revert "resources: support allocating space within a region from the top down"
This reverts commit e7f8567db9a7f6b3151b0b275e245c1cef0d9c70. Acked-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r--kernel/resource.c98
1 files changed, 4 insertions, 94 deletions
diff --git a/kernel/resource.c b/kernel/resource.c
index 9fad33efd0db..560659f7baef 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);
40 40
41static DEFINE_RWLOCK(resource_lock); 41static DEFINE_RWLOCK(resource_lock);
42 42
43/*
44 * By default, we allocate free space bottom-up. The architecture can request
45 * top-down by clearing this flag. The user can override the architecture's
46 * choice with the "resource_alloc_from_bottom" kernel boot option, but that
47 * should only be a debugging tool.
48 */
49int resource_alloc_from_bottom = 1;
50
51static __init int setup_alloc_from_bottom(char *s)
52{
53 printk(KERN_INFO
54 "resource: allocating from bottom-up; please report a bug\n");
55 resource_alloc_from_bottom = 1;
56 return 0;
57}
58early_param("resource_alloc_from_bottom", setup_alloc_from_bottom);
59
60static void *r_next(struct seq_file *m, void *v, loff_t *pos) 43static void *r_next(struct seq_file *m, void *v, loff_t *pos)
61{ 44{
62 struct resource *p = v; 45 struct resource *p = v;
@@ -397,74 +380,7 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
397} 380}
398 381
399/* 382/*
400 * Find the resource before "child" in the sibling list of "root" children.
401 */
402static struct resource *find_sibling_prev(struct resource *root, struct resource *child)
403{
404 struct resource *this;
405
406 for (this = root->child; this; this = this->sibling)
407 if (this->sibling == child)
408 return this;
409
410 return NULL;
411}
412
413/*
414 * Find empty slot in the resource tree given range and alignment.
415 * This version allocates from the end of the root resource first.
416 */
417static int find_resource_from_top(struct resource *root, struct resource *new,
418 resource_size_t size, resource_size_t min,
419 resource_size_t max, resource_size_t align,
420 resource_size_t (*alignf)(void *,
421 const struct resource *,
422 resource_size_t,
423 resource_size_t),
424 void *alignf_data)
425{
426 struct resource *this;
427 struct resource tmp, avail, alloc;
428
429 tmp.start = root->end;
430 tmp.end = root->end;
431
432 this = find_sibling_prev(root, NULL);
433 for (;;) {
434 if (this) {
435 if (this->end < root->end)
436 tmp.start = this->end + 1;
437 } else
438 tmp.start = root->start;
439
440 resource_clip(&tmp, min, max);
441
442 /* Check for overflow after ALIGN() */
443 avail = *new;
444 avail.start = ALIGN(tmp.start, align);
445 avail.end = tmp.end;
446 if (avail.start >= tmp.start) {
447 alloc.start = alignf(alignf_data, &avail, size, align);
448 alloc.end = alloc.start + size - 1;
449 if (resource_contains(&avail, &alloc)) {
450 new->start = alloc.start;
451 new->end = alloc.end;
452 return 0;
453 }
454 }
455
456 if (!this || this->start == root->start)
457 break;
458
459 tmp.end = this->start - 1;
460 this = find_sibling_prev(root, this);
461 }
462 return -EBUSY;
463}
464
465/*
466 * Find empty slot in the resource tree given range and alignment. 383 * Find empty slot in the resource tree given range and alignment.
467 * This version allocates from the beginning of the root resource first.
468 */ 384 */
469static int find_resource(struct resource *root, struct resource *new, 385static int find_resource(struct resource *root, struct resource *new,
470 resource_size_t size, resource_size_t min, 386 resource_size_t size, resource_size_t min,
@@ -480,15 +396,14 @@ static int find_resource(struct resource *root, struct resource *new,
480 396
481 tmp.start = root->start; 397 tmp.start = root->start;
482 /* 398 /*
483 * Skip past an allocated resource that starts at 0, since the 399 * Skip past an allocated resource that starts at 0, since the assignment
484 * assignment of this->start - 1 to tmp->end below would cause an 400 * of this->start - 1 to tmp->end below would cause an underflow.
485 * underflow.
486 */ 401 */
487 if (this && this->start == 0) { 402 if (this && this->start == 0) {
488 tmp.start = this->end + 1; 403 tmp.start = this->end + 1;
489 this = this->sibling; 404 this = this->sibling;
490 } 405 }
491 for (;;) { 406 for(;;) {
492 if (this) 407 if (this)
493 tmp.end = this->start - 1; 408 tmp.end = this->start - 1;
494 else 409 else
@@ -509,10 +424,8 @@ static int find_resource(struct resource *root, struct resource *new,
509 return 0; 424 return 0;
510 } 425 }
511 } 426 }
512
513 if (!this) 427 if (!this)
514 break; 428 break;
515
516 tmp.start = this->end + 1; 429 tmp.start = this->end + 1;
517 this = this->sibling; 430 this = this->sibling;
518 } 431 }
@@ -545,10 +458,7 @@ int allocate_resource(struct resource *root, struct resource *new,
545 alignf = simple_align_resource; 458 alignf = simple_align_resource;
546 459
547 write_lock(&resource_lock); 460 write_lock(&resource_lock);
548 if (resource_alloc_from_bottom) 461 err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
549 err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
550 else
551 err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data);
552 if (err >= 0 && __request_resource(root, new)) 462 if (err >= 0 && __request_resource(root, new))
553 err = -EBUSY; 463 err = -EBUSY;
554 write_unlock(&resource_lock); 464 write_unlock(&resource_lock);