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: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
07ebea251d
commit
63e28a7a5f
3 changed files with 22 additions and 63 deletions
|
@ -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
|
||||
0 - disabled (equivalent to nomtrr)
|
||||
3 - write-combining (default)
|
||||
|
||||
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
|
||||
...
|
||||
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.
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -134,6 +134,7 @@ struct uvesafb_par {
|
|||
|
||||
int mode_idx;
|
||||
struct vbe_crtc_ib crtc;
|
||||
int mtrr_handle;
|
||||
};
|
||||
|
||||
#endif /* _UVESAFB_H */
|
||||
|
|
Loading…
Reference in a new issue