Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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()
...

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