diff options
| -rw-r--r-- | drivers/firmware/efi/efi.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 72a4da76d274..fad7c62cfc0e 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
| @@ -967,36 +967,43 @@ bool efi_is_table_address(unsigned long phys_addr) | |||
| 967 | } | 967 | } |
| 968 | 968 | ||
| 969 | 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; | ||
| 970 | 971 | ||
| 971 | int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) | 972 | int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) |
| 972 | { | 973 | { |
| 973 | struct linux_efi_memreserve *rsv, *parent; | 974 | struct linux_efi_memreserve *rsv; |
| 974 | 975 | ||
| 975 | if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR) | 976 | if (!efi_memreserve_root) |
| 976 | return -ENODEV; | 977 | return -ENODEV; |
| 977 | 978 | ||
| 978 | rsv = kmalloc(sizeof(*rsv), GFP_KERNEL); | 979 | rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC); |
| 979 | if (!rsv) | 980 | if (!rsv) |
| 980 | return -ENOMEM; | 981 | return -ENOMEM; |
| 981 | 982 | ||
| 982 | parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB); | ||
| 983 | if (!parent) { | ||
| 984 | kfree(rsv); | ||
| 985 | return -ENOMEM; | ||
| 986 | } | ||
| 987 | |||
| 988 | rsv->base = addr; | 983 | rsv->base = addr; |
| 989 | rsv->size = size; | 984 | rsv->size = size; |
| 990 | 985 | ||
| 991 | spin_lock(&efi_mem_reserve_persistent_lock); | 986 | spin_lock(&efi_mem_reserve_persistent_lock); |
| 992 | rsv->next = parent->next; | 987 | rsv->next = efi_memreserve_root->next; |
| 993 | parent->next = __pa(rsv); | 988 | efi_memreserve_root->next = __pa(rsv); |
| 994 | spin_unlock(&efi_mem_reserve_persistent_lock); | 989 | spin_unlock(&efi_mem_reserve_persistent_lock); |
| 995 | 990 | ||
| 996 | memunmap(parent); | 991 | return 0; |
| 992 | } | ||
| 997 | 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; | ||
| 998 | return 0; | 1004 | return 0; |
| 999 | } | 1005 | } |
| 1006 | early_initcall(efi_memreserve_root_init); | ||
| 1000 | 1007 | ||
| 1001 | #ifdef CONFIG_KEXEC | 1008 | #ifdef CONFIG_KEXEC |
| 1002 | static int update_efi_random_seed(struct notifier_block *nb, | 1009 | static int update_efi_random_seed(struct notifier_block *nb, |
