Commit 0e838286 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-processor', 'acpi-pm', 'acpi-tables' and 'acpi-sysfs'

Merge ACPI processor driver changes, ACPI power management updates,
changes related to parsing ACPI tables and an ACPI sysfs interface
update for 6.4-rc1:

 - Fix evaluating the _PDC ACPI control method when running as Xen
   dom0 (Roger Pau Monne).

 - Use platform devices to load ACPI PPC and PCC drivers (Petr Pavlu).

 - Check for null return of devm_kzalloc() in fch_misc_setup() (Kang
   Chen).

 - Log a message if enable_irq_wake() fails for the ACPI SCI (Simon
   Gaiser).

 - Initialize the correct IOMMU fwspec while parsing ACPI VIOT
   (Jean-Philippe Brucker).

 - Amend indentation and prefix error messages with FW_BUG in the ACPI
   SPCR parsing code (Andy Shevchenko).

 - Enable ACPI sysfs support for CCEL records (Kuppuswamy
   Sathyanarayanan).

* acpi-processor:
  ACPI: processor: Fix evaluating _PDC method when running as Xen dom0
  ACPI: cpufreq: Use platform devices to load ACPI PPC and PCC drivers
  ACPI: processor: Check for null return of devm_kzalloc() in fch_misc_setup()

* acpi-pm:
  ACPI: s2idle: Log when enabling wakeup IRQ fails

* acpi-tables:
  ACPI: VIOT: Initialize the correct IOMMU fwspec
  ACPI: SPCR: Amend indentation
  ACPI: SPCR: Prefix error messages with FW_BUG

* acpi-sysfs:
  ACPI: sysfs: Enable ACPI sysfs support for CCEL records
...@@ -83,6 +83,8 @@ static int fch_misc_setup(struct apd_private_data *pdata) ...@@ -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)) { if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {
clk_data->name = devm_kzalloc(&adev->dev, obj->string.length, clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,
GFP_KERNEL); GFP_KERNEL);
if (!clk_data->name)
return -ENOMEM;
strcpy(clk_data->name, obj->string.pointer); strcpy(clk_data->name, obj->string.pointer);
} else { } else {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/platform_device.h>
#include <acpi/processor.h> #include <acpi/processor.h>
...@@ -148,6 +149,34 @@ static int acpi_processor_errata(void) ...@@ -148,6 +149,34 @@ static int acpi_processor_errata(void)
return result; 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 */ /* Initialization */
#ifdef CONFIG_ACPI_HOTPLUG_CPU #ifdef CONFIG_ACPI_HOTPLUG_CPU
int __weak acpi_map_cpu(acpi_handle handle, int __weak acpi_map_cpu(acpi_handle handle,
...@@ -280,14 +309,22 @@ static int acpi_processor_get_info(struct acpi_device *device) ...@@ -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"); dev_dbg(&device->dev, "Failed to get CPU physical ID.\n");
pr->id = acpi_map_cpuid(pr->phys_id, pr->acpi_id); 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; cpu0_initialized = 1;
/* /*
* Handle UP system running SMP kernel, with no CPU * Handle UP system running SMP kernel, with no CPU
* entry in MADT * 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; 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) ...@@ -686,6 +723,7 @@ void __init acpi_processor_init(void)
acpi_processor_check_duplicates(); acpi_processor_check_duplicates();
acpi_scan_add_handler_with_hotplug(&processor_handler, "processor"); acpi_scan_add_handler_with_hotplug(&processor_handler, "processor");
acpi_scan_add_handler(&processor_container_handler); acpi_scan_add_handler(&processor_container_handler);
acpi_pcc_cpufreq_init();
} }
#ifdef CONFIG_ACPI_PROCESSOR_CSTATE #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <acpi/processor.h> #include <acpi/processor.h>
#include <xen/xen.h>
#include "internal.h" #include "internal.h"
static bool __init processor_physically_present(acpi_handle handle) static bool __init processor_physically_present(acpi_handle handle)
...@@ -47,6 +49,15 @@ static bool __init processor_physically_present(acpi_handle handle) ...@@ -47,6 +49,15 @@ static bool __init processor_physically_present(acpi_handle handle)
return false; 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; type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
cpuid = acpi_get_cpuid(handle, type, acpi_id); cpuid = acpi_get_cpuid(handle, type, acpi_id);
......
...@@ -714,7 +714,13 @@ int acpi_s2idle_begin(void) ...@@ -714,7 +714,13 @@ int acpi_s2idle_begin(void)
int acpi_s2idle_prepare(void) int acpi_s2idle_prepare(void)
{ {
if (acpi_sci_irq_valid()) { 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); acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE);
} }
......
...@@ -71,7 +71,6 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb) ...@@ -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 * acpi_parse_spcr() - parse ACPI SPCR table and add preferred console
*
* @enable_earlycon: set up earlycon for the console specified by the table * @enable_earlycon: set up earlycon for the console specified by the table
* @enable_console: setup 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) ...@@ -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 * 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. * from arch initialization code as soon as the DT/ACPI decision is made.
*
*/ */
int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) 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) ...@@ -97,9 +95,7 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
status = acpi_get_table(ACPI_SIG_SPCR, 0, status = acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&table);
(struct acpi_table_header **)&table);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENOENT; return -ENOENT;
...@@ -110,12 +106,12 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) ...@@ -110,12 +106,12 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)
u32 bit_width = table->serial_port.access_width; u32 bit_width = table->serial_port.access_width;
if (bit_width > ACPI_ACCESS_BIT_MAX) { 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; bit_width = ACPI_ACCESS_BIT_DEFAULT;
} }
switch (ACPI_ACCESS_BIT_WIDTH((bit_width))) { switch (ACPI_ACCESS_BIT_WIDTH((bit_width))) {
default: 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; fallthrough;
case 8: case 8:
iotype = "mmio"; iotype = "mmio";
...@@ -202,7 +198,8 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) ...@@ -202,7 +198,8 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)
if (xgene_8250_erratum_present(table)) { if (xgene_8250_erratum_present(table)) {
iotype = "mmio32"; 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 * UART so don't attempt to change to the baud rate state
* in the table because driver cannot calculate the dividers * in the table because driver cannot calculate the dividers
*/ */
......
...@@ -458,11 +458,28 @@ static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr) ...@@ -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); 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 { static struct acpi_data_obj {
char *name; char *name;
int (*fn)(void *, struct acpi_data_attr *); int (*fn)(void *, struct acpi_data_attr *);
} acpi_data_objs[] = { } acpi_data_objs[] = {
{ ACPI_SIG_BERT, acpi_bert_data_init }, { ACPI_SIG_BERT, acpi_bert_data_init },
{ ACPI_SIG_CCEL, acpi_ccel_data_init },
}; };
#define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs) #define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs)
......
...@@ -328,6 +328,7 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) ...@@ -328,6 +328,7 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)
{ {
u32 epid; u32 epid;
struct viot_endpoint *ep; struct viot_endpoint *ep;
struct device *aliased_dev = data;
u32 domain_nr = pci_domain_nr(pdev->bus); u32 domain_nr = pci_domain_nr(pdev->bus);
list_for_each_entry(ep, &viot_pci_ranges, list) { 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) ...@@ -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) + epid = ((domain_nr - ep->segment_start) << 16) +
dev_id - ep->bdf_start + ep->endpoint_id; 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); epid);
} }
} }
...@@ -372,7 +373,7 @@ int viot_iommu_configure(struct device *dev) ...@@ -372,7 +373,7 @@ int viot_iommu_configure(struct device *dev)
{ {
if (dev_is_pci(dev)) if (dev_is_pci(dev))
return pci_for_each_dma_alias(to_pci_dev(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)) else if (dev_is_platform(dev))
return viot_mmio_dev_iommu_init(to_platform_device(dev)); return viot_mmio_dev_iommu_init(to_platform_device(dev));
return -ENODEV; return -ENODEV;
......
...@@ -965,7 +965,7 @@ static void __init acpi_cpufreq_boost_init(void) ...@@ -965,7 +965,7 @@ static void __init acpi_cpufreq_boost_init(void)
acpi_cpufreq_driver.boost_enabled = boost_state(0); 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; int ret;
...@@ -1010,13 +1010,32 @@ static int __init acpi_cpufreq_init(void) ...@@ -1010,13 +1010,32 @@ static int __init acpi_cpufreq_init(void)
return ret; return ret;
} }
static void __exit acpi_cpufreq_exit(void) static int acpi_cpufreq_remove(struct platform_device *pdev)
{ {
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
cpufreq_unregister_driver(&acpi_cpufreq_driver); cpufreq_unregister_driver(&acpi_cpufreq_driver);
free_acpi_perf_data(); 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); module_param(acpi_pstate_strict, uint, 0644);
...@@ -1027,18 +1046,4 @@ MODULE_PARM_DESC(acpi_pstate_strict, ...@@ -1027,18 +1046,4 @@ MODULE_PARM_DESC(acpi_pstate_strict,
late_initcall(acpi_cpufreq_init); late_initcall(acpi_cpufreq_init);
module_exit(acpi_cpufreq_exit); module_exit(acpi_cpufreq_exit);
static const struct x86_cpu_id __maybe_unused acpi_cpufreq_ids[] = { MODULE_ALIAS("platform:acpi-cpufreq");
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");
...@@ -384,7 +384,7 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle) ...@@ -384,7 +384,7 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
return ret; return ret;
} }
static int __init pcc_cpufreq_probe(void) static int __init pcc_cpufreq_evaluate(void)
{ {
acpi_status status; acpi_status status;
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
...@@ -576,7 +576,7 @@ static struct cpufreq_driver pcc_cpufreq_driver = { ...@@ -576,7 +576,7 @@ static struct cpufreq_driver pcc_cpufreq_driver = {
.name = "pcc-cpufreq", .name = "pcc-cpufreq",
}; };
static int __init pcc_cpufreq_init(void) static int __init pcc_cpufreq_probe(struct platform_device *pdev)
{ {
int ret; int ret;
...@@ -587,9 +587,9 @@ static int __init pcc_cpufreq_init(void) ...@@ -587,9 +587,9 @@ static int __init pcc_cpufreq_init(void)
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
ret = pcc_cpufreq_probe(); ret = pcc_cpufreq_evaluate();
if (ret) { if (ret) {
pr_debug("pcc_cpufreq_init: PCCH evaluation failed\n"); pr_debug("pcc_cpufreq_probe: PCCH evaluation failed\n");
return ret; return ret;
} }
...@@ -607,21 +607,35 @@ static int __init pcc_cpufreq_init(void) ...@@ -607,21 +607,35 @@ static int __init pcc_cpufreq_init(void)
return ret; return ret;
} }
static void __exit pcc_cpufreq_exit(void) static int pcc_cpufreq_remove(struct platform_device *pdev)
{ {
cpufreq_unregister_driver(&pcc_cpufreq_driver); cpufreq_unregister_driver(&pcc_cpufreq_driver);
pcc_clear_mapping(); pcc_clear_mapping();
free_percpu(pcc_cpu_info); free_percpu(pcc_cpu_info);
return 0;
} }
static const struct acpi_device_id __maybe_unused processor_device_ids[] = { static struct platform_driver pcc_cpufreq_platdrv = {
{ACPI_PROCESSOR_OBJECT_HID, }, .driver = {
{ACPI_PROCESSOR_DEVICE_HID, }, .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_AUTHOR("Matthew Garrett, Naga Chumbalkar");
MODULE_VERSION(PCC_VERSION); MODULE_VERSION(PCC_VERSION);
......
...@@ -58,6 +58,7 @@ struct pcpu { ...@@ -58,6 +58,7 @@ struct pcpu {
struct list_head list; struct list_head list;
struct device dev; struct device dev;
uint32_t cpu_id; uint32_t cpu_id;
uint32_t acpi_id;
uint32_t flags; uint32_t flags;
}; };
...@@ -249,6 +250,7 @@ static struct pcpu *create_and_register_pcpu(struct xenpf_pcpuinfo *info) ...@@ -249,6 +250,7 @@ static struct pcpu *create_and_register_pcpu(struct xenpf_pcpuinfo *info)
INIT_LIST_HEAD(&pcpu->list); INIT_LIST_HEAD(&pcpu->list);
pcpu->cpu_id = info->xen_cpuid; pcpu->cpu_id = info->xen_cpuid;
pcpu->acpi_id = info->acpi_id;
pcpu->flags = info->flags; pcpu->flags = info->flags;
/* Need hold on xen_pcpu_lock before pcpu list manipulations */ /* Need hold on xen_pcpu_lock before pcpu list manipulations */
...@@ -381,3 +383,21 @@ static int __init xen_pcpu_init(void) ...@@ -381,3 +383,21 @@ static int __init xen_pcpu_init(void)
return ret; return ret;
} }
arch_initcall(xen_pcpu_init); 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
...@@ -71,4 +71,15 @@ static inline void xen_free_unpopulated_pages(unsigned int nr_pages, ...@@ -71,4 +71,15 @@ static inline void xen_free_unpopulated_pages(unsigned int nr_pages,
} }
#endif #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 */ #endif /* _XEN_XEN_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment