18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * acpi_processor.c - ACPI processor enumeration support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
68c2ecf20Sopenharmony_ci * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
78c2ecf20Sopenharmony_ci * Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
88c2ecf20Sopenharmony_ci * Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
98c2ecf20Sopenharmony_ci * Copyright (C) 2013, Intel Corporation
108c2ecf20Sopenharmony_ci *                     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/acpi.h>
148c2ecf20Sopenharmony_ci#include <linux/device.h>
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/module.h>
178c2ecf20Sopenharmony_ci#include <linux/pci.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <acpi/processor.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <asm/cpu.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "internal.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define _COMPONENT	ACPI_PROCESSOR_COMPONENT
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciACPI_MODULE_NAME("processor");
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciDEFINE_PER_CPU(struct acpi_processor *, processors);
308c2ecf20Sopenharmony_ciEXPORT_PER_CPU_SYMBOL(processors);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* --------------------------------------------------------------------------
338c2ecf20Sopenharmony_ci                                Errata Handling
348c2ecf20Sopenharmony_ci   -------------------------------------------------------------------------- */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistruct acpi_processor_errata errata __read_mostly;
378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(errata);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic int acpi_processor_errata_piix4(struct pci_dev *dev)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	u8 value1 = 0;
428c2ecf20Sopenharmony_ci	u8 value2 = 0;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (!dev)
468c2ecf20Sopenharmony_ci		return -EINVAL;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	/*
498c2ecf20Sopenharmony_ci	 * Note that 'dev' references the PIIX4 ACPI Controller.
508c2ecf20Sopenharmony_ci	 */
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	switch (dev->revision) {
538c2ecf20Sopenharmony_ci	case 0:
548c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
558c2ecf20Sopenharmony_ci		break;
568c2ecf20Sopenharmony_ci	case 1:
578c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
588c2ecf20Sopenharmony_ci		break;
598c2ecf20Sopenharmony_ci	case 2:
608c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
618c2ecf20Sopenharmony_ci		break;
628c2ecf20Sopenharmony_ci	case 3:
638c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
648c2ecf20Sopenharmony_ci		break;
658c2ecf20Sopenharmony_ci	default:
668c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
678c2ecf20Sopenharmony_ci		break;
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	switch (dev->revision) {
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	case 0:		/* PIIX4 A-step */
738c2ecf20Sopenharmony_ci	case 1:		/* PIIX4 B-step */
748c2ecf20Sopenharmony_ci		/*
758c2ecf20Sopenharmony_ci		 * See specification changes #13 ("Manual Throttle Duty Cycle")
768c2ecf20Sopenharmony_ci		 * and #14 ("Enabling and Disabling Manual Throttle"), plus
778c2ecf20Sopenharmony_ci		 * erratum #5 ("STPCLK# Deassertion Time") from the January
788c2ecf20Sopenharmony_ci		 * 2002 PIIX4 specification update.  Applies to only older
798c2ecf20Sopenharmony_ci		 * PIIX4 models.
808c2ecf20Sopenharmony_ci		 */
818c2ecf20Sopenharmony_ci		errata.piix4.throttle = 1;
828c2ecf20Sopenharmony_ci		fallthrough;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	case 2:		/* PIIX4E */
858c2ecf20Sopenharmony_ci	case 3:		/* PIIX4M */
868c2ecf20Sopenharmony_ci		/*
878c2ecf20Sopenharmony_ci		 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
888c2ecf20Sopenharmony_ci		 * Livelock") from the January 2002 PIIX4 specification update.
898c2ecf20Sopenharmony_ci		 * Applies to all PIIX4 models.
908c2ecf20Sopenharmony_ci		 */
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci		/*
938c2ecf20Sopenharmony_ci		 * BM-IDE
948c2ecf20Sopenharmony_ci		 * ------
958c2ecf20Sopenharmony_ci		 * Find the PIIX4 IDE Controller and get the Bus Master IDE
968c2ecf20Sopenharmony_ci		 * Status register address.  We'll use this later to read
978c2ecf20Sopenharmony_ci		 * each IDE controller's DMA status to make sure we catch all
988c2ecf20Sopenharmony_ci		 * DMA activity.
998c2ecf20Sopenharmony_ci		 */
1008c2ecf20Sopenharmony_ci		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
1018c2ecf20Sopenharmony_ci				     PCI_DEVICE_ID_INTEL_82371AB,
1028c2ecf20Sopenharmony_ci				     PCI_ANY_ID, PCI_ANY_ID, NULL);
1038c2ecf20Sopenharmony_ci		if (dev) {
1048c2ecf20Sopenharmony_ci			errata.piix4.bmisx = pci_resource_start(dev, 4);
1058c2ecf20Sopenharmony_ci			pci_dev_put(dev);
1068c2ecf20Sopenharmony_ci		}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci		/*
1098c2ecf20Sopenharmony_ci		 * Type-F DMA
1108c2ecf20Sopenharmony_ci		 * ----------
1118c2ecf20Sopenharmony_ci		 * Find the PIIX4 ISA Controller and read the Motherboard
1128c2ecf20Sopenharmony_ci		 * DMA controller's status to see if Type-F (Fast) DMA mode
1138c2ecf20Sopenharmony_ci		 * is enabled (bit 7) on either channel.  Note that we'll
1148c2ecf20Sopenharmony_ci		 * disable C3 support if this is enabled, as some legacy
1158c2ecf20Sopenharmony_ci		 * devices won't operate well if fast DMA is disabled.
1168c2ecf20Sopenharmony_ci		 */
1178c2ecf20Sopenharmony_ci		dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
1188c2ecf20Sopenharmony_ci				     PCI_DEVICE_ID_INTEL_82371AB_0,
1198c2ecf20Sopenharmony_ci				     PCI_ANY_ID, PCI_ANY_ID, NULL);
1208c2ecf20Sopenharmony_ci		if (dev) {
1218c2ecf20Sopenharmony_ci			pci_read_config_byte(dev, 0x76, &value1);
1228c2ecf20Sopenharmony_ci			pci_read_config_byte(dev, 0x77, &value2);
1238c2ecf20Sopenharmony_ci			if ((value1 & 0x80) || (value2 & 0x80))
1248c2ecf20Sopenharmony_ci				errata.piix4.fdma = 1;
1258c2ecf20Sopenharmony_ci			pci_dev_put(dev);
1268c2ecf20Sopenharmony_ci		}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci		break;
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (errata.piix4.bmisx)
1328c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1338c2ecf20Sopenharmony_ci				  "Bus master activity detection (BM-IDE) erratum enabled\n"));
1348c2ecf20Sopenharmony_ci	if (errata.piix4.fdma)
1358c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1368c2ecf20Sopenharmony_ci				  "Type-F DMA livelock erratum (C3 disabled)\n"));
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	return 0;
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic int acpi_processor_errata(void)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	int result = 0;
1448c2ecf20Sopenharmony_ci	struct pci_dev *dev = NULL;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	/*
1478c2ecf20Sopenharmony_ci	 * PIIX4
1488c2ecf20Sopenharmony_ci	 */
1498c2ecf20Sopenharmony_ci	dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
1508c2ecf20Sopenharmony_ci			     PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
1518c2ecf20Sopenharmony_ci			     PCI_ANY_ID, NULL);
1528c2ecf20Sopenharmony_ci	if (dev) {
1538c2ecf20Sopenharmony_ci		result = acpi_processor_errata_piix4(dev);
1548c2ecf20Sopenharmony_ci		pci_dev_put(dev);
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	return result;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/* --------------------------------------------------------------------------
1618c2ecf20Sopenharmony_ci                                Initialization
1628c2ecf20Sopenharmony_ci   -------------------------------------------------------------------------- */
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_HOTPLUG_CPU
1658c2ecf20Sopenharmony_ciint __weak acpi_map_cpu(acpi_handle handle,
1668c2ecf20Sopenharmony_ci		phys_cpuid_t physid, u32 acpi_id, int *pcpu)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	return -ENODEV;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ciint __weak acpi_unmap_cpu(int cpu)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	return -ENODEV;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciint __weak arch_register_cpu(int cpu)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	return -ENODEV;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_civoid __weak arch_unregister_cpu(int cpu) {}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic int acpi_processor_hotadd_init(struct acpi_processor *pr)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	unsigned long long sta;
1868c2ecf20Sopenharmony_ci	acpi_status status;
1878c2ecf20Sopenharmony_ci	int ret;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	if (invalid_phys_cpuid(pr->phys_id))
1908c2ecf20Sopenharmony_ci		return -ENODEV;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
1938c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
1948c2ecf20Sopenharmony_ci		return -ENODEV;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	cpu_maps_update_begin();
1978c2ecf20Sopenharmony_ci	cpu_hotplug_begin();
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	ret = acpi_map_cpu(pr->handle, pr->phys_id, pr->acpi_id, &pr->id);
2008c2ecf20Sopenharmony_ci	if (ret)
2018c2ecf20Sopenharmony_ci		goto out;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	ret = arch_register_cpu(pr->id);
2048c2ecf20Sopenharmony_ci	if (ret) {
2058c2ecf20Sopenharmony_ci		acpi_unmap_cpu(pr->id);
2068c2ecf20Sopenharmony_ci		goto out;
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	/*
2108c2ecf20Sopenharmony_ci	 * CPU got hot-added, but cpu_data is not initialized yet.  Set a flag
2118c2ecf20Sopenharmony_ci	 * to delay cpu_idle/throttling initialization and do it when the CPU
2128c2ecf20Sopenharmony_ci	 * gets online for the first time.
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci	pr_info("CPU%d has been hot-added\n", pr->id);
2158c2ecf20Sopenharmony_ci	pr->flags.need_hotplug_init = 1;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ciout:
2188c2ecf20Sopenharmony_ci	cpu_hotplug_done();
2198c2ecf20Sopenharmony_ci	cpu_maps_update_done();
2208c2ecf20Sopenharmony_ci	return ret;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci#else
2238c2ecf20Sopenharmony_cistatic inline int acpi_processor_hotadd_init(struct acpi_processor *pr)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	return -ENODEV;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci#endif /* CONFIG_ACPI_HOTPLUG_CPU */
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic int acpi_processor_get_info(struct acpi_device *device)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	union acpi_object object = { 0 };
2328c2ecf20Sopenharmony_ci	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
2338c2ecf20Sopenharmony_ci	struct acpi_processor *pr = acpi_driver_data(device);
2348c2ecf20Sopenharmony_ci	int device_declaration = 0;
2358c2ecf20Sopenharmony_ci	acpi_status status = AE_OK;
2368c2ecf20Sopenharmony_ci	static int cpu0_initialized;
2378c2ecf20Sopenharmony_ci	unsigned long long value;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	acpi_processor_errata();
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	/*
2428c2ecf20Sopenharmony_ci	 * Check to see if we have bus mastering arbitration control.  This
2438c2ecf20Sopenharmony_ci	 * is required for proper C3 usage (to maintain cache coherency).
2448c2ecf20Sopenharmony_ci	 */
2458c2ecf20Sopenharmony_ci	if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
2468c2ecf20Sopenharmony_ci		pr->flags.bm_control = 1;
2478c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
2488c2ecf20Sopenharmony_ci				  "Bus mastering arbitration control present\n"));
2498c2ecf20Sopenharmony_ci	} else
2508c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
2518c2ecf20Sopenharmony_ci				  "No bus mastering arbitration control\n"));
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
2548c2ecf20Sopenharmony_ci		/* Declared with "Processor" statement; match ProcessorID */
2558c2ecf20Sopenharmony_ci		status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
2568c2ecf20Sopenharmony_ci		if (ACPI_FAILURE(status)) {
2578c2ecf20Sopenharmony_ci			dev_err(&device->dev,
2588c2ecf20Sopenharmony_ci				"Failed to evaluate processor object (0x%x)\n",
2598c2ecf20Sopenharmony_ci				status);
2608c2ecf20Sopenharmony_ci			return -ENODEV;
2618c2ecf20Sopenharmony_ci		}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci		pr->acpi_id = object.processor.proc_id;
2648c2ecf20Sopenharmony_ci	} else {
2658c2ecf20Sopenharmony_ci		/*
2668c2ecf20Sopenharmony_ci		 * Declared with "Device" statement; match _UID.
2678c2ecf20Sopenharmony_ci		 */
2688c2ecf20Sopenharmony_ci		status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
2698c2ecf20Sopenharmony_ci						NULL, &value);
2708c2ecf20Sopenharmony_ci		if (ACPI_FAILURE(status)) {
2718c2ecf20Sopenharmony_ci			dev_err(&device->dev,
2728c2ecf20Sopenharmony_ci				"Failed to evaluate processor _UID (0x%x)\n",
2738c2ecf20Sopenharmony_ci				status);
2748c2ecf20Sopenharmony_ci			return -ENODEV;
2758c2ecf20Sopenharmony_ci		}
2768c2ecf20Sopenharmony_ci		device_declaration = 1;
2778c2ecf20Sopenharmony_ci		pr->acpi_id = value;
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	if (acpi_duplicate_processor_id(pr->acpi_id)) {
2818c2ecf20Sopenharmony_ci		if (pr->acpi_id == 0xff)
2828c2ecf20Sopenharmony_ci			dev_info_once(&device->dev,
2838c2ecf20Sopenharmony_ci				"Entry not well-defined, consider updating BIOS\n");
2848c2ecf20Sopenharmony_ci		else
2858c2ecf20Sopenharmony_ci			dev_err(&device->dev,
2868c2ecf20Sopenharmony_ci				"Failed to get unique processor _UID (0x%x)\n",
2878c2ecf20Sopenharmony_ci				pr->acpi_id);
2888c2ecf20Sopenharmony_ci		return -ENODEV;
2898c2ecf20Sopenharmony_ci	}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	pr->phys_id = acpi_get_phys_id(pr->handle, device_declaration,
2928c2ecf20Sopenharmony_ci					pr->acpi_id);
2938c2ecf20Sopenharmony_ci	if (invalid_phys_cpuid(pr->phys_id))
2948c2ecf20Sopenharmony_ci		acpi_handle_debug(pr->handle, "failed to get CPU physical ID.\n");
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	pr->id = acpi_map_cpuid(pr->phys_id, pr->acpi_id);
2978c2ecf20Sopenharmony_ci	if (!cpu0_initialized && !acpi_has_cpu_in_madt()) {
2988c2ecf20Sopenharmony_ci		cpu0_initialized = 1;
2998c2ecf20Sopenharmony_ci		/*
3008c2ecf20Sopenharmony_ci		 * Handle UP system running SMP kernel, with no CPU
3018c2ecf20Sopenharmony_ci		 * entry in MADT
3028c2ecf20Sopenharmony_ci		 */
3038c2ecf20Sopenharmony_ci		if (invalid_logical_cpuid(pr->id) && (num_online_cpus() == 1))
3048c2ecf20Sopenharmony_ci			pr->id = 0;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/*
3088c2ecf20Sopenharmony_ci	 *  Extra Processor objects may be enumerated on MP systems with
3098c2ecf20Sopenharmony_ci	 *  less than the max # of CPUs. They should be ignored _iff
3108c2ecf20Sopenharmony_ci	 *  they are physically not present.
3118c2ecf20Sopenharmony_ci	 *
3128c2ecf20Sopenharmony_ci	 *  NOTE: Even if the processor has a cpuid, it may not be present
3138c2ecf20Sopenharmony_ci	 *  because cpuid <-> apicid mapping is persistent now.
3148c2ecf20Sopenharmony_ci	 */
3158c2ecf20Sopenharmony_ci	if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id)) {
3168c2ecf20Sopenharmony_ci		int ret = acpi_processor_hotadd_init(pr);
3178c2ecf20Sopenharmony_ci		if (ret)
3188c2ecf20Sopenharmony_ci			return ret;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/*
3228c2ecf20Sopenharmony_ci	 * On some boxes several processors use the same processor bus id.
3238c2ecf20Sopenharmony_ci	 * But they are located in different scope. For example:
3248c2ecf20Sopenharmony_ci	 * \_SB.SCK0.CPU0
3258c2ecf20Sopenharmony_ci	 * \_SB.SCK1.CPU0
3268c2ecf20Sopenharmony_ci	 * Rename the processor device bus id. And the new bus id will be
3278c2ecf20Sopenharmony_ci	 * generated as the following format:
3288c2ecf20Sopenharmony_ci	 * CPU+CPU ID.
3298c2ecf20Sopenharmony_ci	 */
3308c2ecf20Sopenharmony_ci	sprintf(acpi_device_bid(device), "CPU%X", pr->id);
3318c2ecf20Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
3328c2ecf20Sopenharmony_ci			  pr->acpi_id));
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	if (!object.processor.pblk_address)
3358c2ecf20Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
3368c2ecf20Sopenharmony_ci	else if (object.processor.pblk_length != 6)
3378c2ecf20Sopenharmony_ci		dev_err(&device->dev, "Invalid PBLK length [%d]\n",
3388c2ecf20Sopenharmony_ci			    object.processor.pblk_length);
3398c2ecf20Sopenharmony_ci	else {
3408c2ecf20Sopenharmony_ci		pr->throttling.address = object.processor.pblk_address;
3418c2ecf20Sopenharmony_ci		pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
3428c2ecf20Sopenharmony_ci		pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci		pr->pblk = object.processor.pblk_address;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	/*
3488c2ecf20Sopenharmony_ci	 * If ACPI describes a slot number for this CPU, we can use it to
3498c2ecf20Sopenharmony_ci	 * ensure we get the right value in the "physical id" field
3508c2ecf20Sopenharmony_ci	 * of /proc/cpuinfo
3518c2ecf20Sopenharmony_ci	 */
3528c2ecf20Sopenharmony_ci	status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value);
3538c2ecf20Sopenharmony_ci	if (ACPI_SUCCESS(status))
3548c2ecf20Sopenharmony_ci		arch_fix_phys_package_id(pr->id, value);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	return 0;
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci/*
3608c2ecf20Sopenharmony_ci * Do not put anything in here which needs the core to be online.
3618c2ecf20Sopenharmony_ci * For example MSR access or setting up things which check for cpuinfo_x86
3628c2ecf20Sopenharmony_ci * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
3638c2ecf20Sopenharmony_ci * Such things have to be put in and set up by the processor driver's .probe().
3648c2ecf20Sopenharmony_ci */
3658c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(void *, processor_device_array);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic int acpi_processor_add(struct acpi_device *device,
3688c2ecf20Sopenharmony_ci					const struct acpi_device_id *id)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	struct acpi_processor *pr;
3718c2ecf20Sopenharmony_ci	struct device *dev;
3728c2ecf20Sopenharmony_ci	int result = 0;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
3758c2ecf20Sopenharmony_ci	if (!pr)
3768c2ecf20Sopenharmony_ci		return -ENOMEM;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
3798c2ecf20Sopenharmony_ci		result = -ENOMEM;
3808c2ecf20Sopenharmony_ci		goto err_free_pr;
3818c2ecf20Sopenharmony_ci	}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	pr->handle = device->handle;
3848c2ecf20Sopenharmony_ci	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
3858c2ecf20Sopenharmony_ci	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
3868c2ecf20Sopenharmony_ci	device->driver_data = pr;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	result = acpi_processor_get_info(device);
3898c2ecf20Sopenharmony_ci	if (result) /* Processor is not physically present or unavailable */
3908c2ecf20Sopenharmony_ci		return 0;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	BUG_ON(pr->id >= nr_cpu_ids);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	/*
3958c2ecf20Sopenharmony_ci	 * Buggy BIOS check.
3968c2ecf20Sopenharmony_ci	 * ACPI id of processors can be reported wrongly by the BIOS.
3978c2ecf20Sopenharmony_ci	 * Don't trust it blindly
3988c2ecf20Sopenharmony_ci	 */
3998c2ecf20Sopenharmony_ci	if (per_cpu(processor_device_array, pr->id) != NULL &&
4008c2ecf20Sopenharmony_ci	    per_cpu(processor_device_array, pr->id) != device) {
4018c2ecf20Sopenharmony_ci		dev_warn(&device->dev,
4028c2ecf20Sopenharmony_ci			"BIOS reported wrong ACPI id %d for the processor\n",
4038c2ecf20Sopenharmony_ci			pr->id);
4048c2ecf20Sopenharmony_ci		/* Give up, but do not abort the namespace scan. */
4058c2ecf20Sopenharmony_ci		goto err;
4068c2ecf20Sopenharmony_ci	}
4078c2ecf20Sopenharmony_ci	/*
4088c2ecf20Sopenharmony_ci	 * processor_device_array is not cleared on errors to allow buggy BIOS
4098c2ecf20Sopenharmony_ci	 * checks.
4108c2ecf20Sopenharmony_ci	 */
4118c2ecf20Sopenharmony_ci	per_cpu(processor_device_array, pr->id) = device;
4128c2ecf20Sopenharmony_ci	per_cpu(processors, pr->id) = pr;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	dev = get_cpu_device(pr->id);
4158c2ecf20Sopenharmony_ci	if (!dev) {
4168c2ecf20Sopenharmony_ci		result = -ENODEV;
4178c2ecf20Sopenharmony_ci		goto err;
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	result = acpi_bind_one(dev, device);
4218c2ecf20Sopenharmony_ci	if (result)
4228c2ecf20Sopenharmony_ci		goto err;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	pr->dev = dev;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	/* Trigger the processor driver's .probe() if present. */
4278c2ecf20Sopenharmony_ci	if (device_attach(dev) >= 0)
4288c2ecf20Sopenharmony_ci		return 1;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	dev_err(dev, "Processor driver could not be attached\n");
4318c2ecf20Sopenharmony_ci	acpi_unbind_one(dev);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci err:
4348c2ecf20Sopenharmony_ci	free_cpumask_var(pr->throttling.shared_cpu_map);
4358c2ecf20Sopenharmony_ci	device->driver_data = NULL;
4368c2ecf20Sopenharmony_ci	per_cpu(processors, pr->id) = NULL;
4378c2ecf20Sopenharmony_ci err_free_pr:
4388c2ecf20Sopenharmony_ci	kfree(pr);
4398c2ecf20Sopenharmony_ci	return result;
4408c2ecf20Sopenharmony_ci}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_HOTPLUG_CPU
4438c2ecf20Sopenharmony_ci/* --------------------------------------------------------------------------
4448c2ecf20Sopenharmony_ci                                    Removal
4458c2ecf20Sopenharmony_ci   -------------------------------------------------------------------------- */
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic void acpi_processor_remove(struct acpi_device *device)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	struct acpi_processor *pr;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (!device || !acpi_driver_data(device))
4528c2ecf20Sopenharmony_ci		return;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	pr = acpi_driver_data(device);
4558c2ecf20Sopenharmony_ci	if (pr->id >= nr_cpu_ids)
4568c2ecf20Sopenharmony_ci		goto out;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	/*
4598c2ecf20Sopenharmony_ci	 * The only reason why we ever get here is CPU hot-removal.  The CPU is
4608c2ecf20Sopenharmony_ci	 * already offline and the ACPI device removal locking prevents it from
4618c2ecf20Sopenharmony_ci	 * being put back online at this point.
4628c2ecf20Sopenharmony_ci	 *
4638c2ecf20Sopenharmony_ci	 * Unbind the driver from the processor device and detach it from the
4648c2ecf20Sopenharmony_ci	 * ACPI companion object.
4658c2ecf20Sopenharmony_ci	 */
4668c2ecf20Sopenharmony_ci	device_release_driver(pr->dev);
4678c2ecf20Sopenharmony_ci	acpi_unbind_one(pr->dev);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	/* Clean up. */
4708c2ecf20Sopenharmony_ci	per_cpu(processor_device_array, pr->id) = NULL;
4718c2ecf20Sopenharmony_ci	per_cpu(processors, pr->id) = NULL;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	cpu_maps_update_begin();
4748c2ecf20Sopenharmony_ci	cpu_hotplug_begin();
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	/* Remove the CPU. */
4778c2ecf20Sopenharmony_ci	arch_unregister_cpu(pr->id);
4788c2ecf20Sopenharmony_ci	acpi_unmap_cpu(pr->id);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	cpu_hotplug_done();
4818c2ecf20Sopenharmony_ci	cpu_maps_update_done();
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	try_offline_node(cpu_to_node(pr->id));
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci out:
4868c2ecf20Sopenharmony_ci	free_cpumask_var(pr->throttling.shared_cpu_map);
4878c2ecf20Sopenharmony_ci	kfree(pr);
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci#endif /* CONFIG_ACPI_HOTPLUG_CPU */
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci#ifdef CONFIG_X86
4928c2ecf20Sopenharmony_cistatic bool acpi_hwp_native_thermal_lvt_set;
4938c2ecf20Sopenharmony_cistatic acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle,
4948c2ecf20Sopenharmony_ci							  u32 lvl,
4958c2ecf20Sopenharmony_ci							  void *context,
4968c2ecf20Sopenharmony_ci							  void **rv)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";
4998c2ecf20Sopenharmony_ci	u32 capbuf[2];
5008c2ecf20Sopenharmony_ci	struct acpi_osc_context osc_context = {
5018c2ecf20Sopenharmony_ci		.uuid_str = sb_uuid_str,
5028c2ecf20Sopenharmony_ci		.rev = 1,
5038c2ecf20Sopenharmony_ci		.cap.length = 8,
5048c2ecf20Sopenharmony_ci		.cap.pointer = capbuf,
5058c2ecf20Sopenharmony_ci	};
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	if (acpi_hwp_native_thermal_lvt_set)
5088c2ecf20Sopenharmony_ci		return AE_CTRL_TERMINATE;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	capbuf[0] = 0x0000;
5118c2ecf20Sopenharmony_ci	capbuf[1] = 0x1000; /* set bit 12 */
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
5148c2ecf20Sopenharmony_ci		if (osc_context.ret.pointer && osc_context.ret.length > 1) {
5158c2ecf20Sopenharmony_ci			u32 *capbuf_ret = osc_context.ret.pointer;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci			if (capbuf_ret[1] & 0x1000) {
5188c2ecf20Sopenharmony_ci				acpi_handle_info(handle,
5198c2ecf20Sopenharmony_ci					"_OSC native thermal LVT Acked\n");
5208c2ecf20Sopenharmony_ci				acpi_hwp_native_thermal_lvt_set = true;
5218c2ecf20Sopenharmony_ci			}
5228c2ecf20Sopenharmony_ci		}
5238c2ecf20Sopenharmony_ci		kfree(osc_context.ret.pointer);
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	return AE_OK;
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_civoid __init acpi_early_processor_osc(void)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_HWP)) {
5328c2ecf20Sopenharmony_ci		acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
5338c2ecf20Sopenharmony_ci				    ACPI_UINT32_MAX,
5348c2ecf20Sopenharmony_ci				    acpi_hwp_native_thermal_lvt_osc,
5358c2ecf20Sopenharmony_ci				    NULL, NULL, NULL);
5368c2ecf20Sopenharmony_ci		acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID,
5378c2ecf20Sopenharmony_ci				 acpi_hwp_native_thermal_lvt_osc,
5388c2ecf20Sopenharmony_ci				 NULL, NULL);
5398c2ecf20Sopenharmony_ci	}
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci#endif
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci/*
5448c2ecf20Sopenharmony_ci * The following ACPI IDs are known to be suitable for representing as
5458c2ecf20Sopenharmony_ci * processor devices.
5468c2ecf20Sopenharmony_ci */
5478c2ecf20Sopenharmony_cistatic const struct acpi_device_id processor_device_ids[] = {
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	{ ACPI_PROCESSOR_OBJECT_HID, },
5508c2ecf20Sopenharmony_ci	{ ACPI_PROCESSOR_DEVICE_HID, },
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	{ }
5538c2ecf20Sopenharmony_ci};
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic struct acpi_scan_handler processor_handler = {
5568c2ecf20Sopenharmony_ci	.ids = processor_device_ids,
5578c2ecf20Sopenharmony_ci	.attach = acpi_processor_add,
5588c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_HOTPLUG_CPU
5598c2ecf20Sopenharmony_ci	.detach = acpi_processor_remove,
5608c2ecf20Sopenharmony_ci#endif
5618c2ecf20Sopenharmony_ci	.hotplug = {
5628c2ecf20Sopenharmony_ci		.enabled = true,
5638c2ecf20Sopenharmony_ci	},
5648c2ecf20Sopenharmony_ci};
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_cistatic int acpi_processor_container_attach(struct acpi_device *dev,
5678c2ecf20Sopenharmony_ci					   const struct acpi_device_id *id)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	return 1;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cistatic const struct acpi_device_id processor_container_ids[] = {
5738c2ecf20Sopenharmony_ci	{ ACPI_PROCESSOR_CONTAINER_HID, },
5748c2ecf20Sopenharmony_ci	{ }
5758c2ecf20Sopenharmony_ci};
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_cistatic struct acpi_scan_handler processor_container_handler = {
5788c2ecf20Sopenharmony_ci	.ids = processor_container_ids,
5798c2ecf20Sopenharmony_ci	.attach = acpi_processor_container_attach,
5808c2ecf20Sopenharmony_ci};
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci/* The number of the unique processor IDs */
5838c2ecf20Sopenharmony_cistatic int nr_unique_ids __initdata;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci/* The number of the duplicate processor IDs */
5868c2ecf20Sopenharmony_cistatic int nr_duplicate_ids;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci/* Used to store the unique processor IDs */
5898c2ecf20Sopenharmony_cistatic int unique_processor_ids[] __initdata = {
5908c2ecf20Sopenharmony_ci	[0 ... NR_CPUS - 1] = -1,
5918c2ecf20Sopenharmony_ci};
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci/* Used to store the duplicate processor IDs */
5948c2ecf20Sopenharmony_cistatic int duplicate_processor_ids[] = {
5958c2ecf20Sopenharmony_ci	[0 ... NR_CPUS - 1] = -1,
5968c2ecf20Sopenharmony_ci};
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic void __init processor_validated_ids_update(int proc_id)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	int i;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if (nr_unique_ids == NR_CPUS||nr_duplicate_ids == NR_CPUS)
6038c2ecf20Sopenharmony_ci		return;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	/*
6068c2ecf20Sopenharmony_ci	 * Firstly, compare the proc_id with duplicate IDs, if the proc_id is
6078c2ecf20Sopenharmony_ci	 * already in the IDs, do nothing.
6088c2ecf20Sopenharmony_ci	 */
6098c2ecf20Sopenharmony_ci	for (i = 0; i < nr_duplicate_ids; i++) {
6108c2ecf20Sopenharmony_ci		if (duplicate_processor_ids[i] == proc_id)
6118c2ecf20Sopenharmony_ci			return;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	/*
6158c2ecf20Sopenharmony_ci	 * Secondly, compare the proc_id with unique IDs, if the proc_id is in
6168c2ecf20Sopenharmony_ci	 * the IDs, put it in the duplicate IDs.
6178c2ecf20Sopenharmony_ci	 */
6188c2ecf20Sopenharmony_ci	for (i = 0; i < nr_unique_ids; i++) {
6198c2ecf20Sopenharmony_ci		if (unique_processor_ids[i] == proc_id) {
6208c2ecf20Sopenharmony_ci			duplicate_processor_ids[nr_duplicate_ids] = proc_id;
6218c2ecf20Sopenharmony_ci			nr_duplicate_ids++;
6228c2ecf20Sopenharmony_ci			return;
6238c2ecf20Sopenharmony_ci		}
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	/*
6278c2ecf20Sopenharmony_ci	 * Lastly, the proc_id is a unique ID, put it in the unique IDs.
6288c2ecf20Sopenharmony_ci	 */
6298c2ecf20Sopenharmony_ci	unique_processor_ids[nr_unique_ids] = proc_id;
6308c2ecf20Sopenharmony_ci	nr_unique_ids++;
6318c2ecf20Sopenharmony_ci}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic acpi_status __init acpi_processor_ids_walk(acpi_handle handle,
6348c2ecf20Sopenharmony_ci						  u32 lvl,
6358c2ecf20Sopenharmony_ci						  void *context,
6368c2ecf20Sopenharmony_ci						  void **rv)
6378c2ecf20Sopenharmony_ci{
6388c2ecf20Sopenharmony_ci	acpi_status status;
6398c2ecf20Sopenharmony_ci	acpi_object_type acpi_type;
6408c2ecf20Sopenharmony_ci	unsigned long long uid;
6418c2ecf20Sopenharmony_ci	union acpi_object object = { 0 };
6428c2ecf20Sopenharmony_ci	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	status = acpi_get_type(handle, &acpi_type);
6458c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(status))
6468c2ecf20Sopenharmony_ci		return status;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	switch (acpi_type) {
6498c2ecf20Sopenharmony_ci	case ACPI_TYPE_PROCESSOR:
6508c2ecf20Sopenharmony_ci		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
6518c2ecf20Sopenharmony_ci		if (ACPI_FAILURE(status))
6528c2ecf20Sopenharmony_ci			goto err;
6538c2ecf20Sopenharmony_ci		uid = object.processor.proc_id;
6548c2ecf20Sopenharmony_ci		break;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	case ACPI_TYPE_DEVICE:
6578c2ecf20Sopenharmony_ci		status = acpi_evaluate_integer(handle, "_UID", NULL, &uid);
6588c2ecf20Sopenharmony_ci		if (ACPI_FAILURE(status))
6598c2ecf20Sopenharmony_ci			goto err;
6608c2ecf20Sopenharmony_ci		break;
6618c2ecf20Sopenharmony_ci	default:
6628c2ecf20Sopenharmony_ci		goto err;
6638c2ecf20Sopenharmony_ci	}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	processor_validated_ids_update(uid);
6668c2ecf20Sopenharmony_ci	return AE_OK;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cierr:
6698c2ecf20Sopenharmony_ci	/* Exit on error, but don't abort the namespace walk */
6708c2ecf20Sopenharmony_ci	acpi_handle_info(handle, "Invalid processor object\n");
6718c2ecf20Sopenharmony_ci	return AE_OK;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic void __init acpi_processor_check_duplicates(void)
6768c2ecf20Sopenharmony_ci{
6778c2ecf20Sopenharmony_ci	/* check the correctness for all processors in ACPI namespace */
6788c2ecf20Sopenharmony_ci	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
6798c2ecf20Sopenharmony_ci						ACPI_UINT32_MAX,
6808c2ecf20Sopenharmony_ci						acpi_processor_ids_walk,
6818c2ecf20Sopenharmony_ci						NULL, NULL, NULL);
6828c2ecf20Sopenharmony_ci	acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_ids_walk,
6838c2ecf20Sopenharmony_ci						NULL, NULL);
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cibool acpi_duplicate_processor_id(int proc_id)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	int i;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	/*
6918c2ecf20Sopenharmony_ci	 * compare the proc_id with duplicate IDs, if the proc_id is already
6928c2ecf20Sopenharmony_ci	 * in the duplicate IDs, return true, otherwise, return false.
6938c2ecf20Sopenharmony_ci	 */
6948c2ecf20Sopenharmony_ci	for (i = 0; i < nr_duplicate_ids; i++) {
6958c2ecf20Sopenharmony_ci		if (duplicate_processor_ids[i] == proc_id)
6968c2ecf20Sopenharmony_ci			return true;
6978c2ecf20Sopenharmony_ci	}
6988c2ecf20Sopenharmony_ci	return false;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_civoid __init acpi_processor_init(void)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	acpi_processor_check_duplicates();
7048c2ecf20Sopenharmony_ci	acpi_scan_add_handler_with_hotplug(&processor_handler, "processor");
7058c2ecf20Sopenharmony_ci	acpi_scan_add_handler(&processor_container_handler);
7068c2ecf20Sopenharmony_ci}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_PROCESSOR_CSTATE
7098c2ecf20Sopenharmony_ci/**
7108c2ecf20Sopenharmony_ci * acpi_processor_claim_cst_control - Request _CST control from the platform.
7118c2ecf20Sopenharmony_ci */
7128c2ecf20Sopenharmony_cibool acpi_processor_claim_cst_control(void)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	static bool cst_control_claimed;
7158c2ecf20Sopenharmony_ci	acpi_status status;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (!acpi_gbl_FADT.cst_control || cst_control_claimed)
7188c2ecf20Sopenharmony_ci		return true;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
7218c2ecf20Sopenharmony_ci				    acpi_gbl_FADT.cst_control, 8);
7228c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(status)) {
7238c2ecf20Sopenharmony_ci		pr_warn("ACPI: Failed to claim processor _CST control\n");
7248c2ecf20Sopenharmony_ci		return false;
7258c2ecf20Sopenharmony_ci	}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	cst_control_claimed = true;
7288c2ecf20Sopenharmony_ci	return true;
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_processor_claim_cst_control);
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci/**
7338c2ecf20Sopenharmony_ci * acpi_processor_evaluate_cst - Evaluate the processor _CST control method.
7348c2ecf20Sopenharmony_ci * @handle: ACPI handle of the processor object containing the _CST.
7358c2ecf20Sopenharmony_ci * @cpu: The numeric ID of the target CPU.
7368c2ecf20Sopenharmony_ci * @info: Object write the C-states information into.
7378c2ecf20Sopenharmony_ci *
7388c2ecf20Sopenharmony_ci * Extract the C-state information for the given CPU from the output of the _CST
7398c2ecf20Sopenharmony_ci * control method under the corresponding ACPI processor object (or processor
7408c2ecf20Sopenharmony_ci * device object) and populate @info with it.
7418c2ecf20Sopenharmony_ci *
7428c2ecf20Sopenharmony_ci * If any ACPI_ADR_SPACE_FIXED_HARDWARE C-states are found, invoke
7438c2ecf20Sopenharmony_ci * acpi_processor_ffh_cstate_probe() to verify them and update the
7448c2ecf20Sopenharmony_ci * cpu_cstate_entry data for @cpu.
7458c2ecf20Sopenharmony_ci */
7468c2ecf20Sopenharmony_ciint acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
7478c2ecf20Sopenharmony_ci				struct acpi_processor_power *info)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
7508c2ecf20Sopenharmony_ci	union acpi_object *cst;
7518c2ecf20Sopenharmony_ci	acpi_status status;
7528c2ecf20Sopenharmony_ci	u64 count;
7538c2ecf20Sopenharmony_ci	int last_index = 0;
7548c2ecf20Sopenharmony_ci	int i, ret = 0;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
7578c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(status)) {
7588c2ecf20Sopenharmony_ci		acpi_handle_debug(handle, "No _CST\n");
7598c2ecf20Sopenharmony_ci		return -ENODEV;
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	cst = buffer.pointer;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	/* There must be at least 2 elements. */
7658c2ecf20Sopenharmony_ci	if (!cst || cst->type != ACPI_TYPE_PACKAGE || cst->package.count < 2) {
7668c2ecf20Sopenharmony_ci		acpi_handle_warn(handle, "Invalid _CST output\n");
7678c2ecf20Sopenharmony_ci		ret = -EFAULT;
7688c2ecf20Sopenharmony_ci		goto end;
7698c2ecf20Sopenharmony_ci	}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	count = cst->package.elements[0].integer.value;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	/* Validate the number of C-states. */
7748c2ecf20Sopenharmony_ci	if (count < 1 || count != cst->package.count - 1) {
7758c2ecf20Sopenharmony_ci		acpi_handle_warn(handle, "Inconsistent _CST data\n");
7768c2ecf20Sopenharmony_ci		ret = -EFAULT;
7778c2ecf20Sopenharmony_ci		goto end;
7788c2ecf20Sopenharmony_ci	}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	for (i = 1; i <= count; i++) {
7818c2ecf20Sopenharmony_ci		union acpi_object *element;
7828c2ecf20Sopenharmony_ci		union acpi_object *obj;
7838c2ecf20Sopenharmony_ci		struct acpi_power_register *reg;
7848c2ecf20Sopenharmony_ci		struct acpi_processor_cx cx;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci		/*
7878c2ecf20Sopenharmony_ci		 * If there is not enough space for all C-states, skip the
7888c2ecf20Sopenharmony_ci		 * excess ones and log a warning.
7898c2ecf20Sopenharmony_ci		 */
7908c2ecf20Sopenharmony_ci		if (last_index >= ACPI_PROCESSOR_MAX_POWER - 1) {
7918c2ecf20Sopenharmony_ci			acpi_handle_warn(handle,
7928c2ecf20Sopenharmony_ci					 "No room for more idle states (limit: %d)\n",
7938c2ecf20Sopenharmony_ci					 ACPI_PROCESSOR_MAX_POWER - 1);
7948c2ecf20Sopenharmony_ci			break;
7958c2ecf20Sopenharmony_ci		}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		memset(&cx, 0, sizeof(cx));
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci		element = &cst->package.elements[i];
8008c2ecf20Sopenharmony_ci		if (element->type != ACPI_TYPE_PACKAGE) {
8018c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C%d type(%x) is not package, skip...\n",
8028c2ecf20Sopenharmony_ci					 i, element->type);
8038c2ecf20Sopenharmony_ci			continue;
8048c2ecf20Sopenharmony_ci		}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci		if (element->package.count != 4) {
8078c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C%d package count(%d) is not 4, skip...\n",
8088c2ecf20Sopenharmony_ci					 i, element->package.count);
8098c2ecf20Sopenharmony_ci			continue;
8108c2ecf20Sopenharmony_ci		}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci		obj = &element->package.elements[0];
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci		if (obj->type != ACPI_TYPE_BUFFER) {
8158c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C%d package element[0] type(%x) is not buffer, skip...\n",
8168c2ecf20Sopenharmony_ci					 i, obj->type);
8178c2ecf20Sopenharmony_ci			continue;
8188c2ecf20Sopenharmony_ci		}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci		reg = (struct acpi_power_register *)obj->buffer.pointer;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci		obj = &element->package.elements[1];
8238c2ecf20Sopenharmony_ci		if (obj->type != ACPI_TYPE_INTEGER) {
8248c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C[%d] package element[1] type(%x) is not integer, skip...\n",
8258c2ecf20Sopenharmony_ci					 i, obj->type);
8268c2ecf20Sopenharmony_ci			continue;
8278c2ecf20Sopenharmony_ci		}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci		cx.type = obj->integer.value;
8308c2ecf20Sopenharmony_ci		/*
8318c2ecf20Sopenharmony_ci		 * There are known cases in which the _CST output does not
8328c2ecf20Sopenharmony_ci		 * contain C1, so if the type of the first state found is not
8338c2ecf20Sopenharmony_ci		 * C1, leave an empty slot for C1 to be filled in later.
8348c2ecf20Sopenharmony_ci		 */
8358c2ecf20Sopenharmony_ci		if (i == 1 && cx.type != ACPI_STATE_C1)
8368c2ecf20Sopenharmony_ci			last_index = 1;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci		cx.address = reg->address;
8398c2ecf20Sopenharmony_ci		cx.index = last_index + 1;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci		if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
8428c2ecf20Sopenharmony_ci			if (!acpi_processor_ffh_cstate_probe(cpu, &cx, reg)) {
8438c2ecf20Sopenharmony_ci				/*
8448c2ecf20Sopenharmony_ci				 * In the majority of cases _CST describes C1 as
8458c2ecf20Sopenharmony_ci				 * a FIXED_HARDWARE C-state, but if the command
8468c2ecf20Sopenharmony_ci				 * line forbids using MWAIT, use CSTATE_HALT for
8478c2ecf20Sopenharmony_ci				 * C1 regardless.
8488c2ecf20Sopenharmony_ci				 */
8498c2ecf20Sopenharmony_ci				if (cx.type == ACPI_STATE_C1 &&
8508c2ecf20Sopenharmony_ci				    boot_option_idle_override == IDLE_NOMWAIT) {
8518c2ecf20Sopenharmony_ci					cx.entry_method = ACPI_CSTATE_HALT;
8528c2ecf20Sopenharmony_ci					snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
8538c2ecf20Sopenharmony_ci				} else {
8548c2ecf20Sopenharmony_ci					cx.entry_method = ACPI_CSTATE_FFH;
8558c2ecf20Sopenharmony_ci				}
8568c2ecf20Sopenharmony_ci			} else if (cx.type == ACPI_STATE_C1) {
8578c2ecf20Sopenharmony_ci				/*
8588c2ecf20Sopenharmony_ci				 * In the special case of C1, FIXED_HARDWARE can
8598c2ecf20Sopenharmony_ci				 * be handled by executing the HLT instruction.
8608c2ecf20Sopenharmony_ci				 */
8618c2ecf20Sopenharmony_ci				cx.entry_method = ACPI_CSTATE_HALT;
8628c2ecf20Sopenharmony_ci				snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
8638c2ecf20Sopenharmony_ci			} else {
8648c2ecf20Sopenharmony_ci				acpi_handle_info(handle, "_CST C%d declares FIXED_HARDWARE C-state but not supported in hardware, skip...\n",
8658c2ecf20Sopenharmony_ci						 i);
8668c2ecf20Sopenharmony_ci				continue;
8678c2ecf20Sopenharmony_ci			}
8688c2ecf20Sopenharmony_ci		} else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
8698c2ecf20Sopenharmony_ci			cx.entry_method = ACPI_CSTATE_SYSTEMIO;
8708c2ecf20Sopenharmony_ci			snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
8718c2ecf20Sopenharmony_ci				 cx.address);
8728c2ecf20Sopenharmony_ci		} else {
8738c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C%d space_id(%x) neither FIXED_HARDWARE nor SYSTEM_IO, skip...\n",
8748c2ecf20Sopenharmony_ci					 i, reg->space_id);
8758c2ecf20Sopenharmony_ci			continue;
8768c2ecf20Sopenharmony_ci		}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci		if (cx.type == ACPI_STATE_C1)
8798c2ecf20Sopenharmony_ci			cx.valid = 1;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci		obj = &element->package.elements[2];
8828c2ecf20Sopenharmony_ci		if (obj->type != ACPI_TYPE_INTEGER) {
8838c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C%d package element[2] type(%x) not integer, skip...\n",
8848c2ecf20Sopenharmony_ci					 i, obj->type);
8858c2ecf20Sopenharmony_ci			continue;
8868c2ecf20Sopenharmony_ci		}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci		cx.latency = obj->integer.value;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci		obj = &element->package.elements[3];
8918c2ecf20Sopenharmony_ci		if (obj->type != ACPI_TYPE_INTEGER) {
8928c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "_CST C%d package element[3] type(%x) not integer, skip...\n",
8938c2ecf20Sopenharmony_ci					 i, obj->type);
8948c2ecf20Sopenharmony_ci			continue;
8958c2ecf20Sopenharmony_ci		}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci		memcpy(&info->states[++last_index], &cx, sizeof(cx));
8988c2ecf20Sopenharmony_ci	}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	acpi_handle_info(handle, "Found %d idle states\n", last_index);
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	info->count = last_index;
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci      end:
9058c2ecf20Sopenharmony_ci	kfree(buffer.pointer);
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	return ret;
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_processor_evaluate_cst);
9108c2ecf20Sopenharmony_ci#endif /* CONFIG_ACPI_PROCESSOR_CSTATE */
911