| From 90b2adb27bbe06017fb073e766e003a3ce002567 Mon Sep 17 00:00:00 2001 |
| From: Arvind Sankar <nivedita@alum.mit.edu> |
| Date: Tue, 24 Dec 2019 14:29:07 +0100 |
| Subject: [PATCH] efi/earlycon: Fix write-combine mapping on x86 |
| |
| commit d92b54570d24d017d2630e314b525ed792f5aa6c upstream. |
| |
| On x86, until PAT is initialized, WC translates into UC-. Since we |
| calculate and store pgprot_writecombine(PAGE_KERNEL) when earlycon is |
| initialized, this means we actually use UC- mappings instead of WC |
| mappings, which makes scrolling very slow. |
| |
| Instead store a boolean flag to indicate whether we want to use |
| writeback or write-combine mappings, and recalculate the actual pgprot_t |
| we need on every mapping. Once PAT is initialized, we will start using |
| write-combine mappings, which speeds up the scrolling considerably. |
| |
| Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu> |
| Signed-off-by: Ard Biesheuvel <ardb@kernel.org> |
| Cc: Hans de Goede <hdegoede@redhat.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: linux-efi@vger.kernel.org |
| Fixes: 69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation") |
| Link: https://lkml.kernel.org/r/20191224132909.102540-2-ardb@kernel.org |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c |
| index d4077db6dc97..5d4f84781aa0 100644 |
| --- a/drivers/firmware/efi/earlycon.c |
| +++ b/drivers/firmware/efi/earlycon.c |
| @@ -17,7 +17,7 @@ static const struct console *earlycon_console __initdata; |
| static const struct font_desc *font; |
| static u32 efi_x, efi_y; |
| static u64 fb_base; |
| -static pgprot_t fb_prot; |
| +static bool fb_wb; |
| static void *efi_fb; |
| |
| /* |
| @@ -33,10 +33,8 @@ static int __init efi_earlycon_remap_fb(void) |
| if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED)) |
| return 0; |
| |
| - if (pgprot_val(fb_prot) == pgprot_val(PAGE_KERNEL)) |
| - efi_fb = memremap(fb_base, screen_info.lfb_size, MEMREMAP_WB); |
| - else |
| - efi_fb = memremap(fb_base, screen_info.lfb_size, MEMREMAP_WC); |
| + efi_fb = memremap(fb_base, screen_info.lfb_size, |
| + fb_wb ? MEMREMAP_WB : MEMREMAP_WC); |
| |
| return efi_fb ? 0 : -ENOMEM; |
| } |
| @@ -53,9 +51,12 @@ late_initcall(efi_earlycon_unmap_fb); |
| |
| static __ref void *efi_earlycon_map(unsigned long start, unsigned long len) |
| { |
| + pgprot_t fb_prot; |
| + |
| if (efi_fb) |
| return efi_fb + start; |
| |
| + fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL); |
| return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot)); |
| } |
| |
| @@ -215,10 +216,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device, |
| if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) |
| fb_base |= (u64)screen_info.ext_lfb_base << 32; |
| |
| - if (opt && !strcmp(opt, "ram")) |
| - fb_prot = PAGE_KERNEL; |
| - else |
| - fb_prot = pgprot_writecombine(PAGE_KERNEL); |
| + fb_wb = opt && !strcmp(opt, "ram"); |
| |
| si = &screen_info; |
| xres = si->lfb_width; |
| -- |
| 2.7.4 |
| |