aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2011-12-27 05:27:05 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-12-27 05:27:09 -0500
commit44e5ddc4e9d52cd5eeda42bb7518b306beab24ee (patch)
treed2b6cf383e707a87cc82f730dbb7704fab292973 /arch/s390
parentc86cce2a20207cbf2b3dfe97c985a1f5aa5d3798 (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.c122
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[])
64EXPORT_SYMBOL(detect_memory_layout); 64EXPORT_SYMBOL(detect_memory_layout);
65 65
66/* 66/*
67 * Move memory chunks array from index "from" to index "to"
68 */
69static 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 */
79static 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 */
69void create_mem_hole(struct mem_chunk chunks[], unsigned long addr, 90void 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}