mem_pieces.c 3.6 KB

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