int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
        struct linux_efi_memreserve *rsv;
-       int rsvsize = EFI_MEMRESERVE_SIZE(1);
-       int rc;
+       unsigned long prsv;
+       int rc, index;
 
        if (efi_memreserve_root == (void *)ULONG_MAX)
                return -ENODEV;
                        return rc;
        }
 
-       rsv = kmalloc(rsvsize, GFP_ATOMIC);
+       /* first try to find a slot in an existing linked list entry */
+       for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
+               rsv = __va(prsv);
+               index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
+               if (index < rsv->size) {
+                       rsv->entry[index].base = addr;
+                       rsv->entry[index].size = size;
+
+                       return 0;
+               }
+       }
+
+       /* no slot found - allocate a new linked list entry */
+       rsv = (struct linux_efi_memreserve *)__get_free_page(GFP_ATOMIC);
        if (!rsv)
                return -ENOMEM;
 
-       rsv->size = 1;
+       rsv->size = EFI_MEMRESERVE_COUNT(PAGE_SIZE);
        atomic_set(&rsv->count, 1);
        rsv->entry[0].base = addr;
        rsv->entry[0].size = size;
 
 #define EFI_MEMRESERVE_SIZE(count) (sizeof(struct linux_efi_memreserve) + \
        (count) * sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
 
+#define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \
+       / sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
+
 #endif /* _LINUX_EFI_H */