|
20 | 20 | #include <drm/drm_connector.h> /* For DRM_MODE_PANEL_ORIENTATION_* */
|
21 | 21 |
|
22 | 22 | static bool request_mem_succeeded = false;
|
23 |
| -static bool nowc = false; |
| 23 | +static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC; |
24 | 24 |
|
25 | 25 | static struct fb_var_screeninfo efifb_defined = {
|
26 | 26 | .activate = FB_ACTIVATE_NOW,
|
@@ -68,8 +68,12 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
68 | 68 |
|
69 | 69 | static void efifb_destroy(struct fb_info *info)
|
70 | 70 | {
|
71 |
| - if (info->screen_base) |
72 |
| - iounmap(info->screen_base); |
| 71 | + if (info->screen_base) { |
| 72 | + if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) |
| 73 | + iounmap(info->screen_base); |
| 74 | + else |
| 75 | + memunmap(info->screen_base); |
| 76 | + } |
73 | 77 | if (request_mem_succeeded)
|
74 | 78 | release_mem_region(info->apertures->ranges[0].base,
|
75 | 79 | info->apertures->ranges[0].size);
|
@@ -104,7 +108,7 @@ static int efifb_setup(char *options)
|
104 | 108 | else if (!strncmp(this_opt, "width:", 6))
|
105 | 109 | screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
|
106 | 110 | else if (!strcmp(this_opt, "nowc"))
|
107 |
| - nowc = true; |
| 111 | + mem_flags &= ~EFI_MEMORY_WC; |
108 | 112 | }
|
109 | 113 | }
|
110 | 114 |
|
@@ -164,6 +168,7 @@ static int efifb_probe(struct platform_device *dev)
|
164 | 168 | unsigned int size_remap;
|
165 | 169 | unsigned int size_total;
|
166 | 170 | char *option = NULL;
|
| 171 | + efi_memory_desc_t md; |
167 | 172 |
|
168 | 173 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
|
169 | 174 | return -ENODEV;
|
@@ -272,12 +277,35 @@ static int efifb_probe(struct platform_device *dev)
|
272 | 277 | info->apertures->ranges[0].base = efifb_fix.smem_start;
|
273 | 278 | info->apertures->ranges[0].size = size_remap;
|
274 | 279 |
|
275 |
| - if (nowc) |
276 |
| - info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); |
277 |
| - else |
278 |
| - info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len); |
| 280 | + if (!efi_mem_desc_lookup(efifb_fix.smem_start, &md)) { |
| 281 | + if ((efifb_fix.smem_start + efifb_fix.smem_len) > |
| 282 | + (md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) { |
| 283 | + pr_err("efifb: video memory @ 0x%lx spans multiple EFI memory regions\n", |
| 284 | + efifb_fix.smem_start); |
| 285 | + err = -EIO; |
| 286 | + goto err_release_fb; |
| 287 | + } |
| 288 | + /* |
| 289 | + * If the UEFI memory map covers the efifb region, we may only |
| 290 | + * remap it using the attributes the memory map prescribes. |
| 291 | + */ |
| 292 | + mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB; |
| 293 | + mem_flags &= md.attribute; |
| 294 | + } |
| 295 | + if (mem_flags & EFI_MEMORY_WC) |
| 296 | + info->screen_base = ioremap_wc(efifb_fix.smem_start, |
| 297 | + efifb_fix.smem_len); |
| 298 | + else if (mem_flags & EFI_MEMORY_UC) |
| 299 | + info->screen_base = ioremap(efifb_fix.smem_start, |
| 300 | + efifb_fix.smem_len); |
| 301 | + else if (mem_flags & EFI_MEMORY_WT) |
| 302 | + info->screen_base = memremap(efifb_fix.smem_start, |
| 303 | + efifb_fix.smem_len, MEMREMAP_WT); |
| 304 | + else if (mem_flags & EFI_MEMORY_WB) |
| 305 | + info->screen_base = memremap(efifb_fix.smem_start, |
| 306 | + efifb_fix.smem_len, MEMREMAP_WB); |
279 | 307 | if (!info->screen_base) {
|
280 |
| - pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", |
| 308 | + pr_err("efifb: abort, cannot remap video memory 0x%x @ 0x%lx\n", |
281 | 309 | efifb_fix.smem_len, efifb_fix.smem_start);
|
282 | 310 | err = -EIO;
|
283 | 311 | goto err_release_fb;
|
@@ -371,7 +399,10 @@ static int efifb_probe(struct platform_device *dev)
|
371 | 399 | err_groups:
|
372 | 400 | sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
|
373 | 401 | err_unmap:
|
374 |
| - iounmap(info->screen_base); |
| 402 | + if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) |
| 403 | + iounmap(info->screen_base); |
| 404 | + else |
| 405 | + memunmap(info->screen_base); |
375 | 406 | err_release_fb:
|
376 | 407 | framebuffer_release(info);
|
377 | 408 | err_release_mem:
|
|
0 commit comments