diff options
Diffstat (limited to 'drivers/firmware/efi/efi.c')
-rw-r--r-- | drivers/firmware/efi/efi.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 249eb70691b0..fad7c62cfc0e 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -592,7 +592,11 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, | |||
592 | 592 | ||
593 | early_memunmap(tbl, sizeof(*tbl)); | 593 | early_memunmap(tbl, sizeof(*tbl)); |
594 | } | 594 | } |
595 | return 0; | ||
596 | } | ||
595 | 597 | ||
598 | int __init efi_apply_persistent_mem_reservations(void) | ||
599 | { | ||
596 | if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) { | 600 | if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) { |
597 | unsigned long prsv = efi.mem_reserve; | 601 | unsigned long prsv = efi.mem_reserve; |
598 | 602 | ||
@@ -963,36 +967,43 @@ bool efi_is_table_address(unsigned long phys_addr) | |||
963 | } | 967 | } |
964 | 968 | ||
965 | static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); | 969 | static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); |
970 | static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init; | ||
966 | 971 | ||
967 | int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) | 972 | int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) |
968 | { | 973 | { |
969 | struct linux_efi_memreserve *rsv, *parent; | 974 | struct linux_efi_memreserve *rsv; |
970 | 975 | ||
971 | if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR) | 976 | if (!efi_memreserve_root) |
972 | return -ENODEV; | 977 | return -ENODEV; |
973 | 978 | ||
974 | rsv = kmalloc(sizeof(*rsv), GFP_KERNEL); | 979 | rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC); |
975 | if (!rsv) | 980 | if (!rsv) |
976 | return -ENOMEM; | 981 | return -ENOMEM; |
977 | 982 | ||
978 | parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB); | ||
979 | if (!parent) { | ||
980 | kfree(rsv); | ||
981 | return -ENOMEM; | ||
982 | } | ||
983 | |||
984 | rsv->base = addr; | 983 | rsv->base = addr; |
985 | rsv->size = size; | 984 | rsv->size = size; |
986 | 985 | ||
987 | spin_lock(&efi_mem_reserve_persistent_lock); | 986 | spin_lock(&efi_mem_reserve_persistent_lock); |
988 | rsv->next = parent->next; | 987 | rsv->next = efi_memreserve_root->next; |
989 | parent->next = __pa(rsv); | 988 | efi_memreserve_root->next = __pa(rsv); |
990 | spin_unlock(&efi_mem_reserve_persistent_lock); | 989 | spin_unlock(&efi_mem_reserve_persistent_lock); |
991 | 990 | ||
992 | memunmap(parent); | 991 | return 0; |
992 | } | ||
993 | 993 | ||
994 | static int __init efi_memreserve_root_init(void) | ||
995 | { | ||
996 | if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR) | ||
997 | return -ENODEV; | ||
998 | |||
999 | efi_memreserve_root = memremap(efi.mem_reserve, | ||
1000 | sizeof(*efi_memreserve_root), | ||
1001 | MEMREMAP_WB); | ||
1002 | if (!efi_memreserve_root) | ||
1003 | return -ENOMEM; | ||
994 | return 0; | 1004 | return 0; |
995 | } | 1005 | } |
1006 | early_initcall(efi_memreserve_root_init); | ||
996 | 1007 | ||
997 | #ifdef CONFIG_KEXEC | 1008 | #ifdef CONFIG_KEXEC |
998 | static int update_efi_random_seed(struct notifier_block *nb, | 1009 | static int update_efi_random_seed(struct notifier_block *nb, |