diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-05-04 14:20:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-05-04 14:20:42 -0400 |
commit | 0214196ce0e941256797bf54b2fcf1450452df2a (patch) | |
tree | e61fd92b7abe72d6954d28fdfe3fc176c416c446 /arch/x86/platform | |
parent | 0384dcae2b18db80c49117ac57ea15211ca48751 (diff) | |
parent | 5f35eb0e29ca26da82febe49d7698dbeb8882ea0 (diff) |
Merge tag 'efi-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into x86/urgent
Pull EFI fix from Matt Fleming:
" * Fix earlyprintk=efi,keep support by switching to an ioremap() mapping
of the framebuffer when early_ioremap() is no longer available and
dropping __init from functions that may be invoked after
free_initmem() - Dave Young "
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/platform')
-rw-r--r-- | arch/x86/platform/efi/early_printk.c | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/arch/x86/platform/efi/early_printk.c b/arch/x86/platform/efi/early_printk.c index 81b506d5befd..524142117296 100644 --- a/arch/x86/platform/efi/early_printk.c +++ b/arch/x86/platform/efi/early_printk.c | |||
@@ -14,48 +14,92 @@ | |||
14 | 14 | ||
15 | static const struct font_desc *font; | 15 | static const struct font_desc *font; |
16 | static u32 efi_x, efi_y; | 16 | static u32 efi_x, efi_y; |
17 | static void *efi_fb; | ||
18 | static bool early_efi_keep; | ||
17 | 19 | ||
18 | static __init void early_efi_clear_scanline(unsigned int y) | 20 | /* |
21 | * efi earlyprintk need use early_ioremap to map the framebuffer. | ||
22 | * But early_ioremap is not usable for earlyprintk=efi,keep, ioremap should | ||
23 | * be used instead. ioremap will be available after paging_init() which is | ||
24 | * earlier than initcall callbacks. Thus adding this early initcall function | ||
25 | * early_efi_map_fb to map the whole efi framebuffer. | ||
26 | */ | ||
27 | static __init int early_efi_map_fb(void) | ||
19 | { | 28 | { |
20 | unsigned long base, *dst; | 29 | unsigned long base, size; |
21 | u16 len; | 30 | |
31 | if (!early_efi_keep) | ||
32 | return 0; | ||
22 | 33 | ||
23 | base = boot_params.screen_info.lfb_base; | 34 | base = boot_params.screen_info.lfb_base; |
24 | len = boot_params.screen_info.lfb_linelength; | 35 | size = boot_params.screen_info.lfb_size; |
36 | efi_fb = ioremap(base, size); | ||
37 | |||
38 | return efi_fb ? 0 : -ENOMEM; | ||
39 | } | ||
40 | early_initcall(early_efi_map_fb); | ||
41 | |||
42 | /* | ||
43 | * early_efi_map maps efi framebuffer region [start, start + len -1] | ||
44 | * In case earlyprintk=efi,keep we have the whole framebuffer mapped already | ||
45 | * so just return the offset efi_fb + start. | ||
46 | */ | ||
47 | static __init_refok void *early_efi_map(unsigned long start, unsigned long len) | ||
48 | { | ||
49 | unsigned long base; | ||
50 | |||
51 | base = boot_params.screen_info.lfb_base; | ||
52 | |||
53 | if (efi_fb) | ||
54 | return (efi_fb + start); | ||
55 | else | ||
56 | return early_ioremap(base + start, len); | ||
57 | } | ||
25 | 58 | ||
26 | dst = early_ioremap(base + y*len, len); | 59 | static __init_refok void early_efi_unmap(void *addr, unsigned long len) |
60 | { | ||
61 | if (!efi_fb) | ||
62 | early_iounmap(addr, len); | ||
63 | } | ||
64 | |||
65 | static void early_efi_clear_scanline(unsigned int y) | ||
66 | { | ||
67 | unsigned long *dst; | ||
68 | u16 len; | ||
69 | |||
70 | len = boot_params.screen_info.lfb_linelength; | ||
71 | dst = early_efi_map(y*len, len); | ||
27 | if (!dst) | 72 | if (!dst) |
28 | return; | 73 | return; |
29 | 74 | ||
30 | memset(dst, 0, len); | 75 | memset(dst, 0, len); |
31 | early_iounmap(dst, len); | 76 | early_efi_unmap(dst, len); |
32 | } | 77 | } |
33 | 78 | ||
34 | static __init void early_efi_scroll_up(void) | 79 | static void early_efi_scroll_up(void) |
35 | { | 80 | { |
36 | unsigned long base, *dst, *src; | 81 | unsigned long *dst, *src; |
37 | u16 len; | 82 | u16 len; |
38 | u32 i, height; | 83 | u32 i, height; |
39 | 84 | ||
40 | base = boot_params.screen_info.lfb_base; | ||
41 | len = boot_params.screen_info.lfb_linelength; | 85 | len = boot_params.screen_info.lfb_linelength; |
42 | height = boot_params.screen_info.lfb_height; | 86 | height = boot_params.screen_info.lfb_height; |
43 | 87 | ||
44 | for (i = 0; i < height - font->height; i++) { | 88 | for (i = 0; i < height - font->height; i++) { |
45 | dst = early_ioremap(base + i*len, len); | 89 | dst = early_efi_map(i*len, len); |
46 | if (!dst) | 90 | if (!dst) |
47 | return; | 91 | return; |
48 | 92 | ||
49 | src = early_ioremap(base + (i + font->height) * len, len); | 93 | src = early_efi_map((i + font->height) * len, len); |
50 | if (!src) { | 94 | if (!src) { |
51 | early_iounmap(dst, len); | 95 | early_efi_unmap(dst, len); |
52 | return; | 96 | return; |
53 | } | 97 | } |
54 | 98 | ||
55 | memmove(dst, src, len); | 99 | memmove(dst, src, len); |
56 | 100 | ||
57 | early_iounmap(src, len); | 101 | early_efi_unmap(src, len); |
58 | early_iounmap(dst, len); | 102 | early_efi_unmap(dst, len); |
59 | } | 103 | } |
60 | } | 104 | } |
61 | 105 | ||
@@ -79,16 +123,14 @@ static void early_efi_write_char(u32 *dst, unsigned char c, unsigned int h) | |||
79 | } | 123 | } |
80 | } | 124 | } |
81 | 125 | ||
82 | static __init void | 126 | static void |
83 | early_efi_write(struct console *con, const char *str, unsigned int num) | 127 | early_efi_write(struct console *con, const char *str, unsigned int num) |
84 | { | 128 | { |
85 | struct screen_info *si; | 129 | struct screen_info *si; |
86 | unsigned long base; | ||
87 | unsigned int len; | 130 | unsigned int len; |
88 | const char *s; | 131 | const char *s; |
89 | void *dst; | 132 | void *dst; |
90 | 133 | ||
91 | base = boot_params.screen_info.lfb_base; | ||
92 | si = &boot_params.screen_info; | 134 | si = &boot_params.screen_info; |
93 | len = si->lfb_linelength; | 135 | len = si->lfb_linelength; |
94 | 136 | ||
@@ -109,7 +151,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num) | |||
109 | for (h = 0; h < font->height; h++) { | 151 | for (h = 0; h < font->height; h++) { |
110 | unsigned int n, x; | 152 | unsigned int n, x; |
111 | 153 | ||
112 | dst = early_ioremap(base + (efi_y + h) * len, len); | 154 | dst = early_efi_map((efi_y + h) * len, len); |
113 | if (!dst) | 155 | if (!dst) |
114 | return; | 156 | return; |
115 | 157 | ||
@@ -123,7 +165,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num) | |||
123 | s++; | 165 | s++; |
124 | } | 166 | } |
125 | 167 | ||
126 | early_iounmap(dst, len); | 168 | early_efi_unmap(dst, len); |
127 | } | 169 | } |
128 | 170 | ||
129 | num -= count; | 171 | num -= count; |
@@ -179,6 +221,9 @@ static __init int early_efi_setup(struct console *con, char *options) | |||
179 | for (i = 0; i < (yres - efi_y) / font->height; i++) | 221 | for (i = 0; i < (yres - efi_y) / font->height; i++) |
180 | early_efi_scroll_up(); | 222 | early_efi_scroll_up(); |
181 | 223 | ||
224 | /* early_console_register will unset CON_BOOT in case ,keep */ | ||
225 | if (!(con->flags & CON_BOOT)) | ||
226 | early_efi_keep = true; | ||
182 | return 0; | 227 | return 0; |
183 | } | 228 | } |
184 | 229 | ||