Patch "efi/earlycon: Remap entire framebuffer after page initialization" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    efi/earlycon: Remap entire framebuffer after page initialization

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     efi-earlycon-remap-entire-framebuffer-after-page-ini.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit e6d5a8917a10483a734096fa45fb99da52fe503d
Author: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Date:   Fri Dec 6 16:55:42 2019 +0000

    efi/earlycon: Remap entire framebuffer after page initialization
    
    [ Upstream commit b418d660bb9798d2249ac6a46c844389ef50b6a5 ]
    
    When commit:
    
      69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation")
    
    moved the x86 specific EFI earlyprintk implementation to a shared location,
    it also tweaked the behaviour. In particular, it dropped a trick with full
    framebuffer remapping after page initialization, leading to two regressions:
    
      1) very slow scrolling after page initialization,
      2) kernel hang when the 'keep_bootcon' command line argument is passed.
    
    Putting the tweak back fixes #2 and mitigates #1, i.e., it limits the slow
    behavior to the early boot stages, presumably due to eliminating heavy
    map()/unmap() operations per each pixel line on the screen.
    
     [ ardb: ensure efifb is unmapped again unless keep_bootcon is in effect. ]
     [ mingo: speling fixes. ]
    
    Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
    Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx>
    Cc: Arvind Sankar <nivedita@xxxxxxxxxxxx>
    Cc: Bhupesh Sharma <bhsharma@xxxxxxxxxx>
    Cc: Masayoshi Mizuma <m.mizuma@xxxxxxxxxxxxxx>
    Cc: linux-efi@xxxxxxxxxxxxxxx
    Fixes: 69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation")
    Link: https://lkml.kernel.org/r/20191206165542.31469-7-ardb@xxxxxxxxxx
    Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
index c9a0efca17b0..d4077db6dc97 100644
--- a/drivers/firmware/efi/earlycon.c
+++ b/drivers/firmware/efi/earlycon.c
@@ -13,18 +13,57 @@
 
 #include <asm/early_ioremap.h>
 
+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 void *efi_fb;
+
+/*
+ * EFI earlycon needs to use early_memremap() to map the framebuffer.
+ * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
+ * memremap() should be used instead. memremap() will be available after
+ * paging_init() which is earlier than initcall callbacks. Thus adding this
+ * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
+ */
+static int __init efi_earlycon_remap_fb(void)
+{
+	/* bail if there is no bootconsole or it has been disabled already */
+	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);
+
+	return efi_fb ? 0 : -ENOMEM;
+}
+early_initcall(efi_earlycon_remap_fb);
+
+static int __init efi_earlycon_unmap_fb(void)
+{
+	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
+	if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
+		memunmap(efi_fb);
+	return 0;
+}
+late_initcall(efi_earlycon_unmap_fb);
 
 static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
 {
+	if (efi_fb)
+		return efi_fb + start;
+
 	return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
 }
 
 static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
 {
+	if (efi_fb)
+		return;
+
 	early_memunmap(addr, len);
 }
 
@@ -201,6 +240,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
 		efi_earlycon_scroll_up();
 
 	device->con->write = efi_earlycon_write;
+	earlycon_console = device->con;
 	return 0;
 }
 EARLYCON_DECLARE(efifb, efi_earlycon_setup);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux