diff options
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/intel/common/block/acpi/cpu_hybrid.c | 121 |
1 files changed, 64 insertions, 57 deletions
diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c index 81c4add0b6..a6f9103380 100644 --- a/src/soc/intel/common/block/acpi/cpu_hybrid.c +++ b/src/soc/intel/common/block/acpi/cpu_hybrid.c @@ -1,12 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include <acpi/acpi.h> #include <acpi/acpigen.h> -#include <intelblocks/acpi.h> -#include <soc/cpu.h> -#include <smp/spinlock.h> -#include <device/device.h> -#include <device/path.h> +#include <bootstate.h> +#include <commonlib/sort.h> #include <cpu/x86/lapic.h> #include <cpu/x86/mp.h> +#include <cpu/cpu.h> +#include <device/path.h> +#include <intelblocks/acpi.h> +#include <soc/cpu.h> +#include <types.h> #define CPPC_NOM_FREQ_IDX 22 #define CPPC_NOM_PERF_IDX 3 @@ -16,70 +19,74 @@ enum cpu_perf_eff_type { CPU_TYPE_PERF, }; -DECLARE_SPIN_LOCK(cpu_lock); -static u8 global_cpu_type[CONFIG_MAX_CPUS]; +struct cpu_apic_info_type { + /* + * Ordered APIC IDs based on core type. + * Array begins with Performance Cores' APIC IDs, + * then followed by Efficeint Cores's APIC IDs. + */ + int32_t apic_ids[CONFIG_MAX_CPUS]; + + /* Total CPU count */ + uint8_t total_cpu_cnt; + + /* + * Total Performance core count. This will be used + * to identify the start of Efficient Cores's + * APIC ID list + */ + uint8_t perf_cpu_cnt; +}; -static bool is_perf_core(void) -{ - return get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE; -} +static struct cpu_apic_info_type cpu_apic_info; -static enum cpu_perf_eff_type get_core_type(void) +/* + * The function orders APIC IDs such that orders first Performance cores and then + * Efficient cores' APIC IDs in ascending order. Also calculates total number of + * Performance cores and all cores count in the system and populates the information + * in the cpu_apic_info sturct. + */ +static void acpi_set_hybrid_cpu_apicid_order(void *unused) { - return (get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE) ? - CPU_TYPE_PERF : CPU_TYPE_EFF; -} + size_t perf_core_cnt = 0, eff_core_cnt = 0; + int32_t eff_apic_ids[CONFIG_MAX_CPUS] = {0}; + extern struct cpu_info cpu_infos[]; + uint32_t i, j = 0; + + for (i = 0; i < ARRAY_SIZE(cpu_apic_info.apic_ids); i++) { + if (cpu_infos[i].cpu->path.apic.core_type == CPU_TYPE_PERF) + cpu_apic_info.apic_ids[perf_core_cnt++] = + cpu_infos[i].cpu->path.apic.apic_id; + else + eff_apic_ids[eff_core_cnt++] = + cpu_infos[i].cpu->path.apic.apic_id; + } -void set_dev_core_type(void) -{ - struct cpu_info *info = cpu_info(); - info->cpu->path.apic.core_type = get_core_type(); -} + if (perf_core_cnt > 1) + bubblesort(cpu_apic_info.apic_ids, perf_core_cnt, NUM_ASCENDING); -static struct device *get_cpu_bus_first_child(void) -{ - struct device *dev = dev_find_path(NULL, DEVICE_PATH_CPU_CLUSTER); - assert(dev != NULL); - return (dev->link_list)->children; -} + for (i = perf_core_cnt; j < eff_core_cnt; i++, j++) + cpu_apic_info.apic_ids[i] = eff_apic_ids[j]; -static u32 get_cpu_index(void) -{ - u32 cpu_index = 0; - struct device *dev; - u32 my_apic_id = lapicid(); + if (eff_core_cnt > 1) + bubblesort(&cpu_apic_info.apic_ids[perf_core_cnt], eff_core_cnt, NUM_ASCENDING); - for (dev = get_cpu_bus_first_child(); dev; dev = dev->sibling) - if (my_apic_id > dev->path.apic.apic_id) - cpu_index++; + /* Populate total core count */ + cpu_apic_info.total_cpu_cnt = perf_core_cnt + eff_core_cnt; - return cpu_index; + cpu_apic_info.perf_cpu_cnt = perf_core_cnt; } -/* - * This function determines the type (performance or efficient) of the CPU that - * is executing it and stores the information (in a thread-safe manner) in an - * global_cpu_type array. - * It requires the SoC to implement a function `get_soc_cpu_type()` which will be - * called in a critical section to determine the type of the executing CPU. - */ -static void set_cpu_type(void *unused) +static enum cpu_perf_eff_type get_core_type(void) { - spin_lock(&cpu_lock); - u8 cpu_index = get_cpu_index(); - - if (is_perf_core()) - global_cpu_type[cpu_index] = CPU_TYPE_PERF; - - spin_unlock(&cpu_lock); + return (get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE) ? + CPU_TYPE_PERF : CPU_TYPE_EFF; } -static void run_set_cpu_type(void *unused) +void set_dev_core_type(void) { - if (mp_run_on_all_cpus(set_cpu_type, NULL) != CB_SUCCESS) { - printk(BIOS_ERR, "cpu_hybrid: Failed to set global_cpu_type with CPU type info\n"); - return; - } + struct cpu_info *info = cpu_info(); + info->cpu->path.apic.core_type = get_core_type(); } static void acpi_get_cpu_nomi_perf(u16 *eff_core_nom_perf, u16 *perf_core_nom_perf) @@ -114,7 +121,7 @@ static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core acpi_get_cpu_nomi_perf(&eff_core_nom_perf, &perf_core_nom_perf); - if (global_cpu_type[core_id] == CPU_TYPE_PERF) + if (core_id < cpu_apic_info.perf_cpu_cnt) acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, perf_core_nom_perf); else acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, @@ -144,4 +151,4 @@ void acpigen_write_CPPC_hybrid_method(s32 core_id) acpigen_pop_len(); } -BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, run_set_cpu_type, NULL); +BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, acpi_set_hybrid_cpu_apicid_order, NULL); |