diff options
-rw-r--r-- | drivers/acpi/acpi_apd.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpi_processor.c | 42 | ||||
-rw-r--r-- | drivers/acpi/processor_pdc.c | 11 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 8 | ||||
-rw-r--r-- | drivers/acpi/spcr.c | 13 | ||||
-rw-r--r-- | drivers/acpi/sysfs.c | 17 | ||||
-rw-r--r-- | drivers/acpi/viot.c | 5 | ||||
-rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 39 | ||||
-rw-r--r-- | drivers/cpufreq/pcc-cpufreq.c | 34 | ||||
-rw-r--r-- | drivers/xen/pcpu.c | 20 | ||||
-rw-r--r-- | include/xen/xen.h | 11 |
11 files changed, 162 insertions, 40 deletions
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index 3bbe2276cac7..80f945cbec8a 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -83,6 +83,8 @@ static int fch_misc_setup(struct apd_private_data *pdata) if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) { clk_data->name = devm_kzalloc(&adev->dev, obj->string.length, GFP_KERNEL); + if (!clk_data->name) + return -ENOMEM; strcpy(clk_data->name, obj->string.pointer); } else { diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 6737b1cbf6d6..f9aa02cac6d1 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/platform_device.h> #include <acpi/processor.h> @@ -148,6 +149,34 @@ static int acpi_processor_errata(void) return result; } +/* Create a platform device to represent a CPU frequency control mechanism. */ +static void cpufreq_add_device(const char *name) +{ + struct platform_device *pdev; + + pdev = platform_device_register_simple(name, PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(pdev)) + pr_info("%s device creation failed: %ld\n", name, PTR_ERR(pdev)); +} + +#ifdef CONFIG_X86 +/* Check presence of Processor Clocking Control by searching for \_SB.PCCH. */ +static void __init acpi_pcc_cpufreq_init(void) +{ + acpi_status status; + acpi_handle handle; + + status = acpi_get_handle(NULL, "\\_SB", &handle); + if (ACPI_FAILURE(status)) + return; + + if (acpi_has_method(handle, "PCCH")) + cpufreq_add_device("pcc-cpufreq"); +} +#else +static void __init acpi_pcc_cpufreq_init(void) {} +#endif /* CONFIG_X86 */ + /* Initialization */ #ifdef CONFIG_ACPI_HOTPLUG_CPU int __weak acpi_map_cpu(acpi_handle handle, @@ -280,14 +309,22 @@ static int acpi_processor_get_info(struct acpi_device *device) dev_dbg(&device->dev, "Failed to get CPU physical ID.\n"); pr->id = acpi_map_cpuid(pr->phys_id, pr->acpi_id); - if (!cpu0_initialized && !acpi_has_cpu_in_madt()) { + if (!cpu0_initialized) { cpu0_initialized = 1; /* * Handle UP system running SMP kernel, with no CPU * entry in MADT */ - if (invalid_logical_cpuid(pr->id) && (num_online_cpus() == 1)) + if (!acpi_has_cpu_in_madt() && invalid_logical_cpuid(pr->id) && + (num_online_cpus() == 1)) pr->id = 0; + /* + * Check availability of Processor Performance Control by + * looking at the presence of the _PCT object under the first + * processor definition. + */ + if (acpi_has_method(pr->handle, "_PCT")) + cpufreq_add_device("acpi-cpufreq"); } /* @@ -686,6 +723,7 @@ void __init acpi_processor_init(void) acpi_processor_check_duplicates(); acpi_scan_add_handler_with_hotplug(&processor_handler, "processor"); acpi_scan_add_handler(&processor_container_handler); + acpi_pcc_cpufreq_init(); } #ifdef CONFIG_ACPI_PROCESSOR_CSTATE diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 8c3f82c9fff3..18fb04523f93 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -14,6 +14,8 @@ #include <linux/acpi.h> #include <acpi/processor.h> +#include <xen/xen.h> + #include "internal.h" static bool __init processor_physically_present(acpi_handle handle) @@ -47,6 +49,15 @@ static bool __init processor_physically_present(acpi_handle handle) return false; } + if (xen_initial_domain()) + /* + * When running as a Xen dom0 the number of processors Linux + * sees can be different from the real number of processors on + * the system, and we still need to execute _PDC for all of + * them. + */ + return xen_processor_present(acpi_id); + type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; cpuid = acpi_get_cpuid(handle, type, acpi_id); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4ca667251272..72470b9f16c4 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -714,7 +714,13 @@ int acpi_s2idle_begin(void) int acpi_s2idle_prepare(void) { if (acpi_sci_irq_valid()) { - enable_irq_wake(acpi_sci_irq); + int error; + + error = enable_irq_wake(acpi_sci_irq); + if (error) + pr_warn("Warning: Failed to enable wakeup from IRQ %d: %d\n", + acpi_sci_irq, error); + acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE); } diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c index 1eabfcd122ee..cd36a97b0ea2 100644 --- a/drivers/acpi/spcr.c +++ b/drivers/acpi/spcr.c @@ -71,7 +71,6 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb) /** * acpi_parse_spcr() - parse ACPI SPCR table and add preferred console - * * @enable_earlycon: set up earlycon for the console specified by the table * @enable_console: setup the console specified by the table. * @@ -82,7 +81,6 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb) * * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called * from arch initialization code as soon as the DT/ACPI decision is made. - * */ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) { @@ -97,9 +95,7 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) if (acpi_disabled) return -ENODEV; - status = acpi_get_table(ACPI_SIG_SPCR, 0, - (struct acpi_table_header **)&table); - + status = acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&table); if (ACPI_FAILURE(status)) return -ENOENT; @@ -110,12 +106,12 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) u32 bit_width = table->serial_port.access_width; if (bit_width > ACPI_ACCESS_BIT_MAX) { - pr_err("Unacceptable wide SPCR Access Width. Defaulting to byte size\n"); + pr_err(FW_BUG "Unacceptable wide SPCR Access Width. Defaulting to byte size\n"); bit_width = ACPI_ACCESS_BIT_DEFAULT; } switch (ACPI_ACCESS_BIT_WIDTH((bit_width))) { default: - pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n"); + pr_err(FW_BUG "Unexpected SPCR Access Width. Defaulting to byte size\n"); fallthrough; case 8: iotype = "mmio"; @@ -202,7 +198,8 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) if (xgene_8250_erratum_present(table)) { iotype = "mmio32"; - /* for xgene v1 and v2 we don't know the clock rate of the + /* + * For xgene v1 and v2 we don't know the clock rate of the * UART so don't attempt to change to the baud rate state * in the table because driver cannot calculate the dividers */ diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 7f4ff56c9d42..687524b50085 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -458,11 +458,28 @@ static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr) return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr); } +static int acpi_ccel_data_init(void *th, struct acpi_data_attr *data_attr) +{ + struct acpi_table_ccel *ccel = th; + + if (ccel->header.length < sizeof(struct acpi_table_ccel) || + !ccel->log_area_start_address || !ccel->log_area_minimum_length) { + kfree(data_attr); + return -EINVAL; + } + data_attr->addr = ccel->log_area_start_address; + data_attr->attr.size = ccel->log_area_minimum_length; + data_attr->attr.attr.name = "CCEL"; + + return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr); +} + static struct acpi_data_obj { char *name; int (*fn)(void *, struct acpi_data_attr *); } acpi_data_objs[] = { { ACPI_SIG_BERT, acpi_bert_data_init }, + { ACPI_SIG_CCEL, acpi_ccel_data_init }, }; #define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs) diff --git a/drivers/acpi/viot.c b/drivers/acpi/viot.c index ed752cbbe636..c8025921c129 100644 --- a/drivers/acpi/viot.c +++ b/drivers/acpi/viot.c @@ -328,6 +328,7 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) { u32 epid; struct viot_endpoint *ep; + struct device *aliased_dev = data; u32 domain_nr = pci_domain_nr(pdev->bus); list_for_each_entry(ep, &viot_pci_ranges, list) { @@ -338,7 +339,7 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) epid = ((domain_nr - ep->segment_start) << 16) + dev_id - ep->bdf_start + ep->endpoint_id; - return viot_dev_iommu_init(&pdev->dev, ep->viommu, + return viot_dev_iommu_init(aliased_dev, ep->viommu, epid); } } @@ -372,7 +373,7 @@ int viot_iommu_configure(struct device *dev) { if (dev_is_pci(dev)) return pci_for_each_dma_alias(to_pci_dev(dev), - viot_pci_dev_iommu_init, NULL); + viot_pci_dev_iommu_init, dev); else if (dev_is_platform(dev)) return viot_mmio_dev_iommu_init(to_platform_device(dev)); return -ENODEV; diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 78adfb2ffff6..e1a5384cf21c 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -965,7 +965,7 @@ static void __init acpi_cpufreq_boost_init(void) acpi_cpufreq_driver.boost_enabled = boost_state(0); } -static int __init acpi_cpufreq_init(void) +static int __init acpi_cpufreq_probe(struct platform_device *pdev) { int ret; @@ -1010,13 +1010,32 @@ static int __init acpi_cpufreq_init(void) return ret; } -static void __exit acpi_cpufreq_exit(void) +static int acpi_cpufreq_remove(struct platform_device *pdev) { pr_debug("%s\n", __func__); cpufreq_unregister_driver(&acpi_cpufreq_driver); free_acpi_perf_data(); + + return 0; +} + +static struct platform_driver acpi_cpufreq_platdrv = { + .driver = { + .name = "acpi-cpufreq", + }, + .remove = acpi_cpufreq_remove, +}; + +static int __init acpi_cpufreq_init(void) +{ + return platform_driver_probe(&acpi_cpufreq_platdrv, acpi_cpufreq_probe); +} + +static void __exit acpi_cpufreq_exit(void) +{ + platform_driver_unregister(&acpi_cpufreq_platdrv); } module_param(acpi_pstate_strict, uint, 0644); @@ -1027,18 +1046,4 @@ MODULE_PARM_DESC(acpi_pstate_strict, late_initcall(acpi_cpufreq_init); module_exit(acpi_cpufreq_exit); -static const struct x86_cpu_id __maybe_unused acpi_cpufreq_ids[] = { - X86_MATCH_FEATURE(X86_FEATURE_ACPI, NULL), - X86_MATCH_FEATURE(X86_FEATURE_HW_PSTATE, NULL), - {} -}; -MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids); - -static const struct acpi_device_id __maybe_unused processor_device_ids[] = { - {ACPI_PROCESSOR_OBJECT_HID, }, - {ACPI_PROCESSOR_DEVICE_HID, }, - {}, -}; -MODULE_DEVICE_TABLE(acpi, processor_device_ids); - -MODULE_ALIAS("acpi"); +MODULE_ALIAS("platform:acpi-cpufreq"); diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 9f3fc7a073d0..0c362932ca60 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -384,7 +384,7 @@ out_free: return ret; } -static int __init pcc_cpufreq_probe(void) +static int __init pcc_cpufreq_evaluate(void) { acpi_status status; struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; @@ -576,7 +576,7 @@ static struct cpufreq_driver pcc_cpufreq_driver = { .name = "pcc-cpufreq", }; -static int __init pcc_cpufreq_init(void) +static int __init pcc_cpufreq_probe(struct platform_device *pdev) { int ret; @@ -587,9 +587,9 @@ static int __init pcc_cpufreq_init(void) if (acpi_disabled) return -ENODEV; - ret = pcc_cpufreq_probe(); + ret = pcc_cpufreq_evaluate(); if (ret) { - pr_debug("pcc_cpufreq_init: PCCH evaluation failed\n"); + pr_debug("pcc_cpufreq_probe: PCCH evaluation failed\n"); return ret; } @@ -607,21 +607,35 @@ static int __init pcc_cpufreq_init(void) return ret; } -static void __exit pcc_cpufreq_exit(void) +static int pcc_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&pcc_cpufreq_driver); pcc_clear_mapping(); free_percpu(pcc_cpu_info); + + return 0; } -static const struct acpi_device_id __maybe_unused processor_device_ids[] = { - {ACPI_PROCESSOR_OBJECT_HID, }, - {ACPI_PROCESSOR_DEVICE_HID, }, - {}, +static struct platform_driver pcc_cpufreq_platdrv = { + .driver = { + .name = "pcc-cpufreq", + }, + .remove = pcc_cpufreq_remove, }; -MODULE_DEVICE_TABLE(acpi, processor_device_ids); + +static int __init pcc_cpufreq_init(void) +{ + return platform_driver_probe(&pcc_cpufreq_platdrv, pcc_cpufreq_probe); +} + +static void __exit pcc_cpufreq_exit(void) +{ + platform_driver_unregister(&pcc_cpufreq_platdrv); +} + +MODULE_ALIAS("platform:pcc-cpufreq"); MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar"); MODULE_VERSION(PCC_VERSION); diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index fd3a644b0855..b3e3d1bb37f3 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c @@ -58,6 +58,7 @@ struct pcpu { struct list_head list; struct device dev; uint32_t cpu_id; + uint32_t acpi_id; uint32_t flags; }; @@ -249,6 +250,7 @@ static struct pcpu *create_and_register_pcpu(struct xenpf_pcpuinfo *info) INIT_LIST_HEAD(&pcpu->list); pcpu->cpu_id = info->xen_cpuid; + pcpu->acpi_id = info->acpi_id; pcpu->flags = info->flags; /* Need hold on xen_pcpu_lock before pcpu list manipulations */ @@ -381,3 +383,21 @@ err1: return ret; } arch_initcall(xen_pcpu_init); + +#ifdef CONFIG_ACPI +bool __init xen_processor_present(uint32_t acpi_id) +{ + const struct pcpu *pcpu; + bool online = false; + + mutex_lock(&xen_pcpu_lock); + list_for_each_entry(pcpu, &xen_pcpus, list) + if (pcpu->acpi_id == acpi_id) { + online = pcpu->flags & XEN_PCPU_FLAGS_ONLINE; + break; + } + mutex_unlock(&xen_pcpu_lock); + + return online; +} +#endif diff --git a/include/xen/xen.h b/include/xen/xen.h index 7adf59837c25..0efeb652f9b8 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h @@ -71,4 +71,15 @@ static inline void xen_free_unpopulated_pages(unsigned int nr_pages, } #endif +#if defined(CONFIG_XEN_DOM0) && defined(CONFIG_ACPI) && defined(CONFIG_X86) +bool __init xen_processor_present(uint32_t acpi_id); +#else +#include <linux/bug.h> +static inline bool xen_processor_present(uint32_t acpi_id) +{ + BUG(); + return false; +} +#endif + #endif /* _XEN_XEN_H */ |