]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - arch/x86/platform/efi/efi.c
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6.git] / arch / x86 / platform / efi / efi.c
index 11e766deb7b55fa878123fabef628769b201f916..3ae4128013e6063c5f63523342c9a8a284d35603 100644 (file)
@@ -89,26 +89,50 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
 
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
-       return efi_call_virt2(get_time, tm, tc);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt2(get_time, tm, tc);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_set_time(efi_time_t *tm)
 {
-       return efi_call_virt1(set_time, tm);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt1(set_time, tm);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
                                             efi_bool_t *pending,
                                             efi_time_t *tm)
 {
-       return efi_call_virt3(get_wakeup_time,
-                             enabled, pending, tm);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt3(get_wakeup_time,
+                               enabled, pending, tm);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
 {
-       return efi_call_virt2(set_wakeup_time,
-                             enabled, tm);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt2(set_wakeup_time,
+                               enabled, tm);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -208,11 +232,14 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
                                             efi_time_cap_t *tc)
 {
+       unsigned long flags;
        efi_status_t status;
 
+       spin_lock_irqsave(&rtc_lock, flags);
        efi_call_phys_prelog();
        status = efi_call_phys2(efi_phys.get_time, tm, tc);
        efi_call_phys_epilog();
+       spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
 
@@ -354,14 +381,31 @@ void __init efi_reserve_boot_services(void)
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                efi_memory_desc_t *md = p;
-               unsigned long long start = md->phys_addr;
-               unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+               u64 start = md->phys_addr;
+               u64 size = md->num_pages << EFI_PAGE_SHIFT;
 
                if (md->type != EFI_BOOT_SERVICES_CODE &&
                    md->type != EFI_BOOT_SERVICES_DATA)
                        continue;
-
-               memblock_x86_reserve_range(start, start + size, "EFI Boot");
+               /* Only reserve where possible:
+                * - Not within any already allocated areas
+                * - Not over any memory area (really needed, if above?)
+                * - Not within any part of the kernel
+                * - Not the bios reserved area
+               */
+               if ((start+size >= virt_to_phys(_text)
+                               && start <= virt_to_phys(_end)) ||
+                       !e820_all_mapped(start, start+size, E820_RAM) ||
+                       memblock_x86_check_reserved_size(&start, &size,
+                                                       1<<EFI_PAGE_SHIFT)) {
+                       /* Could not reserve, skip it */
+                       md->num_pages = 0;
+                       memblock_dbg(PFX "Could not reserve boot range "
+                                       "[0x%010llx-0x%010llx]\n",
+                                               start, start+size-1);
+               } else
+                       memblock_x86_reserve_range(start, start+size,
+                                                       "EFI Boot");
        }
 }
 
@@ -378,6 +422,10 @@ static void __init efi_free_boot_services(void)
                    md->type != EFI_BOOT_SERVICES_DATA)
                        continue;
 
+               /* Could not reserve boot area */
+               if (!size)
+                       continue;
+
                free_bootmem_late(start, size);
        }
 }
@@ -527,9 +575,6 @@ void __init efi_init(void)
        x86_platform.set_wallclock = efi_set_rtc_mmss;
 #endif
 
-       /* Setup for EFI runtime service */
-       reboot_type = BOOT_EFI;
-
 #if EFI_DEBUG
        print_efi_memmap();
 #endif