From 2f6fe93fede802acfe010752db461ccd34745745 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 13 Jun 2022 20:10:03 +0200 Subject: ACPI: glue: Introduce acpi_find_child_by_adr() Rearrange the ACPI device lookup code used internally by acpi_find_child_device() so it can avoid extra checks after finding one object with a matching _ADR and use it for defining acpi_find_child_by_adr() that will allow the callers to find a given ACPI device's child matching a given bus address without doing any other checks in check_one_child(). Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko --- include/acpi/acpi_bus.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0dc1ea0b52f5..597961969ca1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -622,6 +622,8 @@ static inline int acpi_dma_configure(struct device *dev, } struct acpi_device *acpi_find_child_device(struct acpi_device *parent, u64 address, bool check_children); +struct acpi_device *acpi_find_child_by_adr(struct acpi_device *adev, + acpi_bus_address adr); int acpi_is_root_bridge(acpi_handle); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); -- cgit v1.2.3-70-g09d2 From ff32e59947c87b01dc25a8b5763d609c1a8f56eb Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 13 Jun 2022 20:26:47 +0200 Subject: ACPI: bus: Introduce acpi_dev_for_each_child_reverse() Make it possible to walk the children of an ACPI device in the revese order by defining acpi_dev_for_each_child_reverse() in analogy with acpi_dev_for_each_child(). Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko --- drivers/acpi/bus.c | 12 ++++++++++++ include/acpi/acpi_bus.h | 3 +++ 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7027ff2edfba..4d7c51a33b01 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1115,6 +1115,18 @@ int acpi_dev_for_each_child(struct acpi_device *adev, return device_for_each_child(&adev->dev, &adwc, acpi_dev_for_one_check); } +int acpi_dev_for_each_child_reverse(struct acpi_device *adev, + int (*fn)(struct acpi_device *, void *), + void *data) +{ + struct acpi_dev_walk_context adwc = { + .fn = fn, + .data = data, + }; + + return device_for_each_child_reverse(&adev->dev, &adwc, acpi_dev_for_one_check); +} + /* -------------------------------------------------------------------------- Initialization/Cleanup -------------------------------------------------------------------------- */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 597961969ca1..76de1aa5d221 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -483,6 +483,9 @@ extern struct bus_type acpi_bus_type; int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data); int acpi_dev_for_each_child(struct acpi_device *adev, int (*fn)(struct acpi_device *, void *), void *data); +int acpi_dev_for_each_child_reverse(struct acpi_device *adev, + int (*fn)(struct acpi_device *, void *), + void *data); /* * Events -- cgit v1.2.3-70-g09d2 From a22f18bddd824e96db839ccda75ff7e035e938ca Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 13 Jun 2022 20:36:06 +0200 Subject: ACPI / MMC: PM: Unify fixing up device power Introduce acpi_device_fix_up_power_extended() for fixing up power of a device having an ACPI companion in a manner that takes the device's children into account and make the MMC code use it in two places instead of walking the list of the device ACPI companion's children directly. This will help to eliminate the children list head from struct acpi_device as it is redundant and it is used in questionable ways in some places (in particular, locking is needed for walking the list pointed to it safely, but it is often missing). Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Acked-by: Adrian Hunter Acked-by: Ulf Hansson --- drivers/acpi/device_pm.c | 22 ++++++++++++++++++++++ drivers/mmc/host/sdhci-acpi.c | 7 ++----- drivers/mmc/host/sdhci-pci-core.c | 11 +++-------- include/acpi/acpi_bus.h | 1 + 4 files changed, 28 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 130b5f4a50a3..9dce1245689c 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -369,6 +369,28 @@ int acpi_device_fix_up_power(struct acpi_device *device) } EXPORT_SYMBOL_GPL(acpi_device_fix_up_power); +static int fix_up_power_if_applicable(struct acpi_device *adev, void *not_used) +{ + if (adev->status.present && adev->status.enabled) + acpi_device_fix_up_power(adev); + + return 0; +} + +/** + * acpi_device_fix_up_power_extended - Force device and its children into D0. + * @adev: Parent device object whose power state is to be fixed up. + * + * Call acpi_device_fix_up_power() for @adev and its children so long as they + * are reported as present and enabled. + */ +void acpi_device_fix_up_power_extended(struct acpi_device *adev) +{ + acpi_device_fix_up_power(adev); + acpi_dev_for_each_child(adev, fix_up_power_if_applicable, NULL); +} +EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended); + int acpi_device_update_power(struct acpi_device *device, int *state_p) { int state; diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index c0350e9c03f3..4cca4c90769b 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -775,8 +775,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct sdhci_acpi_slot *slot; - struct acpi_device *device, *child; const struct dmi_system_id *id; + struct acpi_device *device; struct sdhci_acpi_host *c; struct sdhci_host *host; struct resource *iomem; @@ -796,10 +796,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) slot = sdhci_acpi_get_slot(device); /* Power on the SDHCI controller and its children */ - acpi_device_fix_up_power(device); - list_for_each_entry(child, &device->children, node) - if (child->status.present && child->status.enabled) - acpi_device_fix_up_power(child); + acpi_device_fix_up_power_extended(device); if (sdhci_acpi_byt_defer(dev)) return -EPROBE_DEFER; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index ed53276f6ad9..622b7de96c7f 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1240,16 +1240,11 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { #ifdef CONFIG_ACPI static void intel_mrfld_mmc_fix_up_power_slot(struct sdhci_pci_slot *slot) { - struct acpi_device *device, *child; + struct acpi_device *device; device = ACPI_COMPANION(&slot->chip->pdev->dev); - if (!device) - return; - - acpi_device_fix_up_power(device); - list_for_each_entry(child, &device->children, node) - if (child->status.present && child->status.enabled) - acpi_device_fix_up_power(child); + if (device) + acpi_device_fix_up_power_extended(device); } #else static inline void intel_mrfld_mmc_fix_up_power_slot(struct sdhci_pci_slot *slot) {} diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 76de1aa5d221..54c5566df9fe 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -524,6 +524,7 @@ const char *acpi_power_state_string(int state); int acpi_device_set_power(struct acpi_device *device, int state); int acpi_bus_init_power(struct acpi_device *device); int acpi_device_fix_up_power(struct acpi_device *device); +void acpi_device_fix_up_power_extended(struct acpi_device *adev); int acpi_bus_update_power(acpi_handle handle, int *state_p); int acpi_device_update_power(struct acpi_device *device, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle); -- cgit v1.2.3-70-g09d2 From 7fdc74da940ddf8f2eb0dd1202cbfbfe08342cbb Mon Sep 17 00:00:00 2001 From: Riwen Lu Date: Fri, 17 Jun 2022 10:51:51 +0800 Subject: ACPI: processor: Split out thermal initialization from ACPI PSS Commit 239708a3af44 ("ACPI: Split out ACPI PSS from ACPI Processor driver"), moves processor thermal registration to acpi_pss_perf_init(), which doesn't get executed if ACPI_CPU_FREQ_PSS is not enabled. As ARM64 supports P-states using CPPC, it should be possible to also support processor passive cooling even if PSS is not enabled. Split out the processor thermal cooling register from ACPI PSS to support this, and move it into a separate function in processor_thermal.c. Signed-off-by: Riwen Lu Reviewed-by: Punit Agrawal [ rjw: Subject edits ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 2 +- drivers/acpi/Makefile | 5 ++- drivers/acpi/processor_driver.c | 72 +++++----------------------------------- drivers/acpi/processor_thermal.c | 54 ++++++++++++++++++++++++++++++ include/acpi/processor.h | 8 +++-- 5 files changed, 71 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1e34f846508f..2457ade3f82d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -255,7 +255,6 @@ config ACPI_DOCK config ACPI_CPU_FREQ_PSS bool - select THERMAL config ACPI_PROCESSOR_CSTATE def_bool y @@ -287,6 +286,7 @@ config ACPI_PROCESSOR depends on X86 || IA64 || ARM64 || LOONGARCH select ACPI_PROCESSOR_IDLE select ACPI_CPU_FREQ_PSS if X86 || IA64 || LOONGARCH + select THERMAL default y help This driver adds support for the ACPI Processor package. It is required diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b5a8d3e00a52..0002eecbf870 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -109,10 +109,9 @@ obj-$(CONFIG_ACPI_PPTT) += pptt.o obj-$(CONFIG_ACPI_PFRUT) += pfr_update.o pfr_telemetry.o # processor has its own "processor." module_param namespace -processor-y := processor_driver.o +processor-y := processor_driver.o processor_thermal.o processor-$(CONFIG_ACPI_PROCESSOR_IDLE) += processor_idle.o -processor-$(CONFIG_ACPI_CPU_FREQ_PSS) += processor_throttling.o \ - processor_thermal.o +processor-$(CONFIG_ACPI_CPU_FREQ_PSS) += processor_throttling.o processor-$(CONFIG_CPU_FREQ) += processor_perflib.o obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 368a9edefd0c..1278969eec1f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -139,75 +139,17 @@ static int acpi_soft_cpu_dead(unsigned int cpu) } #ifdef CONFIG_ACPI_CPU_FREQ_PSS -static int acpi_pss_perf_init(struct acpi_processor *pr, - struct acpi_device *device) +static void acpi_pss_perf_init(struct acpi_processor *pr) { - int result = 0; - acpi_processor_ppc_has_changed(pr, 0); acpi_processor_get_throttling_info(pr); if (pr->flags.throttling) pr->flags.limit = 1; - - pr->cdev = thermal_cooling_device_register("Processor", device, - &processor_cooling_ops); - if (IS_ERR(pr->cdev)) { - result = PTR_ERR(pr->cdev); - return result; - } - - dev_dbg(&device->dev, "registered as cooling_device%d\n", - pr->cdev->id); - - result = sysfs_create_link(&device->dev.kobj, - &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) { - dev_err(&device->dev, - "Failed to create sysfs link 'thermal_cooling'\n"); - goto err_thermal_unregister; - } - - result = sysfs_create_link(&pr->cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) { - dev_err(&pr->cdev->device, - "Failed to create sysfs link 'device'\n"); - goto err_remove_sysfs_thermal; - } - - return 0; - - err_remove_sysfs_thermal: - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - err_thermal_unregister: - thermal_cooling_device_unregister(pr->cdev); - - return result; -} - -static void acpi_pss_perf_exit(struct acpi_processor *pr, - struct acpi_device *device) -{ - if (pr->cdev) { - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&pr->cdev->device.kobj, "device"); - thermal_cooling_device_unregister(pr->cdev); - pr->cdev = NULL; - } } #else -static inline int acpi_pss_perf_init(struct acpi_processor *pr, - struct acpi_device *device) -{ - return 0; -} - -static inline void acpi_pss_perf_exit(struct acpi_processor *pr, - struct acpi_device *device) {} +static inline void acpi_pss_perf_init(struct acpi_processor *pr) {} #endif /* CONFIG_ACPI_CPU_FREQ_PSS */ static int __acpi_processor_start(struct acpi_device *device) @@ -229,7 +171,9 @@ static int __acpi_processor_start(struct acpi_device *device) if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) acpi_processor_power_init(pr); - result = acpi_pss_perf_init(pr, device); + acpi_pss_perf_init(pr); + + result = acpi_processor_thermal_init(pr, device); if (result) goto err_power_exit; @@ -239,7 +183,7 @@ static int __acpi_processor_start(struct acpi_device *device) return 0; result = -ENODEV; - acpi_pss_perf_exit(pr, device); + acpi_processor_thermal_exit(pr, device); err_power_exit: acpi_processor_power_exit(pr); @@ -277,10 +221,10 @@ static int acpi_processor_stop(struct device *dev) return 0; acpi_processor_power_exit(pr); - acpi_pss_perf_exit(pr, device); - acpi_cppc_processor_exit(pr); + acpi_processor_thermal_exit(pr, device); + return 0; } diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index d8b2dfcd59b5..db6ac540e924 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -266,3 +266,57 @@ const struct thermal_cooling_device_ops processor_cooling_ops = { .get_cur_state = processor_get_cur_state, .set_cur_state = processor_set_cur_state, }; + +int acpi_processor_thermal_init(struct acpi_processor *pr, + struct acpi_device *device) +{ + int result = 0; + + pr->cdev = thermal_cooling_device_register("Processor", device, + &processor_cooling_ops); + if (IS_ERR(pr->cdev)) { + result = PTR_ERR(pr->cdev); + return result; + } + + dev_dbg(&device->dev, "registered as cooling_device%d\n", + pr->cdev->id); + + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) { + dev_err(&device->dev, + "Failed to create sysfs link 'thermal_cooling'\n"); + goto err_thermal_unregister; + } + + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) { + dev_err(&pr->cdev->device, + "Failed to create sysfs link 'device'\n"); + goto err_remove_sysfs_thermal; + } + + return 0; + +err_remove_sysfs_thermal: + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); +err_thermal_unregister: + thermal_cooling_device_unregister(pr->cdev); + + return result; +} + +void acpi_processor_thermal_exit(struct acpi_processor *pr, + struct acpi_device *device) +{ + if (pr->cdev) { + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); + sysfs_remove_link(&pr->cdev->device.kobj, "device"); + thermal_cooling_device_unregister(pr->cdev); + pr->cdev = NULL; + } +} diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 194027371928..ba1e3ed98d3d 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -442,8 +442,12 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr) /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); +int acpi_processor_thermal_init(struct acpi_processor *pr, + struct acpi_device *device); +void acpi_processor_thermal_exit(struct acpi_processor *pr, + struct acpi_device *device); extern const struct thermal_cooling_device_ops processor_cooling_ops; -#if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ) +#ifdef CONFIG_CPU_FREQ void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy); void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy); #else @@ -455,6 +459,6 @@ static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy) { return; } -#endif /* CONFIG_ACPI_CPU_FREQ_PSS */ +#endif /* CONFIG_CPU_FREQ */ #endif -- cgit v1.2.3-70-g09d2 From e414207d12f38bc42222037dbcdbe6b4649418d6 Mon Sep 17 00:00:00 2001 From: Riwen Lu Date: Fri, 17 Jun 2022 10:51:52 +0800 Subject: ACPI: processor: Drop leftover acpi_processor_get_limit_info() declaration Commit 22e7551eb6fd ("ACPI / processor: Remove acpi_processor_get_limit_info()"), left it behind, so drop it. Signed-off-by: Riwen Lu Reviewed-by: Punit Agrawal [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- include/acpi/processor.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/acpi/processor.h b/include/acpi/processor.h index ba1e3ed98d3d..9fa49686957a 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -441,7 +441,6 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr) #endif /* CONFIG_ACPI_PROCESSOR_IDLE */ /* in processor_thermal.c */ -int acpi_processor_get_limit_info(struct acpi_processor *pr); int acpi_processor_thermal_init(struct acpi_processor *pr, struct acpi_device *device); void acpi_processor_thermal_exit(struct acpi_processor *pr, -- cgit v1.2.3-70-g09d2 From d6fb6ee1820cb9c49717b8d28c5b2e940cb2e439 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 18 Jun 2022 13:23:11 +0200 Subject: ACPI: bus: Drop driver member of struct acpi_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct acpi_device::driver tracks the same information as the driver member of struct acpi_device::dev. Fix all users of the former to use the latter and drop the redundant data from struct acpi_device. Signed-off-by: Uwe Kleine-König Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 21 ++++++++++----------- drivers/acpi/device_sysfs.c | 2 +- include/acpi/acpi_bus.h | 1 - 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 479eec8a1ec6..90cabe4fd4d0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -465,7 +465,6 @@ out_free: static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) { struct acpi_device *adev; - struct acpi_driver *driver; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; bool hotplug_event = false; @@ -517,10 +516,13 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) if (!adev) goto err; - driver = adev->driver; - if (driver && driver->ops.notify && - (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) - driver->ops.notify(adev, type); + if (adev->dev.driver) { + struct acpi_driver *driver = to_acpi_driver(adev->dev.driver); + + if (driver && driver->ops.notify && + (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) + driver->ops.notify(adev, type); + } if (!hotplug_event) { acpi_bus_put_acpi_device(adev); @@ -539,8 +541,9 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) static void acpi_notify_device(acpi_handle handle, u32 event, void *data) { struct acpi_device *device = data; + struct acpi_driver *acpi_drv = to_acpi_driver(device->dev.driver); - device->driver->ops.notify(device, event); + acpi_drv->ops.notify(device, event); } static void acpi_notify_device_fixed(void *data) @@ -1033,8 +1036,6 @@ static int acpi_device_probe(struct device *dev) if (ret) return ret; - acpi_dev->driver = acpi_drv; - pr_debug("Driver [%s] successfully bound to device [%s]\n", acpi_drv->name, acpi_dev->pnp.bus_id); @@ -1044,7 +1045,6 @@ static int acpi_device_probe(struct device *dev) if (acpi_drv->ops.remove) acpi_drv->ops.remove(acpi_dev); - acpi_dev->driver = NULL; acpi_dev->driver_data = NULL; return ret; } @@ -1060,7 +1060,7 @@ static int acpi_device_probe(struct device *dev) static void acpi_device_remove(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; + struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); if (acpi_drv->ops.notify) acpi_device_remove_notify_handler(acpi_dev); @@ -1068,7 +1068,6 @@ static void acpi_device_remove(struct device *dev) if (acpi_drv->ops.remove) acpi_drv->ops.remove(acpi_dev); - acpi_dev->driver = NULL; acpi_dev->driver_data = NULL; put_device(dev); diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index d5d6403ba07b..120873dad2cc 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -376,7 +376,7 @@ eject_store(struct device *d, struct device_attribute *attr, return -EINVAL; if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled) - && !acpi_device->driver) + && !d->driver) return -ENODEV; status = acpi_get_type(acpi_device->handle, ¬_used); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 54c5566df9fe..ab239a35cb2a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -379,7 +379,6 @@ struct acpi_device { struct acpi_device_data data; struct acpi_scan_handler *handler; struct acpi_hotplug_context *hp; - struct acpi_driver *driver; const struct acpi_gpio_mapping *driver_gpios; void *driver_data; struct device dev; -- cgit v1.2.3-70-g09d2 From e6bdbcc764af822ff7172a4a78d437dc433a0c74 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 13 Jun 2022 20:38:00 +0200 Subject: ACPI: bus: Drop unused list heads from struct acpi_device Drop the children and node list heads that have no more users from struct acpi_device and the code manipulating them from __acpi_device_add() and acpi_device_del(). Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko --- drivers/acpi/scan.c | 11 +---------- include/acpi/acpi_bus.h | 2 -- 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7b085826d881..b100e6ca9bb4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -465,8 +465,6 @@ static void acpi_device_del(struct acpi_device *device) struct acpi_device_bus_id *acpi_device_bus_id; mutex_lock(&acpi_device_lock); - if (device->parent) - list_del(&device->node); list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) if (!strcmp(acpi_device_bus_id->bus_id, @@ -482,6 +480,7 @@ static void acpi_device_del(struct acpi_device *device) } list_del(&device->wakeup_list); + mutex_unlock(&acpi_device_lock); acpi_power_add_remove_device(device, false); @@ -674,8 +673,6 @@ static int __acpi_device_add(struct acpi_device *device, * ------- * Link this device to its parent and siblings. */ - INIT_LIST_HEAD(&device->children); - INIT_LIST_HEAD(&device->node); INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); INIT_LIST_HEAD(&device->del_list); @@ -715,9 +712,6 @@ static int __acpi_device_add(struct acpi_device *device, list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); } - if (device->parent) - list_add_tail(&device->node, &device->parent->children); - if (device->wakeup.flags.valid) list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); @@ -746,9 +740,6 @@ static int __acpi_device_add(struct acpi_device *device, err: mutex_lock(&acpi_device_lock); - if (device->parent) - list_del(&device->node); - list_del(&device->wakeup_list); err_unlock: diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ab239a35cb2a..48f0fd499274 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -365,8 +365,6 @@ struct acpi_device { acpi_handle handle; /* no handle for fixed hardware */ struct fwnode_handle fwnode; struct acpi_device *parent; - struct list_head children; - struct list_head node; struct list_head wakeup_list; struct list_head del_list; struct acpi_device_status status; -- cgit v1.2.3-70-g09d2 From 3dcb861dbc6ab101838a1548b1efddd00ca3c3ec Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 30 Jun 2022 11:40:59 +0200 Subject: ACPI: VIOT: Fix ACS setup Currently acpi_viot_init() gets called after the pci device has been scanned and pci_enable_acs() has been called. So pci_request_acs() fails to be taken into account leading to wrong single iommu group topologies when dealing with multi-function root ports for instance. We cannot simply move the acpi_viot_init() earlier, similarly as the IORT init because the VIOT parsing relies on the pci scan. However we can detect VIOT is present earlier and in such a case, request ACS. Introduce a new acpi_viot_early_init() routine that allows to call pci_request_acs() before the scan. While at it, guard the call to pci_request_acs() with #ifdef CONFIG_PCI. Fixes: 3cf485540e7b ("ACPI: Add driver for the VIOT table") Signed-off-by: Eric Auger Reported-by: Jin Liu Reviewed-by: Jean-Philippe Brucker Tested-by: Jean-Philippe Brucker Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 1 + drivers/acpi/viot.c | 26 ++++++++++++++++++++------ include/linux/acpi_viot.h | 2 ++ 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 86fa61a21826..906ad8153fd9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1400,6 +1400,7 @@ static int __init acpi_init(void) pci_mmcfg_late_init(); acpi_iort_init(); + acpi_viot_early_init(); acpi_hest_init(); acpi_ghes_init(); acpi_scan_init(); diff --git a/drivers/acpi/viot.c b/drivers/acpi/viot.c index d2256326c73a..647f11cf165d 100644 --- a/drivers/acpi/viot.c +++ b/drivers/acpi/viot.c @@ -248,6 +248,26 @@ err_free: return ret; } +/** + * acpi_viot_early_init - Test the presence of VIOT and enable ACS + * + * If the VIOT does exist, ACS must be enabled. This cannot be + * done in acpi_viot_init() which is called after the bus scan + */ +void __init acpi_viot_early_init(void) +{ +#ifdef CONFIG_PCI + acpi_status status; + struct acpi_table_header *hdr; + + status = acpi_get_table(ACPI_SIG_VIOT, 0, &hdr); + if (ACPI_FAILURE(status)) + return; + pci_request_acs(); + acpi_put_table(hdr); +#endif +} + /** * acpi_viot_init - Parse the VIOT table * @@ -319,12 +339,6 @@ 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; - /* - * If we found a PCI range managed by the viommu, we're - * the one that has to request ACS. - */ - pci_request_acs(); - return viot_dev_iommu_init(&pdev->dev, ep->viommu, epid); } diff --git a/include/linux/acpi_viot.h b/include/linux/acpi_viot.h index 1eb8ee5b0e5f..a5a122431563 100644 --- a/include/linux/acpi_viot.h +++ b/include/linux/acpi_viot.h @@ -6,9 +6,11 @@ #include #ifdef CONFIG_ACPI_VIOT +void __init acpi_viot_early_init(void); void __init acpi_viot_init(void); int viot_iommu_configure(struct device *dev); #else +static inline void acpi_viot_early_init(void) {} static inline void acpi_viot_init(void) {} static inline int viot_iommu_configure(struct device *dev) { -- cgit v1.2.3-70-g09d2 From 4f4179fcf420873002035cf1941d844c9e0e7cb3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Jul 2022 19:41:10 +0200 Subject: ACPI: CPPC: Do not prevent CPPC from working in the future There is a problem with the current revision checks in is_cppc_supported() that they essentially prevent the CPPC support from working if a new _CPC package format revision being a proper superset of the v3 and only causing _CPC to return a package with more entries (while retaining the types and meaning of the entries defined by the v3) is introduced in the future and used by the platform firmware. In that case, as long as the number of entries in the _CPC return package is at least CPPC_V3_NUM_ENT, it should be perfectly fine to use the v3 support code and disregard the additional package entries added by the new package format revision. For this reason, drop is_cppc_supported() altogether, put the revision checks directly into acpi_cppc_processor_probe() so they are easier to follow and rework them to take the case mentioned above into account. Fixes: 4773e77cdc9b ("ACPI / CPPC: Add support for CPPC v3") Cc: 4.18+ # 4.18+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 54 +++++++++++++++++++++--------------------------- include/acpi/cppc_acpi.h | 2 +- 2 files changed, 25 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 3c6d4ef87be0..1e15a9f25ae9 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -618,33 +618,6 @@ static int pcc_data_alloc(int pcc_ss_id) return 0; } -/* Check if CPPC revision + num_ent combination is supported */ -static bool is_cppc_supported(int revision, int num_ent) -{ - int expected_num_ent; - - switch (revision) { - case CPPC_V2_REV: - expected_num_ent = CPPC_V2_NUM_ENT; - break; - case CPPC_V3_REV: - expected_num_ent = CPPC_V3_NUM_ENT; - break; - default: - pr_debug("Firmware exports unsupported CPPC revision: %d\n", - revision); - return false; - } - - if (expected_num_ent != num_ent) { - pr_debug("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n", - num_ent, expected_num_ent, revision); - return false; - } - - return true; -} - /* * An example CPC table looks like the following. * @@ -733,7 +706,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) cpc_obj->type, pr->id); goto out_free; } - cpc_ptr->num_entries = num_ent; /* Second entry should be revision. */ cpc_obj = &out_obj->package.elements[1]; @@ -744,10 +716,32 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) cpc_obj->type, pr->id); goto out_free; } - cpc_ptr->version = cpc_rev; - if (!is_cppc_supported(cpc_rev, num_ent)) + if (cpc_rev < CPPC_V2_REV) { + pr_debug("Unsupported _CPC Revision (%d) for CPU:%d\n", cpc_rev, + pr->id); + goto out_free; + } + + /* + * Disregard _CPC if the number of entries in the return pachage is not + * as expected, but support future revisions being proper supersets of + * the v3 and only causing more entries to be returned by _CPC. + */ + if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) || + (cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) || + (cpc_rev > CPPC_V3_REV && num_ent <= CPPC_V3_NUM_ENT)) { + pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n", + num_ent, pr->id); goto out_free; + } + if (cpc_rev > CPPC_V3_REV) { + num_ent = CPPC_V3_NUM_ENT; + cpc_rev = CPPC_V3_REV; + } + + cpc_ptr->num_entries = num_ent; + cpc_ptr->version = cpc_rev; /* Iterate through remaining entries in _CPC */ for (i = 2; i < num_ent; i++) { diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h index d389bab54241..f73d357ecdf5 100644 --- a/include/acpi/cppc_acpi.h +++ b/include/acpi/cppc_acpi.h @@ -17,7 +17,7 @@ #include #include -/* Support CPPCv2 and CPPCv3 */ +/* CPPCv2 and CPPCv3 support */ #define CPPC_V2_REV 2 #define CPPC_V3_REV 3 #define CPPC_V2_NUM_ENT 21 -- cgit v1.2.3-70-g09d2