Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Michael Holzheu and committed by
Martin Schwidefsky
44e5ddc4 c86cce2a

+67 -55
+67 -55
arch/s390/kernel/mem_detect.c
··· 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 }