diff options
author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2011-12-27 05:27:05 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-12-27 05:27:09 -0500 |
commit | 44e5ddc4e9d52cd5eeda42bb7518b306beab24ee (patch) | |
tree | d2b6cf383e707a87cc82f730dbb7704fab292973 /arch/s390 | |
parent | c86cce2a20207cbf2b3dfe97c985a1f5aa5d3798 (diff) |
[S390] Rework create_mem_hole() function
This patch makes the create_mem_hole() function more readable and
fixes some minor bugs (e.g. off-by-one problems).
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/mem_detect.c | 122 |
1 files changed, 67 insertions, 55 deletions
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c index 19b4568f4cee..22d502e885ed 100644 --- a/arch/s390/kernel/mem_detect.c +++ b/arch/s390/kernel/mem_detect.c | |||
@@ -64,70 +64,82 @@ void detect_memory_layout(struct mem_chunk chunk[]) | |||
64 | EXPORT_SYMBOL(detect_memory_layout); | 64 | EXPORT_SYMBOL(detect_memory_layout); |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Move memory chunks array from index "from" to index "to" | ||
68 | */ | ||
69 | static void mem_chunk_move(struct mem_chunk chunk[], int to, int from) | ||
70 | { | ||
71 | int cnt = MEMORY_CHUNKS - to; | ||
72 | |||
73 | memmove(&chunk[to], &chunk[from], cnt * sizeof(struct mem_chunk)); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Initialize memory chunk | ||
78 | */ | ||
79 | static void mem_chunk_init(struct mem_chunk *chunk, unsigned long addr, | ||
80 | unsigned long size, int type) | ||
81 | { | ||
82 | chunk->type = type; | ||
83 | chunk->addr = addr; | ||
84 | chunk->size = size; | ||
85 | } | ||
86 | |||
87 | /* | ||
67 | * Create memory hole with given address, size, and type | 88 | * Create memory hole with given address, size, and type |
68 | */ | 89 | */ |
69 | void create_mem_hole(struct mem_chunk chunks[], unsigned long addr, | 90 | void create_mem_hole(struct mem_chunk chunk[], unsigned long addr, |
70 | unsigned long size, int type) | 91 | unsigned long size, int type) |
71 | { | 92 | { |
72 | unsigned long start, end, new_size; | 93 | unsigned long lh_start, lh_end, lh_size, ch_start, ch_end, ch_size; |
73 | int i; | 94 | int i, ch_type; |
74 | 95 | ||
75 | for (i = 0; i < MEMORY_CHUNKS; i++) { | 96 | for (i = 0; i < MEMORY_CHUNKS; i++) { |
76 | if (chunks[i].size == 0) | 97 | if (chunk[i].size == 0) |
77 | continue; | ||
78 | if (addr + size < chunks[i].addr) | ||
79 | continue; | ||
80 | if (addr >= chunks[i].addr + chunks[i].size) | ||
81 | continue; | 98 | continue; |
82 | start = max(addr, chunks[i].addr); | 99 | |
83 | end = min(addr + size, chunks[i].addr + chunks[i].size); | 100 | /* Define chunk properties */ |
84 | new_size = end - start; | 101 | ch_start = chunk[i].addr; |
85 | if (new_size == 0) | 102 | ch_size = chunk[i].size; |
86 | continue; | 103 | ch_end = ch_start + ch_size - 1; |
87 | if (start == chunks[i].addr && | 104 | ch_type = chunk[i].type; |
88 | end == chunks[i].addr + chunks[i].size) { | 105 | |
89 | /* Remove chunk */ | 106 | /* Is memory chunk hit by memory hole? */ |
90 | chunks[i].type = type; | 107 | if (addr + size <= ch_start) |
91 | } else if (start == chunks[i].addr) { | 108 | continue; /* No: memory hole in front of chunk */ |
92 | /* Make chunk smaller at start */ | 109 | if (addr > ch_end) |
93 | if (i >= MEMORY_CHUNKS - 1) | 110 | continue; /* No: memory hole after chunk */ |
94 | panic("Unable to create memory hole"); | 111 | |
95 | memmove(&chunks[i + 1], &chunks[i], | 112 | /* Yes: Define local hole properties */ |
96 | sizeof(struct mem_chunk) * | 113 | lh_start = max(addr, chunk[i].addr); |
97 | (MEMORY_CHUNKS - (i + 1))); | 114 | lh_end = min(addr + size - 1, ch_end); |
98 | chunks[i + 1].addr = chunks[i].addr + new_size; | 115 | lh_size = lh_end - lh_start + 1; |
99 | chunks[i + 1].size = chunks[i].size - new_size; | 116 | |
100 | chunks[i].size = new_size; | 117 | if (lh_start == ch_start && lh_end == ch_end) { |
101 | chunks[i].type = type; | 118 | /* Hole covers complete memory chunk */ |
102 | i += 1; | 119 | mem_chunk_init(&chunk[i], lh_start, lh_size, type); |
103 | } else if (end == chunks[i].addr + chunks[i].size) { | 120 | } else if (lh_end == ch_end) { |
104 | /* Make chunk smaller at end */ | 121 | /* Hole starts in memory chunk and convers chunk end */ |
105 | if (i >= MEMORY_CHUNKS - 1) | 122 | mem_chunk_move(chunk, i + 1, i); |
106 | panic("Unable to create memory hole"); | 123 | mem_chunk_init(&chunk[i], ch_start, ch_size - lh_size, |
107 | memmove(&chunks[i + 1], &chunks[i], | 124 | ch_type); |
108 | sizeof(struct mem_chunk) * | 125 | mem_chunk_init(&chunk[i + 1], lh_start, lh_size, type); |
109 | (MEMORY_CHUNKS - (i + 1))); | ||
110 | chunks[i + 1].addr = start; | ||
111 | chunks[i + 1].size = new_size; | ||
112 | chunks[i + 1].type = type; | ||
113 | chunks[i].size -= new_size; | ||
114 | i += 1; | 126 | i += 1; |
127 | } else if (lh_start == ch_start) { | ||
128 | /* Hole ends in memory chunk */ | ||
129 | mem_chunk_move(chunk, i + 1, i); | ||
130 | mem_chunk_init(&chunk[i], lh_start, lh_size, type); | ||
131 | mem_chunk_init(&chunk[i + 1], lh_end + 1, | ||
132 | ch_size - lh_size, ch_type); | ||
133 | break; | ||
115 | } else { | 134 | } else { |
116 | /* Create memory hole */ | 135 | /* Hole splits memory chunk */ |
117 | if (i >= MEMORY_CHUNKS - 2) | 136 | mem_chunk_move(chunk, i + 2, i); |
118 | panic("Unable to create memory hole"); | 137 | mem_chunk_init(&chunk[i], ch_start, |
119 | memmove(&chunks[i + 2], &chunks[i], | 138 | lh_start - ch_start, ch_type); |
120 | sizeof(struct mem_chunk) * | 139 | mem_chunk_init(&chunk[i + 1], lh_start, lh_size, type); |
121 | (MEMORY_CHUNKS - (i + 2))); | 140 | mem_chunk_init(&chunk[i + 2], lh_end + 1, |
122 | chunks[i + 1].addr = addr; | 141 | ch_end - lh_end, ch_type); |
123 | chunks[i + 1].size = size; | 142 | break; |
124 | chunks[i + 1].type = type; | ||
125 | chunks[i + 2].addr = addr + size; | ||
126 | chunks[i + 2].size = | ||
127 | chunks[i].addr + chunks[i].size - (addr + size); | ||
128 | chunks[i + 2].type = chunks[i].type; | ||
129 | chunks[i].size = addr - chunks[i].addr; | ||
130 | i += 2; | ||
131 | } | 143 | } |
132 | } | 144 | } |
133 | } | 145 | } |