diff options
| author | Yinghai Lu <yinghai@kernel.org> | 2009-11-24 05:46:59 -0500 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2009-11-24 16:06:16 -0500 |
| commit | 5bf65b9ba67226eae9ffc398a0369fc4da35c259 (patch) | |
| tree | 8cfea71f3b7ee3e3eaca13888dff6a4b6a83f6ac /arch/x86/kernel/cpu/mtrr | |
| parent | b24c2a925a9837cccf54d50aeac22ba0cbc15455 (diff) | |
x86, mtrr: Fix sorting of mtrr after subtracting
In some cases we can coalesce MTRR entries after cleanup; this may
allow us to have more entries. As such, introduce clean_sort_range to
to sort and coaelsce the MTRR entries.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <4B0BB9A3.5020908@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/cpu/mtrr')
| -rw-r--r-- | arch/x86/kernel/cpu/mtrr/cleanup.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 6e49f6f91f31..6987af786c02 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c | |||
| @@ -170,6 +170,41 @@ static int __init cmp_range(const void *x1, const void *x2) | |||
| 170 | return start1 - start2; | 170 | return start1 - start2; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | static int __init clean_sort_range(struct res_range *range, int az) | ||
| 174 | { | ||
| 175 | int i, j, k = az - 1, nr_range = 0; | ||
| 176 | |||
| 177 | for (i = 0; i < k; i++) { | ||
| 178 | if (range[i].end) | ||
| 179 | continue; | ||
| 180 | for (j = k; j > i; j--) { | ||
| 181 | if (range[j].end) { | ||
| 182 | k = j; | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | if (j == i) | ||
| 187 | break; | ||
| 188 | range[i].start = range[k].start; | ||
| 189 | range[i].end = range[k].end; | ||
| 190 | range[k].start = 0; | ||
| 191 | range[k].end = 0; | ||
| 192 | k--; | ||
| 193 | } | ||
| 194 | /* count it */ | ||
| 195 | for (i = 0; i < az; i++) { | ||
| 196 | if (!range[i].end) { | ||
| 197 | nr_range = i; | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | /* sort them */ | ||
| 203 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | ||
| 204 | |||
| 205 | return nr_range; | ||
| 206 | } | ||
| 207 | |||
| 173 | #define BIOS_BUG_MSG KERN_WARNING \ | 208 | #define BIOS_BUG_MSG KERN_WARNING \ |
| 174 | "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" | 209 | "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" |
| 175 | 210 | ||
| @@ -223,22 +258,18 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
| 223 | subtract_range(range, extra_remove_base, | 258 | subtract_range(range, extra_remove_base, |
| 224 | extra_remove_base + extra_remove_size - 1); | 259 | extra_remove_base + extra_remove_size - 1); |
| 225 | 260 | ||
| 226 | /* get new range num */ | ||
| 227 | nr_range = 0; | ||
| 228 | for (i = 0; i < RANGE_NUM; i++) { | ||
| 229 | if (!range[i].end) | ||
| 230 | continue; | ||
| 231 | nr_range++; | ||
| 232 | } | ||
| 233 | if (debug_print) { | 261 | if (debug_print) { |
| 234 | printk(KERN_DEBUG "After UC checking\n"); | 262 | printk(KERN_DEBUG "After UC checking\n"); |
| 235 | for (i = 0; i < nr_range; i++) | 263 | for (i = 0; i < RANGE_NUM; i++) { |
| 264 | if (!range[i].end) | ||
| 265 | continue; | ||
| 236 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", | 266 | printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", |
| 237 | range[i].start, range[i].end + 1); | 267 | range[i].start, range[i].end + 1); |
| 268 | } | ||
| 238 | } | 269 | } |
| 239 | 270 | ||
| 240 | /* sort the ranges */ | 271 | /* sort the ranges */ |
| 241 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | 272 | nr_range = clean_sort_range(range, RANGE_NUM); |
| 242 | if (debug_print) { | 273 | if (debug_print) { |
| 243 | printk(KERN_DEBUG "After sorting\n"); | 274 | printk(KERN_DEBUG "After sorting\n"); |
| 244 | for (i = 0; i < nr_range; i++) | 275 | for (i = 0; i < nr_range; i++) |
