2009-12-20 19:19:34 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2005 Intel Corporation
|
|
|
|
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
|
|
|
*
|
|
|
|
* Alex Chiang <achiang@hp.com>
|
|
|
|
* - Unified x86/ia64 implementations
|
2015-02-05 05:44:48 +00:00
|
|
|
*
|
|
|
|
* I/O APIC hotplug support
|
|
|
|
* Yinghai Lu <yinghai@kernel.org>
|
|
|
|
* Jiang Liu <jiang.liu@intel.com>
|
2009-12-20 19:19:34 +00:00
|
|
|
*/
|
2011-10-26 20:22:14 +00:00
|
|
|
#include <linux/export.h>
|
2013-12-03 00:49:16 +00:00
|
|
|
#include <linux/acpi.h>
|
2009-12-20 19:19:09 +00:00
|
|
|
#include <acpi/processor.h>
|
|
|
|
|
|
|
|
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
2010-02-22 19:11:14 +00:00
|
|
|
ACPI_MODULE_NAME("processor_core");
|
2009-12-20 19:19:09 +00:00
|
|
|
|
2015-02-05 05:44:48 +00:00
|
|
|
static struct acpi_table_madt *get_madt_table(void)
|
|
|
|
{
|
|
|
|
static struct acpi_table_madt *madt;
|
|
|
|
static int read_madt;
|
|
|
|
|
|
|
|
if (!read_madt) {
|
|
|
|
if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
|
|
|
|
(struct acpi_table_header **)&madt)))
|
|
|
|
madt = NULL;
|
|
|
|
read_madt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return madt;
|
|
|
|
}
|
|
|
|
|
2010-02-22 19:11:24 +00:00
|
|
|
static int map_lapic_id(struct acpi_subtable_header *entry,
|
2016-08-25 08:35:17 +00:00
|
|
|
u32 acpi_id, phys_cpuid_t *apic_id, bool ignore_disabled)
|
2010-02-22 19:11:24 +00:00
|
|
|
{
|
|
|
|
struct acpi_madt_local_apic *lapic =
|
2014-09-14 13:12:43 +00:00
|
|
|
container_of(entry, struct acpi_madt_local_apic, header);
|
2010-02-22 19:11:44 +00:00
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
if (ignore_disabled && !(lapic->lapic_flags & ACPI_MADT_ENABLED))
|
2014-01-17 04:37:02 +00:00
|
|
|
return -ENODEV;
|
2010-02-22 19:11:44 +00:00
|
|
|
|
|
|
|
if (lapic->processor_id != acpi_id)
|
2014-01-17 04:37:02 +00:00
|
|
|
return -EINVAL;
|
2010-02-22 19:11:44 +00:00
|
|
|
|
|
|
|
*apic_id = lapic->id;
|
2014-01-17 04:37:02 +00:00
|
|
|
return 0;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int map_x2apic_id(struct acpi_subtable_header *entry,
|
2016-08-25 08:35:17 +00:00
|
|
|
int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id,
|
|
|
|
bool ignore_disabled)
|
2010-02-22 19:11:24 +00:00
|
|
|
{
|
|
|
|
struct acpi_madt_local_x2apic *apic =
|
2014-09-14 13:12:43 +00:00
|
|
|
container_of(entry, struct acpi_madt_local_x2apic, header);
|
2010-02-22 19:11:24 +00:00
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
if (ignore_disabled && !(apic->lapic_flags & ACPI_MADT_ENABLED))
|
2014-01-17 04:37:02 +00:00
|
|
|
return -ENODEV;
|
2010-02-22 19:11:24 +00:00
|
|
|
|
2010-02-22 19:11:50 +00:00
|
|
|
if (device_declaration && (apic->uid == acpi_id)) {
|
|
|
|
*apic_id = apic->local_apic_id;
|
2014-01-17 04:37:02 +00:00
|
|
|
return 0;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
|
2014-01-17 04:37:02 +00:00
|
|
|
return -EINVAL;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int map_lsapic_id(struct acpi_subtable_header *entry,
|
2016-08-25 08:35:17 +00:00
|
|
|
int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id,
|
|
|
|
bool ignore_disabled)
|
2010-02-22 19:11:24 +00:00
|
|
|
{
|
|
|
|
struct acpi_madt_local_sapic *lsapic =
|
2014-09-14 13:12:43 +00:00
|
|
|
container_of(entry, struct acpi_madt_local_sapic, header);
|
2010-02-22 19:11:24 +00:00
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
if (ignore_disabled && !(lsapic->lapic_flags & ACPI_MADT_ENABLED))
|
2014-01-17 04:37:02 +00:00
|
|
|
return -ENODEV;
|
2010-02-22 19:11:24 +00:00
|
|
|
|
|
|
|
if (device_declaration) {
|
2010-02-22 19:11:55 +00:00
|
|
|
if ((entry->length < 16) || (lsapic->uid != acpi_id))
|
2014-01-17 04:37:02 +00:00
|
|
|
return -EINVAL;
|
2010-02-22 19:11:55 +00:00
|
|
|
} else if (lsapic->processor_id != acpi_id)
|
2014-01-17 04:37:02 +00:00
|
|
|
return -EINVAL;
|
2010-02-22 19:11:24 +00:00
|
|
|
|
2010-02-22 19:11:55 +00:00
|
|
|
*apic_id = (lsapic->id << 8) | lsapic->eid;
|
2014-01-17 04:37:02 +00:00
|
|
|
return 0;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
|
2015-03-24 14:02:47 +00:00
|
|
|
/*
|
|
|
|
* Retrieve the ARM CPU physical identifier (MPIDR)
|
|
|
|
*/
|
|
|
|
static int map_gicc_mpidr(struct acpi_subtable_header *entry,
|
2016-08-25 08:35:17 +00:00
|
|
|
int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr,
|
|
|
|
bool ignore_disabled)
|
2015-03-24 14:02:47 +00:00
|
|
|
{
|
|
|
|
struct acpi_madt_generic_interrupt *gicc =
|
|
|
|
container_of(entry, struct acpi_madt_generic_interrupt, header);
|
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
if (ignore_disabled && !(gicc->flags & ACPI_MADT_ENABLED))
|
2015-03-24 14:02:47 +00:00
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
/* device_declaration means Device object in DSDT, in the
|
|
|
|
* GIC interrupt model, logical processors are required to
|
|
|
|
* have a Processor Device object in the DSDT, so we should
|
|
|
|
* check device_declaration here
|
|
|
|
*/
|
|
|
|
if (device_declaration && (gicc->uid == acpi_id)) {
|
|
|
|
*mpidr = gicc->arm_mpidr;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-05-24 22:35:43 +00:00
|
|
|
static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
|
2016-08-25 08:35:17 +00:00
|
|
|
int type, u32 acpi_id, bool ignore_disabled)
|
2010-02-22 19:11:24 +00:00
|
|
|
{
|
|
|
|
unsigned long madt_end, entry;
|
2015-03-24 14:02:46 +00:00
|
|
|
phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */
|
2010-02-22 19:11:24 +00:00
|
|
|
|
|
|
|
if (!madt)
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
return phys_id;
|
2010-02-22 19:11:24 +00:00
|
|
|
|
|
|
|
entry = (unsigned long)madt;
|
|
|
|
madt_end = entry + madt->header.length;
|
|
|
|
|
|
|
|
/* Parse all entries looking for a match. */
|
|
|
|
|
|
|
|
entry += sizeof(struct acpi_table_madt);
|
|
|
|
while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
|
|
|
|
struct acpi_subtable_header *header =
|
|
|
|
(struct acpi_subtable_header *)entry;
|
|
|
|
if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
|
2016-08-25 08:35:17 +00:00
|
|
|
if (!map_lapic_id(header, acpi_id, &phys_id,
|
|
|
|
ignore_disabled))
|
2010-02-22 19:11:24 +00:00
|
|
|
break;
|
|
|
|
} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
|
2016-08-25 08:35:17 +00:00
|
|
|
if (!map_x2apic_id(header, type, acpi_id, &phys_id,
|
|
|
|
ignore_disabled))
|
2010-02-22 19:11:24 +00:00
|
|
|
break;
|
|
|
|
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
|
2016-08-25 08:35:17 +00:00
|
|
|
if (!map_lsapic_id(header, type, acpi_id, &phys_id,
|
|
|
|
ignore_disabled))
|
2010-02-22 19:11:24 +00:00
|
|
|
break;
|
2015-03-24 14:02:47 +00:00
|
|
|
} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
|
2016-08-25 08:35:17 +00:00
|
|
|
if (!map_gicc_mpidr(header, type, acpi_id, &phys_id,
|
|
|
|
ignore_disabled))
|
2015-03-24 14:02:47 +00:00
|
|
|
break;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
entry += header->length;
|
|
|
|
}
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
return phys_id;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
|
2016-05-24 22:35:43 +00:00
|
|
|
phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
|
|
|
|
{
|
|
|
|
struct acpi_table_madt *madt = NULL;
|
|
|
|
acpi_size tbl_size;
|
|
|
|
phys_cpuid_t rv;
|
|
|
|
|
|
|
|
acpi_get_table_with_size(ACPI_SIG_MADT, 0,
|
|
|
|
(struct acpi_table_header **)&madt,
|
|
|
|
&tbl_size);
|
|
|
|
if (!madt)
|
|
|
|
return PHYS_CPUID_INVALID;
|
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
rv = map_madt_entry(madt, 1, acpi_id, true);
|
2016-05-24 22:35:43 +00:00
|
|
|
|
|
|
|
early_acpi_os_unmap_memory(madt, tbl_size);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id,
|
|
|
|
bool ignore_disabled)
|
2010-02-22 19:11:24 +00:00
|
|
|
{
|
|
|
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
|
|
|
union acpi_object *obj;
|
|
|
|
struct acpi_subtable_header *header;
|
2015-03-24 14:02:46 +00:00
|
|
|
phys_cpuid_t phys_id = PHYS_CPUID_INVALID;
|
2010-02-22 19:11:24 +00:00
|
|
|
|
|
|
|
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (!buffer.length || !buffer.pointer)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
obj = buffer.pointer;
|
|
|
|
if (obj->type != ACPI_TYPE_BUFFER ||
|
|
|
|
obj->buffer.length < sizeof(struct acpi_subtable_header)) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
header = (struct acpi_subtable_header *)obj->buffer.pointer;
|
2014-10-27 05:21:36 +00:00
|
|
|
if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
|
2016-08-25 08:35:17 +00:00
|
|
|
map_lapic_id(header, acpi_id, &phys_id, ignore_disabled);
|
2014-10-27 05:21:36 +00:00
|
|
|
else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
|
2016-08-25 08:35:17 +00:00
|
|
|
map_lsapic_id(header, type, acpi_id, &phys_id, ignore_disabled);
|
2014-10-27 05:21:36 +00:00
|
|
|
else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
|
2016-08-25 08:35:17 +00:00
|
|
|
map_x2apic_id(header, type, acpi_id, &phys_id, ignore_disabled);
|
2015-03-24 14:02:47 +00:00
|
|
|
else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
|
2016-08-25 08:35:17 +00:00
|
|
|
map_gicc_mpidr(header, type, acpi_id, &phys_id,
|
|
|
|
ignore_disabled);
|
2010-02-22 19:11:24 +00:00
|
|
|
|
|
|
|
exit:
|
2013-02-24 23:12:53 +00:00
|
|
|
kfree(buffer.pointer);
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
return phys_id;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
static phys_cpuid_t __acpi_get_phys_id(acpi_handle handle, int type,
|
|
|
|
u32 acpi_id, bool ignore_disabled)
|
2010-02-22 19:11:24 +00:00
|
|
|
{
|
2015-03-24 14:02:46 +00:00
|
|
|
phys_cpuid_t phys_id;
|
2010-02-22 19:11:24 +00:00
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
phys_id = map_mat_entry(handle, type, acpi_id, ignore_disabled);
|
2015-05-13 08:19:30 +00:00
|
|
|
if (invalid_phys_cpuid(phys_id))
|
2016-08-25 08:35:17 +00:00
|
|
|
phys_id = map_madt_entry(get_madt_table(), type, acpi_id,
|
|
|
|
ignore_disabled);
|
2013-09-02 03:57:34 +00:00
|
|
|
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
return phys_id;
|
2013-09-02 03:57:34 +00:00
|
|
|
}
|
|
|
|
|
2016-08-25 08:35:17 +00:00
|
|
|
phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
|
|
|
|
{
|
|
|
|
return __acpi_get_phys_id(handle, type, acpi_id, true);
|
|
|
|
}
|
|
|
|
|
2015-03-24 14:02:46 +00:00
|
|
|
int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id)
|
2013-09-02 03:57:34 +00:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
int i;
|
|
|
|
#endif
|
|
|
|
|
2015-05-13 08:19:30 +00:00
|
|
|
if (invalid_phys_cpuid(phys_id)) {
|
ACPI: processor: fix acpi_get_cpuid for UP processor
For UP processor, it is likely that no _MAT method or MADT table defined.
So currently acpi_get_cpuid(...) always return -1 for UP processor.
This is wrong. It should return valid value for CPU0.
In the other hand, BIOS may define multiple CPU handles even for UP
processor, for example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
We should only return valid value for CPU0's acpi handle.
And return invalid value for others.
http://marc.info/?t=132329819900003&r=1&w=2
Cc: stable@vger.kernel.org
Reported-and-tested-by: wallak@free.fr
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-12-13 01:36:03 +00:00
|
|
|
/*
|
|
|
|
* On UP processor, there is no _MAT or MADT table.
|
2015-03-24 14:02:46 +00:00
|
|
|
* So above phys_id is always set to PHYS_CPUID_INVALID.
|
ACPI: processor: fix acpi_get_cpuid for UP processor
For UP processor, it is likely that no _MAT method or MADT table defined.
So currently acpi_get_cpuid(...) always return -1 for UP processor.
This is wrong. It should return valid value for CPU0.
In the other hand, BIOS may define multiple CPU handles even for UP
processor, for example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
We should only return valid value for CPU0's acpi handle.
And return invalid value for others.
http://marc.info/?t=132329819900003&r=1&w=2
Cc: stable@vger.kernel.org
Reported-and-tested-by: wallak@free.fr
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-12-13 01:36:03 +00:00
|
|
|
*
|
|
|
|
* BIOS may define multiple CPU handles even for UP processor.
|
|
|
|
* For example,
|
|
|
|
*
|
|
|
|
* Scope (_PR)
|
2014-10-27 05:21:36 +00:00
|
|
|
* {
|
ACPI: processor: fix acpi_get_cpuid for UP processor
For UP processor, it is likely that no _MAT method or MADT table defined.
So currently acpi_get_cpuid(...) always return -1 for UP processor.
This is wrong. It should return valid value for CPU0.
In the other hand, BIOS may define multiple CPU handles even for UP
processor, for example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
We should only return valid value for CPU0's acpi handle.
And return invalid value for others.
http://marc.info/?t=132329819900003&r=1&w=2
Cc: stable@vger.kernel.org
Reported-and-tested-by: wallak@free.fr
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-12-13 01:36:03 +00:00
|
|
|
* Processor (CPU0, 0x00, 0x00000410, 0x06) {}
|
|
|
|
* Processor (CPU1, 0x01, 0x00000410, 0x06) {}
|
|
|
|
* Processor (CPU2, 0x02, 0x00000410, 0x06) {}
|
|
|
|
* Processor (CPU3, 0x03, 0x00000410, 0x06) {}
|
|
|
|
* }
|
|
|
|
*
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
* Ignores phys_id and always returns 0 for the processor
|
2012-07-12 10:24:33 +00:00
|
|
|
* handle with acpi id 0 if nr_cpu_ids is 1.
|
|
|
|
* This should be the case if SMP tables are not found.
|
2015-05-11 04:17:18 +00:00
|
|
|
* Return -EINVAL for other CPU's handle.
|
ACPI: processor: fix acpi_get_cpuid for UP processor
For UP processor, it is likely that no _MAT method or MADT table defined.
So currently acpi_get_cpuid(...) always return -1 for UP processor.
This is wrong. It should return valid value for CPU0.
In the other hand, BIOS may define multiple CPU handles even for UP
processor, for example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
We should only return valid value for CPU0's acpi handle.
And return invalid value for others.
http://marc.info/?t=132329819900003&r=1&w=2
Cc: stable@vger.kernel.org
Reported-and-tested-by: wallak@free.fr
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-12-13 01:36:03 +00:00
|
|
|
*/
|
2012-07-12 10:24:33 +00:00
|
|
|
if (nr_cpu_ids <= 1 && acpi_id == 0)
|
ACPI: processor: fix acpi_get_cpuid for UP processor
For UP processor, it is likely that no _MAT method or MADT table defined.
So currently acpi_get_cpuid(...) always return -1 for UP processor.
This is wrong. It should return valid value for CPU0.
In the other hand, BIOS may define multiple CPU handles even for UP
processor, for example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
We should only return valid value for CPU0's acpi handle.
And return invalid value for others.
http://marc.info/?t=132329819900003&r=1&w=2
Cc: stable@vger.kernel.org
Reported-and-tested-by: wallak@free.fr
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-12-13 01:36:03 +00:00
|
|
|
return acpi_id;
|
|
|
|
else
|
2015-05-11 04:17:18 +00:00
|
|
|
return -EINVAL;
|
ACPI: processor: fix acpi_get_cpuid for UP processor
For UP processor, it is likely that no _MAT method or MADT table defined.
So currently acpi_get_cpuid(...) always return -1 for UP processor.
This is wrong. It should return valid value for CPU0.
In the other hand, BIOS may define multiple CPU handles even for UP
processor, for example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
We should only return valid value for CPU0's acpi handle.
And return invalid value for others.
http://marc.info/?t=132329819900003&r=1&w=2
Cc: stable@vger.kernel.org
Reported-and-tested-by: wallak@free.fr
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-12-13 01:36:03 +00:00
|
|
|
}
|
2010-02-22 19:11:24 +00:00
|
|
|
|
ACPI: processor: fix processor_physically_present in UP kernel
Usually, there are multiple processors defined in ACPI table, for
example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
processor_physically_present(...) will be called to check whether those
processors are physically present.
Currently we have below codes in processor_physically_present,
cpuid = acpi_get_cpuid(...);
if ((cpuid == -1) && (num_possible_cpus() > 1))
return false;
return true;
In UP kernel, acpi_get_cpuid(...) always return -1 and
num_possible_cpus() always return 1, so
processor_physically_present(...) always returns true for all passed in
processor handles.
This is wrong for UP processor or SMP processor running UP kernel.
This patch removes the !SMP version of acpi_get_cpuid(), so both UP and
SMP kernel use the same acpi_get_cpuid function.
And for UP kernel, only processor 0 is valid.
https://bugzilla.kernel.org/show_bug.cgi?id=16548
https://bugzilla.kernel.org/show_bug.cgi?id=16357
Tested-by: Anton Kochkov <anton.kochkov@gmail.com>
Tested-by: Ambroz Bizjak <ambrop7@gmail.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-05-16 01:11:00 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2010-02-22 19:11:24 +00:00
|
|
|
for_each_possible_cpu(i) {
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
if (cpu_physical_id(i) == phys_id)
|
2010-02-22 19:11:24 +00:00
|
|
|
return i;
|
|
|
|
}
|
ACPI: processor: fix processor_physically_present in UP kernel
Usually, there are multiple processors defined in ACPI table, for
example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
processor_physically_present(...) will be called to check whether those
processors are physically present.
Currently we have below codes in processor_physically_present,
cpuid = acpi_get_cpuid(...);
if ((cpuid == -1) && (num_possible_cpus() > 1))
return false;
return true;
In UP kernel, acpi_get_cpuid(...) always return -1 and
num_possible_cpus() always return 1, so
processor_physically_present(...) always returns true for all passed in
processor handles.
This is wrong for UP processor or SMP processor running UP kernel.
This patch removes the !SMP version of acpi_get_cpuid(), so both UP and
SMP kernel use the same acpi_get_cpuid function.
And for UP kernel, only processor 0 is valid.
https://bugzilla.kernel.org/show_bug.cgi?id=16548
https://bugzilla.kernel.org/show_bug.cgi?id=16357
Tested-by: Anton Kochkov <anton.kochkov@gmail.com>
Tested-by: Ambroz Bizjak <ambrop7@gmail.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-05-16 01:11:00 +00:00
|
|
|
#else
|
|
|
|
/* In UP kernel, only processor 0 is valid */
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
if (phys_id == 0)
|
|
|
|
return phys_id;
|
ACPI: processor: fix processor_physically_present in UP kernel
Usually, there are multiple processors defined in ACPI table, for
example
Scope (_PR)
{
Processor (CPU0, 0x00, 0x00000410, 0x06) {}
Processor (CPU1, 0x01, 0x00000410, 0x06) {}
Processor (CPU2, 0x02, 0x00000410, 0x06) {}
Processor (CPU3, 0x03, 0x00000410, 0x06) {}
}
processor_physically_present(...) will be called to check whether those
processors are physically present.
Currently we have below codes in processor_physically_present,
cpuid = acpi_get_cpuid(...);
if ((cpuid == -1) && (num_possible_cpus() > 1))
return false;
return true;
In UP kernel, acpi_get_cpuid(...) always return -1 and
num_possible_cpus() always return 1, so
processor_physically_present(...) always returns true for all passed in
processor handles.
This is wrong for UP processor or SMP processor running UP kernel.
This patch removes the !SMP version of acpi_get_cpuid(), so both UP and
SMP kernel use the same acpi_get_cpuid function.
And for UP kernel, only processor 0 is valid.
https://bugzilla.kernel.org/show_bug.cgi?id=16548
https://bugzilla.kernel.org/show_bug.cgi?id=16357
Tested-by: Anton Kochkov <anton.kochkov@gmail.com>
Tested-by: Ambroz Bizjak <ambrop7@gmail.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2011-05-16 01:11:00 +00:00
|
|
|
#endif
|
2015-05-11 04:17:18 +00:00
|
|
|
return -ENODEV;
|
2010-02-22 19:11:24 +00:00
|
|
|
}
|
2013-09-02 03:57:34 +00:00
|
|
|
|
|
|
|
int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
|
|
|
|
{
|
2015-03-24 14:02:46 +00:00
|
|
|
phys_cpuid_t phys_id;
|
2013-09-02 03:57:34 +00:00
|
|
|
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
phys_id = acpi_get_phys_id(handle, type, acpi_id);
|
2013-09-02 03:57:34 +00:00
|
|
|
|
ACPI / processor: Convert apic_id to phys_id to make it arch agnostic
apic_id in MADT table is the CPU hardware id which identify
it self in the system for x86 and ia64, OSPM will use it for
SMP init to map APIC ID to logical cpu number in the early
boot, when the DSDT/SSDT (ACPI namespace) is scanned later, the
ACPI processor driver is probed and the driver will use acpi_id
in DSDT to get the apic_id, then map to the logical cpu number
which is needed by the processor driver.
Before ACPI 5.0, only x86 and ia64 were supported in ACPI spec,
so apic_id is used both in arch code and ACPI core which is
pretty fine. Since ACPI 5.0, ARM is supported by ACPI and
APIC is not available on ARM, this will confuse people when
apic_id is both used by x86 and ARM in one function.
So convert apic_id to phys_id (which is the original meaning)
in ACPI processor dirver to make it arch agnostic, but leave the
arch dependent code unchanged, no functional change.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-01-04 10:55:02 +00:00
|
|
|
return acpi_map_cpuid(phys_id, acpi_id);
|
2013-09-02 03:57:34 +00:00
|
|
|
}
|
2010-02-22 19:11:24 +00:00
|
|
|
EXPORT_SYMBOL_GPL(acpi_get_cpuid);
|
2015-02-05 05:44:48 +00:00
|
|
|
|
2016-08-25 08:35:18 +00:00
|
|
|
#ifdef CONFIG_ACPI_HOTPLUG_CPU
|
|
|
|
static bool __init
|
|
|
|
map_processor(acpi_handle handle, phys_cpuid_t *phys_id, int *cpuid)
|
|
|
|
{
|
2016-09-23 15:08:04 +00:00
|
|
|
int type, id;
|
2016-08-25 08:35:18 +00:00
|
|
|
u32 acpi_id;
|
|
|
|
acpi_status status;
|
|
|
|
acpi_object_type acpi_type;
|
|
|
|
unsigned long long tmp;
|
|
|
|
union acpi_object object = { 0 };
|
|
|
|
struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
|
|
|
|
|
|
|
|
status = acpi_get_type(handle, &acpi_type);
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (acpi_type) {
|
|
|
|
case ACPI_TYPE_PROCESSOR:
|
|
|
|
status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
return false;
|
|
|
|
acpi_id = object.processor.proc_id;
|
2016-08-25 08:35:20 +00:00
|
|
|
|
|
|
|
/* validate the acpi_id */
|
|
|
|
if(acpi_processor_validate_proc_id(acpi_id))
|
|
|
|
return false;
|
2016-08-25 08:35:18 +00:00
|
|
|
break;
|
|
|
|
case ACPI_TYPE_DEVICE:
|
|
|
|
status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
return false;
|
|
|
|
acpi_id = tmp;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
|
|
|
|
|
|
|
|
*phys_id = __acpi_get_phys_id(handle, type, acpi_id, false);
|
2016-09-23 15:08:04 +00:00
|
|
|
id = acpi_map_cpuid(*phys_id, acpi_id);
|
2016-08-25 08:35:18 +00:00
|
|
|
|
2016-09-23 15:08:04 +00:00
|
|
|
if (id < 0)
|
|
|
|
return false;
|
|
|
|
*cpuid = id;
|
2016-08-25 08:35:18 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static acpi_status __init
|
|
|
|
set_processor_node_mapping(acpi_handle handle, u32 lvl, void *context,
|
|
|
|
void **rv)
|
|
|
|
{
|
|
|
|
phys_cpuid_t phys_id;
|
|
|
|
int cpu_id;
|
|
|
|
|
|
|
|
if (!map_processor(handle, &phys_id, &cpu_id))
|
|
|
|
return AE_ERROR;
|
|
|
|
|
|
|
|
acpi_map_cpu2node(handle, cpu_id, phys_id);
|
|
|
|
return AE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __init acpi_set_processor_mapping(void)
|
|
|
|
{
|
|
|
|
/* Set persistent cpu <-> node mapping for all processors. */
|
|
|
|
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
|
|
|
ACPI_UINT32_MAX, set_processor_node_mapping,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void __init acpi_set_processor_mapping(void) {}
|
|
|
|
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
|
|
|
|
|
2015-02-05 05:44:48 +00:00
|
|
|
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
|
|
|
|
static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base,
|
|
|
|
u64 *phys_addr, int *ioapic_id)
|
|
|
|
{
|
|
|
|
struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry;
|
|
|
|
|
|
|
|
if (ioapic->global_irq_base != gsi_base)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*phys_addr = ioapic->address;
|
|
|
|
*ioapic_id = ioapic->id;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr)
|
|
|
|
{
|
|
|
|
struct acpi_subtable_header *hdr;
|
|
|
|
unsigned long madt_end, entry;
|
|
|
|
struct acpi_table_madt *madt;
|
|
|
|
int apic_id = -1;
|
|
|
|
|
|
|
|
madt = get_madt_table();
|
|
|
|
if (!madt)
|
|
|
|
return apic_id;
|
|
|
|
|
|
|
|
entry = (unsigned long)madt;
|
|
|
|
madt_end = entry + madt->header.length;
|
|
|
|
|
|
|
|
/* Parse all entries looking for a match. */
|
|
|
|
entry += sizeof(struct acpi_table_madt);
|
|
|
|
while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
|
|
|
|
hdr = (struct acpi_subtable_header *)entry;
|
|
|
|
if (hdr->type == ACPI_MADT_TYPE_IO_APIC &&
|
|
|
|
get_ioapic_id(hdr, gsi_base, phys_addr, &apic_id))
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
entry += hdr->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
return apic_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_mat_ioapic_entry(acpi_handle handle, u32 gsi_base,
|
|
|
|
u64 *phys_addr)
|
|
|
|
{
|
|
|
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
|
|
|
struct acpi_subtable_header *header;
|
|
|
|
union acpi_object *obj;
|
|
|
|
int apic_id = -1;
|
|
|
|
|
|
|
|
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (!buffer.length || !buffer.pointer)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
obj = buffer.pointer;
|
|
|
|
if (obj->type != ACPI_TYPE_BUFFER ||
|
|
|
|
obj->buffer.length < sizeof(struct acpi_subtable_header))
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
header = (struct acpi_subtable_header *)obj->buffer.pointer;
|
|
|
|
if (header->type == ACPI_MADT_TYPE_IO_APIC)
|
|
|
|
get_ioapic_id(header, gsi_base, phys_addr, &apic_id);
|
|
|
|
|
|
|
|
exit:
|
|
|
|
kfree(buffer.pointer);
|
|
|
|
return apic_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* acpi_get_ioapic_id - Get IOAPIC ID and physical address matching @gsi_base
|
|
|
|
* @handle: ACPI object for IOAPIC device
|
|
|
|
* @gsi_base: GSI base to match with
|
|
|
|
* @phys_addr: Pointer to store physical address of matching IOAPIC record
|
|
|
|
*
|
|
|
|
* Walk resources returned by ACPI_MAT method, then ACPI MADT table, to search
|
|
|
|
* for an ACPI IOAPIC record matching @gsi_base.
|
|
|
|
* Return IOAPIC id and store physical address in @phys_addr if found a match,
|
|
|
|
* otherwise return <0.
|
|
|
|
*/
|
|
|
|
int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr)
|
|
|
|
{
|
|
|
|
int apic_id;
|
|
|
|
|
|
|
|
apic_id = parse_mat_ioapic_entry(handle, gsi_base, phys_addr);
|
|
|
|
if (apic_id == -1)
|
|
|
|
apic_id = parse_madt_ioapic_entry(gsi_base, phys_addr);
|
|
|
|
|
|
|
|
return apic_id;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_ACPI_HOTPLUG_IOAPIC */
|