]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
x86: mtrr_cleanup hole size should be less than half of chunk_size, v2
authorYinghai Lu <yhlu.kernel@gmail.com>
Sun, 28 Sep 2008 03:26:06 +0000 (20:26 -0700)
committerIngo Molnar <mingo@elte.hu>
Sun, 28 Sep 2008 07:12:27 +0000 (09:12 +0200)
v2: should check with half of range0 size instead of chunk_size

So don't have silly big hole.

in hpa's case we could auto detect instead of adding mtrr_chunk_size in
command line.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/cpu/mtrr/main.c

index aff46b99ff0127a8593199b5d2c2bee926b09c25..bccf57f5b6153d53f47bf8190a323d6a60006c9c 100644 (file)
@@ -992,22 +992,17 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
        /* only cut back, when it is not the last */
        if (sizek) {
                while (range0_basek + range0_sizek > (basek + sizek)) {
-                       range0_sizek -= chunk_sizek;
+                       if (range0_sizek >= chunk_sizek)
+                               range0_sizek -= chunk_sizek;
+                       else
+                               range0_sizek = 0;
+
                        if (!range0_sizek)
                                break;
                }
        }
 
-       if (range0_sizek) {
-               if (debug_print)
-                       printk(KERN_DEBUG "range0: %016lx - %016lx\n",
-                               range0_basek<<10,
-                               (range0_basek + range0_sizek)<<10);
-               state->reg = range_to_mtrr(state->reg, range0_basek,
-                               range0_sizek, MTRR_TYPE_WRBACK);
-
-       }
-
+second_try:
        range_basek = range0_basek + range0_sizek;
 
        /* one hole in the middle */
@@ -1015,33 +1010,50 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
                second_sizek = range_basek - basek;
 
        if (range0_sizek > state->range_sizek) {
-               unsigned long hole_basek, hole_sizek;
 
                /* one hole in middle or at end */
                hole_sizek = range0_sizek - state->range_sizek - second_sizek;
-               if (hole_sizek) {
-                       hole_basek = range_basek - hole_sizek - second_sizek;
-                       if (debug_print)
-                               printk(KERN_DEBUG "hole: %016lx - %016lx\n",
-                                        hole_basek<<10,
-                                        (hole_basek + hole_sizek)<<10);
-                       state->reg = range_to_mtrr(state->reg, hole_basek,
-                                                  hole_sizek,
-                                                  MTRR_TYPE_UNCACHABLE);
+
+               /* hole size should be less than half of range0 size */
+               if (hole_sizek > (range0_sizek >> 1) &&
+                   range0_sizek >= chunk_sizek) {
+                       range0_sizek -= chunk_sizek;
+                       second_sizek = 0;
+                       hole_sizek = 0;
+
+                       goto second_try;
                }
-       } else  {
+       }
+
+       if (range0_sizek) {
+               if (debug_print)
+                       printk(KERN_DEBUG "range0: %016lx - %016lx\n",
+                               range0_basek<<10,
+                               (range0_basek + range0_sizek)<<10);
+               state->reg = range_to_mtrr(state->reg, range0_basek,
+                               range0_sizek, MTRR_TYPE_WRBACK);
+       }
+
+       if (range0_sizek < state->range_sizek) {
                /* need to handle left over */
                range_sizek = state->range_sizek - range0_sizek;
 
-               if (range_sizek) {
-                       if (debug_print)
-                               printk(KERN_DEBUG "range: %016lx - %016lx\n",
-                                        range_basek<<10,
-                                        (range_basek + range_sizek)<<10);
-                       state->reg = range_to_mtrr(state->reg, range_basek,
-                                        range_sizek,
-                                        MTRR_TYPE_WRBACK);
-               }
+               if (debug_print)
+                       printk(KERN_DEBUG "range: %016lx - %016lx\n",
+                                range_basek<<10,
+                                (range_basek + range_sizek)<<10);
+               state->reg = range_to_mtrr(state->reg, range_basek,
+                                range_sizek, MTRR_TYPE_WRBACK);
+       }
+
+       if (hole_sizek) {
+               hole_basek = range_basek - hole_sizek - second_sizek;
+               if (debug_print)
+                       printk(KERN_DEBUG "hole: %016lx - %016lx\n",
+                                hole_basek<<10,
+                                (hole_basek + hole_sizek)<<10);
+               state->reg = range_to_mtrr(state->reg, hole_basek,
+                                hole_sizek, MTRR_TYPE_UNCACHABLE);
        }
 
        return second_sizek;