Commit 44e5ddc4e9d52cd5eeda42bb7518b306beab24ee
Committed by
Martin Schwidefsky
1 parent
c86cce2a20
Exists in
master
and in
6 other branches
[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>
Showing 1 changed file with 67 additions and 55 deletions Side-by-side Diff
arch/s390/kernel/mem_detect.c
... | ... | @@ -64,70 +64,82 @@ |
64 | 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 | 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 | 91 | unsigned long size, int type) |
71 | 92 | { |
72 | - unsigned long start, end, new_size; | |
73 | - int i; | |
93 | + unsigned long lh_start, lh_end, lh_size, ch_start, ch_end, ch_size; | |
94 | + int i, ch_type; | |
74 | 95 | |
75 | 96 | for (i = 0; i < MEMORY_CHUNKS; i++) { |
76 | - if (chunks[i].size == 0) | |
97 | + if (chunk[i].size == 0) | |
77 | 98 | continue; |
78 | - if (addr + size < chunks[i].addr) | |
79 | - continue; | |
80 | - if (addr >= chunks[i].addr + chunks[i].size) | |
81 | - continue; | |
82 | - start = max(addr, chunks[i].addr); | |
83 | - end = min(addr + size, chunks[i].addr + chunks[i].size); | |
84 | - new_size = end - start; | |
85 | - if (new_size == 0) | |
86 | - continue; | |
87 | - if (start == chunks[i].addr && | |
88 | - end == chunks[i].addr + chunks[i].size) { | |
89 | - /* Remove chunk */ | |
90 | - chunks[i].type = type; | |
91 | - } else if (start == chunks[i].addr) { | |
92 | - /* Make chunk smaller at start */ | |
93 | - if (i >= MEMORY_CHUNKS - 1) | |
94 | - panic("Unable to create memory hole"); | |
95 | - memmove(&chunks[i + 1], &chunks[i], | |
96 | - sizeof(struct mem_chunk) * | |
97 | - (MEMORY_CHUNKS - (i + 1))); | |
98 | - chunks[i + 1].addr = chunks[i].addr + new_size; | |
99 | - chunks[i + 1].size = chunks[i].size - new_size; | |
100 | - chunks[i].size = new_size; | |
101 | - chunks[i].type = type; | |
99 | + | |
100 | + /* Define chunk properties */ | |
101 | + ch_start = chunk[i].addr; | |
102 | + ch_size = chunk[i].size; | |
103 | + ch_end = ch_start + ch_size - 1; | |
104 | + ch_type = chunk[i].type; | |
105 | + | |
106 | + /* Is memory chunk hit by memory hole? */ | |
107 | + if (addr + size <= ch_start) | |
108 | + continue; /* No: memory hole in front of chunk */ | |
109 | + if (addr > ch_end) | |
110 | + continue; /* No: memory hole after chunk */ | |
111 | + | |
112 | + /* Yes: Define local hole properties */ | |
113 | + lh_start = max(addr, chunk[i].addr); | |
114 | + lh_end = min(addr + size - 1, ch_end); | |
115 | + lh_size = lh_end - lh_start + 1; | |
116 | + | |
117 | + if (lh_start == ch_start && lh_end == ch_end) { | |
118 | + /* Hole covers complete memory chunk */ | |
119 | + mem_chunk_init(&chunk[i], lh_start, lh_size, type); | |
120 | + } else if (lh_end == ch_end) { | |
121 | + /* Hole starts in memory chunk and convers chunk end */ | |
122 | + mem_chunk_move(chunk, i + 1, i); | |
123 | + mem_chunk_init(&chunk[i], ch_start, ch_size - lh_size, | |
124 | + ch_type); | |
125 | + mem_chunk_init(&chunk[i + 1], lh_start, lh_size, type); | |
102 | 126 | i += 1; |
103 | - } else if (end == chunks[i].addr + chunks[i].size) { | |
104 | - /* Make chunk smaller at end */ | |
105 | - if (i >= MEMORY_CHUNKS - 1) | |
106 | - panic("Unable to create memory hole"); | |
107 | - memmove(&chunks[i + 1], &chunks[i], | |
108 | - sizeof(struct mem_chunk) * | |
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; | |
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 | 134 | } else { |
116 | - /* Create memory hole */ | |
117 | - if (i >= MEMORY_CHUNKS - 2) | |
118 | - panic("Unable to create memory hole"); | |
119 | - memmove(&chunks[i + 2], &chunks[i], | |
120 | - sizeof(struct mem_chunk) * | |
121 | - (MEMORY_CHUNKS - (i + 2))); | |
122 | - chunks[i + 1].addr = addr; | |
123 | - chunks[i + 1].size = size; | |
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; | |
135 | + /* Hole splits memory chunk */ | |
136 | + mem_chunk_move(chunk, i + 2, i); | |
137 | + mem_chunk_init(&chunk[i], ch_start, | |
138 | + lh_start - ch_start, ch_type); | |
139 | + mem_chunk_init(&chunk[i + 1], lh_start, lh_size, type); | |
140 | + mem_chunk_init(&chunk[i + 2], lh_end + 1, | |
141 | + ch_end - lh_end, ch_type); | |
142 | + break; | |
131 | 143 | } |
132 | 144 | } |
133 | 145 | } |