[PATCH] vesafb: Fix mtrr bugs
authorAntonino A. Daplas <adaplas@gmail.com>
Fri, 29 Jul 2005 21:03:31 +0000 (14:03 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 29 Jul 2005 22:01:13 +0000 (15:01 -0700)
>> vesafb: mode is 800x600x16, linelength=1600, pages=16
>> vesafb: scrolling: redraw
>> vesafb: Truecolor: size=0:5:6:5, shift=0:11:5:0
>> mtrr: type mismatch for fc000000,1000000 old: write-back new: write-
>> combining

Range is already set to write-back, vesafb attempts to add a write-combining
mtrr (default for vesafb).

>> mtrr: size and base must be multiples of 4 kiB

This is a bug, vesafb attempts to add a size < PAGE_SIZE triggering
the messages below.

To eliminate the warning messages, you can add the option mtrr:2 to add a
write-back mtrr for vesafb.  Or just use nomtrr option.

1. Fix algorithm for finding the best power of 2 size with mtrr_add().

2. Add option to choose the mtrr type by extending the mtrr boot option:

   mtrr:n where n

        0 = no mtrr (equivalent to using the nomtrr option)
        1 = uncachable
        2 = write back
        3 = write combining (default)
        4 = write through

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/video/vesafb.c

index 9ed1a931dd315c8008d7d6b952f1a34900c2222f..a272592b037391858ab28d31ad93171fc15be1bb 100644 (file)
@@ -45,7 +45,7 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = {
 };
 
 static int             inverse   = 0;
-static int             mtrr      = 1;
+static int             mtrr      = 3; /* default to write-combining */
 static int            vram_remap __initdata = 0; /* Set amount of memory to be used */
 static int            vram_total __initdata = 0; /* Set total amount of memory */
 static int             pmi_setpal = 0; /* pmi for palette changes ??? */
@@ -204,8 +204,8 @@ static int __init vesafb_setup(char *options)
                        pmi_setpal=0;
                else if (! strcmp(this_opt, "pmipal"))
                        pmi_setpal=1;
-               else if (! strcmp(this_opt, "mtrr"))
-                       mtrr=1;
+               else if (! strncmp(this_opt, "mtrr:", 5))
+                       mtrr = simple_strtoul(this_opt+5, NULL, 0);
                else if (! strcmp(this_opt, "nomtrr"))
                        mtrr=0;
                else if (! strncmp(this_opt, "vtotal:", 7))
@@ -387,14 +387,39 @@ static int __init vesafb_probe(struct device *device)
 
        if (mtrr) {
                unsigned int temp_size = size_total;
-               /* Find the largest power-of-two */
-               while (temp_size & (temp_size - 1))
-                       temp_size &= (temp_size - 1);
-
-               /* Try and find a power of two to add */
-               while (temp_size > PAGE_SIZE &&
-                       mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
-                       temp_size >>= 1;
+               unsigned int type = 0;
+
+               switch (mtrr) {
+               case 1:
+                       type = MTRR_TYPE_UNCACHABLE;
+                       break;
+               case 2:
+                       type = MTRR_TYPE_WRBACK;
+                       break;
+               case 3:
+                       type = MTRR_TYPE_WRCOMB;
+                       break;
+               case 4:
+                       type = MTRR_TYPE_WRTHROUGH;
+                       break;
+               default:
+                       type = 0;
+                       break;
+               }
+
+               if (type) {
+                       int rc;
+
+                       /* Find the largest power-of-two */
+                       while (temp_size & (temp_size - 1))
+                               temp_size &= (temp_size - 1);
+
+                       /* Try and find a power of two to add */
+                       do {
+                               rc = mtrr_add(vesafb_fix.smem_start, temp_size,
+                                             type, 1);
+                               temp_size >>= 1;
+                       } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
                }
        }