diff options
Diffstat (limited to 'arch/powerpc/lib')
-rw-r--r-- | arch/powerpc/lib/rheap.c | 117 |
1 files changed, 67 insertions, 50 deletions
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 6c5c5dd183ee..b2f6dcc59600 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c | |||
@@ -133,7 +133,7 @@ static rh_block_t *get_slot(rh_info_t * info) | |||
133 | info->empty_slots--; | 133 | info->empty_slots--; |
134 | 134 | ||
135 | /* Initialize */ | 135 | /* Initialize */ |
136 | blk->start = NULL; | 136 | blk->start = 0; |
137 | blk->size = 0; | 137 | blk->size = 0; |
138 | blk->owner = NULL; | 138 | blk->owner = NULL; |
139 | 139 | ||
@@ -158,7 +158,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) | |||
158 | 158 | ||
159 | /* We assume that they are aligned properly */ | 159 | /* We assume that they are aligned properly */ |
160 | size = blkn->size; | 160 | size = blkn->size; |
161 | s = (unsigned long)blkn->start; | 161 | s = blkn->start; |
162 | e = s + size; | 162 | e = s + size; |
163 | 163 | ||
164 | /* Find the blocks immediately before and after the given one | 164 | /* Find the blocks immediately before and after the given one |
@@ -170,7 +170,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) | |||
170 | list_for_each(l, &info->free_list) { | 170 | list_for_each(l, &info->free_list) { |
171 | blk = list_entry(l, rh_block_t, list); | 171 | blk = list_entry(l, rh_block_t, list); |
172 | 172 | ||
173 | bs = (unsigned long)blk->start; | 173 | bs = blk->start; |
174 | be = bs + blk->size; | 174 | be = bs + blk->size; |
175 | 175 | ||
176 | if (next == NULL && s >= bs) | 176 | if (next == NULL && s >= bs) |
@@ -188,10 +188,10 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) | |||
188 | } | 188 | } |
189 | 189 | ||
190 | /* Now check if they are really adjacent */ | 190 | /* Now check if they are really adjacent */ |
191 | if (before != NULL && s != (unsigned long)before->start + before->size) | 191 | if (before && s != (before->start + before->size)) |
192 | before = NULL; | 192 | before = NULL; |
193 | 193 | ||
194 | if (after != NULL && e != (unsigned long)after->start) | 194 | if (after && e != after->start) |
195 | after = NULL; | 195 | after = NULL; |
196 | 196 | ||
197 | /* No coalescing; list insert and return */ | 197 | /* No coalescing; list insert and return */ |
@@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) | |||
216 | 216 | ||
217 | /* Grow the after block backwards */ | 217 | /* Grow the after block backwards */ |
218 | if (before == NULL && after != NULL) { | 218 | if (before == NULL && after != NULL) { |
219 | after->start = (int8_t *)after->start - size; | 219 | after->start -= size; |
220 | after->size += size; | 220 | after->size += size; |
221 | return; | 221 | return; |
222 | } | 222 | } |
@@ -321,14 +321,14 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks, | |||
321 | } | 321 | } |
322 | 322 | ||
323 | /* Attach a free memory region, coalesces regions if adjuscent */ | 323 | /* Attach a free memory region, coalesces regions if adjuscent */ |
324 | int rh_attach_region(rh_info_t * info, void *start, int size) | 324 | int rh_attach_region(rh_info_t * info, unsigned long start, int size) |
325 | { | 325 | { |
326 | rh_block_t *blk; | 326 | rh_block_t *blk; |
327 | unsigned long s, e, m; | 327 | unsigned long s, e, m; |
328 | int r; | 328 | int r; |
329 | 329 | ||
330 | /* The region must be aligned */ | 330 | /* The region must be aligned */ |
331 | s = (unsigned long)start; | 331 | s = start; |
332 | e = s + size; | 332 | e = s + size; |
333 | m = info->alignment - 1; | 333 | m = info->alignment - 1; |
334 | 334 | ||
@@ -338,9 +338,12 @@ int rh_attach_region(rh_info_t * info, void *start, int size) | |||
338 | /* Round end down */ | 338 | /* Round end down */ |
339 | e = e & ~m; | 339 | e = e & ~m; |
340 | 340 | ||
341 | if (IS_ERR_VALUE(e) || (e < s)) | ||
342 | return -ERANGE; | ||
343 | |||
341 | /* Take final values */ | 344 | /* Take final values */ |
342 | start = (void *)s; | 345 | start = s; |
343 | size = (int)(e - s); | 346 | size = e - s; |
344 | 347 | ||
345 | /* Grow the blocks, if needed */ | 348 | /* Grow the blocks, if needed */ |
346 | r = assure_empty(info, 1); | 349 | r = assure_empty(info, 1); |
@@ -358,7 +361,7 @@ int rh_attach_region(rh_info_t * info, void *start, int size) | |||
358 | } | 361 | } |
359 | 362 | ||
360 | /* Detatch given address range, splits free block if needed. */ | 363 | /* Detatch given address range, splits free block if needed. */ |
361 | void *rh_detach_region(rh_info_t * info, void *start, int size) | 364 | unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) |
362 | { | 365 | { |
363 | struct list_head *l; | 366 | struct list_head *l; |
364 | rh_block_t *blk, *newblk; | 367 | rh_block_t *blk, *newblk; |
@@ -366,10 +369,10 @@ void *rh_detach_region(rh_info_t * info, void *start, int size) | |||
366 | 369 | ||
367 | /* Validate size */ | 370 | /* Validate size */ |
368 | if (size <= 0) | 371 | if (size <= 0) |
369 | return ERR_PTR(-EINVAL); | 372 | return (unsigned long) -EINVAL; |
370 | 373 | ||
371 | /* The region must be aligned */ | 374 | /* The region must be aligned */ |
372 | s = (unsigned long)start; | 375 | s = start; |
373 | e = s + size; | 376 | e = s + size; |
374 | m = info->alignment - 1; | 377 | m = info->alignment - 1; |
375 | 378 | ||
@@ -380,34 +383,34 @@ void *rh_detach_region(rh_info_t * info, void *start, int size) | |||
380 | e = e & ~m; | 383 | e = e & ~m; |
381 | 384 | ||
382 | if (assure_empty(info, 1) < 0) | 385 | if (assure_empty(info, 1) < 0) |
383 | return ERR_PTR(-ENOMEM); | 386 | return (unsigned long) -ENOMEM; |
384 | 387 | ||
385 | blk = NULL; | 388 | blk = NULL; |
386 | list_for_each(l, &info->free_list) { | 389 | list_for_each(l, &info->free_list) { |
387 | blk = list_entry(l, rh_block_t, list); | 390 | blk = list_entry(l, rh_block_t, list); |
388 | /* The range must lie entirely inside one free block */ | 391 | /* The range must lie entirely inside one free block */ |
389 | bs = (unsigned long)blk->start; | 392 | bs = blk->start; |
390 | be = (unsigned long)blk->start + blk->size; | 393 | be = blk->start + blk->size; |
391 | if (s >= bs && e <= be) | 394 | if (s >= bs && e <= be) |
392 | break; | 395 | break; |
393 | blk = NULL; | 396 | blk = NULL; |
394 | } | 397 | } |
395 | 398 | ||
396 | if (blk == NULL) | 399 | if (blk == NULL) |
397 | return ERR_PTR(-ENOMEM); | 400 | return (unsigned long) -ENOMEM; |
398 | 401 | ||
399 | /* Perfect fit */ | 402 | /* Perfect fit */ |
400 | if (bs == s && be == e) { | 403 | if (bs == s && be == e) { |
401 | /* Delete from free list, release slot */ | 404 | /* Delete from free list, release slot */ |
402 | list_del(&blk->list); | 405 | list_del(&blk->list); |
403 | release_slot(info, blk); | 406 | release_slot(info, blk); |
404 | return (void *)s; | 407 | return s; |
405 | } | 408 | } |
406 | 409 | ||
407 | /* blk still in free list, with updated start and/or size */ | 410 | /* blk still in free list, with updated start and/or size */ |
408 | if (bs == s || be == e) { | 411 | if (bs == s || be == e) { |
409 | if (bs == s) | 412 | if (bs == s) |
410 | blk->start = (int8_t *)blk->start + size; | 413 | blk->start += size; |
411 | blk->size -= size; | 414 | blk->size -= size; |
412 | 415 | ||
413 | } else { | 416 | } else { |
@@ -416,25 +419,29 @@ void *rh_detach_region(rh_info_t * info, void *start, int size) | |||
416 | 419 | ||
417 | /* the back free fragment */ | 420 | /* the back free fragment */ |
418 | newblk = get_slot(info); | 421 | newblk = get_slot(info); |
419 | newblk->start = (void *)e; | 422 | newblk->start = e; |
420 | newblk->size = be - e; | 423 | newblk->size = be - e; |
421 | 424 | ||
422 | list_add(&newblk->list, &blk->list); | 425 | list_add(&newblk->list, &blk->list); |
423 | } | 426 | } |
424 | 427 | ||
425 | return (void *)s; | 428 | return s; |
426 | } | 429 | } |
427 | 430 | ||
428 | void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner) | 431 | /* Allocate a block of memory at the specified alignment. The value returned |
432 | * is an offset into the buffer initialized by rh_init(), or a negative number | ||
433 | * if there is an error. | ||
434 | */ | ||
435 | unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner) | ||
429 | { | 436 | { |
430 | struct list_head *l; | 437 | struct list_head *l; |
431 | rh_block_t *blk; | 438 | rh_block_t *blk; |
432 | rh_block_t *newblk; | 439 | rh_block_t *newblk; |
433 | void *start; | 440 | unsigned long start; |
434 | 441 | ||
435 | /* Validate size, (must be power of two) */ | 442 | /* Validate size, and alignment must be power of two */ |
436 | if (size <= 0 || (alignment & (alignment - 1)) != 0) | 443 | if (size <= 0 || (alignment & (alignment - 1)) != 0) |
437 | return ERR_PTR(-EINVAL); | 444 | return (unsigned long) -EINVAL; |
438 | 445 | ||
439 | /* given alignment larger that default rheap alignment */ | 446 | /* given alignment larger that default rheap alignment */ |
440 | if (alignment > info->alignment) | 447 | if (alignment > info->alignment) |
@@ -444,7 +451,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne | |||
444 | size = (size + (info->alignment - 1)) & ~(info->alignment - 1); | 451 | size = (size + (info->alignment - 1)) & ~(info->alignment - 1); |
445 | 452 | ||
446 | if (assure_empty(info, 1) < 0) | 453 | if (assure_empty(info, 1) < 0) |
447 | return ERR_PTR(-ENOMEM); | 454 | return (unsigned long) -ENOMEM; |
448 | 455 | ||
449 | blk = NULL; | 456 | blk = NULL; |
450 | list_for_each(l, &info->free_list) { | 457 | list_for_each(l, &info->free_list) { |
@@ -455,7 +462,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne | |||
455 | } | 462 | } |
456 | 463 | ||
457 | if (blk == NULL) | 464 | if (blk == NULL) |
458 | return ERR_PTR(-ENOMEM); | 465 | return (unsigned long) -ENOMEM; |
459 | 466 | ||
460 | /* Just fits */ | 467 | /* Just fits */ |
461 | if (blk->size == size) { | 468 | if (blk->size == size) { |
@@ -475,7 +482,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne | |||
475 | newblk->owner = owner; | 482 | newblk->owner = owner; |
476 | 483 | ||
477 | /* blk still in free list, with updated start, size */ | 484 | /* blk still in free list, with updated start, size */ |
478 | blk->start = (int8_t *)blk->start + size; | 485 | blk->start += size; |
479 | blk->size -= size; | 486 | blk->size -= size; |
480 | 487 | ||
481 | start = newblk->start; | 488 | start = newblk->start; |
@@ -486,19 +493,25 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne | |||
486 | /* this is no problem with the deallocator since */ | 493 | /* this is no problem with the deallocator since */ |
487 | /* we scan for pointers that lie in the blocks */ | 494 | /* we scan for pointers that lie in the blocks */ |
488 | if (alignment > info->alignment) | 495 | if (alignment > info->alignment) |
489 | start = (void *)(((unsigned long)start + alignment - 1) & | 496 | start = (start + alignment - 1) & ~(alignment - 1); |
490 | ~(alignment - 1)); | ||
491 | 497 | ||
492 | return start; | 498 | return start; |
493 | } | 499 | } |
494 | 500 | ||
495 | void *rh_alloc(rh_info_t * info, int size, const char *owner) | 501 | /* Allocate a block of memory at the default alignment. The value returned is |
502 | * an offset into the buffer initialized by rh_init(), or a negative number if | ||
503 | * there is an error. | ||
504 | */ | ||
505 | unsigned long rh_alloc(rh_info_t * info, int size, const char *owner) | ||
496 | { | 506 | { |
497 | return rh_alloc_align(info, size, info->alignment, owner); | 507 | return rh_alloc_align(info, size, info->alignment, owner); |
498 | } | 508 | } |
499 | 509 | ||
500 | /* allocate at precisely the given address */ | 510 | /* Allocate a block of memory at the given offset, rounded up to the default |
501 | void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) | 511 | * alignment. The value returned is an offset into the buffer initialized by |
512 | * rh_init(), or a negative number if there is an error. | ||
513 | */ | ||
514 | unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, const char *owner) | ||
502 | { | 515 | { |
503 | struct list_head *l; | 516 | struct list_head *l; |
504 | rh_block_t *blk, *newblk1, *newblk2; | 517 | rh_block_t *blk, *newblk1, *newblk2; |
@@ -506,10 +519,10 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) | |||
506 | 519 | ||
507 | /* Validate size */ | 520 | /* Validate size */ |
508 | if (size <= 0) | 521 | if (size <= 0) |
509 | return ERR_PTR(-EINVAL); | 522 | return (unsigned long) -EINVAL; |
510 | 523 | ||
511 | /* The region must be aligned */ | 524 | /* The region must be aligned */ |
512 | s = (unsigned long)start; | 525 | s = start; |
513 | e = s + size; | 526 | e = s + size; |
514 | m = info->alignment - 1; | 527 | m = info->alignment - 1; |
515 | 528 | ||
@@ -520,20 +533,20 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) | |||
520 | e = e & ~m; | 533 | e = e & ~m; |
521 | 534 | ||
522 | if (assure_empty(info, 2) < 0) | 535 | if (assure_empty(info, 2) < 0) |
523 | return ERR_PTR(-ENOMEM); | 536 | return (unsigned long) -ENOMEM; |
524 | 537 | ||
525 | blk = NULL; | 538 | blk = NULL; |
526 | list_for_each(l, &info->free_list) { | 539 | list_for_each(l, &info->free_list) { |
527 | blk = list_entry(l, rh_block_t, list); | 540 | blk = list_entry(l, rh_block_t, list); |
528 | /* The range must lie entirely inside one free block */ | 541 | /* The range must lie entirely inside one free block */ |
529 | bs = (unsigned long)blk->start; | 542 | bs = blk->start; |
530 | be = (unsigned long)blk->start + blk->size; | 543 | be = blk->start + blk->size; |
531 | if (s >= bs && e <= be) | 544 | if (s >= bs && e <= be) |
532 | break; | 545 | break; |
533 | } | 546 | } |
534 | 547 | ||
535 | if (blk == NULL) | 548 | if (blk == NULL) |
536 | return ERR_PTR(-ENOMEM); | 549 | return (unsigned long) -ENOMEM; |
537 | 550 | ||
538 | /* Perfect fit */ | 551 | /* Perfect fit */ |
539 | if (bs == s && be == e) { | 552 | if (bs == s && be == e) { |
@@ -551,7 +564,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) | |||
551 | /* blk still in free list, with updated start and/or size */ | 564 | /* blk still in free list, with updated start and/or size */ |
552 | if (bs == s || be == e) { | 565 | if (bs == s || be == e) { |
553 | if (bs == s) | 566 | if (bs == s) |
554 | blk->start = (int8_t *)blk->start + size; | 567 | blk->start += size; |
555 | blk->size -= size; | 568 | blk->size -= size; |
556 | 569 | ||
557 | } else { | 570 | } else { |
@@ -560,14 +573,14 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) | |||
560 | 573 | ||
561 | /* The back free fragment */ | 574 | /* The back free fragment */ |
562 | newblk2 = get_slot(info); | 575 | newblk2 = get_slot(info); |
563 | newblk2->start = (void *)e; | 576 | newblk2->start = e; |
564 | newblk2->size = be - e; | 577 | newblk2->size = be - e; |
565 | 578 | ||
566 | list_add(&newblk2->list, &blk->list); | 579 | list_add(&newblk2->list, &blk->list); |
567 | } | 580 | } |
568 | 581 | ||
569 | newblk1 = get_slot(info); | 582 | newblk1 = get_slot(info); |
570 | newblk1->start = (void *)s; | 583 | newblk1->start = s; |
571 | newblk1->size = e - s; | 584 | newblk1->size = e - s; |
572 | newblk1->owner = owner; | 585 | newblk1->owner = owner; |
573 | 586 | ||
@@ -577,7 +590,11 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) | |||
577 | return start; | 590 | return start; |
578 | } | 591 | } |
579 | 592 | ||
580 | int rh_free(rh_info_t * info, void *start) | 593 | /* Deallocate the memory previously allocated by one of the rh_alloc functions. |
594 | * The return value is the size of the deallocated block, or a negative number | ||
595 | * if there is an error. | ||
596 | */ | ||
597 | int rh_free(rh_info_t * info, unsigned long start) | ||
581 | { | 598 | { |
582 | rh_block_t *blk, *blk2; | 599 | rh_block_t *blk, *blk2; |
583 | struct list_head *l; | 600 | struct list_head *l; |
@@ -642,7 +659,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) | |||
642 | return nr; | 659 | return nr; |
643 | } | 660 | } |
644 | 661 | ||
645 | int rh_set_owner(rh_info_t * info, void *start, const char *owner) | 662 | int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner) |
646 | { | 663 | { |
647 | rh_block_t *blk, *blk2; | 664 | rh_block_t *blk, *blk2; |
648 | struct list_head *l; | 665 | struct list_head *l; |
@@ -684,8 +701,8 @@ void rh_dump(rh_info_t * info) | |||
684 | nr = maxnr; | 701 | nr = maxnr; |
685 | for (i = 0; i < nr; i++) | 702 | for (i = 0; i < nr; i++) |
686 | printk(KERN_INFO | 703 | printk(KERN_INFO |
687 | " 0x%p-0x%p (%u)\n", | 704 | " 0x%lx-0x%lx (%u)\n", |
688 | st[i].start, (int8_t *) st[i].start + st[i].size, | 705 | st[i].start, st[i].start + st[i].size, |
689 | st[i].size); | 706 | st[i].size); |
690 | printk(KERN_INFO "\n"); | 707 | printk(KERN_INFO "\n"); |
691 | 708 | ||
@@ -695,8 +712,8 @@ void rh_dump(rh_info_t * info) | |||
695 | nr = maxnr; | 712 | nr = maxnr; |
696 | for (i = 0; i < nr; i++) | 713 | for (i = 0; i < nr; i++) |
697 | printk(KERN_INFO | 714 | printk(KERN_INFO |
698 | " 0x%p-0x%p (%u) %s\n", | 715 | " 0x%lx-0x%lx (%u) %s\n", |
699 | st[i].start, (int8_t *) st[i].start + st[i].size, | 716 | st[i].start, st[i].start + st[i].size, |
700 | st[i].size, st[i].owner != NULL ? st[i].owner : ""); | 717 | st[i].size, st[i].owner != NULL ? st[i].owner : ""); |
701 | printk(KERN_INFO "\n"); | 718 | printk(KERN_INFO "\n"); |
702 | } | 719 | } |
@@ -704,6 +721,6 @@ void rh_dump(rh_info_t * info) | |||
704 | void rh_dump_blk(rh_info_t * info, rh_block_t * blk) | 721 | void rh_dump_blk(rh_info_t * info, rh_block_t * blk) |
705 | { | 722 | { |
706 | printk(KERN_INFO | 723 | printk(KERN_INFO |
707 | "blk @0x%p: 0x%p-0x%p (%u)\n", | 724 | "blk @0x%p: 0x%lx-0x%lx (%u)\n", |
708 | blk, blk->start, (int8_t *) blk->start + blk->size, blk->size); | 725 | blk, blk->start, blk->start + blk->size, blk->size); |
709 | } | 726 | } |