History

Merge tag 'acpi-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI updates from Rafael Wysocki: "These add Microsoft fan extensions support to the ACPI fan driver, fix a bug in ACPICA, update other ACPI drivers (processor, time and alarm device), update ACPI power management code and ACPI device properties management, and fix an ACPI utility: - Avoid walking the ACPI namespace in the AML interpreter if the starting node cannot be determined (Cryolitia PukNgae) - Use min() instead of min_t() in the ACPI device properties handling code to avoid discarding significant bits (David Laight) - Fix potential fwnode refcount leak in acpi_fwnode_graph_parse_endpoint() that may prevent the parent fwnode from being released (Haotian Zhang) - Rework acpi_graph_get_next_endpoint() to use ACPI functions only, remove unnecessary conditionals from it to make it easier to follow, and make acpi_get_next_subnode() static (Sakari Ailus) - Drop unused function acpi_get_lps0_constraint(), make some Low-Power S0 callback functions for suspend-to-idle static, and rearrange the code retrieving Low-Power S0 constraints so it only runs when the constraints are actually used (Rafael Wysocki) - Drop redundant locking from the ACPI battery driver (Rafael Wysocki) - Improve runtime PM in the ACPI time and alarm device (TAD) driver using guard macros and rearrange code related to runtime PM in acpi_tad_remove() (Rafael Wysocki) - Add support for Microsoft fan extensions to the ACPI fan driver along with notification support and work around a 64-bit firmware bug in that driver (Armin Wolf) - Use ACPI_FREE() to free ACPI buffer in the ACPI DPTF code (Kaushlendra Kumar) - Fix a memory leak and a resource leak in the ACPI pfrut utility (Malaya Kumar Rout) - Replace `core::mem::zeroed` with `pin_init::zeroed` in the ACPI Rust code (Siyuan Huang) - Update the ACPI code to use the new style of allocating workqueues and new global workqueues (Marco Crivellari) - Fix two spelling mistakes in the ACPI code (Chu Guangqing) - Fix ISAPNP to generate uevents to auto-load modules (René Rebe) - Relocate the state flags initialization in the ACPI processor idle driver and drop redundant C-state count checks from it (Huisong Li) - Fix map_x2apic_id() in the ACPI processor core driver for amd-pstate on am4 (René Rebe)" * tag 'acpi-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (30 commits) ACPI: PM: Fix a spelling mistake ACPI: LPSS: Fix a spelling mistake ACPI: processor_core: fix map_x2apic_id for amd-pstate on am4 ACPICA: Avoid walking the Namespace if start_node is NULL ACPI: tools: pfrut: fix memory leak and resource leak in pfrut.c ACPI: property: use min() instead of min_t() PNP: Fix ISAPNP to generate uevents to auto-load modules ACPI: property: Fix fwnode refcount leak in acpi_fwnode_graph_parse_endpoint() ACPI: DPTF: Use ACPI_FREE() for ACPI buffer deallocation ACPI: processor: idle: Drop redundant C-state count checks ACPI: thermal: Add WQ_PERCPU to alloc_workqueue() users ACPI: OSL: Add WQ_PERCPU to alloc_workqueue() users ACPI: EC: Add WQ_PERCPU to alloc_workqueue() users ACPI: OSL: replace use of system_wq with system_percpu_wq ACPI: scan: replace use of system_unbound_wq with system_dfl_wq ACPI: fan: Add support for Microsoft fan extensions ACPI: fan: Add hwmon notification support ACPI: fan: Add basic notification support ACPI: TAD: Improve runtime PM using guard macros ACPI: TAD: Rearrange runtime PM operations in acpi_tad_remove() ...

Linus Torvalds committed 11 months ago

Commit 959bfe42 parents 44fc843 af47d9822 files · +420 −168Browse files

Unified · Split

22 files
  1. drivers/acpi/acpi_tad.c +39 −34
  2. drivers/acpi/acpica/nswalk.c +6 −3
  3. drivers/acpi/battery.c +0 −12
  4. drivers/acpi/dptf/dptf_pch_fivr.c +1 −1
  5. drivers/acpi/ec.c +2 −1
  6. drivers/acpi/fan.h +40 −0
  7. drivers/acpi/fan_core.c +222 −1
  8. drivers/acpi/fan_hwmon.c +14 −11
  9. drivers/acpi/osl.c +3 −3
  10. drivers/acpi/processor_core.c +1 −1
  11. drivers/acpi/processor_idle.c +16 −26
  12. drivers/acpi/property.c +17 −12
  13. drivers/acpi/scan.c +1 −1
  14. drivers/acpi/sleep.c +1 −1
  15. drivers/acpi/sleep.h +0 −3
  16. drivers/acpi/thermal.c +2 −1
  17. drivers/acpi/x86/lpss.c +1 −1
  18. drivers/acpi/x86/s2idle.c +29 −36
  19. drivers/pnp/driver.c +19 −0
  20. include/linux/acpi.h +0 −15
  21. rust/kernel/acpi.rs +1 −3
  22. tools/power/acpi/tools/pfrut/pfrut.c +5 −2
drivers/acpi/acpi_tad.c+39−34
@@ -90,19 +90,18 @@ static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt) · 89 unmodified lines
90 args[0].buffer.pointer = (u8 *)rt;90 args[0].buffer.pointer = (u8 *)rt;
91 args[0].buffer.length = sizeof(*rt);91 args[0].buffer.length = sizeof(*rt);
92 92
93 pm_runtime_get_sync(dev);93 ACQUIRE(pm_runtime_active_try, pm)(dev);
94 if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
95 return -ENXIO;
94 96
95 status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval);97 status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval);
96
97 pm_runtime_put_sync(dev);
98
99 if (ACPI_FAILURE(status) || retval)98 if (ACPI_FAILURE(status) || retval)
100 return -EIO;99 return -EIO;
101 100
102 return 0;101 return 0;
103}102}
104 103
105static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)104static int acpi_tad_evaluate_grt(struct device *dev, struct acpi_tad_rt *rt)
106{105{
107 acpi_handle handle = ACPI_HANDLE(dev);106 acpi_handle handle = ACPI_HANDLE(dev);
108 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER };107 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER };
@@ -111,12 +110,7 @@ static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt) · 2 unmodified lines
111 acpi_status status;110 acpi_status status;
112 int ret = -EIO;111 int ret = -EIO;
113 112
114 pm_runtime_get_sync(dev);
115
116 status = acpi_evaluate_object(handle, "_GRT", NULL, &output);113 status = acpi_evaluate_object(handle, "_GRT", NULL, &output);
117
118 pm_runtime_put_sync(dev);
119
120 if (ACPI_FAILURE(status))114 if (ACPI_FAILURE(status))
121 goto out_free;115 goto out_free;
122 116
@@ -139,6 +133,21 @@ out_free: · 16 unmodified lines
139 return ret;133 return ret;
140}134}
141 135
136static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
137{
138 int ret;
139
140 ACQUIRE(pm_runtime_active_try, pm)(dev);
141 if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
142 return -ENXIO;
143
144 ret = acpi_tad_evaluate_grt(dev, rt);
145 if (ret)
146 return ret;
147
148 return 0;
149}
150
142static char *acpi_tad_rt_next_field(char *s, int *val)151static char *acpi_tad_rt_next_field(char *s, int *val)
143{152{
144 char *p;153 char *p;
@@ -266,12 +275,11 @@ static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id, · 121 unmodified lines
266 args[0].integer.value = timer_id;275 args[0].integer.value = timer_id;
267 args[1].integer.value = value;276 args[1].integer.value = value;
268 277
269 pm_runtime_get_sync(dev);278 ACQUIRE(pm_runtime_active_try, pm)(dev);
279 if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
280 return -ENXIO;
270 281
271 status = acpi_evaluate_integer(handle, method, &arg_list, &retval);282 status = acpi_evaluate_integer(handle, method, &arg_list, &retval);
272
273 pm_runtime_put_sync(dev);
274
275 if (ACPI_FAILURE(status) || retval)283 if (ACPI_FAILURE(status) || retval)
276 return -EIO;284 return -EIO;
277 285
@@ -314,12 +322,11 @@ static ssize_t acpi_tad_wake_read(struct device *dev, char *buf, char *method, · 36 unmodified lines
314 322
315 args[0].integer.value = timer_id;323 args[0].integer.value = timer_id;
316 324
317 pm_runtime_get_sync(dev);325 ACQUIRE(pm_runtime_active_try, pm)(dev);
326 if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
327 return -ENXIO;
318 328
319 status = acpi_evaluate_integer(handle, method, &arg_list, &retval);329 status = acpi_evaluate_integer(handle, method, &arg_list, &retval);
320
321 pm_runtime_put_sync(dev);
322
323 if (ACPI_FAILURE(status))330 if (ACPI_FAILURE(status))
324 return -EIO;331 return -EIO;
325 332
@@ -370,12 +377,11 @@ static int acpi_tad_clear_status(struct device *dev, u32 timer_id) · 44 unmodified lines
370 377
371 args[0].integer.value = timer_id;378 args[0].integer.value = timer_id;
372 379
373 pm_runtime_get_sync(dev);380 ACQUIRE(pm_runtime_active_try, pm)(dev);
381 if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
382 return -ENXIO;
374 383
375 status = acpi_evaluate_integer(handle, "_CWS", &arg_list, &retval);384 status = acpi_evaluate_integer(handle, "_CWS", &arg_list, &retval);
376
377 pm_runtime_put_sync(dev);
378
379 if (ACPI_FAILURE(status) || retval)385 if (ACPI_FAILURE(status) || retval)
380 return -EIO;386 return -EIO;
381 387
@@ -411,12 +417,11 @@ static ssize_t acpi_tad_status_read(struct device *dev, char *buf, u32 timer_id) · 29 unmodified lines
411 417
412 args[0].integer.value = timer_id;418 args[0].integer.value = timer_id;
413 419
414 pm_runtime_get_sync(dev);420 ACQUIRE(pm_runtime_active_try, pm)(dev);
421 if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
422 return -ENXIO;
415 423
416 status = acpi_evaluate_integer(handle, "_GWS", &arg_list, &retval);424 status = acpi_evaluate_integer(handle, "_GWS", &arg_list, &retval);
417
418 pm_runtime_put_sync(dev);
419
420 if (ACPI_FAILURE(status))425 if (ACPI_FAILURE(status))
421 return -EIO;426 return -EIO;
422 427
@@ -563,8 +568,6 @@ static void acpi_tad_remove(struct platform_device *pdev) · 140 unmodified lines
563 568
564 device_init_wakeup(dev, false);569 device_init_wakeup(dev, false);
565 570
566 pm_runtime_get_sync(dev);
567
568 if (dd->capabilities & ACPI_TAD_RT)571 if (dd->capabilities & ACPI_TAD_RT)
569 sysfs_remove_group(&dev->kobj, &acpi_tad_time_attr_group);572 sysfs_remove_group(&dev->kobj, &acpi_tad_time_attr_group);
570 573
@@ -573,14 +576,16 @@ static void acpi_tad_remove(struct platform_device *pdev) · 2 unmodified lines
573 576
574 sysfs_remove_group(&dev->kobj, &acpi_tad_attr_group);577 sysfs_remove_group(&dev->kobj, &acpi_tad_attr_group);
575 578
576 acpi_tad_disable_timer(dev, ACPI_TAD_AC_TIMER);579 scoped_guard(pm_runtime_noresume, dev) {
577 acpi_tad_clear_status(dev, ACPI_TAD_AC_TIMER);580 acpi_tad_disable_timer(dev, ACPI_TAD_AC_TIMER);
578 if (dd->capabilities & ACPI_TAD_DC_WAKE) {581 acpi_tad_clear_status(dev, ACPI_TAD_AC_TIMER);
579 acpi_tad_disable_timer(dev, ACPI_TAD_DC_TIMER);582 if (dd->capabilities & ACPI_TAD_DC_WAKE) {
580 acpi_tad_clear_status(dev, ACPI_TAD_DC_TIMER);583 acpi_tad_disable_timer(dev, ACPI_TAD_DC_TIMER);
584 acpi_tad_clear_status(dev, ACPI_TAD_DC_TIMER);
585 }
581 }586 }
582 587
583 pm_runtime_put_sync(dev);588 pm_runtime_suspend(dev);
584 pm_runtime_disable(dev);589 pm_runtime_disable(dev);
585 acpi_remove_cmos_rtc_space_handler(handle);590 acpi_remove_cmos_rtc_space_handler(handle);
586}591}
drivers/acpi/acpica/nswalk.c+6−3
@@ -169,9 +169,12 @@ acpi_ns_walk_namespace(acpi_object_type type, · 168 unmodified lines
169 169
170 if (start_node == ACPI_ROOT_OBJECT) {170 if (start_node == ACPI_ROOT_OBJECT) {
171 start_node = acpi_gbl_root_node;171 start_node = acpi_gbl_root_node;
172 if (!start_node) {172 }
173 return_ACPI_STATUS(AE_NO_NAMESPACE);173
174 }174 /* Avoid walking the namespace if the StartNode is NULL */
175
176 if (!start_node) {
177 return_ACPI_STATUS(AE_NO_NAMESPACE);
175 }178 }
176 179
177 /* Null child means "get first node" */180 /* Null child means "get first node" */
drivers/acpi/battery.c+0−12
@@ -91,7 +91,6 @@ enum { · 90 unmodified lines
91};91};
92 92
93struct acpi_battery {93struct acpi_battery {
94 struct mutex lock;
95 struct mutex update_lock;94 struct mutex update_lock;
96 struct power_supply *bat;95 struct power_supply *bat;
97 struct power_supply_desc bat_desc;96 struct power_supply_desc bat_desc;
@@ -535,11 +534,9 @@ static int acpi_battery_get_info(struct acpi_battery *battery) · 437 unmodified lines
535 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };534 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
536 acpi_status status = AE_ERROR;535 acpi_status status = AE_ERROR;
537 536
538 mutex_lock(&battery->lock);
539 status = acpi_evaluate_object(battery->device->handle,537 status = acpi_evaluate_object(battery->device->handle,
540 use_bix ? "_BIX":"_BIF",538 use_bix ? "_BIX":"_BIF",
541 NULL, &buffer);539 NULL, &buffer);
542 mutex_unlock(&battery->lock);
543 540
544 if (ACPI_FAILURE(status)) {541 if (ACPI_FAILURE(status)) {
545 acpi_handle_info(battery->device->handle,542 acpi_handle_info(battery->device->handle,
@@ -576,11 +573,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery) · 30 unmodified lines
576 msecs_to_jiffies(cache_time)))573 msecs_to_jiffies(cache_time)))
577 return 0;574 return 0;
578 575
579 mutex_lock(&battery->lock);
580 status = acpi_evaluate_object(battery->device->handle, "_BST",576 status = acpi_evaluate_object(battery->device->handle, "_BST",
581 NULL, &buffer);577 NULL, &buffer);
582 mutex_unlock(&battery->lock);
583
584 if (ACPI_FAILURE(status)) {578 if (ACPI_FAILURE(status)) {
585 acpi_handle_info(battery->device->handle,579 acpi_handle_info(battery->device->handle,
586 "_BST evaluation failed: %s",580 "_BST evaluation failed: %s",
@@ -628,11 +622,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) · 41 unmodified lines
628 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))622 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
629 return -ENODEV;623 return -ENODEV;
630 624
631 mutex_lock(&battery->lock);
632 status = acpi_execute_simple_method(battery->device->handle, "_BTP",625 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
633 battery->alarm);626 battery->alarm);
634 mutex_unlock(&battery->lock);
635
636 if (ACPI_FAILURE(status))627 if (ACPI_FAILURE(status))
637 return -ENODEV;628 return -ENODEV;
638 629
@@ -1235,9 +1226,6 @@ static int acpi_battery_add(struct acpi_device *device) · 596 unmodified lines
1235 strscpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);1226 strscpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1236 strscpy(acpi_device_class(device), ACPI_BATTERY_CLASS);1227 strscpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
1237 device->driver_data = battery;1228 device->driver_data = battery;
1238 result = devm_mutex_init(&device->dev, &battery->lock);
1239 if (result)
1240 return result;
1241 1229
1242 result = devm_mutex_init(&device->dev, &battery->update_lock);1230 result = devm_mutex_init(&device->dev, &battery->update_lock);
1243 if (result)1231 if (result)
drivers/acpi/dptf/dptf_pch_fivr.c+1−1
@@ -41,7 +41,7 @@ static int pch_fivr_read(acpi_handle handle, char *method, struct pch_fivr_resp · 40 unmodified lines
41 ret = 0;41 ret = 0;
42 42
43release_buffer:43release_buffer:
44 kfree(buffer.pointer);44 ACPI_FREE(buffer.pointer);
45 return ret;45 return ret;
46}46}
47 47
drivers/acpi/ec.c+2−1
@@ -2294,7 +2294,8 @@ static int acpi_ec_init_workqueues(void) · 2293 unmodified lines
2294 ec_wq = alloc_ordered_workqueue("kec", 0);2294 ec_wq = alloc_ordered_workqueue("kec", 0);
2295 2295
2296 if (!ec_query_wq)2296 if (!ec_query_wq)
2297 ec_query_wq = alloc_workqueue("kec_query", 0, ec_max_queries);2297 ec_query_wq = alloc_workqueue("kec_query", WQ_PERCPU,
2298 ec_max_queries);
2298 2299
2299 if (!ec_wq || !ec_query_wq) {2300 if (!ec_wq || !ec_query_wq) {
2300 acpi_ec_destroy_workqueues();2301 acpi_ec_destroy_workqueues();
drivers/acpi/fan.h+40−0
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#define _ACPI_FAN_H_11#define _ACPI_FAN_H_
12 12
13#include <linux/kconfig.h>13#include <linux/kconfig.h>
14#include <linux/limits.h>
14 15
15#define ACPI_FAN_DEVICE_IDS \16#define ACPI_FAN_DEVICE_IDS \
16 {"INT3404", }, /* Fan */ \17 {"INT3404", }, /* Fan */ \
@@ -55,19 +56,58 @@ struct acpi_fan { · 38 unmodified lines
55 struct acpi_fan_fif fif;56 struct acpi_fan_fif fif;
56 struct acpi_fan_fps *fps;57 struct acpi_fan_fps *fps;
57 int fps_count;58 int fps_count;
59 /* A value of 0 means that trippoint-related functions are not supported */
60 u32 fan_trip_granularity;
61#if IS_REACHABLE(CONFIG_HWMON)
62 struct device *hdev;
63#endif
58 struct thermal_cooling_device *cdev;64 struct thermal_cooling_device *cdev;
59 struct device_attribute fst_speed;65 struct device_attribute fst_speed;
60 struct device_attribute fine_grain_control;66 struct device_attribute fine_grain_control;
61};67};
62 68
69/**
70 * acpi_fan_speed_valid - Check if fan speed value is valid
71 * @speeed: Speed value returned by the ACPI firmware
72 *
73 * Check if the fan speed value returned by the ACPI firmware is valid. This function is
74 * necessary as ACPI firmware implementations can return 0xFFFFFFFF to signal that the
75 * ACPI fan does not support speed reporting. Additionally, some buggy ACPI firmware
76 * implementations return a value larger than the 32-bit integer value defined by
77 * the ACPI specification when using placeholder values. Such invalid values are also
78 * detected by this function.
79 *
80 * Returns: True if the fan speed value is valid, false otherwise.
81 */
82static inline bool acpi_fan_speed_valid(u64 speed)
83{
84 return speed < U32_MAX;
85}
86
87/**
88 * acpi_fan_power_valid - Check if fan power value is valid
89 * @power: Power value returned by the ACPI firmware
90 *
91 * Check if the fan power value returned by the ACPI firmware is valid.
92 * See acpi_fan_speed_valid() for details.
93 *
94 * Returns: True if the fan power value is valid, false otherwise.
95 */
96static inline bool acpi_fan_power_valid(u64 power)
97{
98 return power < U32_MAX;
99}
100
63int acpi_fan_get_fst(acpi_handle handle, struct acpi_fan_fst *fst);101int acpi_fan_get_fst(acpi_handle handle, struct acpi_fan_fst *fst);
64int acpi_fan_create_attributes(struct acpi_device *device);102int acpi_fan_create_attributes(struct acpi_device *device);
65void acpi_fan_delete_attributes(struct acpi_device *device);103void acpi_fan_delete_attributes(struct acpi_device *device);
66 104
67#if IS_REACHABLE(CONFIG_HWMON)105#if IS_REACHABLE(CONFIG_HWMON)
68int devm_acpi_fan_create_hwmon(struct device *dev);106int devm_acpi_fan_create_hwmon(struct device *dev);
107void acpi_fan_notify_hwmon(struct device *dev);
69#else108#else
70static inline int devm_acpi_fan_create_hwmon(struct device *dev) { return 0; };109static inline int devm_acpi_fan_create_hwmon(struct device *dev) { return 0; };
110static inline void acpi_fan_notify_hwmon(struct device *dev) { };
71#endif111#endif
72 112
73#endif113#endif
drivers/acpi/fan_core.c+222−1
@@ -7,11 +7,16 @@ · 6 unmodified lines
7 * Copyright (C) 2022 Intel Corporation. All rights reserved.7 * Copyright (C) 2022 Intel Corporation. All rights reserved.
8 */8 */
9 9
10#include <linux/bits.h>
10#include <linux/kernel.h>11#include <linux/kernel.h>
12#include <linux/limits.h>
13#include <linux/math.h>
14#include <linux/math64.h>
11#include <linux/module.h>15#include <linux/module.h>
12#include <linux/init.h>16#include <linux/init.h>
13#include <linux/types.h>17#include <linux/types.h>
14#include <linux/uaccess.h>18#include <linux/uaccess.h>
19#include <linux/uuid.h>
15#include <linux/thermal.h>20#include <linux/thermal.h>
16#include <linux/acpi.h>21#include <linux/acpi.h>
17#include <linux/platform_device.h>22#include <linux/platform_device.h>
@@ -19,6 +24,26 @@ · 1 unmodified line
19 24
20#include "fan.h"25#include "fan.h"
21 26
27#define ACPI_FAN_NOTIFY_STATE_CHANGED 0x80
28
29/*
30 * Defined inside the "Fan Noise Signal" section at
31 * https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/design-guide.
32 */
33static const guid_t acpi_fan_microsoft_guid = GUID_INIT(0xA7611840, 0x99FE, 0x41AE, 0xA4, 0x88,
34 0x35, 0xC7, 0x59, 0x26, 0xC8, 0xEB);
35#define ACPI_FAN_DSM_GET_TRIP_POINT_GRANULARITY 1
36#define ACPI_FAN_DSM_SET_TRIP_POINTS 2
37#define ACPI_FAN_DSM_GET_OPERATING_RANGES 3
38
39/*
40 * Ensures that fans with a very low trip point granularity
41 * do not send too many notifications.
42 */
43static uint min_trip_distance = 100;
44module_param(min_trip_distance, uint, 0);
45MODULE_PARM_DESC(min_trip_distance, "Minimum distance between fan speed trip points in RPM");
46
22static const struct acpi_device_id fan_device_ids[] = {47static const struct acpi_device_id fan_device_ids[] = {
23 ACPI_FAN_DEVICE_IDS,48 ACPI_FAN_DEVICE_IDS,
24 {"", 0},49 {"", 0},
@@ -308,6 +333,182 @@ err: · 283 unmodified lines
308 return status;333 return status;
309}334}
310 335
336static int acpi_fan_dsm_init(struct device *dev)
337{
338 union acpi_object dummy = {
339 .package = {
340 .type = ACPI_TYPE_PACKAGE,
341 .count = 0,
342 .elements = NULL,
343 },
344 };
345 struct acpi_fan *fan = dev_get_drvdata(dev);
346 union acpi_object *obj;
347 int ret = 0;
348
349 if (!acpi_check_dsm(fan->handle, &acpi_fan_microsoft_guid, 0,
350 BIT(ACPI_FAN_DSM_GET_TRIP_POINT_GRANULARITY) |
351 BIT(ACPI_FAN_DSM_SET_TRIP_POINTS)))
352 return 0;
353
354 dev_info(dev, "Using Microsoft fan extensions\n");
355
356 obj = acpi_evaluate_dsm_typed(fan->handle, &acpi_fan_microsoft_guid, 0,
357 ACPI_FAN_DSM_GET_TRIP_POINT_GRANULARITY, &dummy,
358 ACPI_TYPE_INTEGER);
359 if (!obj)
360 return -EIO;
361
362 if (obj->integer.value > U32_MAX)
363 ret = -EOVERFLOW;
364 else
365 fan->fan_trip_granularity = obj->integer.value;
366
367 kfree(obj);
368
369 return ret;
370}
371
372static int acpi_fan_dsm_set_trip_points(struct device *dev, u64 upper, u64 lower)
373{
374 union acpi_object args[2] = {
375 {
376 .integer = {
377 .type = ACPI_TYPE_INTEGER,
378 .value = lower,
379 },
380 },
381 {
382 .integer = {
383 .type = ACPI_TYPE_INTEGER,
384 .value = upper,
385 },
386 },
387 };
388 struct acpi_fan *fan = dev_get_drvdata(dev);
389 union acpi_object in = {
390 .package = {
391 .type = ACPI_TYPE_PACKAGE,
392 .count = ARRAY_SIZE(args),
393 .elements = args,
394 },
395 };
396 union acpi_object *obj;
397
398 obj = acpi_evaluate_dsm(fan->handle, &acpi_fan_microsoft_guid, 0,
399 ACPI_FAN_DSM_SET_TRIP_POINTS, &in);
400 kfree(obj);
401
402 return 0;
403}
404
405static int acpi_fan_dsm_start(struct device *dev)
406{
407 struct acpi_fan *fan = dev_get_drvdata(dev);
408 int ret;
409
410 if (!fan->fan_trip_granularity)
411 return 0;
412
413 /*
414 * Some firmware implementations only update the values returned by the
415 * _FST control method when a notification is received. This usually
416 * works with Microsoft Windows as setting up trip points will keep
417 * triggering said notifications, but will cause issues when using _FST
418 * without the Microsoft-specific trip point extension.
419 *
420 * Because of this, an initial notification needs to be triggered to
421 * start the cycle of trip points updates. This is achieved by setting
422 * the trip points sequencially to two separate ranges. As by the
423 * Microsoft specification the firmware should trigger a notification
424 * immediately if the fan speed is outside the trip point range. This
425 * _should_ result in at least one notification as both ranges do not
426 * overlap, meaning that the current fan speed needs to be outside at
427 * least one range.
428 */
429 ret = acpi_fan_dsm_set_trip_points(dev, fan->fan_trip_granularity, 0);
430 if (ret < 0)
431 return ret;
432
433 return acpi_fan_dsm_set_trip_points(dev, fan->fan_trip_granularity * 3,
434 fan->fan_trip_granularity * 2);
435}
436
437static int acpi_fan_dsm_update_trips_points(struct device *dev, struct acpi_fan_fst *fst)
438{
439 struct acpi_fan *fan = dev_get_drvdata(dev);
440 u64 upper, lower;
441
442 if (!fan->fan_trip_granularity)
443 return 0;
444
445 if (!acpi_fan_speed_valid(fst->speed))
446 return -EINVAL;
447
448 upper = roundup_u64(fst->speed + min_trip_distance, fan->fan_trip_granularity);
449 if (fst->speed <= min_trip_distance) {
450 lower = 0;
451 } else {
452 /*
453 * Valid fan speed values cannot be larger than 32 bit, so
454 * we can safely assume that no overflow will happen here.
455 */
456 lower = rounddown((u32)fst->speed - min_trip_distance, fan->fan_trip_granularity);
457 }
458
459 return acpi_fan_dsm_set_trip_points(dev, upper, lower);
460}
461
462static void acpi_fan_notify_handler(acpi_handle handle, u32 event, void *context)
463{
464 struct device *dev = context;
465 struct acpi_fan_fst fst;
466 int ret;
467
468 switch (event) {
469 case ACPI_FAN_NOTIFY_STATE_CHANGED:
470 /*
471 * The ACPI specification says that we must evaluate _FST when we
472 * receive an ACPI event indicating that the fan state has changed.
473 */
474 ret = acpi_fan_get_fst(handle, &fst);
475 if (ret < 0) {
476 dev_err(dev, "Error retrieving current fan status: %d\n", ret);
477 } else {
478 ret = acpi_fan_dsm_update_trips_points(dev, &fst);
479 if (ret < 0)
480 dev_err(dev, "Failed to update trip points: %d\n", ret);
481 }
482
483 acpi_fan_notify_hwmon(dev);
484 acpi_bus_generate_netlink_event("fan", dev_name(dev), event, 0);
485 break;
486 default:
487 dev_dbg(dev, "Unsupported ACPI notification 0x%x\n", event);
488 break;
489 }
490}
491
492static void acpi_fan_notify_remove(void *data)
493{
494 struct acpi_fan *fan = data;
495
496 acpi_remove_notify_handler(fan->handle, ACPI_DEVICE_NOTIFY, acpi_fan_notify_handler);
497}
498
499static int devm_acpi_fan_notify_init(struct device *dev)
500{
501 struct acpi_fan *fan = dev_get_drvdata(dev);
502 acpi_status status;
503
504 status = acpi_install_notify_handler(fan->handle, ACPI_DEVICE_NOTIFY,
505 acpi_fan_notify_handler, dev);
506 if (ACPI_FAILURE(status))
507 return -EIO;
508
509 return devm_add_action_or_reset(dev, acpi_fan_notify_remove, fan);
510}
511
311static int acpi_fan_probe(struct platform_device *pdev)512static int acpi_fan_probe(struct platform_device *pdev)
312{513{
313 int result = 0;514 int result = 0;
@@ -347,10 +548,24 @@ static int acpi_fan_probe(struct platform_device *pdev) · 33 unmodified lines
347 }548 }
348 549
349 if (fan->has_fst) {550 if (fan->has_fst) {
551 result = acpi_fan_dsm_init(&pdev->dev);
552 if (result)
553 return result;
554
350 result = devm_acpi_fan_create_hwmon(&pdev->dev);555 result = devm_acpi_fan_create_hwmon(&pdev->dev);
351 if (result)556 if (result)
352 return result;557 return result;
353 558
559 result = devm_acpi_fan_notify_init(&pdev->dev);
560 if (result)
561 return result;
562
563 result = acpi_fan_dsm_start(&pdev->dev);
564 if (result) {
565 dev_err(&pdev->dev, "Failed to start Microsoft fan extensions\n");
566 return result;
567 }
568
354 result = acpi_fan_create_attributes(device);569 result = acpi_fan_create_attributes(device);
355 if (result)570 if (result)
356 return result;571 return result;
@@ -436,8 +651,14 @@ static int acpi_fan_suspend(struct device *dev) · 79 unmodified lines
436 651
437static int acpi_fan_resume(struct device *dev)652static int acpi_fan_resume(struct device *dev)
438{653{
439 int result;
440 struct acpi_fan *fan = dev_get_drvdata(dev);654 struct acpi_fan *fan = dev_get_drvdata(dev);
655 int result;
656
657 if (fan->has_fst) {
658 result = acpi_fan_dsm_start(dev);
659 if (result)
660 dev_err(dev, "Failed to start Microsoft fan extensions: %d\n", result);
661 }
441 662
442 if (fan->acpi4)663 if (fan->acpi4)
443 return 0;664 return 0;
drivers/acpi/fan_hwmon.c+14−11
@@ -15,10 +15,6 @@ · 14 unmodified lines
15 15
16#include "fan.h"16#include "fan.h"
17 17
18/* Returned when the ACPI fan does not support speed reporting */
19#define FAN_SPEED_UNAVAILABLE U32_MAX
20#define FAN_POWER_UNAVAILABLE U32_MAX
21
22static struct acpi_fan_fps *acpi_fan_get_current_fps(struct acpi_fan *fan, u64 control)18static struct acpi_fan_fps *acpi_fan_get_current_fps(struct acpi_fan *fan, u64 control)
23{19{
24 unsigned int i;20 unsigned int i;
@@ -77,7 +73,7 @@ static umode_t acpi_fan_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_ · 52 unmodified lines
77 * when the associated attribute should not be created.73 * when the associated attribute should not be created.
78 */74 */
79 for (i = 0; i < fan->fps_count; i++) {75 for (i = 0; i < fan->fps_count; i++) {
80 if (fan->fps[i].power != FAN_POWER_UNAVAILABLE)76 if (acpi_fan_power_valid(fan->fps[i].power))
81 return 0444;77 return 0444;
82 }78 }
83 79
@@ -106,7 +102,7 @@ static int acpi_fan_hwmon_read(struct device *dev, enum hwmon_sensor_types type, · 22 unmodified lines
106 case hwmon_fan:102 case hwmon_fan:
107 switch (attr) {103 switch (attr) {
108 case hwmon_fan_input:104 case hwmon_fan_input:
109 if (fst.speed == FAN_SPEED_UNAVAILABLE)105 if (!acpi_fan_speed_valid(fst.speed))
110 return -ENODEV;106 return -ENODEV;
111 107
112 if (fst.speed > LONG_MAX)108 if (fst.speed > LONG_MAX)
@@ -134,7 +130,7 @@ static int acpi_fan_hwmon_read(struct device *dev, enum hwmon_sensor_types type, · 21 unmodified lines
134 if (!fps)130 if (!fps)
135 return -EIO;131 return -EIO;
136 132
137 if (fps->power == FAN_POWER_UNAVAILABLE)133 if (!acpi_fan_power_valid(fps->power))
138 return -ENODEV;134 return -ENODEV;
139 135
140 if (fps->power > LONG_MAX / MICROWATT_PER_MILLIWATT)136 if (fps->power > LONG_MAX / MICROWATT_PER_MILLIWATT)
@@ -166,12 +162,19 @@ static const struct hwmon_chip_info acpi_fan_hwmon_chip_info = { · 25 unmodified lines
166 .info = acpi_fan_hwmon_info,162 .info = acpi_fan_hwmon_info,
167};163};
168 164
165void acpi_fan_notify_hwmon(struct device *dev)
166{
167 struct acpi_fan *fan = dev_get_drvdata(dev);
168
169 hwmon_notify_event(fan->hdev, hwmon_fan, hwmon_fan_input, 0);
170}
171
169int devm_acpi_fan_create_hwmon(struct device *dev)172int devm_acpi_fan_create_hwmon(struct device *dev)
170{173{
171 struct acpi_fan *fan = dev_get_drvdata(dev);174 struct acpi_fan *fan = dev_get_drvdata(dev);
172 struct device *hdev;
173 175
174 hdev = devm_hwmon_device_register_with_info(dev, "acpi_fan", fan, &acpi_fan_hwmon_chip_info,176 fan->hdev = devm_hwmon_device_register_with_info(dev, "acpi_fan", fan,
175 NULL);177 &acpi_fan_hwmon_chip_info, NULL);
176 return PTR_ERR_OR_ZERO(hdev);178
179 return PTR_ERR_OR_ZERO(fan->hdev);
177}180}
drivers/acpi/osl.c+3−3
@@ -398,7 +398,7 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map) · 397 unmodified lines
398 list_del_rcu(&map->list);398 list_del_rcu(&map->list);
399 399
400 INIT_RCU_WORK(&map->track.rwork, acpi_os_map_remove);400 INIT_RCU_WORK(&map->track.rwork, acpi_os_map_remove);
401 queue_rcu_work(system_wq, &map->track.rwork);401 queue_rcu_work(system_percpu_wq, &map->track.rwork);
402}402}
403 403
404/**404/**
@@ -1694,8 +1694,8 @@ acpi_status __init acpi_os_initialize(void) · 1289 unmodified lines
1694 1694
1695acpi_status __init acpi_os_initialize1(void)1695acpi_status __init acpi_os_initialize1(void)
1696{1696{
1697 kacpid_wq = alloc_workqueue("kacpid", 0, 1);1697 kacpid_wq = alloc_workqueue("kacpid", WQ_PERCPU, 1);
1698 kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 0);1698 kacpi_notify_wq = alloc_workqueue("kacpi_notify", WQ_PERCPU, 0);
1699 kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);1699 kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
1700 BUG_ON(!kacpid_wq);1700 BUG_ON(!kacpid_wq);
1701 BUG_ON(!kacpi_notify_wq);1701 BUG_ON(!kacpi_notify_wq);
drivers/acpi/processor_core.c+1−1
@@ -54,7 +54,7 @@ static int map_x2apic_id(struct acpi_subtable_header *entry, · 53 unmodified lines
54 if (!(apic->lapic_flags & ACPI_MADT_ENABLED))54 if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
55 return -ENODEV;55 return -ENODEV;
56 56
57 if (device_declaration && (apic->uid == acpi_id)) {57 if (apic->uid == acpi_id && (device_declaration || acpi_id < 255)) {
58 *apic_id = apic->local_apic_id;58 *apic_id = apic->local_apic_id;
59 return 0;59 return 0;
60 }60 }
drivers/acpi/processor_idle.c+16−26
@@ -732,18 +732,16 @@ static int __cpuidle acpi_idle_enter_s2idle(struct cpuidle_device *dev, · 731 unmodified lines
732 return 0;732 return 0;
733}733}
734 734
735static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,735static void acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
736 struct cpuidle_device *dev)736 struct cpuidle_device *dev)
737{737{
738 int i, count = ACPI_IDLE_STATE_START;738 int i, count = ACPI_IDLE_STATE_START;
739 struct acpi_processor_cx *cx;739 struct acpi_processor_cx *cx;
740 struct cpuidle_state *state;
741 740
742 if (max_cstate == 0)741 if (max_cstate == 0)
743 max_cstate = 1;742 max_cstate = 1;
744 743
745 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {744 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
746 state = &acpi_idle_driver.states[count];
747 cx = &pr->power.states[i];745 cx = &pr->power.states[i];
748 746
749 if (!cx->valid)747 if (!cx->valid)
@@ -751,27 +749,13 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, · 1 unmodified line
751 749
752 per_cpu(acpi_cstate[count], dev->cpu) = cx;750 per_cpu(acpi_cstate[count], dev->cpu) = cx;
753 751
754 if (lapic_timer_needs_broadcast(pr, cx))
755 state->flags |= CPUIDLE_FLAG_TIMER_STOP;
756
757 if (cx->type == ACPI_STATE_C3) {
758 state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
759 if (pr->flags.bm_check)
760 state->flags |= CPUIDLE_FLAG_RCU_IDLE;
761 }
762
763 count++;752 count++;
764 if (count == CPUIDLE_STATE_MAX)753 if (count == CPUIDLE_STATE_MAX)
765 break;754 break;
766 }755 }
767
768 if (!count)
769 return -EINVAL;
770
771 return 0;
772}756}
773 757
774static int acpi_processor_setup_cstates(struct acpi_processor *pr)758static void acpi_processor_setup_cstates(struct acpi_processor *pr)
775{759{
776 int i, count;760 int i, count;
777 struct acpi_processor_cx *cx;761 struct acpi_processor_cx *cx;
@@ -818,17 +802,21 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) · 40 unmodified lines
818 if (cx->type != ACPI_STATE_C1 && !acpi_idle_fallback_to_c1(pr))802 if (cx->type != ACPI_STATE_C1 && !acpi_idle_fallback_to_c1(pr))
819 state->enter_s2idle = acpi_idle_enter_s2idle;803 state->enter_s2idle = acpi_idle_enter_s2idle;
820 804
805 if (lapic_timer_needs_broadcast(pr, cx))
806 state->flags |= CPUIDLE_FLAG_TIMER_STOP;
807
808 if (cx->type == ACPI_STATE_C3) {
809 state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
810 if (pr->flags.bm_check)
811 state->flags |= CPUIDLE_FLAG_RCU_IDLE;
812 }
813
821 count++;814 count++;
822 if (count == CPUIDLE_STATE_MAX)815 if (count == CPUIDLE_STATE_MAX)
823 break;816 break;
824 }817 }
825 818
826 drv->state_count = count;819 drv->state_count = count;
827
828 if (!count)
829 return -EINVAL;
830
831 return 0;
832}820}
833 821
834static inline void acpi_processor_cstate_first_run_checks(void)822static inline void acpi_processor_cstate_first_run_checks(void)
@@ -1243,7 +1231,8 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) · 408 unmodified lines
1243 if (pr->flags.has_lpi)1231 if (pr->flags.has_lpi)
1244 return acpi_processor_setup_lpi_states(pr);1232 return acpi_processor_setup_lpi_states(pr);
1245 1233
1246 return acpi_processor_setup_cstates(pr);1234 acpi_processor_setup_cstates(pr);
1235 return 0;
1247}1236}
1248 1237
1249/**1238/**
@@ -1263,7 +1252,8 @@ static int acpi_processor_setup_cpuidle_dev(struct acpi_processor *pr, · 13 unmodified lines
1263 if (pr->flags.has_lpi)1252 if (pr->flags.has_lpi)
1264 return acpi_processor_ffh_lpi_probe(pr->id);1253 return acpi_processor_ffh_lpi_probe(pr->id);
1265 1254
1266 return acpi_processor_setup_cpuidle_cx(pr, dev);1255 acpi_processor_setup_cpuidle_cx(pr, dev);
1256 return 0;
1267}1257}
1268 1258
1269static int acpi_processor_get_power_info(struct acpi_processor *pr)1259static int acpi_processor_get_power_info(struct acpi_processor *pr)
drivers/acpi/property.c+17−12
@@ -1280,7 +1280,7 @@ static int acpi_data_prop_read(const struct acpi_device_data *data, · 1279 unmodified lines
1280 ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);1280 ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);
1281 break;1281 break;
1282 case DEV_PROP_STRING:1282 case DEV_PROP_STRING:
1283 nval = min_t(u32, nval, obj->package.count);1283 nval = min(nval, obj->package.count);
1284 if (nval == 0)1284 if (nval == 0)
1285 return -ENODATA;1285 return -ENODATA;
1286 1286
@@ -1329,13 +1329,14 @@ static int stop_on_next(struct acpi_device *adev, void *data) · 42 unmodified lines
1329 return 0;1329 return 0;
1330}1330}
1331 1331
1332/**1332/*
1333 * acpi_get_next_subnode - Return the next child node handle for a fwnode1333 * acpi_get_next_subnode - Return the next child node handle for a fwnode
1334 * @fwnode: Firmware node to find the next child node for.1334 * @fwnode: Firmware node to find the next child node for.
1335 * @child: Handle to one of the device's child nodes or a null handle.1335 * @child: Handle to one of the device's child nodes or a null handle.
1336 */1336 */
1337struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,1337static struct fwnode_handle *
1338 struct fwnode_handle *child)1338acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1339 struct fwnode_handle *child)
1339{1340{
1340 struct acpi_device *adev = to_acpi_device_node(fwnode);1341 struct acpi_device *adev = to_acpi_device_node(fwnode);
1341 1342
@@ -1472,7 +1473,7 @@ static struct fwnode_handle *acpi_graph_get_next_endpoint( · 130 unmodified lines
1472 1473
1473 if (!prev) {1474 if (!prev) {
1474 do {1475 do {
1475 port = fwnode_get_next_child_node(fwnode, port);1476 port = acpi_get_next_subnode(fwnode, port);
1476 /*1477 /*
1477 * The names of the port nodes begin with "port@"1478 * The names of the port nodes begin with "port@"
1478 * followed by the number of the port node and they also1479 * followed by the number of the port node and they also
@@ -1490,14 +1491,17 @@ static struct fwnode_handle *acpi_graph_get_next_endpoint( · 11 unmodified lines
1490 if (!port)1491 if (!port)
1491 return NULL;1492 return NULL;
1492 1493
1493 endpoint = fwnode_get_next_child_node(port, prev);1494 do {
1494 while (!endpoint) {1495 endpoint = acpi_get_next_subnode(port, prev);
1495 port = fwnode_get_next_child_node(fwnode, port);1496 if (endpoint)
1496 if (!port)
1497 break;1497 break;
1498 if (is_acpi_graph_node(port, "port"))1498
1499 endpoint = fwnode_get_next_child_node(port, NULL);1499 prev = NULL;
1500 }1500
1501 do {
1502 port = acpi_get_next_subnode(fwnode, port);
1503 } while (port && !is_acpi_graph_node(port, "port"));
1504 } while (port);
1501 1505
1502 /*1506 /*
1503 * The names of the endpoint nodes begin with "endpoint@" followed by1507 * The names of the endpoint nodes begin with "endpoint@" followed by
@@ -1714,6 +1718,7 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, · 210 unmodified lines
1714 if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))1718 if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
1715 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);1719 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
1716 1720
1721 fwnode_handle_put(port_fwnode);
1717 return 0;1722 return 0;
1718}1723}
1719 1724
drivers/acpi/scan.c+1−1
@@ -2397,7 +2397,7 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev) · 2396 unmodified lines
2397 * initial enumeration of devices is complete, put it into the unbound2397 * initial enumeration of devices is complete, put it into the unbound
2398 * workqueue.2398 * workqueue.
2399 */2399 */
2400 queue_work(system_unbound_wq, &cdw->work);2400 queue_work(system_dfl_wq, &cdw->work);
2401 2401
2402 return true;2402 return true;
2403}2403}
drivers/acpi/sleep.c+1−1
@@ -642,7 +642,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) · 641 unmodified lines
642 /*642 /*
643 * Disable all GPE and clear their status bits before interrupts are643 * Disable all GPE and clear their status bits before interrupts are
644 * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can644 * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can
645 * prevent them from producing spurious interrups.645 * prevent them from producing spurious interrupts.
646 *646 *
647 * acpi_leave_sleep_state() will reenable specific GPEs later.647 * acpi_leave_sleep_state() will reenable specific GPEs later.
648 *648 *
drivers/acpi/sleep.h+0−3
@@ -17,10 +17,7 @@ static inline acpi_status acpi_set_waking_vector(u32 wakeup_address) · 16 unmodified lines
17 17
18extern int acpi_s2idle_begin(void);18extern int acpi_s2idle_begin(void);
19extern int acpi_s2idle_prepare(void);19extern int acpi_s2idle_prepare(void);
20extern int acpi_s2idle_prepare_late(void);
21extern void acpi_s2idle_check(void);
22extern bool acpi_s2idle_wake(void);20extern bool acpi_s2idle_wake(void);
23extern void acpi_s2idle_restore_early(void);
24extern void acpi_s2idle_restore(void);21extern void acpi_s2idle_restore(void);
25extern void acpi_s2idle_end(void);22extern void acpi_s2idle_end(void);
26 23
drivers/acpi/thermal.c+2−1
@@ -1060,7 +1060,8 @@ static int __init acpi_thermal_init(void) · 1059 unmodified lines
1060 }1060 }
1061 1061
1062 acpi_thermal_pm_queue = alloc_workqueue("acpi_thermal_pm",1062 acpi_thermal_pm_queue = alloc_workqueue("acpi_thermal_pm",
1063 WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);1063 WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_PERCPU,
1064 0);
1064 if (!acpi_thermal_pm_queue)1065 if (!acpi_thermal_pm_queue)
1065 return -ENODEV;1066 return -ENODEV;
1066 1067
drivers/acpi/x86/lpss.c+1−1
@@ -181,7 +181,7 @@ static void byt_i2c_setup(struct lpss_private_data *pdata) · 180 unmodified lines
181 acpi_status status;181 acpi_status status;
182 u64 uid;182 u64 uid;
183 183
184 /* Expected to always be successfull, but better safe then sorry */184 /* Expected to always be successful, but better safe then sorry */
185 if (!acpi_dev_uid_to_integer(pdata->adev, &uid) && uid) {185 if (!acpi_dev_uid_to_integer(pdata->adev, &uid) && uid) {
186 /* Detect I2C bus shared with PUNIT and ignore its d3 status */186 /* Detect I2C bus shared with PUNIT and ignore its d3 status */
187 status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host);187 status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host);
drivers/acpi/x86/s2idle.c+29−36
@@ -299,34 +299,13 @@ free_acpi_buffer: · 298 unmodified lines
299 ACPI_FREE(out_obj);299 ACPI_FREE(out_obj);
300}300}
301 301
302/**
303 * acpi_get_lps0_constraint - Get the LPS0 constraint for a device.
304 * @adev: Device to get the constraint for.
305 *
306 * The LPS0 constraint is the shallowest (minimum) power state in which the
307 * device can be so as to allow the platform as a whole to achieve additional
308 * energy conservation by utilizing a system-wide low-power state.
309 *
310 * Returns:
311 * - ACPI power state value of the constraint for @adev on success.
312 * - Otherwise, ACPI_STATE_UNKNOWN.
313 */
314int acpi_get_lps0_constraint(struct acpi_device *adev)
315{
316 struct lpi_constraints *entry;
317
318 for_each_lpi_constraint(entry) {
319 if (adev->handle == entry->handle)
320 return entry->min_dstate;
321 }
322
323 return ACPI_STATE_UNKNOWN;
324}
325
326static void lpi_check_constraints(void)302static void lpi_check_constraints(void)
327{303{
328 struct lpi_constraints *entry;304 struct lpi_constraints *entry;
329 305
306 if (IS_ERR_OR_NULL(lpi_constraints_table))
307 return;
308
330 for_each_lpi_constraint(entry) {309 for_each_lpi_constraint(entry) {
331 struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);310 struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);
332 311
@@ -508,11 +487,6 @@ static int lps0_device_attach(struct acpi_device *adev, · 175 unmodified lines
508 487
509 lps0_device_handle = adev->handle;488 lps0_device_handle = adev->handle;
510 489
511 if (acpi_s2idle_vendor_amd())
512 lpi_device_get_constraints_amd();
513 else
514 lpi_device_get_constraints();
515
516 /*490 /*
517 * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set in491 * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set in
518 * the FADT and the default suspend mode was not set from the command492 * the FADT and the default suspend mode was not set from the command
@@ -539,7 +513,26 @@ static struct acpi_scan_handler lps0_handler = { · 20 unmodified lines
539 .attach = lps0_device_attach,513 .attach = lps0_device_attach,
540};514};
541 515
542int acpi_s2idle_prepare_late(void)516static int acpi_s2idle_begin_lps0(void)
517{
518 if (pm_debug_messages_on && !lpi_constraints_table) {
519 if (acpi_s2idle_vendor_amd())
520 lpi_device_get_constraints_amd();
521 else
522 lpi_device_get_constraints();
523
524 /*
525 * Try to retrieve the constraints only once because failures
526 * to do so usually are sticky.
527 */
528 if (!lpi_constraints_table)
529 lpi_constraints_table = ERR_PTR(-ENODATA);
530 }
531
532 return acpi_s2idle_begin();
533}
534
535static int acpi_s2idle_prepare_late_lps0(void)
543{536{
544 struct acpi_s2idle_dev_ops *handler;537 struct acpi_s2idle_dev_ops *handler;
545 538
@@ -585,7 +578,7 @@ int acpi_s2idle_prepare_late(void) · 39 unmodified lines
585 return 0;578 return 0;
586}579}
587 580
588void acpi_s2idle_check(void)581static void acpi_s2idle_check_lps0(void)
589{582{
590 struct acpi_s2idle_dev_ops *handler;583 struct acpi_s2idle_dev_ops *handler;
591 584
@@ -598,7 +591,7 @@ void acpi_s2idle_check(void) · 6 unmodified lines
598 }591 }
599}592}
600 593
601void acpi_s2idle_restore_early(void)594static void acpi_s2idle_restore_early_lps0(void)
602{595{
603 struct acpi_s2idle_dev_ops *handler;596 struct acpi_s2idle_dev_ops *handler;
604 597
@@ -636,12 +629,12 @@ void acpi_s2idle_restore_early(void) · 31 unmodified lines
636}629}
637 630
638static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {631static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
639 .begin = acpi_s2idle_begin,632 .begin = acpi_s2idle_begin_lps0,
640 .prepare = acpi_s2idle_prepare,633 .prepare = acpi_s2idle_prepare,
641 .prepare_late = acpi_s2idle_prepare_late,634 .prepare_late = acpi_s2idle_prepare_late_lps0,
642 .check = acpi_s2idle_check,635 .check = acpi_s2idle_check_lps0,
643 .wake = acpi_s2idle_wake,636 .wake = acpi_s2idle_wake,
644 .restore_early = acpi_s2idle_restore_early,637 .restore_early = acpi_s2idle_restore_early_lps0,
645 .restore = acpi_s2idle_restore,638 .restore = acpi_s2idle_restore,
646 .end = acpi_s2idle_end,639 .end = acpi_s2idle_end,
647};640};
drivers/pnp/driver.c+19−0
@@ -150,6 +150,24 @@ static void pnp_device_shutdown(struct device *dev) · 149 unmodified lines
150 drv->shutdown(pnp_dev);150 drv->shutdown(pnp_dev);
151}151}
152 152
153static int pnp_uevent(const struct device *dev, struct kobj_uevent_env *env)
154{
155 struct pnp_id *pos;
156 const struct pnp_dev *pnp_dev = to_pnp_dev(dev);
157
158 if (!dev)
159 return -ENODEV;
160
161 pos = pnp_dev->id;
162 while (pos) {
163 if (add_uevent_var(env, "MODALIAS=pnp:d%s", pos->id))
164 return -ENOMEM;
165 pos = pos->next;
166 }
167
168 return 0;
169}
170
153static int pnp_bus_match(struct device *dev, const struct device_driver *drv)171static int pnp_bus_match(struct device *dev, const struct device_driver *drv)
154{172{
155 struct pnp_dev *pnp_dev = to_pnp_dev(dev);173 struct pnp_dev *pnp_dev = to_pnp_dev(dev);
@@ -259,6 +277,7 @@ static const struct dev_pm_ops pnp_bus_dev_pm_ops = { · 103 unmodified lines
259const struct bus_type pnp_bus_type = {277const struct bus_type pnp_bus_type = {
260 .name = "pnp",278 .name = "pnp",
261 .match = pnp_bus_match,279 .match = pnp_bus_match,
280 .uevent = pnp_uevent,
262 .probe = pnp_device_probe,281 .probe = pnp_device_probe,
263 .remove = pnp_device_remove,282 .remove = pnp_device_remove,
264 .shutdown = pnp_device_shutdown,283 .shutdown = pnp_device_shutdown,
include/linux/acpi.h+0−15
@@ -1157,12 +1157,7 @@ struct acpi_s2idle_dev_ops { · 1156 unmodified lines
1157#if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)1157#if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)
1158int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);1158int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
1159void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);1159void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
1160int acpi_get_lps0_constraint(struct acpi_device *adev);
1161#else /* CONFIG_SUSPEND && CONFIG_X86 */1160#else /* CONFIG_SUSPEND && CONFIG_X86 */
1162static inline int acpi_get_lps0_constraint(struct device *dev)
1163{
1164 return ACPI_STATE_UNKNOWN;
1165}
1166static inline int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)1161static inline int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
1167{1162{
1168 return -ENODEV;1163 return -ENODEV;
@@ -1360,9 +1355,6 @@ acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid, · 191 unmodified lines
1360int acpi_node_prop_get(const struct fwnode_handle *fwnode, const char *propname,1355int acpi_node_prop_get(const struct fwnode_handle *fwnode, const char *propname,
1361 void **valptr);1356 void **valptr);
1362 1357
1363struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1364 struct fwnode_handle *child);
1365
1366struct acpi_probe_entry;1358struct acpi_probe_entry;
1367typedef bool (*acpi_probe_entry_validate_subtbl)(struct acpi_subtable_header *,1359typedef bool (*acpi_probe_entry_validate_subtbl)(struct acpi_subtable_header *,
1368 struct acpi_probe_entry *);1360 struct acpi_probe_entry *);
@@ -1461,13 +1453,6 @@ static inline int acpi_node_prop_get(const struct fwnode_handle *fwnode, · 92 unmodified lines
1461 return -ENXIO;1453 return -ENXIO;
1462}1454}
1463 1455
1464static inline struct fwnode_handle *
1465acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1466 struct fwnode_handle *child)
1467{
1468 return NULL;
1469}
1470
1471static inline struct fwnode_handle *1456static inline struct fwnode_handle *
1472acpi_graph_get_next_endpoint(const struct fwnode_handle *fwnode,1457acpi_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
1473 struct fwnode_handle *prev)1458 struct fwnode_handle *prev)
rust/kernel/acpi.rs+1−3
@@ -39,9 +39,7 @@ impl DeviceId { · 38 unmodified lines
39 pub const fn new(id: &'static CStr) -> Self {39 pub const fn new(id: &'static CStr) -> Self {
40 let src = id.to_bytes_with_nul();40 let src = id.to_bytes_with_nul();
41 build_assert!(src.len() <= Self::ACPI_ID_LEN, "ID exceeds 16 bytes");41 build_assert!(src.len() <= Self::ACPI_ID_LEN, "ID exceeds 16 bytes");
42 // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`.42 let mut acpi: bindings::acpi_device_id = pin_init::zeroed();
43 // SAFETY: FFI type is valid to be zero-initialized.
44 let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() };
45 let mut i = 0;43 let mut i = 0;
46 while i < src.len() {44 while i < src.len() {
47 acpi.id[i] = src[i];45 acpi.id[i] = src[i];
tools/power/acpi/tools/pfrut/pfrut.c+5−2
@@ -222,6 +222,7 @@ int main(int argc, char *argv[]) · 221 unmodified lines
222 fd_update_log = open("/dev/acpi_pfr_telemetry0", O_RDWR);222 fd_update_log = open("/dev/acpi_pfr_telemetry0", O_RDWR);
223 if (fd_update_log < 0) {223 if (fd_update_log < 0) {
224 printf("PFRT device not supported - Quit...\n");224 printf("PFRT device not supported - Quit...\n");
225 close(fd_update);
225 return 1;226 return 1;
226 }227 }
227 228
@@ -265,7 +266,8 @@ int main(int argc, char *argv[]) · 37 unmodified lines
265 printf("chunk2_size:%d\n", data_info.chunk2_size);266 printf("chunk2_size:%d\n", data_info.chunk2_size);
266 printf("rollover_cnt:%d\n", data_info.rollover_cnt);267 printf("rollover_cnt:%d\n", data_info.rollover_cnt);
267 printf("reset_cnt:%d\n", data_info.reset_cnt);268 printf("reset_cnt:%d\n", data_info.reset_cnt);
268 269 close(fd_update);
270 close(fd_update_log);
269 return 0;271 return 0;
270 }272 }
271 273
@@ -358,6 +360,7 @@ int main(int argc, char *argv[]) · 86 unmodified lines
358 360
359 if (ret == -1) {361 if (ret == -1) {
360 perror("Failed to load capsule file");362 perror("Failed to load capsule file");
363 munmap(addr_map_capsule, st.st_size);
361 close(fd_capsule);364 close(fd_capsule);
362 close(fd_update);365 close(fd_update);
363 close(fd_update_log);366 close(fd_update_log);
@@ -420,7 +423,7 @@ int main(int argc, char *argv[]) · 56 unmodified lines
420 if (p_mmap == MAP_FAILED) {423 if (p_mmap == MAP_FAILED) {
421 perror("mmap error.");424 perror("mmap error.");
422 close(fd_update_log);425 close(fd_update_log);
423 426 free(log_buf);
424 return 1;427 return 1;
425 }428 }
426 429