diff options
Diffstat (limited to 'arch/x86/kernel/acpi')
| -rw-r--r-- | arch/x86/kernel/acpi/boot.c | 20 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 23 | 
2 files changed, 33 insertions, 10 deletions
| diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 1c38174b5f01..21b542a6866c 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -146,7 +146,11 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)  		pr_debug("Local APIC address 0x%08x\n", madt->address);  	} -	if (madt->header.revision >= 5) + +	/* ACPI 6.3 and newer support the online capable bit. */ +	if (acpi_gbl_FADT.header.revision > 6 || +	    (acpi_gbl_FADT.header.revision == 6 && +	     acpi_gbl_FADT.minor_revision >= 3))  		acpi_support_online_capable = true;  	default_acpi_madt_oem_check(madt->header.oem_id, @@ -193,7 +197,8 @@ static bool __init acpi_is_processor_usable(u32 lapic_flags)  	if (lapic_flags & ACPI_MADT_ENABLED)  		return true; -	if (acpi_support_online_capable && (lapic_flags & ACPI_MADT_ONLINE_CAPABLE)) +	if (!acpi_support_online_capable || +	    (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))  		return true;  	return false; @@ -1853,13 +1858,18 @@ early_param("acpi_sci", setup_acpi_sci);  int __acpi_acquire_global_lock(unsigned int *lock)  { -	unsigned int old, new; +	unsigned int old, new, val;  	old = READ_ONCE(*lock);  	do { -		new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1)); +		val = (old >> 1) & 0x1; +		new = (old & ~0x3) + 2 + val;  	} while (!try_cmpxchg(lock, &old, new)); -	return ((new & 0x3) < 3) ? -1 : 0; + +	if (val) +		return 0; + +	return -1;  }  int __acpi_release_global_lock(unsigned int *lock) diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 3b7f4cdbf2e0..1328c221af30 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -111,13 +111,26 @@ int x86_acpi_suspend_lowlevel(void)  	saved_magic = 0x12345678;  #else /* CONFIG_64BIT */  #ifdef CONFIG_SMP -	initial_stack = (unsigned long)temp_stack + sizeof(temp_stack); -	early_gdt_descr.address = -			(unsigned long)get_cpu_gdt_rw(smp_processor_id()); -	initial_gs = per_cpu_offset(smp_processor_id()); +	/* +	 * As each CPU starts up, it will find its own stack pointer +	 * from its current_task->thread.sp. Typically that will be +	 * the idle thread for a newly-started AP, or even the boot +	 * CPU which will find it set to &init_task in the static +	 * per-cpu data. +	 * +	 * Make the resuming CPU use the temporary stack at startup +	 * by setting current->thread.sp to point to that. The true +	 * %rsp will be restored with the rest of the CPU context, +	 * by do_suspend_lowlevel(). And unwinders don't care about +	 * the abuse of ->thread.sp because it's a dead variable +	 * while the thread is running on the CPU anyway; the true +	 * value is in the actual %rsp register. +	 */ +	current->thread.sp = (unsigned long)temp_stack + sizeof(temp_stack); +	smpboot_control = smp_processor_id();  #endif  	initial_code = (unsigned long)wakeup_long64; -       saved_magic = 0x123456789abcdef0L; +	saved_magic = 0x123456789abcdef0L;  #endif /* CONFIG_64BIT */  	/* | 
