uvesafb: Clean up MTRR code
authorAndy Lutomirski <luto@amacapital.net>
Mon, 13 May 2013 23:58:46 +0000 (23:58 +0000)
committerDave Airlie <airlied@redhat.com>
Fri, 31 May 2013 03:37:36 +0000 (13:37 +1000)
The old code allowed very strange memory types.  Now it works like
all the other video drivers: ioremap_wc is used unconditionally,
and MTRRs are set if PAT is unavailable (unless MTRR is disabled
by a module parameter).

UC, WB, and WT support is gone.  If there are MTRR conflicts that prevent
addition of a WC MTRR, adding a non-conflicting MTRR is pointless; it's
better to just turn off MTRR support entirely.

As an added bonus, any MTRR added is freed on unload.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Documentation/fb/uvesafb.txt
drivers/video/uvesafb.c
include/video/uvesafb.h

index eefdd91..f6362d8 100644 (file)
@@ -81,17 +81,11 @@ pmipal  Use the protected mode interface for palette changes.
 
 mtrr:n  Setup memory type range registers for the framebuffer
         where n:
-              0 - disabled (equivalent to nomtrr) (default)
-              1 - uncachable
-              2 - write-back
-              3 - write-combining
-              4 - write-through
-
-        If you see the following in dmesg, choose the type that matches
-        the old one.  In this example, use "mtrr:2".
-...
-mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
-...
+              0 - disabled (equivalent to nomtrr)
+              3 - write-combining (default)
+
+       Values other than 0 and 3 will result in a warning and will be
+       treated just like 3.
 
 nomtrr  Do not use memory type range registers.
 
index e328a61..296279b 100644 (file)
@@ -24,9 +24,6 @@
 #ifdef CONFIG_X86
 #include <video/vga.h>
 #endif
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
 #include "edid.h"
 
 static struct cb_id uvesafb_cn_id = {
@@ -1540,67 +1537,30 @@ static void uvesafb_init_info(struct fb_info *info, struct vbe_mode_ib *mode)
 
 static void uvesafb_init_mtrr(struct fb_info *info)
 {
-#ifdef CONFIG_MTRR
+       struct uvesafb_par *par = info->par;
+
        if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
                int temp_size = info->fix.smem_len;
-               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;
-               }
+               int rc;
 
-               if (type) {
-                       int rc;
+               /* Find the largest power-of-two */
+               temp_size = roundup_pow_of_two(temp_size);
 
-                       /* Find the largest power-of-two */
-                       temp_size = roundup_pow_of_two(temp_size);
+               /* Try and find a power of two to add */
+               do {
+                       rc = arch_phys_wc_add(info->fix.smem_start, temp_size);
+                       temp_size >>= 1;
+               } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
 
-                       /* Try and find a power of two to add */
-                       do {
-                               rc = mtrr_add(info->fix.smem_start,
-                                             temp_size, type, 1);
-                               temp_size >>= 1;
-                       } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
-               }
+               if (rc >= 0)
+                       par->mtrr_handle = rc;
        }
-#endif /* CONFIG_MTRR */
 }
 
 static void uvesafb_ioremap(struct fb_info *info)
 {
-#ifdef CONFIG_X86
-       switch (mtrr) {
-       case 1: /* uncachable */
-               info->screen_base = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
-               break;
-       case 2: /* write-back */
-               info->screen_base = ioremap_cache(info->fix.smem_start, info->fix.smem_len);
-               break;
-       case 3: /* write-combining */
-               info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len);
-               break;
-       case 4: /* write-through */
-       default:
-               info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-               break;
-       }
-#else
-       info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
-#endif /* CONFIG_X86 */
+       info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len);
 }
 
 static ssize_t uvesafb_show_vbe_ver(struct device *dev,
@@ -1851,6 +1811,7 @@ static int uvesafb_remove(struct platform_device *dev)
                unregister_framebuffer(info);
                release_region(0x3c0, 32);
                iounmap(info->screen_base);
+               arch_phys_wc_del(par->mtrr_handle);
                release_mem_region(info->fix.smem_start, info->fix.smem_len);
                fb_destroy_modedb(info->monspecs.modedb);
                fb_dealloc_cmap(&info->cmap);
@@ -1930,6 +1891,9 @@ static int uvesafb_setup(char *options)
                }
        }
 
+       if (mtrr != 3 && mtrr != 1)
+               pr_warn("uvesafb: mtrr should be set to 0 or 3; %d is unsupported", mtrr);
+
        return 0;
 }
 #endif /* !MODULE */
index 1a91850..30f5362 100644 (file)
@@ -134,6 +134,7 @@ struct uvesafb_par {
 
        int mode_idx;
        struct vbe_crtc_ib crtc;
+       int mtrr_handle;
 };
 
 #endif /* _UVESAFB_H */