diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-02 15:58:39 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-02 15:58:39 -0700 |
commit | c0d6586afa3546a3d148cf4b9d9a407b4f79d0bb (patch) | |
tree | 54e09bd2d7f63efeeaf6d34a65e246bb05206f40 /drivers | |
parent | 33fb42636a938be01d951b4cee68127a59a1e7e4 (diff) | |
parent | 90e17edac46882ee5fa4dfb6a72956b89dd188f3 (diff) | |
download | linux-c0d6586afa3546a3d148cf4b9d9a407b4f79d0bb.tar.bz2 |
Merge tag 'acpi-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI updates from Rafael Wysocki:
"These update the ACPICA code in the kernel to the most recent upstream
revision, address some issues related to the ACPI power resources
management, simplify the enumeration of PCI devices having ACPI
companions, add new quirks, fix assorted problems, update the
ACPI-related information in maintainers and clean up code in several
places.
Specifics:
- Update the ACPICA code in the kernel to upstream revision 20210930
including the following changes:
- Fix system-wide resume issue caused by evaluating control
methods too early in the resume path (Rafael Wysocki).
- Add support for Windows 2020 _OSI string (Mario Limonciello).
- Add Generic Port Affinity type for SRAT (Alison Schofield).
- Add disassembly support for the NHLT ACPI table (Bob Moore).
- Avoid flushing caches before entering C3 type of idle states on AMD
processors (Deepak Sharma).
- Avoid enumerating CPUs that are not present and not online-capable
according to the platform firmware (Mario Limonciello).
- Add DMI-based mechanism to quirk IRQ overrides and use it for two
platforms (Hui Wang).
- Change the configuration of unused ACPI device objects to reflect
the D3cold power state after enumerating devices (Rafael Wysocki).
- Update MAINTAINERS information regarding ACPI (Rafael Wysocki).
- Fix typo in ACPI Kconfig (Masanari Iid).
- Use sysfs_emit() instead of snprintf() in some places (Qing Wang).
- Make the association of ACPI device objects with PCI devices more
straightforward and simplify the code doing that for all devices in
general (Rafael Wysocki).
- Use acpi_device_adr() in acpi_find_child_device() instead of
evaluating _ADR (Rafael Wysocki).
- Drop duplicate device IDs from PNP device IDs list (Krzysztof
Kozlowski).
- Allow acpi_idle_play_dead() to use C3 on AMD processors (Richard
Gong).
- Use ACPI_COMPANION() to simplify code in some drivers (Rafael
Wysocki).
- Check the states of all ACPI power resources during initialization
to avoid dealing with power resources in unknown states (Rafael
Wysocki).
- Fix ACPI power resource issues related to sharing wakeup power
resources (Rafael Wysocki).
- Avoid registering redundant suspend_ops (Rafael Wysocki).
- Report battery charging state as "full" if it appears to be over
the design capacity (André Almeida).
- Quirk GK45 mini PC to skip reading _PSR in the AC driver (Stefan
Schaeckeler).
- Mark apei_hest_parse() static (Christoph Hellwig).
- Relax platform response timeout to 1 second after instructing it to
inject an error (Shuai Xue).
- Make the PRM code handle memory allocation and remapping failures
more gracefully and drop some unnecessary blank lines from that
code (Aubrey Li).
- Fix spelling mistake in the ACPI documentation (Colin Ian King)"
* tag 'acpi-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (36 commits)
ACPI: glue: Use acpi_device_adr() in acpi_find_child_device()
perf: qcom_l2_pmu: ACPI: Use ACPI_COMPANION() directly
ACPI: APEI: mark apei_hest_parse() static
ACPI: APEI: EINJ: Relax platform response timeout to 1 second
gpio-amdpt: ACPI: Use the ACPI_COMPANION() macro directly
nouveau: ACPI: Use the ACPI_COMPANION() macro directly
ACPI: resources: Add one more Medion model in IRQ override quirk
ACPI: AC: Quirk GK45 to skip reading _PSR
ACPI: PM: sleep: Do not set suspend_ops unnecessarily
ACPI: PRM: Handle memory allocation and memory remap failure
ACPI: PRM: Remove unnecessary blank lines
ACPI: PM: Turn off wakeup power resources on _DSW/_PSW errors
ACPI: PM: Fix sharing of wakeup power resources
ACPI: PM: Turn off unused wakeup power resources
ACPI: PM: Check states of power resources during initialization
ACPI: replace snprintf() in "show" functions with sysfs_emit()
ACPI: LPSS: Use ACPI_COMPANION() directly
ACPI: scan: Release PM resources blocked by unused objects
ACPI: battery: Accept charges over the design capacity as full
ACPICA: Update version to 20210930
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/acpi/ac.c | 19 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 13 | ||||
-rw-r--r-- | drivers/acpi/acpi_pnp.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwesleep.c | 8 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 11 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwxfsleep.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/utosi.c | 1 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 15 | ||||
-rw-r--r-- | drivers/acpi/apei/hest.c | 5 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 8 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 66 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/power.c | 97 | ||||
-rw-r--r-- | drivers/acpi/prmt.c | 35 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 3 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 56 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 6 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 10 | ||||
-rw-r--r-- | drivers/gpio/gpio-amdpt.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 9 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 31 | ||||
-rw-r--r-- | drivers/perf/qcom_l2_pmu.c | 7 |
25 files changed, 253 insertions, 167 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1da360c51d66..cdbdf68bd98f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -71,7 +71,7 @@ config ACPI_DEBUGGER if ACPI_DEBUGGER config ACPI_DEBUGGER_USER - tristate "Userspace debugger accessiblity" + tristate "Userspace debugger accessibility" depends on DEBUG_FS help Export /sys/kernel/debug/acpi/acpidbg for userspace utilities diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index b0cb662233f1..81aff651a0d4 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -61,6 +61,7 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); static int ac_sleep_before_get_state_ms; static int ac_check_pmic = 1; +static int ac_only; static struct acpi_driver acpi_ac_driver = { .name = "ac", @@ -93,6 +94,11 @@ static int acpi_ac_get_state(struct acpi_ac *ac) if (!ac) return -EINVAL; + if (ac_only) { + ac->state = 1; + return 0; + } + status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); if (ACPI_FAILURE(status)) { @@ -200,6 +206,12 @@ static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) return 0; } +static int __init ac_only_quirk(const struct dmi_system_id *d) +{ + ac_only = 1; + return 0; +} + /* Please keep this list alphabetically sorted */ static const struct dmi_system_id ac_dmi_table[] __initconst = { { @@ -210,6 +222,13 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { }, }, { + /* Kodlix GK45 returning incorrect state */ + .callback = ac_only_quirk, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "GK45"), + }, + }, + { /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ .callback = ac_do_not_check_pmic_quirk, .matches = { diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 30b1f511c2af..bcae0f03572b 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -712,14 +712,13 @@ static void __lpss_reg_write(u32 val, struct lpss_private_data *pdata, static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) { - struct acpi_device *adev; + struct acpi_device *adev = ACPI_COMPANION(dev); struct lpss_private_data *pdata; unsigned long flags; int ret; - ret = acpi_bus_get_device(ACPI_HANDLE(dev), &adev); - if (WARN_ON(ret)) - return ret; + if (WARN_ON(!adev)) + return -ENODEV; spin_lock_irqsave(&dev->power.lock, flags); if (pm_runtime_suspended(dev)) { @@ -732,6 +731,7 @@ static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) goto out; } *val = __lpss_reg_read(pdata, reg); + ret = 0; out: spin_unlock_irqrestore(&dev->power.lock, flags); @@ -750,7 +750,7 @@ static ssize_t lpss_ltr_show(struct device *dev, struct device_attribute *attr, if (ret) return ret; - return snprintf(buf, PAGE_SIZE, "%08x\n", ltr_value); + return sysfs_emit(buf, "%08x\n", ltr_value); } static ssize_t lpss_ltr_mode_show(struct device *dev, @@ -1266,7 +1266,8 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, if (!id || !id->driver_data) return 0; - if (acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) return 0; pdata = acpi_driver_data(adev); diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 8f2dc176bb41..ffdcfcd4a10d 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -156,8 +156,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */ {"BRI1400"}, /* Boca Research 33,600 ACF Modem */ {"BRI3400"}, /* Boca 33.6 Kbps Internal FD34FSVD */ - {"BRI0A49"}, /* Boca 33.6 Kbps Internal FD34FSVD */ - {"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */ {"CPI4050"}, /* Computer Peripherals Inc. EuroViVa CommCenter-33.6 SP PnP */ {"CTL3001"}, /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ {"CTL3011"}, /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index d41b810e367c..4366d36ef119 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -226,6 +226,8 @@ extern struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a); ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b); +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a_s0); +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b_s0); /***************************************************************************** * diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 803402aefaeb..808fdf54aeeb 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -147,17 +147,13 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) { - acpi_status status; u8 sleep_type_value; ACPI_FUNCTION_TRACE(hw_extended_wake_prep); - status = acpi_get_sleep_type_data(ACPI_STATE_S0, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_SUCCESS(status)) { + if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { sleep_type_value = - ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & + ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) & ACPI_X_SLEEP_TYPE_MASK); (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 14baa13bf848..34a3825f25d3 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -179,7 +179,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) { - acpi_status status; + acpi_status status = AE_OK; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 pm1a_control; @@ -192,10 +192,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) * This is unclear from the ACPI Spec, but it is required * by some machines. */ - status = acpi_get_sleep_type_data(ACPI_STATE_S0, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_SUCCESS(status)) { + if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { sleep_type_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = @@ -216,9 +213,9 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) /* Insert the SLP_TYP bits */ - pm1a_control |= (acpi_gbl_sleep_type_a << + pm1a_control |= (acpi_gbl_sleep_type_a_s0 << sleep_type_reg_info->bit_position); - pm1b_control |= (acpi_gbl_sleep_type_b << + pm1b_control |= (acpi_gbl_sleep_type_b_s0 << sleep_type_reg_info->bit_position); /* Write the control registers and ignore any errors */ diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 89b12afed564..e4cde23a2906 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -217,6 +217,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) return_ACPI_STATUS(status); } + status = acpi_get_sleep_type_data(ACPI_STATE_S0, + &acpi_gbl_sleep_type_a_s0, + &acpi_gbl_sleep_type_b_s0); + if (ACPI_FAILURE(status)) { + acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID; + } + /* Execute the _PTS method (Prepare To Sleep) */ arg_list.count = 1; diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 7b8e8bf1e824..8afa1ccaf12e 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -73,6 +73,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */ {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5}, /* Windows 10 version 1809 - Added 11/2018 */ {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1}, /* Windows 10 version 1903 - Added 08/2019 */ + {"Windows 2020", NULL, 0, ACPI_OSI_WIN_10_20H1}, /* Windows 10 version 2004 - Added 08/2021 */ /* Feature Group Strings */ diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 2882450c443e..edb2622fd35f 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -28,9 +28,10 @@ #undef pr_fmt #define pr_fmt(fmt) "EINJ: " fmt -#define SPIN_UNIT 100 /* 100ns */ -/* Firmware should respond within 1 milliseconds */ -#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) +#define SLEEP_UNIT_MIN 1000 /* 1ms */ +#define SLEEP_UNIT_MAX 5000 /* 5ms */ +/* Firmware should respond within 1 seconds */ +#define FIRMWARE_TIMEOUT (1 * USEC_PER_SEC) #define ACPI5_VENDOR_BIT BIT(31) #define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \ ACPI_EINJ_MEMORY_UNCORRECTABLE | \ @@ -171,13 +172,13 @@ static int einj_get_available_error_type(u32 *type) static int einj_timedout(u64 *t) { - if ((s64)*t < SPIN_UNIT) { + if ((s64)*t < SLEEP_UNIT_MIN) { pr_warn(FW_WARN "Firmware does not respond in time\n"); return 1; } - *t -= SPIN_UNIT; - ndelay(SPIN_UNIT); - touch_nmi_watchdog(); + *t -= SLEEP_UNIT_MIN; + usleep_range(SLEEP_UNIT_MIN, SLEEP_UNIT_MAX); + return 0; } diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 277f00b288d1..0edc1ed47673 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -86,7 +86,9 @@ static int hest_esrc_len(struct acpi_hest_header *hest_hdr) return len; }; -int apei_hest_parse(apei_hest_func_t func, void *data) +typedef int (*apei_hest_func_t)(struct acpi_hest_header *hest_hdr, void *data); + +static int apei_hest_parse(apei_hest_func_t func, void *data) { struct acpi_hest_header *hest_hdr; int i, rc, len; @@ -121,7 +123,6 @@ int apei_hest_parse(apei_hest_func_t func, void *data) return 0; } -EXPORT_SYMBOL_GPL(apei_hest_parse); /* * Check if firmware advertises firmware first mode. We need FF bit to be set diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index dae91f906cea..8afa85d6eb6a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -169,7 +169,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery) return 1; /* fallback to using design values for broken batteries */ - if (battery->design_capacity == battery->capacity_now) + if (battery->design_capacity <= battery->capacity_now) return 1; /* we don't do any sort of metric based on percentages */ diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7cf92158008f..c8e9b962e18c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -492,7 +492,7 @@ static ssize_t docked_show(struct device *dev, struct acpi_device *adev = NULL; acpi_bus_get_device(dock_station->handle, &adev); - return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev)); + return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev)); } static DEVICE_ATTR_RO(docked); @@ -504,7 +504,7 @@ static ssize_t flags_show(struct device *dev, { struct dock_station *dock_station = dev->platform_data; - return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); + return sysfs_emit(buf, "%d\n", dock_station->flags); } static DEVICE_ATTR_RO(flags); @@ -543,7 +543,7 @@ static ssize_t uid_show(struct device *dev, if (ACPI_FAILURE(status)) return 0; - return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf); + return sysfs_emit(buf, "%llx\n", lbuf); } static DEVICE_ATTR_RO(uid); @@ -562,7 +562,7 @@ static ssize_t type_show(struct device *dev, else type = "unknown"; - return snprintf(buf, PAGE_SIZE, "%s\n", type); + return sysfs_emit(buf, "%s\n", type); } static DEVICE_ATTR_RO(type); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 7a33a6d985f8..7cd0009e7ff3 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -17,6 +17,8 @@ #include <linux/rwsem.h> #include <linux/acpi.h> #include <linux/dma-mapping.h> +#include <linux/pci.h> +#include <linux/pci-acpi.h> #include <linux/platform_device.h> #include "internal.h" @@ -111,13 +113,10 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent, return NULL; list_for_each_entry(adev, &parent->children, node) { - unsigned long long addr; - acpi_status status; + acpi_bus_address addr = acpi_device_adr(adev); int score; - status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR, - NULL, &addr); - if (ACPI_FAILURE(status) || addr != address) + if (!adev->pnp.type.bus_address || addr != address) continue; if (!ret) { @@ -287,12 +286,13 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one); void acpi_device_notify(struct device *dev) { - struct acpi_bus_type *type = acpi_get_bus_type(dev); struct acpi_device *adev; int ret; ret = acpi_bind_one(dev, NULL); if (ret) { + struct acpi_bus_type *type = acpi_get_bus_type(dev); + if (!type) goto err; @@ -304,17 +304,26 @@ void acpi_device_notify(struct device *dev) ret = acpi_bind_one(dev, adev); if (ret) goto err; - } - adev = ACPI_COMPANION(dev); - if (dev_is_platform(dev)) - acpi_configure_pmsi_domain(dev); + if (type->setup) { + type->setup(dev); + goto done; + } + } else { + adev = ACPI_COMPANION(dev); + + if (dev_is_pci(dev)) { + pci_acpi_setup(dev, adev); + goto done; + } else if (dev_is_platform(dev)) { + acpi_configure_pmsi_domain(dev); + } + } - if (type && type->setup) - type->setup(dev); - else if (adev->handler && adev->handler->bind) + if (adev->handler && adev->handler->bind) adev->handler->bind(dev); +done: acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n", dev_name(dev)); @@ -327,16 +336,39 @@ err: void acpi_device_notify_remove(struct device *dev) { struct acpi_device *adev = ACPI_COMPANION(dev); - struct acpi_bus_type *type; if (!adev) return; - type = acpi_get_bus_type(dev); - if (type && type->cleanup) - type->cleanup(dev); + if (dev_is_pci(dev)) + pci_acpi_cleanup(dev, adev); else if (adev->handler && adev->handler->unbind) adev->handler->unbind(dev); acpi_unbind_one(dev); } + +int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used) +{ + struct acpi_device *adev = to_acpi_device(dev); + + /* + * Skip device objects with device IDs, because they may be in use even + * if they are not companions of any physical device objects. + */ + if (adev->pnp.type.hardware_id) + return 0; + + mutex_lock(&adev->physical_node_lock); + + /* + * Device objects without device IDs are not in use if they have no + * corresponding physical device objects. + */ + if (list_empty(&adev->physical_node_list)) + acpi_device_set_power(adev, ACPI_STATE_D3_COLD); + + mutex_unlock(&adev->physical_node_lock); + + return 0; +} diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index d91b560e8867..8fbdc172864b 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -117,6 +117,7 @@ bool acpi_device_is_battery(struct acpi_device *adev); bool acpi_device_is_first_physical_node(struct acpi_device *adev, const struct device *dev); int acpi_bus_register_early_device(int type); +int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used); /* -------------------------------------------------------------------------- Device Matching and Notification diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index f0ed4414edb1..112256154880 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -52,7 +52,6 @@ struct acpi_power_resource { u32 order; unsigned int ref_count; u8 state; - bool wakeup_enabled; struct mutex resource_lock; struct list_head dependents; }; @@ -615,20 +614,19 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) list_for_each_entry(entry, list, node) { struct acpi_power_resource *resource = entry->resource; - int result; u8 state; mutex_lock(&resource->resource_lock); - result = acpi_power_get_state(resource, &state); - if (result) { - mutex_unlock(&resource->resource_lock); - return result; - } - if (state == ACPI_POWER_RESOURCE_STATE_ON) { - resource->ref_count++; - resource->wakeup_enabled = true; - } + /* + * Make sure that the power resource state and its reference + * counter value are consistent with each other. + */ + if (!resource->ref_count && + !acpi_power_get_state(resource, &state) && + state == ACPI_POWER_RESOURCE_STATE_ON) + __acpi_power_off(resource); + if (system_level > resource->system_level) system_level = resource->system_level; @@ -711,7 +709,6 @@ int acpi_device_sleep_wake(struct acpi_device *dev, */ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) { - struct acpi_power_resource_entry *entry; int err = 0; if (!dev || !dev->wakeup.flags.valid) @@ -722,33 +719,22 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) if (dev->wakeup.prepare_count++) goto out; - list_for_each_entry(entry, &dev->wakeup.resources, node) { - struct acpi_power_resource *resource = entry->resource; - - mutex_lock(&resource->resource_lock); - - if (!resource->wakeup_enabled) { - err = acpi_power_on_unlocked(resource); - if (!err) - resource->wakeup_enabled = true; - } - - mutex_unlock(&resource->resource_lock); - - if (err) { - dev_err(&dev->dev, - "Cannot turn wakeup power resources on\n"); - dev->wakeup.flags.valid = 0; - goto out; - } + err = acpi_power_on_list(&dev->wakeup.resources); + if (err) { + dev_err(&dev->dev, "Cannot turn on wakeup power resources\n"); + dev->wakeup.flags.valid = 0; + goto out; } + /* * Passing 3 as the third argument below means the device may be * put into arbitrary power state afterward. */ err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); - if (err) + if (err) { + acpi_power_off_list(&dev->wakeup.resources); dev->wakeup.prepare_count = 0; + } out: mutex_unlock(&acpi_device_lock); @@ -771,39 +757,33 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) mutex_lock(&acpi_device_lock); - if (--dev->wakeup.prepare_count > 0) + if (dev->wakeup.prepare_count > 1) { + dev->wakeup.prepare_count--; goto out; + } - /* - * Executing the code below even if prepare_count is already zero when - * the function is called may be useful, for example for initialisation. - */ - if (dev->wakeup.prepare_count < 0) - dev->wakeup.prepare_count = 0; + /* Do nothing if wakeup power has not been enabled for this device. */ + if (!dev->wakeup.prepare_count) + goto out; err = acpi_device_sleep_wake(dev, 0, 0, 0); if (err) goto out; + /* + * All of the power resources in the list need to be turned off even if + * there are errors. + */ list_for_each_entry(entry, &dev->wakeup.resources, node) { - struct acpi_power_resource *resource = entry->resource; - - mutex_lock(&resource->resource_lock); - - if (resource->wakeup_enabled) { - err = acpi_power_off_unlocked(resource); - if (!err) - resource->wakeup_enabled = false; - } - - mutex_unlock(&resource->resource_lock); + int ret; - if (err) { - dev_err(&dev->dev, - "Cannot turn wakeup power resources off\n"); - dev->wakeup.flags.valid = 0; - break; - } + ret = acpi_power_off(entry->resource); + if (ret && !err) + err = ret; + } + if (err) { + dev_err(&dev->dev, "Cannot turn off wakeup power resources\n"); + dev->wakeup.flags.valid = 0; } out: @@ -943,6 +923,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) union acpi_object acpi_object; struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; acpi_status status; + u8 state_dummy; int result; acpi_bus_get_device(handle, &device); @@ -971,6 +952,10 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) resource->order = acpi_object.power_resource.resource_order; resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN; + /* Get the initial state or just flip it on if that fails. */ + if (acpi_power_get_state(resource, &state_dummy)) + __acpi_power_on(resource); + pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); device->flags.match_driver = true; diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 89c22bc55057..4d3a219c67f8 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -49,7 +49,6 @@ struct prm_context_buffer { }; #pragma pack() - static LIST_HEAD(prm_module_list); struct prm_handler_info { @@ -73,7 +72,6 @@ struct prm_module_info { struct prm_handler_info handlers[]; }; - static u64 efi_pa_va_lookup(u64 pa) { efi_memory_desc_t *md; @@ -88,7 +86,6 @@ static u64 efi_pa_va_lookup(u64 pa) return 0; } - #define get_first_handler(a) ((struct acpi_prmt_handler_info *) ((char *) (a) + a->handler_info_offset)) #define get_next_handler(a) ((struct acpi_prmt_handler_info *) (sizeof(struct acpi_prmt_handler_info) + (char *) a)) @@ -99,7 +96,7 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) struct acpi_prmt_handler_info *handler_info; struct prm_handler_info *th; struct prm_module_info *tm; - u64 mmio_count = 0; + u64 *mmio_count; u64 cur_handler = 0; u32 module_info_size = 0; u64 mmio_range_size = 0; @@ -108,6 +105,8 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) module_info = (struct acpi_prmt_module_info *) header; module_info_size = struct_size(tm, handlers, module_info->handler_info_count); tm = kmalloc(module_info_size, GFP_KERNEL); + if (!tm) + goto parse_prmt_out1; guid_copy(&tm->guid, (guid_t *) module_info->module_guid); tm->major_rev = module_info->major_rev; @@ -120,14 +119,24 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) * Each module is associated with a list of addr * ranges that it can use during the service */ - mmio_count = *(u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB); - mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); + mmio_count = (u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB); + if (!mmio_count) + goto parse_prmt_out2; + + mmio_range_size = struct_size(tm->mmio_info, addr_ranges, *mmio_count); tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + if (!tm->mmio_info) + goto parse_prmt_out3; + temp_mmio = memremap(module_info->mmio_list_pointer, mmio_range_size, MEMREMAP_WB); + if (!temp_mmio) + goto parse_prmt_out4; memmove(tm->mmio_info, temp_mmio, mmio_range_size); } else { - mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); - tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + tm->mmio_info = kmalloc(sizeof(*tm->mmio_info), GFP_KERNEL); + if (!tm->mmio_info) + goto parse_prmt_out2; + tm->mmio_info->mmio_count = 0; } @@ -145,6 +154,15 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); return 0; + +parse_prmt_out4: + kfree(tm->mmio_info); +parse_prmt_out3: + memunmap(mmio_count); +parse_prmt_out2: + kfree(tm); +parse_prmt_out1: + return -ENOMEM; } #define GET_MODULE 0 @@ -171,7 +189,6 @@ static void *find_guid_info(const guid_t *guid, u8 mode) return NULL; } - static struct prm_module_info *find_prm_module(const guid_t *guid) { return (struct prm_module_info *)find_guid_info(guid, GET_MODULE); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f37fba9e5ba0..76ef1bcc8848 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -789,7 +789,8 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) state->enter = acpi_idle_enter; state->flags = 0; - if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2) { + if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 || + cx->type == ACPI_STATE_C3) { state->enter_dead = acpi_idle_play_dead; drv->safe_state_index = count; } diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index ee78a210c606..3c25ce8c95ba 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -16,6 +16,7 @@ #include <linux/ioport.h> #include <linux/slab.h> #include <linux/irq.h> +#include <linux/dmi.h> #ifdef CONFIG_X86 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) @@ -380,9 +381,58 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) } EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); +static const struct dmi_system_id medion_laptop[] = { + { + .ident = "MEDION P15651", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_BOARD_NAME, "M15T"), + }, + }, + { + .ident = "MEDION S17405", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_BOARD_NAME, "M17T"), + }, + }, + { } +}; + +struct irq_override_cmp { + const struct dmi_system_id *system; + unsigned char irq; + unsigned char triggering; + unsigned char polarity; + unsigned char shareable; +}; + +static const struct irq_override_cmp skip_override_table[] = { + { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 }, +}; + +static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, + u8 shareable) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(skip_override_table); i++) { + const struct irq_override_cmp *entry = &skip_override_table[i]; + + if (dmi_check_system(entry->system) && + entry->irq == gsi && + entry->triggering == triggering && + entry->polarity == polarity && + entry->shareable == shareable) + return false; + } + + return true; +} + static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, u8 triggering, u8 polarity, u8 shareable, - bool legacy) + bool check_override) { int irq, p, t; @@ -401,7 +451,9 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, * using extended IRQ descriptors we take the IRQ configuration * from _CRS directly. */ - if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { + if (check_override && + acpi_dev_irq_override(gsi, triggering, polarity, shareable) && + !acpi_get_override_irq(gsi, &t, &p)) { u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f456ba7c1060..dce2c291b982 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2560,6 +2560,12 @@ int __init acpi_scan_init(void) } } + /* + * Make sure that power management resources are not blocked by ACPI + * device objects with no users. + */ + bus_for_each_dev(&acpi_bus_type, NULL, NULL, acpi_dev_turn_off_if_unused); + acpi_turn_off_unused_power_resources(); acpi_scan_initialized = true; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3023224515ab..eaa47753b758 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -815,14 +815,18 @@ void __weak acpi_s2idle_setup(void) static void acpi_sleep_suspend_setup(void) { + bool suspend_ops_needed = false; int i; for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) - if (acpi_sleep_state_supported(i)) + if (acpi_sleep_state_supported(i)) { sleep_states[i] = 1; + suspend_ops_needed = true; + } - suspend_set_ops(old_suspend_ordering ? - &acpi_suspend_ops_old : &acpi_suspend_ops); + if (suspend_ops_needed) + suspend_set_ops(old_suspend_ordering ? + &acpi_suspend_ops_old : &acpi_suspend_ops); acpi_s2idle_setup(); } diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index 44398992ae15..bbf53e289141 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -72,12 +72,10 @@ static void pt_gpio_free(struct gpio_chip *gc, unsigned offset) static int pt_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acpi_device *acpi_dev; - acpi_handle handle = ACPI_HANDLE(dev); struct pt_gpio_chip *pt_gpio; int ret = 0; - if (acpi_bus_get_device(handle, &acpi_dev)) { + if (!ACPI_COMPANION(dev)) { dev_err(dev, "PT GPIO device node not found\n"); return -ENODEV; } diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 7c15f6448428..6140db756d06 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -364,7 +364,6 @@ void * nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { struct acpi_device *acpidev; - acpi_handle handle; int type, ret; void *edid; @@ -377,12 +376,8 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) return NULL; } - handle = ACPI_HANDLE(dev->dev); - if (!handle) - return NULL; - - ret = acpi_bus_get_device(handle, &acpidev); - if (ret) + acpidev = ACPI_COMPANION(dev->dev); + if (!acpidev) return NULL; ret = acpi_video_get_edid(acpidev, type, -1, &edid); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 260a06fb78a6..b00d80370379 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -1356,13 +1356,9 @@ static void pci_acpi_set_external_facing(struct pci_dev *dev) dev->external_facing = 1; } -static void pci_acpi_setup(struct device *dev) +void pci_acpi_setup(struct device *dev, struct acpi_device *adev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct acpi_device *adev = ACPI_COMPANION(dev); - - if (!adev) - return; pci_acpi_optimize_delay(pci_dev, adev->handle); pci_acpi_set_external_facing(pci_dev); @@ -1386,14 +1382,10 @@ static void pci_acpi_setup(struct device *dev) acpi_device_power_add_dependent(adev, dev); } -static void pci_acpi_cleanup(struct device *dev) +void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev) { - struct acpi_device *adev = ACPI_COMPANION(dev); struct pci_dev *pci_dev = to_pci_dev(dev); - if (!adev) - return; - pci_acpi_remove_edr_notifier(pci_dev); pci_acpi_remove_pm_notifier(adev); if (adev->wakeup.flags.valid) { @@ -1405,20 +1397,6 @@ static void pci_acpi_cleanup(struct device *dev) } } -static bool pci_acpi_bus_match(struct device *dev) -{ - return dev_is_pci(dev); -} - -static struct acpi_bus_type acpi_pci_bus = { - .name = "PCI", - .match = pci_acpi_bus_match, - .find_companion = acpi_pci_find_companion, - .setup = pci_acpi_setup, - .cleanup = pci_acpi_cleanup, -}; - - static struct fwnode_handle *(*pci_msi_get_fwnode_cb)(struct device *dev); /** @@ -1460,8 +1438,6 @@ struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus) static int __init acpi_pci_init(void) { - int ret; - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) { pr_info("ACPI FADT declares the system doesn't support MSI, so disable it\n"); pci_no_msi(); @@ -1472,8 +1448,7 @@ static int __init acpi_pci_init(void) pcie_no_aspm(); } - ret = register_acpi_bus_type(&acpi_pci_bus); - if (ret) + if (acpi_pci_disabled) return 0; pci_set_platform_pm(&acpi_pci_platform_pm); diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c index 5b093badd0f6..7640491aab12 100644 --- a/drivers/perf/qcom_l2_pmu.c +++ b/drivers/perf/qcom_l2_pmu.c @@ -840,17 +840,14 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data) { struct platform_device *pdev = to_platform_device(dev->parent); struct platform_device *sdev = to_platform_device(dev); + struct acpi_device *adev = ACPI_COMPANION(dev); struct l2cache_pmu *l2cache_pmu = data; struct cluster_pmu *cluster; - struct acpi_device *device; unsigned long fw_cluster_id; int err; int irq; - if (acpi_bus_get_device(ACPI_HANDLE(dev), &device)) - return -ENODEV; - - if (kstrtoul(device->pnp.unique_id, 10, &fw_cluster_id) < 0) { + if (!adev || kstrtoul(adev->pnp.unique_id, 10, &fw_cluster_id) < 0) { dev_err(&pdev->dev, "unable to read ACPI uid\n"); return -ENODEV; } |