OSDN Git Service

ACPI: processor: LoongArch: Get physical ID from MADT
authorBibo Mao <maobibo@loongson.cn>
Mon, 17 Jul 2023 02:22:58 +0000 (10:22 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 17 Aug 2023 16:39:28 +0000 (18:39 +0200)
With ACPI Spec 6.5 chapter 5.2.12.20, each processor in LoongArch
systems has a Core Programmable Interrupt Controller in MADT. The
value of its type is 0x11 in the spec and defined as enum variable
ACPI_MADT_TYPE_CORE_PIC in the Linux kernel.

Physical IDs can be retrieved from MADT for LoongArch systems during
initialization and they can be retrieved from the _MAT output for
hotplug CPUs.

Add physical CPU ID enumeration for LoongArch systems.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
[ rjw: Subject and changelog edits ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/processor_core.c

index d6606a9..7dd6dba 100644 (file)
@@ -132,6 +132,30 @@ static int map_rintc_hartid(struct acpi_subtable_header *entry,
        return -EINVAL;
 }
 
+/*
+ * Retrieve LoongArch CPU physical id
+ */
+static int map_core_pic_id(struct acpi_subtable_header *entry,
+               int device_declaration, u32 acpi_id, phys_cpuid_t *phys_id)
+{
+       struct acpi_madt_core_pic *core_pic =
+               container_of(entry, struct acpi_madt_core_pic, header);
+
+       if (!(core_pic->flags & ACPI_MADT_ENABLED))
+               return -ENODEV;
+
+       /* device_declaration means Device object in DSDT, in LoongArch
+        * system, logical processor acpi_id is required in _UID property
+        * of DSDT table, so we should check device_declaration here
+        */
+       if (device_declaration && (core_pic->processor_id == acpi_id)) {
+               *phys_id = core_pic->core_id;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
                                   int type, u32 acpi_id)
 {
@@ -165,6 +189,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
                } else if (header->type == ACPI_MADT_TYPE_RINTC) {
                        if (!map_rintc_hartid(header, type, acpi_id, &phys_id))
                                break;
+               } else if (header->type == ACPI_MADT_TYPE_CORE_PIC) {
+                       if (!map_core_pic_id(header, type, acpi_id, &phys_id))
+                               break;
                }
                entry += header->length;
        }
@@ -216,6 +243,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
                map_x2apic_id(header, type, acpi_id, &phys_id);
        else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
                map_gicc_mpidr(header, type, acpi_id, &phys_id);
+       else if (header->type == ACPI_MADT_TYPE_CORE_PIC)
+               map_core_pic_id(header, type, acpi_id, &phys_id);
 
 exit:
        kfree(buffer.pointer);