aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/lib/rheap.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/lib/rheap.c')
-rw-r--r--arch/ppc/lib/rheap.c95
1 files changed, 49 insertions, 46 deletions
diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c
index d40700795a9c..9dc2f3458ded 100644
--- a/arch/ppc/lib/rheap.c
+++ b/arch/ppc/lib/rheap.c
@@ -132,7 +132,7 @@ static rh_block_t *get_slot(rh_info_t * info)
132 info->empty_slots--; 132 info->empty_slots--;
133 133
134 /* Initialize */ 134 /* Initialize */
135 blk->start = NULL; 135 blk->start = 0;
136 blk->size = 0; 136 blk->size = 0;
137 blk->owner = NULL; 137 blk->owner = NULL;
138 138
@@ -157,7 +157,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
157 157
158 /* We assume that they are aligned properly */ 158 /* We assume that they are aligned properly */
159 size = blkn->size; 159 size = blkn->size;
160 s = (unsigned long)blkn->start; 160 s = blkn->start;
161 e = s + size; 161 e = s + size;
162 162
163 /* Find the blocks immediately before and after the given one 163 /* Find the blocks immediately before and after the given one
@@ -169,7 +169,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
169 list_for_each(l, &info->free_list) { 169 list_for_each(l, &info->free_list) {
170 blk = list_entry(l, rh_block_t, list); 170 blk = list_entry(l, rh_block_t, list);
171 171
172 bs = (unsigned long)blk->start; 172 bs = blk->start;
173 be = bs + blk->size; 173 be = bs + blk->size;
174 174
175 if (next == NULL && s >= bs) 175 if (next == NULL && s >= bs)
@@ -187,10 +187,10 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
187 } 187 }
188 188
189 /* Now check if they are really adjacent */ 189 /* Now check if they are really adjacent */
190 if (before != NULL && s != (unsigned long)before->start + before->size) 190 if (before && s != (before->start + before->size))
191 before = NULL; 191 before = NULL;
192 192
193 if (after != NULL && e != (unsigned long)after->start) 193 if (after && e != after->start)
194 after = NULL; 194 after = NULL;
195 195
196 /* No coalescing; list insert and return */ 196 /* No coalescing; list insert and return */
@@ -215,7 +215,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
215 215
216 /* Grow the after block backwards */ 216 /* Grow the after block backwards */
217 if (before == NULL && after != NULL) { 217 if (before == NULL && after != NULL) {
218 after->start = (int8_t *)after->start - size; 218 after->start -= size;
219 after->size += size; 219 after->size += size;
220 return; 220 return;
221 } 221 }
@@ -320,14 +320,14 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
320} 320}
321 321
322/* Attach a free memory region, coalesces regions if adjuscent */ 322/* Attach a free memory region, coalesces regions if adjuscent */
323int rh_attach_region(rh_info_t * info, void *start, int size) 323int rh_attach_region(rh_info_t * info, unsigned long start, int size)
324{ 324{
325 rh_block_t *blk; 325 rh_block_t *blk;
326 unsigned long s, e, m; 326 unsigned long s, e, m;
327 int r; 327 int r;
328 328
329 /* The region must be aligned */ 329 /* The region must be aligned */
330 s = (unsigned long)start; 330 s = start;
331 e = s + size; 331 e = s + size;
332 m = info->alignment - 1; 332 m = info->alignment - 1;
333 333
@@ -337,9 +337,12 @@ int rh_attach_region(rh_info_t * info, void *start, int size)
337 /* Round end down */ 337 /* Round end down */
338 e = e & ~m; 338 e = e & ~m;
339 339
340 if (IS_ERR_VALUE(e) || (e < s))
341 return -ERANGE;
342
340 /* Take final values */ 343 /* Take final values */
341 start = (void *)s; 344 start = s;
342 size = (int)(e - s); 345 size = e - s;
343 346
344 /* Grow the blocks, if needed */ 347 /* Grow the blocks, if needed */
345 r = assure_empty(info, 1); 348 r = assure_empty(info, 1);
@@ -357,7 +360,7 @@ int rh_attach_region(rh_info_t * info, void *start, int size)
357} 360}
358 361
359/* Detatch given address range, splits free block if needed. */ 362/* Detatch given address range, splits free block if needed. */
360void *rh_detach_region(rh_info_t * info, void *start, int size) 363unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
361{ 364{
362 struct list_head *l; 365 struct list_head *l;
363 rh_block_t *blk, *newblk; 366 rh_block_t *blk, *newblk;
@@ -365,10 +368,10 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
365 368
366 /* Validate size */ 369 /* Validate size */
367 if (size <= 0) 370 if (size <= 0)
368 return ERR_PTR(-EINVAL); 371 return (unsigned long) -EINVAL;
369 372
370 /* The region must be aligned */ 373 /* The region must be aligned */
371 s = (unsigned long)start; 374 s = start;
372 e = s + size; 375 e = s + size;
373 m = info->alignment - 1; 376 m = info->alignment - 1;
374 377
@@ -379,34 +382,34 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
379 e = e & ~m; 382 e = e & ~m;
380 383
381 if (assure_empty(info, 1) < 0) 384 if (assure_empty(info, 1) < 0)
382 return ERR_PTR(-ENOMEM); 385 return (unsigned long) -ENOMEM;
383 386
384 blk = NULL; 387 blk = NULL;
385 list_for_each(l, &info->free_list) { 388 list_for_each(l, &info->free_list) {
386 blk = list_entry(l, rh_block_t, list); 389 blk = list_entry(l, rh_block_t, list);
387 /* The range must lie entirely inside one free block */ 390 /* The range must lie entirely inside one free block */
388 bs = (unsigned long)blk->start; 391 bs = blk->start;
389 be = (unsigned long)blk->start + blk->size; 392 be = blk->start + blk->size;
390 if (s >= bs && e <= be) 393 if (s >= bs && e <= be)
391 break; 394 break;
392 blk = NULL; 395 blk = NULL;
393 } 396 }
394 397
395 if (blk == NULL) 398 if (blk == NULL)
396 return ERR_PTR(-ENOMEM); 399 return (unsigned long) -ENOMEM;
397 400
398 /* Perfect fit */ 401 /* Perfect fit */
399 if (bs == s && be == e) { 402 if (bs == s && be == e) {
400 /* Delete from free list, release slot */ 403 /* Delete from free list, release slot */
401 list_del(&blk->list); 404 list_del(&blk->list);
402 release_slot(info, blk); 405 release_slot(info, blk);
403 return (void *)s; 406 return s;
404 } 407 }
405 408
406 /* blk still in free list, with updated start and/or size */ 409 /* blk still in free list, with updated start and/or size */
407 if (bs == s || be == e) { 410 if (bs == s || be == e) {
408 if (bs == s) 411 if (bs == s)
409 blk->start = (int8_t *)blk->start + size; 412 blk->start += size;
410 blk->size -= size; 413 blk->size -= size;
411 414
412 } else { 415 } else {
@@ -415,31 +418,31 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
415 418
416 /* the back free fragment */ 419 /* the back free fragment */
417 newblk = get_slot(info); 420 newblk = get_slot(info);
418 newblk->start = (void *)e; 421 newblk->start = e;
419 newblk->size = be - e; 422 newblk->size = be - e;
420 423
421 list_add(&newblk->list, &blk->list); 424 list_add(&newblk->list, &blk->list);
422 } 425 }
423 426
424 return (void *)s; 427 return s;
425} 428}
426 429
427void *rh_alloc(rh_info_t * info, int size, const char *owner) 430unsigned long rh_alloc(rh_info_t * info, int size, const char *owner)
428{ 431{
429 struct list_head *l; 432 struct list_head *l;
430 rh_block_t *blk; 433 rh_block_t *blk;
431 rh_block_t *newblk; 434 rh_block_t *newblk;
432 void *start; 435 unsigned long start;
433 436
434 /* Validate size */ 437 /* Validate size */
435 if (size <= 0) 438 if (size <= 0)
436 return ERR_PTR(-EINVAL); 439 return (unsigned long) -EINVAL;
437 440
438 /* Align to configured alignment */ 441 /* Align to configured alignment */
439 size = (size + (info->alignment - 1)) & ~(info->alignment - 1); 442 size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
440 443
441 if (assure_empty(info, 1) < 0) 444 if (assure_empty(info, 1) < 0)
442 return ERR_PTR(-ENOMEM); 445 return (unsigned long) -ENOMEM;
443 446
444 blk = NULL; 447 blk = NULL;
445 list_for_each(l, &info->free_list) { 448 list_for_each(l, &info->free_list) {
@@ -450,7 +453,7 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner)
450 } 453 }
451 454
452 if (blk == NULL) 455 if (blk == NULL)
453 return ERR_PTR(-ENOMEM); 456 return (unsigned long) -ENOMEM;
454 457
455 /* Just fits */ 458 /* Just fits */
456 if (blk->size == size) { 459 if (blk->size == size) {
@@ -470,7 +473,7 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner)
470 newblk->owner = owner; 473 newblk->owner = owner;
471 474
472 /* blk still in free list, with updated start, size */ 475 /* blk still in free list, with updated start, size */
473 blk->start = (int8_t *)blk->start + size; 476 blk->start += size;
474 blk->size -= size; 477 blk->size -= size;
475 478
476 start = newblk->start; 479 start = newblk->start;
@@ -481,18 +484,18 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner)
481} 484}
482 485
483/* allocate at precisely the given address */ 486/* allocate at precisely the given address */
484void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) 487unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, const char *owner)
485{ 488{
486 struct list_head *l; 489 struct list_head *l;
487 rh_block_t *blk, *newblk1, *newblk2; 490 rh_block_t *blk, *newblk1, *newblk2;
488 unsigned long s, e, m, bs, be; 491 unsigned long s, e, m, bs=0, be=0;
489 492
490 /* Validate size */ 493 /* Validate size */
491 if (size <= 0) 494 if (size <= 0)
492 return ERR_PTR(-EINVAL); 495 return (unsigned long) -EINVAL;
493 496
494 /* The region must be aligned */ 497 /* The region must be aligned */
495 s = (unsigned long)start; 498 s = start;
496 e = s + size; 499 e = s + size;
497 m = info->alignment - 1; 500 m = info->alignment - 1;
498 501
@@ -503,20 +506,20 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
503 e = e & ~m; 506 e = e & ~m;
504 507
505 if (assure_empty(info, 2) < 0) 508 if (assure_empty(info, 2) < 0)
506 return ERR_PTR(-ENOMEM); 509 return (unsigned long) -ENOMEM;
507 510
508 blk = NULL; 511 blk = NULL;
509 list_for_each(l, &info->free_list) { 512 list_for_each(l, &info->free_list) {
510 blk = list_entry(l, rh_block_t, list); 513 blk = list_entry(l, rh_block_t, list);
511 /* The range must lie entirely inside one free block */ 514 /* The range must lie entirely inside one free block */
512 bs = (unsigned long)blk->start; 515 bs = blk->start;
513 be = (unsigned long)blk->start + blk->size; 516 be = blk->start + blk->size;
514 if (s >= bs && e <= be) 517 if (s >= bs && e <= be)
515 break; 518 break;
516 } 519 }
517 520
518 if (blk == NULL) 521 if (blk == NULL)
519 return ERR_PTR(-ENOMEM); 522 return (unsigned long) -ENOMEM;
520 523
521 /* Perfect fit */ 524 /* Perfect fit */
522 if (bs == s && be == e) { 525 if (bs == s && be == e) {
@@ -534,7 +537,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
534 /* blk still in free list, with updated start and/or size */ 537 /* blk still in free list, with updated start and/or size */
535 if (bs == s || be == e) { 538 if (bs == s || be == e) {
536 if (bs == s) 539 if (bs == s)
537 blk->start = (int8_t *)blk->start + size; 540 blk->start += size;
538 blk->size -= size; 541 blk->size -= size;
539 542
540 } else { 543 } else {
@@ -543,14 +546,14 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
543 546
544 /* The back free fragment */ 547 /* The back free fragment */
545 newblk2 = get_slot(info); 548 newblk2 = get_slot(info);
546 newblk2->start = (void *)e; 549 newblk2->start = e;
547 newblk2->size = be - e; 550 newblk2->size = be - e;
548 551
549 list_add(&newblk2->list, &blk->list); 552 list_add(&newblk2->list, &blk->list);
550 } 553 }
551 554
552 newblk1 = get_slot(info); 555 newblk1 = get_slot(info);
553 newblk1->start = (void *)s; 556 newblk1->start = s;
554 newblk1->size = e - s; 557 newblk1->size = e - s;
555 newblk1->owner = owner; 558 newblk1->owner = owner;
556 559
@@ -560,7 +563,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
560 return start; 563 return start;
561} 564}
562 565
563int rh_free(rh_info_t * info, void *start) 566int rh_free(rh_info_t * info, unsigned long start)
564{ 567{
565 rh_block_t *blk, *blk2; 568 rh_block_t *blk, *blk2;
566 struct list_head *l; 569 struct list_head *l;
@@ -625,7 +628,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
625 return nr; 628 return nr;
626} 629}
627 630
628int rh_set_owner(rh_info_t * info, void *start, const char *owner) 631int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
629{ 632{
630 rh_block_t *blk, *blk2; 633 rh_block_t *blk, *blk2;
631 struct list_head *l; 634 struct list_head *l;
@@ -667,8 +670,8 @@ void rh_dump(rh_info_t * info)
667 nr = maxnr; 670 nr = maxnr;
668 for (i = 0; i < nr; i++) 671 for (i = 0; i < nr; i++)
669 printk(KERN_INFO 672 printk(KERN_INFO
670 " 0x%p-0x%p (%u)\n", 673 " 0x%lx-0x%lx (%u)\n",
671 st[i].start, (int8_t *) st[i].start + st[i].size, 674 st[i].start, st[i].start + st[i].size,
672 st[i].size); 675 st[i].size);
673 printk(KERN_INFO "\n"); 676 printk(KERN_INFO "\n");
674 677
@@ -678,8 +681,8 @@ void rh_dump(rh_info_t * info)
678 nr = maxnr; 681 nr = maxnr;
679 for (i = 0; i < nr; i++) 682 for (i = 0; i < nr; i++)
680 printk(KERN_INFO 683 printk(KERN_INFO
681 " 0x%p-0x%p (%u) %s\n", 684 " 0x%lx-0x%lx (%u) %s\n",
682 st[i].start, (int8_t *) st[i].start + st[i].size, 685 st[i].start, st[i].start + st[i].size,
683 st[i].size, st[i].owner != NULL ? st[i].owner : ""); 686 st[i].size, st[i].owner != NULL ? st[i].owner : "");
684 printk(KERN_INFO "\n"); 687 printk(KERN_INFO "\n");
685} 688}
@@ -687,6 +690,6 @@ void rh_dump(rh_info_t * info)
687void rh_dump_blk(rh_info_t * info, rh_block_t * blk) 690void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
688{ 691{
689 printk(KERN_INFO 692 printk(KERN_INFO
690 "blk @0x%p: 0x%p-0x%p (%u)\n", 693 "blk @0x%p: 0x%lx-0x%lx (%u)\n",
691 blk, blk->start, (int8_t *) blk->start + blk->size, blk->size); 694 blk, blk->start, blk->start + blk->size, blk->size);
692} 695}