mem_pieces.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  3. * Changes to accommodate Power Macintoshes.
  4. * Cort Dougan <cort@cs.nmt.edu>
  5. * Rewrites.
  6. * Grant Erickson <grant@lcse.umn.edu>
  7. * General rework and split from mm/init.c.
  8. *
  9. * Module name: mem_pieces.c
  10. *
  11. * Description:
  12. * Routines and data structures for manipulating and representing
  13. * phyiscal memory extents (i.e. address/length pairs).
  14. *
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/stddef.h>
  18. #include <linux/init.h>
  19. #include <asm/page.h>
  20. #include "mem_pieces.h"
  21. extern struct mem_pieces phys_avail;
  22. static void mem_pieces_print(struct mem_pieces *);
  23. /*
  24. * Scan a region for a piece of a given size with the required alignment.
  25. */
  26. void __init *
  27. mem_pieces_find(unsigned int size, unsigned int align)
  28. {
  29. int i;
  30. unsigned a, e;
  31. struct mem_pieces *mp = &phys_avail;
  32. for (i = 0; i < mp->n_regions; ++i) {
  33. a = mp->regions[i].address;
  34. e = a + mp->regions[i].size;
  35. a = (a + align - 1) & -align;
  36. if (a + size <= e) {
  37. mem_pieces_remove(mp, a, size, 1);
  38. return (void *) __va(a);
  39. }
  40. }
  41. panic("Couldn't find %u bytes at %u alignment\n", size, align);
  42. return NULL;
  43. }
  44. /*
  45. * Remove some memory from an array of pieces
  46. */
  47. void __init
  48. mem_pieces_remove(struct mem_pieces *mp, unsigned int start, unsigned int size,
  49. int must_exist)
  50. {
  51. int i, j;
  52. unsigned int end, rs, re;
  53. struct reg_property *rp;
  54. end = start + size;
  55. for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
  56. if (end > rp->address && start < rp->address + rp->size)
  57. break;
  58. }
  59. if (i >= mp->n_regions) {
  60. if (must_exist)
  61. printk("mem_pieces_remove: [%x,%x) not in any region\n",
  62. start, end);
  63. return;
  64. }
  65. for (; i < mp->n_regions && end > rp->address; ++i, ++rp) {
  66. rs = rp->address;
  67. re = rs + rp->size;
  68. if (must_exist && (start < rs || end > re)) {
  69. printk("mem_pieces_remove: bad overlap [%x,%x) with",
  70. start, end);
  71. mem_pieces_print(mp);
  72. must_exist = 0;
  73. }
  74. if (start > rs) {
  75. rp->size = start - rs;
  76. if (end < re) {
  77. /* need to split this entry */
  78. if (mp->n_regions >= MEM_PIECES_MAX)
  79. panic("eek... mem_pieces overflow");
  80. for (j = mp->n_regions; j > i + 1; --j)
  81. mp->regions[j] = mp->regions[j-1];
  82. ++mp->n_regions;
  83. rp[1].address = end;
  84. rp[1].size = re - end;
  85. }
  86. } else {
  87. if (end < re) {
  88. rp->address = end;
  89. rp->size = re - end;
  90. } else {
  91. /* need to delete this entry */
  92. for (j = i; j < mp->n_regions - 1; ++j)
  93. mp->regions[j] = mp->regions[j+1];
  94. --mp->n_regions;
  95. --i;
  96. --rp;
  97. }
  98. }
  99. }
  100. }
  101. static void __init
  102. mem_pieces_print(struct mem_pieces *mp)
  103. {
  104. int i;
  105. for (i = 0; i < mp->n_regions; ++i)
  106. printk(" [%x, %x)", mp->regions[i].address,
  107. mp->regions[i].address + mp->regions[i].size);
  108. printk("\n");
  109. }
  110. void __init
  111. mem_pieces_sort(struct mem_pieces *mp)
  112. {
  113. unsigned long a, s;
  114. int i, j;
  115. for (i = 1; i < mp->n_regions; ++i) {
  116. a = mp->regions[i].address;
  117. s = mp->regions[i].size;
  118. for (j = i - 1; j >= 0; --j) {
  119. if (a >= mp->regions[j].address)
  120. break;
  121. mp->regions[j+1] = mp->regions[j];
  122. }
  123. mp->regions[j+1].address = a;
  124. mp->regions[j+1].size = s;
  125. }
  126. }
  127. void __init
  128. mem_pieces_coalesce(struct mem_pieces *mp)
  129. {
  130. unsigned long a, s, ns;
  131. int i, j, d;
  132. d = 0;
  133. for (i = 0; i < mp->n_regions; i = j) {
  134. a = mp->regions[i].address;
  135. s = mp->regions[i].size;
  136. for (j = i + 1; j < mp->n_regions
  137. && mp->regions[j].address - a <= s; ++j) {
  138. ns = mp->regions[j].address + mp->regions[j].size - a;
  139. if (ns > s)
  140. s = ns;
  141. }
  142. mp->regions[d].address = a;
  143. mp->regions[d].size = s;
  144. ++d;
  145. }
  146. mp->n_regions = d;
  147. }