Commit 63e28a7a authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Dave Airlie

uvesafb: Clean up MTRR code

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: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 07ebea25
...@@ -81,17 +81,11 @@ pmipal Use the protected mode interface for palette changes. ...@@ -81,17 +81,11 @@ pmipal Use the protected mode interface for palette changes.
mtrr:n Setup memory type range registers for the framebuffer mtrr:n Setup memory type range registers for the framebuffer
where n: where n:
0 - disabled (equivalent to nomtrr) (default) 0 - disabled (equivalent to nomtrr)
1 - uncachable 3 - write-combining (default)
2 - write-back
3 - write-combining Values other than 0 and 3 will result in a warning and will be
4 - write-through treated just like 3.
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
...
nomtrr Do not use memory type range registers. nomtrr Do not use memory type range registers.
......
...@@ -24,9 +24,6 @@ ...@@ -24,9 +24,6 @@
#ifdef CONFIG_X86 #ifdef CONFIG_X86
#include <video/vga.h> #include <video/vga.h>
#endif #endif
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
#include "edid.h" #include "edid.h"
static struct cb_id uvesafb_cn_id = { 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) ...@@ -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) 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))) { if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
int temp_size = info->fix.smem_len; int temp_size = info->fix.smem_len;
unsigned int type = 0;
switch (mtrr) { int rc;
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) { /* Find the largest power-of-two */
int rc; temp_size = roundup_pow_of_two(temp_size);
/* Find the largest power-of-two */ /* Try and find a power of two to add */
temp_size = roundup_pow_of_two(temp_size); 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 */ if (rc >= 0)
do { par->mtrr_handle = rc;
rc = mtrr_add(info->fix.smem_start,
temp_size, type, 1);
temp_size >>= 1;
} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
}
} }
#endif /* CONFIG_MTRR */
} }
static void uvesafb_ioremap(struct fb_info *info) static void uvesafb_ioremap(struct fb_info *info)
{ {
#ifdef CONFIG_X86 info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len);
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 */
} }
static ssize_t uvesafb_show_vbe_ver(struct device *dev, static ssize_t uvesafb_show_vbe_ver(struct device *dev,
...@@ -1851,6 +1811,7 @@ static int uvesafb_remove(struct platform_device *dev) ...@@ -1851,6 +1811,7 @@ static int uvesafb_remove(struct platform_device *dev)
unregister_framebuffer(info); unregister_framebuffer(info);
release_region(0x3c0, 32); release_region(0x3c0, 32);
iounmap(info->screen_base); iounmap(info->screen_base);
arch_phys_wc_del(par->mtrr_handle);
release_mem_region(info->fix.smem_start, info->fix.smem_len); release_mem_region(info->fix.smem_start, info->fix.smem_len);
fb_destroy_modedb(info->monspecs.modedb); fb_destroy_modedb(info->monspecs.modedb);
fb_dealloc_cmap(&info->cmap); fb_dealloc_cmap(&info->cmap);
...@@ -1930,6 +1891,9 @@ static int uvesafb_setup(char *options) ...@@ -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; return 0;
} }
#endif /* !MODULE */ #endif /* !MODULE */
......
...@@ -134,6 +134,7 @@ struct uvesafb_par { ...@@ -134,6 +134,7 @@ struct uvesafb_par {
int mode_idx; int mode_idx;
struct vbe_crtc_ib crtc; struct vbe_crtc_ib crtc;
int mtrr_handle;
}; };
#endif /* _UVESAFB_H */ #endif /* _UVESAFB_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment