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

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

Pull ACPI updates from Rafael Wysocki:
"From the new functionality perspective, the most significant items
here are the new driver for the 'ARM Generic Diagnostic Dump and
Reset' device, the extension of fine grain fan control in the ACPI fan
driver, and the change making it possible to use CPPC information to
obtain CPU capacity.

There are also a few new quirks, a bunch of fixes, including the
platform-level _OSC handling change to make it actually take the
platform firmware response into account, some code and documentation
cleanups, and a notable update of the ACPI device enumeration
documentation.

Specifics:

- Use uintptr_t and offsetof() in the ACPICA code to avoid compiler
warnings regarding NULL pointer arithmetic (Rafael Wysocki).

- Fix possible NULL pointer dereference in acpi_ns_walk_namespace()
when passed "acpi=off" in the command line (Rafael Wysocki).

- Fix and clean up acpi_os_read/write_port() (Rafael Wysocki).

- Introduce acpi_bus_for_each_dev() and use it for walking all ACPI
device objects in the Type C code (Rafael Wysocki).

- Fix the _OSC platform capabilities negotioation and prevent CPPC
from being used if the platform firmware indicates that it not
supported via _OSC (Rafael Wysocki).

- Use ida_alloc() instead of ida_simple_get() for ACPI enumeration of
devices (Rafael Wysocki).

- Add AGDI and CEDT to the list of known ACPI table signatures (Ilkka
Koskinen, Robert Kiraly).

- Add power management debug messages related to suspend-to-idle in
two places (Rafael Wysocki).

- Fix __acpi_node_get_property_reference() return value and clean up
that function (Andy Shevchenko, Sakari Ailus).

- Fix return value of the __setup handler in the ACPI PM timer clock
source driver (Randy Dunlap).

- Clean up double words in two comments (Tom Rix).

- Add "skip i2c clients" quirks for Lenovo Yoga Tablet 1050F/L and
Nextbook Ares 8 (Hans de Goede).

- Clean up frequency invariance handling on x86 in the ACPI CPPC
library (Huang Rui).

- Work around broken XSDT on the Advantech DAC-BJ01 board (Mark
Cilissen).

- Make wakeup events checks in the ACPI EC driver more
straightforward and clean up acpi_ec_submit_event() (Rafael
Wysocki).

- Make it possible to obtain the CPU capacity with the help of CPPC
information (Ionela Voinescu).

- Improve fine grained fan control in the ACPI fan driver and
document it (Srinivas Pandruvada).

- Add device HID and quirk for Microsoft Surface Go 3 to the ACPI
battery driver (Maximilian Luz).

- Make the ACPI driver for Intel SoCs (LPSS) let the SPI driver know
the exact type of the controller (Andy Shevchenko).

- Force native backlight mode on Clevo NL5xRU and NL5xNU (Werner
Sembach).

- Fix return value of __setup handlers in the APEI code (Randy
Dunlap).

- Add Arm Generic Diagnostic Dump and Reset device driver (Ilkka
Koskinen).

- Limit printable size of BERT table data (Darren Hart).

- Fix up HEST and GHES initialization (Shuai Xue).

- Update the ACPI device enumeration documentation and unify the ASL
style in GPIO-related examples (Andy Shevchenko)"

* tag 'acpi-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (52 commits)
clocksource: acpi_pm: fix return value of __setup handler
ACPI: bus: Avoid using CPPC if not supported by firmware
Revert "ACPI: Pass the same capabilities to the _OSC regardless of the query flag"
ACPI: video: Force backlight native for Clevo NL5xRU and NL5xNU
arm64, topology: enable use of init_cpu_capacity_cppc()
arch_topology: obtain cpu capacity using information from CPPC
x86, ACPI: rename init_freq_invariance_cppc() to arch_init_invariance_cppc()
ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device
ACPI: tables: Add AGDI to the list of known table signatures
ACPI/APEI: Limit printable size of BERT table data
ACPI: docs: gpio-properties: Unify ASL style for GPIO examples
ACPI / x86: Work around broken XSDT on Advantech DAC-BJ01 board
ACPI: APEI: fix return value of __setup handlers
x86/ACPI: CPPC: Move init_freq_invariance_cppc() into x86 CPPC
x86: Expose init_freq_invariance() to topology header
x86/ACPI: CPPC: Move AMD maximum frequency ratio setting function into x86 CPPC
x86/ACPI: CPPC: Rename cppc_msr.c to cppc.c
ACPI / x86: Add skip i2c clients quirk for Lenovo Yoga Tablet 1050F/L
ACPI / x86: Add skip i2c clients quirk for Nextbook Ares 8
ACPICA: Avoid walking the ACPI Namespace if it is not there
...

+1008 -460
+28
Documentation/admin-guide/acpi/fan_performance_states.rst
··· 60 60 61 61 When a given field is not populated or its value provided by the platform 62 62 firmware is invalid, the "not-defined" string is shown instead of the value. 63 + 64 + ACPI Fan Fine Grain Control 65 + ============================= 66 + 67 + When _FIF object specifies support for fine grain control, then fan speed 68 + can be set from 0 to 100% with the recommended minimum "step size" via 69 + _FSL object. User can adjust fan speed using thermal sysfs cooling device. 70 + 71 + Here use can look at fan performance states for a reference speed (speed_rpm) 72 + and set it by changing cooling device cur_state. If the fine grain control 73 + is supported then user can also adjust to some other speeds which are 74 + not defined in the performance states. 75 + 76 + The support of fine grain control is presented via sysfs attribute 77 + "fine_grain_control". If fine grain control is present, this attribute 78 + will show "1" otherwise "0". 79 + 80 + This sysfs attribute is presented in the same directory as performance states. 81 + 82 + ACPI Fan Performance Feedback 83 + ============================= 84 + 85 + The optional _FST object provides status information for the fan device. 86 + This includes field to provide current fan speed in revolutions per minute 87 + at which the fan is rotating. 88 + 89 + This speed is presented in the sysfs using the attribute "fan_speed_rpm", 90 + in the same directory as performance states.
+9 -12
Documentation/driver-api/gpio/board.rst
··· 71 71 72 72 Device (FOO) { 73 73 Name (_CRS, ResourceTemplate () { 74 - GpioIo (Exclusive, ..., IoRestrictionOutputOnly, 75 - "\\_SB.GPI0") {15} // red 76 - GpioIo (Exclusive, ..., IoRestrictionOutputOnly, 77 - "\\_SB.GPI0") {16} // green 78 - GpioIo (Exclusive, ..., IoRestrictionOutputOnly, 79 - "\\_SB.GPI0") {17} // blue 80 - GpioIo (Exclusive, ..., IoRestrictionOutputOnly, 81 - "\\_SB.GPI0") {1} // power 74 + GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly, 75 + "\\_SB.GPI0", 0, ResourceConsumer) { 15 } // red 76 + GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly, 77 + "\\_SB.GPI0", 0, ResourceConsumer) { 16 } // green 78 + GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly, 79 + "\\_SB.GPI0", 0, ResourceConsumer) { 17 } // blue 80 + GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly, 81 + "\\_SB.GPI0", 0, ResourceConsumer) { 1 } // power 82 82 }) 83 83 84 84 Name (_DSD, Package () { ··· 92 92 ^FOO, 2, 0, 1, 93 93 } 94 94 }, 95 - Package () { 96 - "power-gpios", 97 - Package () {^FOO, 3, 0, 0}, 98 - }, 95 + Package () { "power-gpios", Package () { ^FOO, 3, 0, 0 } }, 99 96 } 100 97 }) 101 98 }
+44 -67
Documentation/firmware-guide/acpi/enumeration.rst
··· 19 19 platform devices. 20 20 21 21 - Devices behind real busses where there is a connector resource 22 - are represented as struct spi_device or struct i2c_device 23 - (standard UARTs are not busses so there is no struct uart_device). 22 + are represented as struct spi_device or struct i2c_device. Note 23 + that standard UARTs are not busses so there is no struct uart_device, 24 + although some of them may be represented by sturct serdev_device. 24 25 25 26 As both ACPI and Device Tree represent a tree of devices (and their 26 27 resources) this implementation follows the Device Tree way as much as 27 28 possible. 28 29 29 - The ACPI implementation enumerates devices behind busses (platform, SPI and 30 - I2C), creates the physical devices and binds them to their ACPI handle in 31 - the ACPI namespace. 30 + The ACPI implementation enumerates devices behind busses (platform, SPI, 31 + I2C, and in some cases UART), creates the physical devices and binds them 32 + to their ACPI handle in the ACPI namespace. 32 33 33 34 This means that when ACPI_HANDLE(dev) returns non-NULL the device was 34 35 enumerated from ACPI namespace. This handle can be used to extract other ··· 47 46 Adding ACPI support for an existing driver should be pretty 48 47 straightforward. Here is the simplest example:: 49 48 50 - #ifdef CONFIG_ACPI 51 49 static const struct acpi_device_id mydrv_acpi_match[] = { 52 50 /* ACPI IDs here */ 53 51 { } 54 52 }; 55 53 MODULE_DEVICE_TABLE(acpi, mydrv_acpi_match); 56 - #endif 57 54 58 55 static struct platform_driver my_driver = { 59 56 ... 60 57 .driver = { 61 - .acpi_match_table = ACPI_PTR(mydrv_acpi_match), 58 + .acpi_match_table = mydrv_acpi_match, 62 59 }, 63 60 }; 64 61 ··· 154 155 Device (EEP0) 155 156 { 156 157 Name (_ADR, 1) 157 - Name (_CID, Package() { 158 + Name (_CID, Package () { 158 159 "ATML0025", 159 160 "AT25", 160 161 }) ··· 171 172 the platform device drivers. Below is an example where we add ACPI support 172 173 to at25 SPI eeprom driver (this is meant for the above ACPI snippet):: 173 174 174 - #ifdef CONFIG_ACPI 175 175 static const struct acpi_device_id at25_acpi_match[] = { 176 176 { "AT25", 0 }, 177 - { }, 177 + { } 178 178 }; 179 179 MODULE_DEVICE_TABLE(acpi, at25_acpi_match); 180 - #endif 181 180 182 181 static struct spi_driver at25_driver = { 183 182 .driver = { 184 183 ... 185 - .acpi_match_table = ACPI_PTR(at25_acpi_match), 184 + .acpi_match_table = at25_acpi_match, 186 185 }, 187 186 }; 188 187 189 188 Note that this driver actually needs more information like page size of the 190 - eeprom etc. but at the time writing this there is no standard way of 191 - passing those. One idea is to return this in _DSM method like:: 189 + eeprom, etc. This information can be passed via _DSD method like:: 192 190 193 191 Device (EEP0) 194 192 { 195 193 ... 196 - Method (_DSM, 4, NotSerialized) 194 + Name (_DSD, Package () 197 195 { 198 - Store (Package (6) 196 + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 197 + Package () 199 198 { 200 - "byte-len", 1024, 201 - "addr-mode", 2, 202 - "page-size, 32 203 - }, Local0) 199 + Package () { "size", 1024 }, 200 + Package () { "pagesize", 32 }, 201 + Package () { "address-width", 16 }, 202 + } 203 + }) 204 + } 204 205 205 - // Check UUIDs etc. 206 + Then the at25 SPI driver can get this configuration by calling device property 207 + APIs during ->probe() phase like:: 206 208 207 - Return (Local0) 208 - } 209 + err = device_property_read_u32(dev, "size", &size); 210 + if (err) 211 + ...error handling... 209 212 210 - Then the at25 SPI driver can get this configuration by calling _DSM on its 211 - ACPI handle like:: 213 + err = device_property_read_u32(dev, "pagesize", &page_size); 214 + if (err) 215 + ...error handling... 212 216 213 - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 214 - struct acpi_object_list input; 215 - acpi_status status; 216 - 217 - /* Fill in the input buffer */ 218 - 219 - status = acpi_evaluate_object(ACPI_HANDLE(&spi->dev), "_DSM", 220 - &input, &output); 221 - if (ACPI_FAILURE(status)) 222 - /* Handle the error */ 223 - 224 - /* Extract the data here */ 225 - 226 - kfree(output.pointer); 217 + err = device_property_read_u32(dev, "address-width", &addr_width); 218 + if (err) 219 + ...error handling... 227 220 228 221 I2C serial bus support 229 222 ====================== ··· 228 237 Below is an example of how to add ACPI support to the existing mpu3050 229 238 input driver:: 230 239 231 - #ifdef CONFIG_ACPI 232 240 static const struct acpi_device_id mpu3050_acpi_match[] = { 233 241 { "MPU3050", 0 }, 234 - { }, 242 + { } 235 243 }; 236 244 MODULE_DEVICE_TABLE(acpi, mpu3050_acpi_match); 237 - #endif 238 245 239 246 static struct i2c_driver mpu3050_i2c_driver = { 240 247 .driver = { 241 248 .name = "mpu3050", 242 - .owner = THIS_MODULE, 243 249 .pm = &mpu3050_pm, 244 250 .of_match_table = mpu3050_of_match, 245 - .acpi_match_table = ACPI_PTR(mpu3050_acpi_match), 251 + .acpi_match_table = mpu3050_acpi_match, 246 252 }, 247 253 .probe = mpu3050_probe, 248 254 .remove = mpu3050_remove, 249 255 .id_table = mpu3050_ids, 250 256 }; 257 + module_i2c_driver(mpu3050_i2c_driver); 251 258 252 259 Reference to PWM device 253 260 ======================= ··· 271 282 } 272 283 } 273 284 } 274 - 275 285 }) 276 286 ... 287 + } 277 288 278 289 In the above example the PWM-based LED driver references to the PWM channel 0 279 290 of \_SB.PCI0.PWM device with initial period setting equal to 600 ms (note that ··· 295 306 { 296 307 Name (SBUF, ResourceTemplate() 297 308 { 298 - ... 299 309 // Used to power on/off the device 300 - GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, 301 - IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0", 302 - 0x00, ResourceConsumer,,) 303 - { 304 - // Pin List 305 - 0x0055 306 - } 310 + GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly, 311 + "\\_SB.PCI0.GPI0", 0, ResourceConsumer) { 85 } 307 312 308 313 // Interrupt for the device 309 - GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone, 310 - 0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer,,) 311 - { 312 - // Pin list 313 - 0x0058 314 - } 315 - 316 - ... 317 - 314 + GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone, 0, 315 + "\\_SB.PCI0.GPI0", 0, ResourceConsumer) { 88 } 318 316 } 319 317 320 318 Return (SBUF) ··· 313 337 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 314 338 Package () 315 339 { 316 - Package () {"power-gpios", Package() {^DEV, 0, 0, 0 }}, 317 - Package () {"irq-gpios", Package() {^DEV, 1, 0, 0 }}, 340 + Package () { "power-gpios", Package () { ^DEV, 0, 0, 0 } }, 341 + Package () { "irq-gpios", Package () { ^DEV, 1, 0, 0 } }, 318 342 } 319 343 }) 320 344 ... 345 + } 321 346 322 347 These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0" 323 348 specifies the path to the controller. In order to use these GPIOs in Linux ··· 437 460 Device (TMP0) 438 461 { 439 462 Name (_HID, "PRP0001") 440 - Name (_DSD, Package() { 463 + Name (_DSD, Package () { 441 464 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 442 465 Package () { 443 - Package (2) { "compatible", "ti,tmp75" }, 466 + Package () { "compatible", "ti,tmp75" }, 444 467 } 445 468 }) 446 469 Method (_CRS, 0, Serialized)
+14 -12
Documentation/firmware-guide/acpi/gpio-properties.rst
··· 21 21 Name (_CRS, ResourceTemplate () 22 22 { 23 23 GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly, 24 - "\\_SB.GPO0", 0, ResourceConsumer) {15} 24 + "\\_SB.GPO0", 0, ResourceConsumer) { 15 } 25 25 GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly, 26 - "\\_SB.GPO0", 0, ResourceConsumer) {27, 31} 26 + "\\_SB.GPO0", 0, ResourceConsumer) { 27, 31 } 27 27 }) 28 28 29 29 Name (_DSD, Package () 30 30 { 31 31 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 32 32 Package () 33 - { 34 - Package () {"reset-gpios", Package() {^BTH, 1, 1, 0 }}, 35 - Package () {"shutdown-gpios", Package() {^BTH, 0, 0, 0 }}, 33 + { 34 + Package () { "reset-gpios", Package () { ^BTH, 1, 1, 0 } }, 35 + Package () { "shutdown-gpios", Package () { ^BTH, 0, 0, 0 } }, 36 36 } 37 37 }) 38 38 } ··· 123 123 // _DSD Hierarchical Properties Extension UUID 124 124 ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), 125 125 Package () { 126 - Package () {"hog-gpio8", "G8PU"} 126 + Package () { "hog-gpio8", "G8PU" } 127 127 } 128 128 }) 129 129 130 130 Name (G8PU, Package () { 131 131 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 132 132 Package () { 133 - Package () {"gpio-hog", 1}, 134 - Package () {"gpios", Package () {8, 0}}, 135 - Package () {"output-high", 1}, 136 - Package () {"line-name", "gpio8-pullup"}, 133 + Package () { "gpio-hog", 1 }, 134 + Package () { "gpios", Package () { 8, 0 } }, 135 + Package () { "output-high", 1 }, 136 + Package () { "line-name", "gpio8-pullup" }, 137 137 } 138 138 }) 139 139 ··· 266 266 267 267 Name (_CRS, ResourceTemplate () { 268 268 GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone, 269 - "\\_SB.GPO0", 0, ResourceConsumer) {15} 269 + "\\_SB.GPO0", 0, ResourceConsumer) { 15 } 270 270 GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone, 271 - "\\_SB.GPO0", 0, ResourceConsumer) {27} 271 + "\\_SB.GPO0", 0, ResourceConsumer) { 27 } 272 272 }) 273 273 } 274 274 275 275 The driver might expect to get the right GPIO when it does:: 276 276 277 277 desc = gpiod_get(dev, "reset", GPIOD_OUT_LOW); 278 + if (IS_ERR(desc)) 279 + ...error handling... 278 280 279 281 but since there is no way to know the mapping between "reset" and 280 282 the GpioIo() in _CRS desc will hold ERR_PTR(-ENOENT).
+4
arch/arm64/include/asm/topology.h
··· 24 24 #define arch_scale_freq_capacity topology_get_freq_scale 25 25 #define arch_scale_freq_invariant topology_scale_freq_invariant 26 26 27 + #ifdef CONFIG_ACPI_CPPC_LIB 28 + #define arch_init_invariance_cppc topology_init_cpu_capacity_cppc 29 + #endif 30 + 27 31 /* Replace task scheduler's default cpu-invariant accounting */ 28 32 #define arch_scale_cpu_capacity topology_get_cpu_scale 29 33
+13 -2
arch/x86/include/asm/topology.h
··· 216 216 #define arch_scale_freq_tick arch_scale_freq_tick 217 217 218 218 extern void arch_set_max_freq_ratio(bool turbo_disabled); 219 + void init_freq_invariance(bool secondary, bool cppc_ready); 219 220 #else 220 221 static inline void arch_set_max_freq_ratio(bool turbo_disabled) 221 222 { 222 223 } 224 + static inline void init_freq_invariance(bool secondary, bool cppc_ready) 225 + { 226 + } 223 227 #endif 224 228 225 - #if defined(CONFIG_ACPI_CPPC_LIB) && defined(CONFIG_SMP) 229 + #ifdef CONFIG_ACPI_CPPC_LIB 226 230 void init_freq_invariance_cppc(void); 227 - #define init_freq_invariance_cppc init_freq_invariance_cppc 231 + #define arch_init_invariance_cppc init_freq_invariance_cppc 232 + 233 + bool amd_set_max_freq_ratio(u64 *ratio); 234 + #else 235 + static inline bool amd_set_max_freq_ratio(u64 *ratio) 236 + { 237 + return false; 238 + } 228 239 #endif 229 240 230 241 #endif /* _ASM_X86_TOPOLOGY_H */
+1 -1
arch/x86/kernel/acpi/Makefile
··· 3 3 obj-$(CONFIG_ACPI) += boot.o 4 4 obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o 5 5 obj-$(CONFIG_ACPI_APEI) += apei.o 6 - obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_msr.o 6 + obj-$(CONFIG_ACPI_CPPC_LIB) += cppc.o 7 7 8 8 ifneq ($(CONFIG_ACPI_PROCESSOR),) 9 9 obj-y += cstate.o
+24
arch/x86/kernel/acpi/boot.c
··· 1328 1328 return 0; 1329 1329 } 1330 1330 1331 + static int __init disable_acpi_xsdt(const struct dmi_system_id *d) 1332 + { 1333 + if (!acpi_force) { 1334 + pr_notice("%s detected: force use of acpi=rsdt\n", d->ident); 1335 + acpi_gbl_do_not_use_xsdt = TRUE; 1336 + } else { 1337 + pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n"); 1338 + } 1339 + return 0; 1340 + } 1341 + 1331 1342 static int __init dmi_disable_acpi(const struct dmi_system_id *d) 1332 1343 { 1333 1344 if (!acpi_force) { ··· 1460 1449 .matches = { 1461 1450 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1462 1451 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), 1452 + }, 1453 + }, 1454 + /* 1455 + * Boxes that need ACPI XSDT use disabled due to corrupted tables 1456 + */ 1457 + { 1458 + .callback = disable_acpi_xsdt, 1459 + .ident = "Advantech DAC-BJ01", 1460 + .matches = { 1461 + DMI_MATCH(DMI_SYS_VENDOR, "NEC"), 1462 + DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"), 1463 + DMI_MATCH(DMI_BIOS_VERSION, "V1.12"), 1464 + DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"), 1463 1465 }, 1464 1466 }, 1465 1467 {}
+103
arch/x86/kernel/acpi/cppc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * cppc.c: CPPC Interface for x86 4 + * Copyright (c) 2016, Intel Corporation. 5 + */ 6 + 7 + #include <acpi/cppc_acpi.h> 8 + #include <asm/msr.h> 9 + #include <asm/processor.h> 10 + #include <asm/topology.h> 11 + 12 + /* Refer to drivers/acpi/cppc_acpi.c for the description of functions */ 13 + 14 + bool cpc_ffh_supported(void) 15 + { 16 + return true; 17 + } 18 + 19 + int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val) 20 + { 21 + int err; 22 + 23 + err = rdmsrl_safe_on_cpu(cpunum, reg->address, val); 24 + if (!err) { 25 + u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, 26 + reg->bit_offset); 27 + 28 + *val &= mask; 29 + *val >>= reg->bit_offset; 30 + } 31 + return err; 32 + } 33 + 34 + int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val) 35 + { 36 + u64 rd_val; 37 + int err; 38 + 39 + err = rdmsrl_safe_on_cpu(cpunum, reg->address, &rd_val); 40 + if (!err) { 41 + u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, 42 + reg->bit_offset); 43 + 44 + val <<= reg->bit_offset; 45 + val &= mask; 46 + rd_val &= ~mask; 47 + rd_val |= val; 48 + err = wrmsrl_safe_on_cpu(cpunum, reg->address, rd_val); 49 + } 50 + return err; 51 + } 52 + 53 + bool amd_set_max_freq_ratio(u64 *ratio) 54 + { 55 + struct cppc_perf_caps perf_caps; 56 + u64 highest_perf, nominal_perf; 57 + u64 perf_ratio; 58 + int rc; 59 + 60 + if (!ratio) 61 + return false; 62 + 63 + rc = cppc_get_perf_caps(0, &perf_caps); 64 + if (rc) { 65 + pr_debug("Could not retrieve perf counters (%d)\n", rc); 66 + return false; 67 + } 68 + 69 + highest_perf = amd_get_highest_perf(); 70 + nominal_perf = perf_caps.nominal_perf; 71 + 72 + if (!highest_perf || !nominal_perf) { 73 + pr_debug("Could not retrieve highest or nominal performance\n"); 74 + return false; 75 + } 76 + 77 + perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf); 78 + /* midpoint between max_boost and max_P */ 79 + perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1; 80 + if (!perf_ratio) { 81 + pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n"); 82 + return false; 83 + } 84 + 85 + *ratio = perf_ratio; 86 + arch_set_max_freq_ratio(false); 87 + 88 + return true; 89 + } 90 + 91 + static DEFINE_MUTEX(freq_invariance_lock); 92 + 93 + void init_freq_invariance_cppc(void) 94 + { 95 + static bool secondary; 96 + 97 + mutex_lock(&freq_invariance_lock); 98 + 99 + init_freq_invariance(secondary, true); 100 + secondary = true; 101 + 102 + mutex_unlock(&freq_invariance_lock); 103 + }
-49
arch/x86/kernel/acpi/cppc_msr.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * cppc_msr.c: MSR Interface for CPPC 4 - * Copyright (c) 2016, Intel Corporation. 5 - */ 6 - 7 - #include <acpi/cppc_acpi.h> 8 - #include <asm/msr.h> 9 - 10 - /* Refer to drivers/acpi/cppc_acpi.c for the description of functions */ 11 - 12 - bool cpc_ffh_supported(void) 13 - { 14 - return true; 15 - } 16 - 17 - int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val) 18 - { 19 - int err; 20 - 21 - err = rdmsrl_safe_on_cpu(cpunum, reg->address, val); 22 - if (!err) { 23 - u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, 24 - reg->bit_offset); 25 - 26 - *val &= mask; 27 - *val >>= reg->bit_offset; 28 - } 29 - return err; 30 - } 31 - 32 - int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val) 33 - { 34 - u64 rd_val; 35 - int err; 36 - 37 - err = rdmsrl_safe_on_cpu(cpunum, reg->address, &rd_val); 38 - if (!err) { 39 - u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, 40 - reg->bit_offset); 41 - 42 - val <<= reg->bit_offset; 43 - val &= mask; 44 - rd_val &= ~mask; 45 - rd_val |= val; 46 - err = wrmsrl_safe_on_cpu(cpunum, reg->address, rd_val); 47 - } 48 - return err; 49 - }
+2 -70
arch/x86/kernel/smpboot.c
··· 83 83 #include <asm/hw_irq.h> 84 84 #include <asm/stackprotector.h> 85 85 86 - #ifdef CONFIG_ACPI_CPPC_LIB 87 - #include <acpi/cppc_acpi.h> 88 - #endif 89 - 90 86 /* representing HT siblings of each logical CPU */ 91 87 DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); 92 88 EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); ··· 150 154 151 155 *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; 152 156 } 153 - 154 - static void init_freq_invariance(bool secondary, bool cppc_ready); 155 157 156 158 /* 157 159 * Report back to the Boot Processor during boot time or to the caller processor ··· 2091 2097 return true; 2092 2098 } 2093 2099 2094 - #ifdef CONFIG_ACPI_CPPC_LIB 2095 - static bool amd_set_max_freq_ratio(void) 2096 - { 2097 - struct cppc_perf_caps perf_caps; 2098 - u64 highest_perf, nominal_perf; 2099 - u64 perf_ratio; 2100 - int rc; 2101 - 2102 - rc = cppc_get_perf_caps(0, &perf_caps); 2103 - if (rc) { 2104 - pr_debug("Could not retrieve perf counters (%d)\n", rc); 2105 - return false; 2106 - } 2107 - 2108 - highest_perf = amd_get_highest_perf(); 2109 - nominal_perf = perf_caps.nominal_perf; 2110 - 2111 - if (!highest_perf || !nominal_perf) { 2112 - pr_debug("Could not retrieve highest or nominal performance\n"); 2113 - return false; 2114 - } 2115 - 2116 - perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf); 2117 - /* midpoint between max_boost and max_P */ 2118 - perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1; 2119 - if (!perf_ratio) { 2120 - pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n"); 2121 - return false; 2122 - } 2123 - 2124 - arch_turbo_freq_ratio = perf_ratio; 2125 - arch_set_max_freq_ratio(false); 2126 - 2127 - return true; 2128 - } 2129 - #else 2130 - static bool amd_set_max_freq_ratio(void) 2131 - { 2132 - return false; 2133 - } 2134 - #endif 2135 - 2136 2100 static void init_counter_refs(void) 2137 2101 { 2138 2102 u64 aperf, mperf; ··· 2119 2167 static inline void register_freq_invariance_syscore_ops(void) {} 2120 2168 #endif 2121 2169 2122 - static void init_freq_invariance(bool secondary, bool cppc_ready) 2170 + void init_freq_invariance(bool secondary, bool cppc_ready) 2123 2171 { 2124 2172 bool ret = false; 2125 2173 ··· 2139 2187 if (!cppc_ready) { 2140 2188 return; 2141 2189 } 2142 - ret = amd_set_max_freq_ratio(); 2190 + ret = amd_set_max_freq_ratio(&arch_turbo_freq_ratio); 2143 2191 } 2144 2192 2145 2193 if (ret) { ··· 2151 2199 pr_debug("Couldn't determine max cpu frequency, necessary for scale-invariant accounting.\n"); 2152 2200 } 2153 2201 } 2154 - 2155 - #ifdef CONFIG_ACPI_CPPC_LIB 2156 - static DEFINE_MUTEX(freq_invariance_lock); 2157 - 2158 - void init_freq_invariance_cppc(void) 2159 - { 2160 - static bool secondary; 2161 - 2162 - mutex_lock(&freq_invariance_lock); 2163 - 2164 - init_freq_invariance(secondary, true); 2165 - secondary = true; 2166 - 2167 - mutex_unlock(&freq_invariance_lock); 2168 - } 2169 - #endif 2170 2202 2171 2203 static void disable_freq_invariance_workfn(struct work_struct *work) 2172 2204 { ··· 2199 2263 error: 2200 2264 pr_warn("Scheduler frequency invariance went wobbly, disabling!\n"); 2201 2265 schedule_work(&disable_freq_invariance_work); 2202 - } 2203 - #else 2204 - static inline void init_freq_invariance(bool secondary, bool cppc_ready) 2205 - { 2206 2266 } 2207 2267 #endif /* CONFIG_X86_64 */
+1 -1
drivers/acpi/Kconfig
··· 302 302 help 303 303 This driver enables the ACPI to access the BMC controller. And it 304 304 uses the IPMI request/response message to communicate with BMC 305 - controller, which can be found on on the server. 305 + controller, which can be found on the server. 306 306 307 307 To compile this driver as a module, choose M here: 308 308 the module will be called as acpi_ipmi.
+3
drivers/acpi/Makefile
··· 81 81 obj-$(CONFIG_ACPI_BUTTON) += button.o 82 82 obj-$(CONFIG_ACPI_TINY_POWER_BUTTON) += tiny-power-button.o 83 83 obj-$(CONFIG_ACPI_FAN) += fan.o 84 + fan-objs := fan_core.o 85 + fan-objs += fan_attr.o 86 + 84 87 obj-$(CONFIG_ACPI_VIDEO) += video.o 85 88 obj-$(CONFIG_ACPI_TAD) += acpi_tad.o 86 89 obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
+26 -7
drivers/acpi/acpi_lpss.c
··· 21 21 #include <linux/pm_domain.h> 22 22 #include <linux/pm_runtime.h> 23 23 #include <linux/pwm.h> 24 + #include <linux/pxa2xx_ssp.h> 24 25 #include <linux/suspend.h> 25 26 #include <linux/delay.h> 26 27 ··· 83 82 const char *clk_con_id; 84 83 unsigned int prv_offset; 85 84 size_t prv_size_override; 86 - struct property_entry *properties; 85 + const struct property_entry *properties; 87 86 void (*setup)(struct lpss_private_data *pdata); 88 87 bool resume_from_noirq; 89 88 }; ··· 220 219 pwm_add_table(bsw_pwm_lookup, ARRAY_SIZE(bsw_pwm_lookup)); 221 220 } 222 221 223 - static const struct lpss_device_desc lpt_dev_desc = { 222 + static const struct property_entry lpt_spi_properties[] = { 223 + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_LPT_SSP), 224 + { } 225 + }; 226 + 227 + static const struct lpss_device_desc lpt_spi_dev_desc = { 224 228 .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR 225 229 | LPSS_SAVE_CTX, 226 230 .prv_offset = 0x800, 231 + .properties = lpt_spi_properties, 227 232 }; 228 233 229 234 static const struct lpss_device_desc lpt_i2c_dev_desc = { ··· 289 282 .properties = uart_properties, 290 283 }; 291 284 285 + static const struct property_entry byt_spi_properties[] = { 286 + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BYT_SSP), 287 + { } 288 + }; 289 + 292 290 static const struct lpss_device_desc byt_spi_dev_desc = { 293 291 .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, 294 292 .prv_offset = 0x400, 293 + .properties = byt_spi_properties, 295 294 }; 296 295 297 296 static const struct lpss_device_desc byt_sdio_dev_desc = { ··· 318 305 .resume_from_noirq = true, 319 306 }; 320 307 308 + static const struct property_entry bsw_spi_properties[] = { 309 + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP), 310 + { } 311 + }; 312 + 321 313 static const struct lpss_device_desc bsw_spi_dev_desc = { 322 314 .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX 323 315 | LPSS_NO_D3_DELAY, 324 316 .prv_offset = 0x400, 325 317 .setup = lpss_deassert_reset, 318 + .properties = bsw_spi_properties, 326 319 }; 327 320 328 321 static const struct x86_cpu_id lpss_cpu_ids[] = { ··· 348 329 { "INTL9C60", LPSS_ADDR(lpss_dma_desc) }, 349 330 350 331 /* Lynxpoint LPSS devices */ 351 - { "INT33C0", LPSS_ADDR(lpt_dev_desc) }, 352 - { "INT33C1", LPSS_ADDR(lpt_dev_desc) }, 332 + { "INT33C0", LPSS_ADDR(lpt_spi_dev_desc) }, 333 + { "INT33C1", LPSS_ADDR(lpt_spi_dev_desc) }, 353 334 { "INT33C2", LPSS_ADDR(lpt_i2c_dev_desc) }, 354 335 { "INT33C3", LPSS_ADDR(lpt_i2c_dev_desc) }, 355 336 { "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) }, ··· 375 356 { "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) }, 376 357 377 358 /* Broadwell LPSS devices */ 378 - { "INT3430", LPSS_ADDR(lpt_dev_desc) }, 379 - { "INT3431", LPSS_ADDR(lpt_dev_desc) }, 359 + { "INT3430", LPSS_ADDR(lpt_spi_dev_desc) }, 360 + { "INT3431", LPSS_ADDR(lpt_spi_dev_desc) }, 380 361 { "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) }, 381 362 { "INT3433", LPSS_ADDR(lpt_i2c_dev_desc) }, 382 363 { "INT3434", LPSS_ADDR(lpt_uart_dev_desc) }, ··· 385 366 { "INT3437", }, 386 367 387 368 /* Wildcat Point LPSS devices */ 388 - { "INT3438", LPSS_ADDR(lpt_dev_desc) }, 369 + { "INT3438", LPSS_ADDR(lpt_spi_dev_desc) }, 389 370 390 371 { } 391 372 };
+1 -1
drivers/acpi/acpi_platform.c
··· 95 95 * Name of the platform device will be the same as @adev's. 96 96 */ 97 97 struct platform_device *acpi_create_platform_device(struct acpi_device *adev, 98 - struct property_entry *properties) 98 + const struct property_entry *properties) 99 99 { 100 100 struct platform_device *pdev = NULL; 101 101 struct platform_device_info pdevinfo;
+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 175 } 173 176 174 177 /* Null child means "get first node" */
+7 -3
drivers/acpi/apei/bert.c
··· 29 29 30 30 #undef pr_fmt 31 31 #define pr_fmt(fmt) "BERT: " fmt 32 + #define ACPI_BERT_PRINT_MAX_LEN 1024 32 33 33 34 static int bert_disable; 34 35 ··· 59 58 } 60 59 61 60 pr_info_once("Error records from previous boot:\n"); 62 - 63 - cper_estatus_print(KERN_INFO HW_ERR, estatus); 61 + if (region_len < ACPI_BERT_PRINT_MAX_LEN) 62 + cper_estatus_print(KERN_INFO HW_ERR, estatus); 63 + else 64 + pr_info_once("Max print length exceeded, table data is available at:\n" 65 + "/sys/firmware/acpi/tables/data/BERT"); 64 66 65 67 /* 66 68 * Because the boot error source is "one-time polled" type, ··· 81 77 { 82 78 bert_disable = 1; 83 79 84 - return 0; 80 + return 1; 85 81 } 86 82 __setup("bert_disable", setup_bert_disable); 87 83
+1 -1
drivers/acpi/apei/erst.c
··· 891 891 static int __init setup_erst_disable(char *str) 892 892 { 893 893 erst_disable = 1; 894 - return 0; 894 + return 1; 895 895 } 896 896 897 897 __setup("erst_disable", setup_erst_disable);
+8 -11
drivers/acpi/apei/ghes.c
··· 1457 1457 .remove = ghes_remove, 1458 1458 }; 1459 1459 1460 - static int __init ghes_init(void) 1460 + void __init acpi_ghes_init(void) 1461 1461 { 1462 1462 int rc; 1463 1463 1464 + sdei_init(); 1465 + 1464 1466 if (acpi_disabled) 1465 - return -ENODEV; 1467 + return; 1466 1468 1467 1469 switch (hest_disable) { 1468 1470 case HEST_NOT_FOUND: 1469 - return -ENODEV; 1471 + return; 1470 1472 case HEST_DISABLED: 1471 1473 pr_info(GHES_PFX "HEST is not enabled!\n"); 1472 - return -EINVAL; 1474 + return; 1473 1475 default: 1474 1476 break; 1475 1477 } 1476 1478 1477 1479 if (ghes_disable) { 1478 1480 pr_info(GHES_PFX "GHES is not enabled!\n"); 1479 - return -EINVAL; 1481 + return; 1480 1482 } 1481 1483 1482 1484 ghes_nmi_init_cxt(); 1483 1485 1484 1486 rc = platform_driver_register(&ghes_platform_driver); 1485 1487 if (rc) 1486 - goto err; 1488 + return; 1487 1489 1488 1490 rc = apei_osc_setup(); 1489 1491 if (rc == 0 && osc_sb_apei_support_acked) ··· 1496 1494 pr_info(GHES_PFX "APEI firmware first mode is enabled by APEI bit.\n"); 1497 1495 else 1498 1496 pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n"); 1499 - 1500 - return 0; 1501 - err: 1502 - return rc; 1503 1497 } 1504 - device_initcall(ghes_init);
+1 -1
drivers/acpi/apei/hest.c
··· 224 224 static int __init setup_hest_disable(char *str) 225 225 { 226 226 hest_disable = HEST_DISABLED; 227 - return 0; 227 + return 1; 228 228 } 229 229 230 230 __setup("hest_disable", setup_hest_disable);
+10
drivers/acpi/arm64/Kconfig
··· 8 8 9 9 config ACPI_GTDT 10 10 bool 11 + 12 + config ACPI_AGDI 13 + bool "Arm Generic Diagnostic Dump and Reset Device Interface" 14 + depends on ARM_SDE_INTERFACE 15 + help 16 + Arm Generic Diagnostic Dump and Reset Device Interface (AGDI) is 17 + a standard that enables issuing a non-maskable diagnostic dump and 18 + reset command. 19 + 20 + If set, the kernel parses AGDI table and listens for the command.
+1
drivers/acpi/arm64/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 + obj-$(CONFIG_ACPI_AGDI) += agdi.o 2 3 obj-$(CONFIG_ACPI_IORT) += iort.o 3 4 obj-$(CONFIG_ACPI_GTDT) += gtdt.o 4 5 obj-y += dma.o
+116
drivers/acpi/arm64/agdi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * This file implements handling of 4 + * Arm Generic Diagnostic Dump and Reset Interface table (AGDI) 5 + * 6 + * Copyright (c) 2022, Ampere Computing LLC 7 + */ 8 + 9 + #define pr_fmt(fmt) "ACPI: AGDI: " fmt 10 + 11 + #include <linux/acpi.h> 12 + #include <linux/arm_sdei.h> 13 + #include <linux/io.h> 14 + #include <linux/kernel.h> 15 + #include <linux/platform_device.h> 16 + 17 + struct agdi_data { 18 + int sdei_event; 19 + }; 20 + 21 + static int agdi_sdei_handler(u32 sdei_event, struct pt_regs *regs, void *arg) 22 + { 23 + nmi_panic(regs, "Arm Generic Diagnostic Dump and Reset SDEI event issued"); 24 + return 0; 25 + } 26 + 27 + static int agdi_sdei_probe(struct platform_device *pdev, 28 + struct agdi_data *adata) 29 + { 30 + int err; 31 + 32 + err = sdei_event_register(adata->sdei_event, agdi_sdei_handler, pdev); 33 + if (err) { 34 + dev_err(&pdev->dev, "Failed to register for SDEI event %d", 35 + adata->sdei_event); 36 + return err; 37 + } 38 + 39 + err = sdei_event_enable(adata->sdei_event); 40 + if (err) { 41 + sdei_event_unregister(adata->sdei_event); 42 + dev_err(&pdev->dev, "Failed to enable event %d\n", 43 + adata->sdei_event); 44 + return err; 45 + } 46 + 47 + return 0; 48 + } 49 + 50 + static int agdi_probe(struct platform_device *pdev) 51 + { 52 + struct agdi_data *adata = dev_get_platdata(&pdev->dev); 53 + 54 + if (!adata) 55 + return -EINVAL; 56 + 57 + return agdi_sdei_probe(pdev, adata); 58 + } 59 + 60 + static int agdi_remove(struct platform_device *pdev) 61 + { 62 + struct agdi_data *adata = dev_get_platdata(&pdev->dev); 63 + int err, i; 64 + 65 + err = sdei_event_disable(adata->sdei_event); 66 + if (err) 67 + return err; 68 + 69 + for (i = 0; i < 3; i++) { 70 + err = sdei_event_unregister(adata->sdei_event); 71 + if (err != -EINPROGRESS) 72 + break; 73 + 74 + schedule(); 75 + } 76 + 77 + return err; 78 + } 79 + 80 + static struct platform_driver agdi_driver = { 81 + .driver = { 82 + .name = "agdi", 83 + }, 84 + .probe = agdi_probe, 85 + .remove = agdi_remove, 86 + }; 87 + 88 + void __init acpi_agdi_init(void) 89 + { 90 + struct acpi_table_agdi *agdi_table; 91 + struct agdi_data pdata; 92 + struct platform_device *pdev; 93 + acpi_status status; 94 + 95 + status = acpi_get_table(ACPI_SIG_AGDI, 0, 96 + (struct acpi_table_header **) &agdi_table); 97 + if (ACPI_FAILURE(status)) 98 + return; 99 + 100 + if (agdi_table->flags & ACPI_AGDI_SIGNALING_MODE) { 101 + pr_warn("Interrupt signaling is not supported"); 102 + goto err_put_table; 103 + } 104 + 105 + pdata.sdei_event = agdi_table->sdei_event; 106 + 107 + pdev = platform_device_register_data(NULL, "agdi", 0, &pdata, sizeof(pdata)); 108 + if (IS_ERR(pdev)) 109 + goto err_put_table; 110 + 111 + if (platform_driver_register(&agdi_driver)) 112 + platform_device_unregister(pdev); 113 + 114 + err_put_table: 115 + acpi_put_table((struct acpi_table_header *)agdi_table); 116 + }
+12
drivers/acpi/battery.c
··· 59 59 60 60 static const struct acpi_device_id battery_device_ids[] = { 61 61 {"PNP0C0A", 0}, 62 + 63 + /* Microsoft Surface Go 3 */ 64 + {"MSHW0146", 0}, 65 + 62 66 {"", 0}, 63 67 }; 64 68 ··· 1150 1146 .matches = { 1151 1147 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1152 1148 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"), 1149 + }, 1150 + }, 1151 + { 1152 + /* Microsoft Surface Go 3 */ 1153 + .callback = battery_notification_delay_quirk, 1154 + .matches = { 1155 + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), 1156 + DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), 1153 1157 }, 1154 1158 }, 1155 1159 {},
+37 -9
drivers/acpi/bus.c
··· 26 26 #include <asm/mpspec.h> 27 27 #include <linux/dmi.h> 28 28 #endif 29 + #include <linux/acpi_agdi.h> 29 30 #include <linux/acpi_iort.h> 30 31 #include <linux/acpi_viot.h> 31 32 #include <linux/pci.h> ··· 284 283 bool osc_sb_native_usb4_support_confirmed; 285 284 EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed); 286 285 286 + bool osc_sb_cppc_not_supported; 287 + 287 288 static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; 288 289 static void acpi_bus_osc_negotiate_platform_control(void) 289 290 { ··· 335 332 if (ACPI_FAILURE(acpi_run_osc(handle, &context))) 336 333 return; 337 334 338 - kfree(context.ret.pointer); 335 + capbuf_ret = context.ret.pointer; 336 + if (context.ret.length <= OSC_SUPPORT_DWORD) { 337 + kfree(context.ret.pointer); 338 + return; 339 + } 339 340 340 - /* Now run _OSC again with query flag clear */ 341 + #ifdef CONFIG_X86 342 + if (boot_cpu_has(X86_FEATURE_HWP)) 343 + osc_sb_cppc_not_supported = !(capbuf_ret[OSC_SUPPORT_DWORD] & 344 + (OSC_SB_CPC_SUPPORT | OSC_SB_CPCV2_SUPPORT)); 345 + #endif 346 + 347 + /* 348 + * Now run _OSC again with query flag clear and with the caps 349 + * supported by both the OS and the platform. 350 + */ 341 351 capbuf[OSC_QUERY_DWORD] = 0; 352 + capbuf[OSC_SUPPORT_DWORD] = capbuf_ret[OSC_SUPPORT_DWORD]; 353 + kfree(context.ret.pointer); 342 354 343 355 if (ACPI_FAILURE(acpi_run_osc(handle, &context))) 344 356 return; 345 357 346 358 capbuf_ret = context.ret.pointer; 347 - osc_sb_apei_support_acked = 348 - capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; 349 - osc_pc_lpi_support_confirmed = 350 - capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT; 351 - osc_sb_native_usb4_support_confirmed = 352 - capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT; 359 + if (context.ret.length > OSC_SUPPORT_DWORD) { 360 + osc_sb_apei_support_acked = 361 + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; 362 + osc_pc_lpi_support_confirmed = 363 + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT; 364 + osc_sb_native_usb4_support_confirmed = 365 + capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT; 366 + } 353 367 354 368 kfree(context.ret.pointer); 355 369 } ··· 1063 1043 .remove = acpi_device_remove, 1064 1044 .uevent = acpi_device_uevent, 1065 1045 }; 1066 - EXPORT_SYMBOL_GPL(acpi_bus_type); 1046 + 1047 + int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data) 1048 + { 1049 + return bus_for_each_dev(&acpi_bus_type, NULL, data, fn); 1050 + } 1051 + EXPORT_SYMBOL_GPL(acpi_bus_for_each_dev); 1067 1052 1068 1053 /* -------------------------------------------------------------------------- 1069 1054 Initialization/Cleanup ··· 1356 1331 1357 1332 pci_mmcfg_late_init(); 1358 1333 acpi_iort_init(); 1334 + acpi_hest_init(); 1335 + acpi_ghes_init(); 1359 1336 acpi_scan_init(); 1360 1337 acpi_ec_init(); 1361 1338 acpi_debugfs_init(); ··· 1366 1339 acpi_debugger_init(); 1367 1340 acpi_setup_sb_notify_handler(); 1368 1341 acpi_viot_init(); 1342 + acpi_agdi_init(); 1369 1343 return 0; 1370 1344 } 1371 1345
+6 -3
drivers/acpi/cppc_acpi.c
··· 633 633 * ) 634 634 */ 635 635 636 - #ifndef init_freq_invariance_cppc 637 - static inline void init_freq_invariance_cppc(void) { } 636 + #ifndef arch_init_invariance_cppc 637 + static inline void arch_init_invariance_cppc(void) { } 638 638 #endif 639 639 640 640 /** ··· 655 655 int pcc_subspace_id = -1; 656 656 acpi_status status; 657 657 int ret = -EFAULT; 658 + 659 + if (osc_sb_cppc_not_supported) 660 + return -ENODEV; 658 661 659 662 /* Parse the ACPI _CPC table for this CPU. */ 660 663 status = acpi_evaluate_object_typed(handle, "_CPC", NULL, &output, ··· 819 816 goto out_free; 820 817 } 821 818 822 - init_freq_invariance_cppc(); 819 + arch_init_invariance_cppc(); 823 820 824 821 kfree(output.pointer); 825 822 return 0;
+49 -41
drivers/acpi/ec.c
··· 168 168 }; 169 169 170 170 static int acpi_ec_submit_query(struct acpi_ec *ec); 171 - static bool advance_transaction(struct acpi_ec *ec, bool interrupt); 171 + static void advance_transaction(struct acpi_ec *ec, bool interrupt); 172 172 static void acpi_ec_event_handler(struct work_struct *work); 173 173 174 174 struct acpi_ec *first_ec; ··· 441 441 return true; 442 442 } 443 443 444 - static bool acpi_ec_submit_event(struct acpi_ec *ec) 444 + static void acpi_ec_submit_event(struct acpi_ec *ec) 445 445 { 446 + /* 447 + * It is safe to mask the events here, because acpi_ec_close_event() 448 + * will run at least once after this. 449 + */ 446 450 acpi_ec_mask_events(ec); 447 451 if (!acpi_ec_event_enabled(ec)) 448 - return false; 452 + return; 449 453 450 - if (ec->event_state == EC_EVENT_READY) { 451 - ec_dbg_evt("Command(%s) submitted/blocked", 452 - acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); 454 + if (ec->event_state != EC_EVENT_READY) 455 + return; 453 456 454 - ec->event_state = EC_EVENT_IN_PROGRESS; 455 - /* 456 - * If events_to_process is greqter than 0 at this point, the 457 - * while () loop in acpi_ec_event_handler() is still running 458 - * and incrementing events_to_process will cause it to invoke 459 - * acpi_ec_submit_query() once more, so it is not necessary to 460 - * queue up the event work to start the same loop again. 461 - */ 462 - if (ec->events_to_process++ > 0) 463 - return true; 457 + ec_dbg_evt("Command(%s) submitted/blocked", 458 + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); 464 459 465 - ec->events_in_progress++; 466 - return queue_work(ec_wq, &ec->work); 467 - } 468 - 460 + ec->event_state = EC_EVENT_IN_PROGRESS; 469 461 /* 470 - * The event handling work has not been completed yet, so it needs to be 471 - * flushed. 462 + * If events_to_process is greater than 0 at this point, the while () 463 + * loop in acpi_ec_event_handler() is still running and incrementing 464 + * events_to_process will cause it to invoke acpi_ec_submit_query() once 465 + * more, so it is not necessary to queue up the event work to start the 466 + * same loop again. 472 467 */ 473 - return true; 468 + if (ec->events_to_process++ > 0) 469 + return; 470 + 471 + ec->events_in_progress++; 472 + queue_work(ec_wq, &ec->work); 474 473 } 475 474 476 475 static void acpi_ec_complete_event(struct acpi_ec *ec) ··· 654 655 acpi_ec_mask_events(ec); 655 656 } 656 657 657 - static bool advance_transaction(struct acpi_ec *ec, bool interrupt) 658 + static void advance_transaction(struct acpi_ec *ec, bool interrupt) 658 659 { 659 660 struct transaction *t = ec->curr; 660 661 bool wakeup = false; 661 - bool ret = false; 662 662 u8 status; 663 663 664 664 ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id()); ··· 722 724 723 725 out: 724 726 if (status & ACPI_EC_FLAG_SCI) 725 - ret = acpi_ec_submit_event(ec); 727 + acpi_ec_submit_event(ec); 726 728 727 729 if (wakeup && interrupt) 728 730 wake_up(&ec->wait); 729 - 730 - return ret; 731 731 } 732 732 733 733 static void start_transaction(struct acpi_ec *ec) ··· 1238 1242 acpi_ec_submit_query(ec); 1239 1243 1240 1244 spin_lock_irq(&ec->lock); 1245 + 1241 1246 ec->events_to_process--; 1242 1247 } 1243 1248 ··· 1247 1250 * event handling work again regardless of whether or not the query 1248 1251 * queued up above is processed successfully. 1249 1252 */ 1250 - if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) 1253 + if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) { 1254 + bool guard_timeout; 1255 + 1251 1256 acpi_ec_complete_event(ec); 1252 - else 1253 - acpi_ec_close_event(ec); 1254 1257 1255 - spin_unlock_irq(&ec->lock); 1258 + ec_dbg_evt("Event stopped"); 1256 1259 1257 - ec_dbg_evt("Event stopped"); 1260 + spin_unlock_irq(&ec->lock); 1258 1261 1259 - if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && ec_guard(ec)) { 1262 + guard_timeout = !!ec_guard(ec); 1263 + 1260 1264 spin_lock_irq(&ec->lock); 1261 1265 1262 1266 /* Take care of SCI_EVT unless someone else is doing that. */ 1263 - if (!ec->curr) 1267 + if (guard_timeout && !ec->curr) 1264 1268 advance_transaction(ec, false); 1269 + } else { 1270 + acpi_ec_close_event(ec); 1265 1271 1266 - spin_unlock_irq(&ec->lock); 1272 + ec_dbg_evt("Event stopped"); 1267 1273 } 1268 1274 1269 - spin_lock_irq(&ec->lock); 1270 1275 ec->events_in_progress--; 1276 + 1271 1277 spin_unlock_irq(&ec->lock); 1272 1278 } 1273 1279 ··· 2051 2051 acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); 2052 2052 } 2053 2053 2054 + static bool acpi_ec_work_in_progress(struct acpi_ec *ec) 2055 + { 2056 + return ec->events_in_progress + ec->queries_in_progress > 0; 2057 + } 2058 + 2054 2059 bool acpi_ec_dispatch_gpe(void) 2055 2060 { 2056 2061 bool work_in_progress = false; ··· 2086 2081 */ 2087 2082 spin_lock_irq(&first_ec->lock); 2088 2083 2089 - if (acpi_ec_gpe_status_set(first_ec)) 2090 - work_in_progress = advance_transaction(first_ec, false); 2084 + if (acpi_ec_gpe_status_set(first_ec)) { 2085 + pm_pr_dbg("ACPI EC GPE status set\n"); 2086 + 2087 + advance_transaction(first_ec, false); 2088 + work_in_progress = acpi_ec_work_in_progress(first_ec); 2089 + } 2091 2090 2092 2091 spin_unlock_irq(&first_ec->lock); 2093 2092 ··· 2108 2099 2109 2100 spin_lock_irq(&first_ec->lock); 2110 2101 2111 - work_in_progress = first_ec->events_in_progress + 2112 - first_ec->queries_in_progress > 0; 2102 + work_in_progress = acpi_ec_work_in_progress(first_ec); 2113 2103 2114 2104 spin_unlock_irq(&first_ec->lock); 2115 2105 } while (work_in_progress && !pm_wakeup_pending());
+87 -119
drivers/acpi/fan.c drivers/acpi/fan_core.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * acpi_fan.c - ACPI Fan Driver ($Revision: 29 $) 3 + * fan_core.c - ACPI Fan core Driver 4 4 * 5 5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 6 6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 7 + * Copyright (C) 2022 Intel Corporation. All rights reserved. 7 8 */ 8 9 9 10 #include <linux/kernel.h> ··· 46 45 #define FAN_PM_OPS_PTR NULL 47 46 #endif 48 47 49 - #define ACPI_FPS_NAME_LEN 20 50 - 51 - struct acpi_fan_fps { 52 - u64 control; 53 - u64 trip_point; 54 - u64 speed; 55 - u64 noise_level; 56 - u64 power; 57 - char name[ACPI_FPS_NAME_LEN]; 58 - struct device_attribute dev_attr; 59 - }; 60 - 61 - struct acpi_fan_fif { 62 - u64 revision; 63 - u64 fine_grain_ctrl; 64 - u64 step_size; 65 - u64 low_speed_notification; 66 - }; 67 - 68 - struct acpi_fan { 69 - bool acpi4; 70 - struct acpi_fan_fif fif; 71 - struct acpi_fan_fps *fps; 72 - int fps_count; 73 - struct thermal_cooling_device *cdev; 74 - }; 75 - 76 48 static struct platform_driver acpi_fan_driver = { 77 49 .probe = acpi_fan_probe, 78 50 .remove = acpi_fan_remove, ··· 63 89 struct acpi_device *device = cdev->devdata; 64 90 struct acpi_fan *fan = acpi_driver_data(device); 65 91 66 - if (fan->acpi4) 67 - *state = fan->fps_count - 1; 68 - else 92 + if (fan->acpi4) { 93 + if (fan->fif.fine_grain_ctrl) 94 + *state = 100 / fan->fif.step_size; 95 + else 96 + *state = fan->fps_count - 1; 97 + } else { 69 98 *state = 1; 99 + } 100 + 70 101 return 0; 71 102 } 72 103 73 - static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state) 104 + int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst) 74 105 { 75 106 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 76 - struct acpi_fan *fan = acpi_driver_data(device); 77 107 union acpi_object *obj; 78 108 acpi_status status; 79 - int control, i; 109 + int ret = 0; 80 110 81 111 status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer); 82 112 if (ACPI_FAILURE(status)) { 83 113 dev_err(&device->dev, "Get fan state failed\n"); 84 - return status; 114 + return -ENODEV; 85 115 } 86 116 87 117 obj = buffer.pointer; ··· 93 115 obj->package.count != 3 || 94 116 obj->package.elements[1].type != ACPI_TYPE_INTEGER) { 95 117 dev_err(&device->dev, "Invalid _FST data\n"); 96 - status = -EINVAL; 118 + ret = -EINVAL; 97 119 goto err; 98 120 } 99 121 100 - control = obj->package.elements[1].integer.value; 101 - for (i = 0; i < fan->fps_count; i++) { 102 - /* 103 - * When Fine Grain Control is set, return the state 104 - * corresponding to maximum fan->fps[i].control 105 - * value compared to the current speed. Here the 106 - * fan->fps[] is sorted array with increasing speed. 107 - */ 108 - if (fan->fif.fine_grain_ctrl && control < fan->fps[i].control) { 109 - i = (i > 0) ? i - 1 : 0; 110 - break; 111 - } else if (control == fan->fps[i].control) { 112 - break; 122 + fst->revision = obj->package.elements[0].integer.value; 123 + fst->control = obj->package.elements[1].integer.value; 124 + fst->speed = obj->package.elements[2].integer.value; 125 + 126 + err: 127 + kfree(obj); 128 + return ret; 129 + } 130 + 131 + static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state) 132 + { 133 + struct acpi_fan *fan = acpi_driver_data(device); 134 + struct acpi_fan_fst fst; 135 + int status, i; 136 + 137 + status = acpi_fan_get_fst(device, &fst); 138 + if (status) 139 + return status; 140 + 141 + if (fan->fif.fine_grain_ctrl) { 142 + /* This control should be same what we set using _FSL by spec */ 143 + if (fst.control > 100) { 144 + dev_dbg(&device->dev, "Invalid control value returned\n"); 145 + goto match_fps; 113 146 } 147 + 148 + *state = (int) fst.control / fan->fif.step_size; 149 + return 0; 150 + } 151 + 152 + match_fps: 153 + for (i = 0; i < fan->fps_count; i++) { 154 + if (fst.control == fan->fps[i].control) 155 + break; 114 156 } 115 157 if (i == fan->fps_count) { 116 158 dev_dbg(&device->dev, "Invalid control value returned\n"); 117 - status = -EINVAL; 118 - goto err; 159 + return -EINVAL; 119 160 } 120 161 121 162 *state = i; 122 163 123 - err: 124 - kfree(obj); 125 164 return status; 126 165 } 127 166 ··· 182 187 { 183 188 struct acpi_fan *fan = acpi_driver_data(device); 184 189 acpi_status status; 190 + u64 value = state; 191 + int max_state; 185 192 186 - if (state >= fan->fps_count) 193 + if (fan->fif.fine_grain_ctrl) 194 + max_state = 100 / fan->fif.step_size; 195 + else 196 + max_state = fan->fps_count - 1; 197 + 198 + if (state > max_state) 187 199 return -EINVAL; 188 200 189 - status = acpi_execute_simple_method(device->handle, "_FSL", 190 - fan->fps[state].control); 201 + if (fan->fif.fine_grain_ctrl) { 202 + value *= fan->fif.step_size; 203 + /* Spec allows compensate the last step only */ 204 + if (value + fan->fif.step_size > 100) 205 + value = 100; 206 + } else { 207 + value = fan->fps[state].control; 208 + } 209 + 210 + status = acpi_execute_simple_method(device->handle, "_FSL", value); 191 211 if (ACPI_FAILURE(status)) { 192 212 dev_dbg(&device->dev, "Failed to set state by _FSL\n"); 193 - return status; 213 + return -ENODEV; 194 214 } 195 215 196 216 return 0; ··· 247 237 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 248 238 struct acpi_fan *fan = acpi_driver_data(device); 249 239 struct acpi_buffer format = { sizeof("NNNN"), "NNNN" }; 250 - struct acpi_buffer fif = { sizeof(fan->fif), &fan->fif }; 240 + u64 fields[4]; 241 + struct acpi_buffer fif = { sizeof(fields), fields }; 251 242 union acpi_object *obj; 252 243 acpi_status status; 253 244 ··· 269 258 status = -EINVAL; 270 259 } 271 260 261 + fan->fif.revision = fields[0]; 262 + fan->fif.fine_grain_ctrl = fields[1]; 263 + fan->fif.step_size = fields[2]; 264 + fan->fif.low_speed_notification = fields[3]; 265 + 266 + /* If there is a bug in step size and set as 0, change to 1 */ 267 + if (!fan->fif.step_size) 268 + fan->fif.step_size = 1; 269 + /* If step size > 9, change to 9 (by spec valid values 1-9) */ 270 + else if (fan->fif.step_size > 9) 271 + fan->fif.step_size = 9; 272 272 err: 273 273 kfree(obj); 274 274 return status; ··· 290 268 const struct acpi_fan_fps *fps1 = a; 291 269 const struct acpi_fan_fps *fps2 = b; 292 270 return fps1->speed - fps2->speed; 293 - } 294 - 295 - static ssize_t show_state(struct device *dev, struct device_attribute *attr, char *buf) 296 - { 297 - struct acpi_fan_fps *fps = container_of(attr, struct acpi_fan_fps, dev_attr); 298 - int count; 299 - 300 - if (fps->control == 0xFFFFFFFF || fps->control > 100) 301 - count = scnprintf(buf, PAGE_SIZE, "not-defined:"); 302 - else 303 - count = scnprintf(buf, PAGE_SIZE, "%lld:", fps->control); 304 - 305 - if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9) 306 - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); 307 - else 308 - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->trip_point); 309 - 310 - if (fps->speed == 0xFFFFFFFF) 311 - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); 312 - else 313 - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->speed); 314 - 315 - if (fps->noise_level == 0xFFFFFFFF) 316 - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); 317 - else 318 - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->noise_level * 100); 319 - 320 - if (fps->power == 0xFFFFFFFF) 321 - count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined\n"); 322 - else 323 - count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld\n", fps->power); 324 - 325 - return count; 326 271 } 327 272 328 273 static int acpi_fan_get_fps(struct acpi_device *device) ··· 336 347 sort(fan->fps, fan->fps_count, sizeof(*fan->fps), 337 348 acpi_fan_speed_cmp, NULL); 338 349 339 - for (i = 0; i < fan->fps_count; ++i) { 340 - struct acpi_fan_fps *fps = &fan->fps[i]; 341 - 342 - snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i); 343 - sysfs_attr_init(&fps->dev_attr.attr); 344 - fps->dev_attr.show = show_state; 345 - fps->dev_attr.store = NULL; 346 - fps->dev_attr.attr.name = fps->name; 347 - fps->dev_attr.attr.mode = 0444; 348 - status = sysfs_create_file(&device->dev.kobj, &fps->dev_attr.attr); 349 - if (status) { 350 - int j; 351 - 352 - for (j = 0; j < i; ++j) 353 - sysfs_remove_file(&device->dev.kobj, &fan->fps[j].dev_attr.attr); 354 - break; 355 - } 356 - } 357 - 358 350 err: 359 351 kfree(obj); 360 352 return status; ··· 363 393 return result; 364 394 365 395 result = acpi_fan_get_fps(device); 396 + if (result) 397 + return result; 398 + 399 + result = acpi_fan_create_attributes(device); 366 400 if (result) 367 401 return result; 368 402 ··· 411 437 return 0; 412 438 413 439 err_end: 414 - if (fan->acpi4) { 415 - int i; 416 - 417 - for (i = 0; i < fan->fps_count; ++i) 418 - sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr); 419 - } 440 + if (fan->acpi4) 441 + acpi_fan_delete_attributes(device); 420 442 421 443 return result; 422 444 } ··· 423 453 424 454 if (fan->acpi4) { 425 455 struct acpi_device *device = ACPI_COMPANION(&pdev->dev); 426 - int i; 427 456 428 - for (i = 0; i < fan->fps_count; ++i) 429 - sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr); 457 + acpi_fan_delete_attributes(device); 430 458 } 431 459 sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling"); 432 460 sysfs_remove_link(&fan->cdev->device.kobj, "device");
+44
drivers/acpi/fan.h
··· 6 6 * 7 7 * Add new device IDs before the generic ACPI fan one. 8 8 */ 9 + 10 + #ifndef _ACPI_FAN_H_ 11 + #define _ACPI_FAN_H_ 12 + 9 13 #define ACPI_FAN_DEVICE_IDS \ 10 14 {"INT3404", }, /* Fan */ \ 11 15 {"INTC1044", }, /* Fan for Tiger Lake generation */ \ 12 16 {"INTC1048", }, /* Fan for Alder Lake generation */ \ 13 17 {"INTC10A2", }, /* Fan for Raptor Lake generation */ \ 14 18 {"PNP0C0B", } /* Generic ACPI fan */ 19 + 20 + #define ACPI_FPS_NAME_LEN 20 21 + 22 + struct acpi_fan_fps { 23 + u64 control; 24 + u64 trip_point; 25 + u64 speed; 26 + u64 noise_level; 27 + u64 power; 28 + char name[ACPI_FPS_NAME_LEN]; 29 + struct device_attribute dev_attr; 30 + }; 31 + 32 + struct acpi_fan_fif { 33 + u8 revision; 34 + u8 fine_grain_ctrl; 35 + u8 step_size; 36 + u8 low_speed_notification; 37 + }; 38 + 39 + struct acpi_fan_fst { 40 + u64 revision; 41 + u64 control; 42 + u64 speed; 43 + }; 44 + 45 + struct acpi_fan { 46 + bool acpi4; 47 + struct acpi_fan_fif fif; 48 + struct acpi_fan_fps *fps; 49 + int fps_count; 50 + struct thermal_cooling_device *cdev; 51 + struct device_attribute fst_speed; 52 + struct device_attribute fine_grain_control; 53 + }; 54 + 55 + int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst); 56 + int acpi_fan_create_attributes(struct acpi_device *device); 57 + void acpi_fan_delete_attributes(struct acpi_device *device); 58 + #endif
+137
drivers/acpi/fan_attr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * fan_attr.c - Create extra attributes for ACPI Fan driver 4 + * 5 + * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 6 + * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 7 + * Copyright (C) 2022 Intel Corporation. All rights reserved. 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/init.h> 13 + #include <linux/acpi.h> 14 + 15 + #include "fan.h" 16 + 17 + MODULE_LICENSE("GPL"); 18 + 19 + static ssize_t show_state(struct device *dev, struct device_attribute *attr, char *buf) 20 + { 21 + struct acpi_fan_fps *fps = container_of(attr, struct acpi_fan_fps, dev_attr); 22 + int count; 23 + 24 + if (fps->control == 0xFFFFFFFF || fps->control > 100) 25 + count = scnprintf(buf, PAGE_SIZE, "not-defined:"); 26 + else 27 + count = scnprintf(buf, PAGE_SIZE, "%lld:", fps->control); 28 + 29 + if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9) 30 + count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); 31 + else 32 + count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->trip_point); 33 + 34 + if (fps->speed == 0xFFFFFFFF) 35 + count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); 36 + else 37 + count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->speed); 38 + 39 + if (fps->noise_level == 0xFFFFFFFF) 40 + count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:"); 41 + else 42 + count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->noise_level * 100); 43 + 44 + if (fps->power == 0xFFFFFFFF) 45 + count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined\n"); 46 + else 47 + count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld\n", fps->power); 48 + 49 + return count; 50 + } 51 + 52 + static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf) 53 + { 54 + struct acpi_device *acpi_dev = container_of(dev, struct acpi_device, dev); 55 + struct acpi_fan_fst fst; 56 + int status; 57 + 58 + status = acpi_fan_get_fst(acpi_dev, &fst); 59 + if (status) 60 + return status; 61 + 62 + return sprintf(buf, "%lld\n", fst.speed); 63 + } 64 + 65 + static ssize_t show_fine_grain_control(struct device *dev, struct device_attribute *attr, char *buf) 66 + { 67 + struct acpi_device *acpi_dev = container_of(dev, struct acpi_device, dev); 68 + struct acpi_fan *fan = acpi_driver_data(acpi_dev); 69 + 70 + return sprintf(buf, "%d\n", fan->fif.fine_grain_ctrl); 71 + } 72 + 73 + int acpi_fan_create_attributes(struct acpi_device *device) 74 + { 75 + struct acpi_fan *fan = acpi_driver_data(device); 76 + int i, status; 77 + 78 + sysfs_attr_init(&fan->fine_grain_control.attr); 79 + fan->fine_grain_control.show = show_fine_grain_control; 80 + fan->fine_grain_control.store = NULL; 81 + fan->fine_grain_control.attr.name = "fine_grain_control"; 82 + fan->fine_grain_control.attr.mode = 0444; 83 + status = sysfs_create_file(&device->dev.kobj, &fan->fine_grain_control.attr); 84 + if (status) 85 + return status; 86 + 87 + /* _FST is present if we are here */ 88 + sysfs_attr_init(&fan->fst_speed.attr); 89 + fan->fst_speed.show = show_fan_speed; 90 + fan->fst_speed.store = NULL; 91 + fan->fst_speed.attr.name = "fan_speed_rpm"; 92 + fan->fst_speed.attr.mode = 0444; 93 + status = sysfs_create_file(&device->dev.kobj, &fan->fst_speed.attr); 94 + if (status) 95 + goto rem_fine_grain_attr; 96 + 97 + for (i = 0; i < fan->fps_count; ++i) { 98 + struct acpi_fan_fps *fps = &fan->fps[i]; 99 + 100 + snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i); 101 + sysfs_attr_init(&fps->dev_attr.attr); 102 + fps->dev_attr.show = show_state; 103 + fps->dev_attr.store = NULL; 104 + fps->dev_attr.attr.name = fps->name; 105 + fps->dev_attr.attr.mode = 0444; 106 + status = sysfs_create_file(&device->dev.kobj, &fps->dev_attr.attr); 107 + if (status) { 108 + int j; 109 + 110 + for (j = 0; j < i; ++j) 111 + sysfs_remove_file(&device->dev.kobj, &fan->fps[j].dev_attr.attr); 112 + goto rem_fst_attr; 113 + } 114 + } 115 + 116 + return 0; 117 + 118 + rem_fst_attr: 119 + sysfs_remove_file(&device->dev.kobj, &fan->fst_speed.attr); 120 + 121 + rem_fine_grain_attr: 122 + sysfs_remove_file(&device->dev.kobj, &fan->fine_grain_control.attr); 123 + 124 + return status; 125 + } 126 + 127 + void acpi_fan_delete_attributes(struct acpi_device *device) 128 + { 129 + struct acpi_fan *fan = acpi_driver_data(device); 130 + int i; 131 + 132 + for (i = 0; i < fan->fps_count; ++i) 133 + sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr); 134 + 135 + sysfs_remove_file(&device->dev.kobj, &fan->fst_speed.attr); 136 + sysfs_remove_file(&device->dev.kobj, &fan->fine_grain_control.attr); 137 + }
-2
drivers/acpi/internal.h
··· 96 96 97 97 extern struct list_head acpi_bus_id_list; 98 98 99 - #define ACPI_MAX_DEVICE_INSTANCES 4096 100 - 101 99 struct acpi_device_bus_id { 102 100 const char *bus_id; 103 101 struct ida instance_ida;
+11 -8
drivers/acpi/osl.c
··· 642 642 (ACPI_100NSEC_PER_SEC / HZ); 643 643 } 644 644 645 - acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) 645 + acpi_status acpi_os_read_port(acpi_io_address port, u32 *value, u32 width) 646 646 { 647 647 u32 dummy; 648 648 649 - if (!value) 649 + if (value) 650 + *value = 0; 651 + else 650 652 value = &dummy; 651 653 652 - *value = 0; 653 654 if (width <= 8) { 654 - *(u8 *) value = inb(port); 655 + *value = inb(port); 655 656 } else if (width <= 16) { 656 - *(u16 *) value = inw(port); 657 + *value = inw(port); 657 658 } else if (width <= 32) { 658 - *(u32 *) value = inl(port); 659 + *value = inl(port); 659 660 } else { 660 - BUG(); 661 + pr_debug("%s: Access width %d not supported\n", __func__, width); 662 + return AE_BAD_PARAMETER; 661 663 } 662 664 663 665 return AE_OK; ··· 676 674 } else if (width <= 32) { 677 675 outl(value, port); 678 676 } else { 679 - BUG(); 677 + pr_debug("%s: Access width %d not supported\n", __func__, width); 678 + return AE_BAD_PARAMETER; 680 679 } 681 680 682 681 return AE_OK;
+1 -1
drivers/acpi/pci_link.c
··· 185 185 if (!p || !p->interrupt_count) { 186 186 /* 187 187 * IRQ descriptors may have no IRQ# bits set, 188 - * particularly those those w/ _STA disabled 188 + * particularly those w/ _STA disabled 189 189 */ 190 190 pr_debug("Blank _CRS IRQ resource\n"); 191 191 return AE_OK;
-3
drivers/acpi/pci_root.c
··· 22 22 #include <linux/slab.h> 23 23 #include <linux/dmi.h> 24 24 #include <linux/platform_data/x86/apple.h> 25 - #include <acpi/apei.h> /* for acpi_hest_init() */ 26 - 27 25 #include "internal.h" 28 26 29 27 #define ACPI_PCI_ROOT_CLASS "pci_bridge" ··· 941 943 942 944 void __init acpi_pci_root_init(void) 943 945 { 944 - acpi_hest_init(); 945 946 if (acpi_pci_disabled) 946 947 return; 947 948
+16 -13
drivers/acpi/property.c
··· 541 541 if (is_acpi_device_node(fwnode)) { 542 542 const struct acpi_device *adev = to_acpi_device_node(fwnode); 543 543 return &adev->data; 544 - } else if (is_acpi_data_node(fwnode)) { 544 + } 545 + if (is_acpi_data_node(fwnode)) { 545 546 const struct acpi_data_node *dn = to_acpi_data_node(fwnode); 546 547 return &dn->data; 547 548 } ··· 686 685 */ 687 686 if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) { 688 687 if (index) 689 - return -EINVAL; 688 + return -ENOENT; 690 689 691 690 device = acpi_fetch_acpi_dev(obj->reference.handle); 692 691 if (!device) ··· 740 739 return -EINVAL; 741 740 } 742 741 743 - /* assume following integer elements are all args */ 742 + /* 743 + * Assume the following integer elements are all args. 744 + * Stop counting on the first reference or end of the 745 + * package arguments. In case of neither reference, 746 + * nor integer, return an error, we can't parse it. 747 + */ 744 748 for (i = 0; element + i < end && i < num_args; i++) { 745 749 int type = element[i].type; 746 750 751 + if (type == ACPI_TYPE_LOCAL_REFERENCE) 752 + break; 747 753 if (type == ACPI_TYPE_INTEGER) 748 754 nargs++; 749 - else if (type == ACPI_TYPE_LOCAL_REFERENCE) 750 - break; 751 755 else 752 756 return -EINVAL; 753 757 } ··· 956 950 957 951 if (proptype != DEV_PROP_STRING && nval > obj->package.count) 958 952 return -EOVERFLOW; 959 - else if (nval <= 0) 953 + if (nval == 0) 960 954 return -EINVAL; 961 955 962 956 items = obj->package.elements; ··· 1018 1012 const struct list_head *head; 1019 1013 struct list_head *next; 1020 1014 1021 - if (!child || is_acpi_device_node(child)) { 1015 + if ((!child || is_acpi_device_node(child)) && adev) { 1022 1016 struct acpi_device *child_adev; 1023 1017 1024 - if (adev) 1025 - head = &adev->children; 1026 - else 1027 - goto nondev; 1028 - 1018 + head = &adev->children; 1029 1019 if (list_empty(head)) 1030 1020 goto nondev; 1031 1021 ··· 1091 1089 if (is_acpi_data_node(fwnode)) { 1092 1090 /* All data nodes have parent pointer so just return that */ 1093 1091 return to_acpi_data_node(fwnode)->parent; 1094 - } else if (is_acpi_device_node(fwnode)) { 1092 + } 1093 + if (is_acpi_device_node(fwnode)) { 1095 1094 struct device *dev = to_acpi_device_node(fwnode)->dev.parent; 1096 1095 1097 1096 if (dev)
+3 -2
drivers/acpi/scan.c
··· 477 477 list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) 478 478 if (!strcmp(acpi_device_bus_id->bus_id, 479 479 acpi_device_hid(device))) { 480 - ida_simple_remove(&acpi_device_bus_id->instance_ida, device->pnp.instance_no); 480 + ida_free(&acpi_device_bus_id->instance_ida, 481 + device->pnp.instance_no); 481 482 if (ida_is_empty(&acpi_device_bus_id->instance_ida)) { 482 483 list_del(&acpi_device_bus_id->node); 483 484 kfree_const(acpi_device_bus_id->bus_id); ··· 643 642 struct ida *instance_ida = &acpi_device_bus_id->instance_ida; 644 643 int result; 645 644 646 - result = ida_simple_get(instance_ida, 0, ACPI_MAX_DEVICE_INSTANCES, GFP_KERNEL); 645 + result = ida_alloc(instance_ida, GFP_KERNEL); 647 646 if (result < 0) 648 647 return result; 649 648
+2
drivers/acpi/sleep.c
··· 758 758 return true; 759 759 } 760 760 761 + pm_pr_dbg("Rearming ACPI SCI for wakeup\n"); 762 + 761 763 pm_wakeup_clear(acpi_sci_irq); 762 764 rearm_wake_irq(acpi_sci_irq); 763 765 }
+1 -1
drivers/acpi/tables.c
··· 545 545 ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, 546 546 ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, 547 547 ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT, 548 - ACPI_SIG_NHLT, ACPI_SIG_AEST }; 548 + ACPI_SIG_NHLT, ACPI_SIG_AEST, ACPI_SIG_CEDT, ACPI_SIG_AGDI }; 549 549 550 550 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) 551 551
+75
drivers/acpi/video_detect.c
··· 415 415 DMI_MATCH(DMI_PRODUCT_NAME, "GA503"), 416 416 }, 417 417 }, 418 + /* 419 + * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a 420 + * working native and video interface. However the default detection 421 + * mechanism first registers the video interface before unregistering 422 + * it again and switching to the native interface during boot. This 423 + * results in a dangling SBIOS request for backlight change for some 424 + * reason, causing the backlight to switch to ~2% once per boot on the 425 + * first power cord connect or disconnect event. Setting the native 426 + * interface explicitly circumvents this buggy behaviour, by avoiding 427 + * the unregistering process. 428 + */ 429 + { 430 + .callback = video_detect_force_native, 431 + .ident = "Clevo NL5xRU", 432 + .matches = { 433 + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 434 + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), 435 + }, 436 + }, 437 + { 438 + .callback = video_detect_force_native, 439 + .ident = "Clevo NL5xRU", 440 + .matches = { 441 + DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), 442 + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), 443 + }, 444 + }, 445 + { 446 + .callback = video_detect_force_native, 447 + .ident = "Clevo NL5xRU", 448 + .matches = { 449 + DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), 450 + DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), 451 + }, 452 + }, 453 + { 454 + .callback = video_detect_force_native, 455 + .ident = "Clevo NL5xRU", 456 + .matches = { 457 + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 458 + DMI_MATCH(DMI_BOARD_NAME, "AURA1501"), 459 + }, 460 + }, 461 + { 462 + .callback = video_detect_force_native, 463 + .ident = "Clevo NL5xRU", 464 + .matches = { 465 + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 466 + DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"), 467 + }, 468 + }, 469 + { 470 + .callback = video_detect_force_native, 471 + .ident = "Clevo NL5xNU", 472 + .matches = { 473 + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 474 + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), 475 + }, 476 + }, 477 + { 478 + .callback = video_detect_force_native, 479 + .ident = "Clevo NL5xNU", 480 + .matches = { 481 + DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), 482 + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), 483 + }, 484 + }, 485 + { 486 + .callback = video_detect_force_native, 487 + .ident = "Clevo NL5xNU", 488 + .matches = { 489 + DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), 490 + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), 491 + }, 492 + }, 418 493 419 494 /* 420 495 * Desktops which falsely report a backlight and which our heuristics
+21
drivers/acpi/x86/utils.c
··· 285 285 ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), 286 286 }, 287 287 { 288 + /* Lenovo Yoga Tablet 1050F/L */ 289 + .matches = { 290 + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), 291 + DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"), 292 + DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"), 293 + /* Partial match on beginning of BIOS version */ 294 + DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), 295 + }, 296 + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | 297 + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), 298 + }, 299 + { 300 + /* Nextbook Ares 8 */ 301 + .matches = { 302 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 303 + DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"), 304 + }, 305 + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | 306 + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), 307 + }, 308 + { 288 309 /* Whitelabel (sold as various brands) TM800A550L */ 289 310 .matches = { 290 311 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+42 -3
drivers/base/arch_topology.c
··· 339 339 return !ret; 340 340 } 341 341 342 + #ifdef CONFIG_ACPI_CPPC_LIB 343 + #include <acpi/cppc_acpi.h> 344 + 345 + void topology_init_cpu_capacity_cppc(void) 346 + { 347 + struct cppc_perf_caps perf_caps; 348 + int cpu; 349 + 350 + if (likely(acpi_disabled || !acpi_cpc_valid())) 351 + return; 352 + 353 + raw_capacity = kcalloc(num_possible_cpus(), sizeof(*raw_capacity), 354 + GFP_KERNEL); 355 + if (!raw_capacity) 356 + return; 357 + 358 + for_each_possible_cpu(cpu) { 359 + if (!cppc_get_perf_caps(cpu, &perf_caps) && 360 + (perf_caps.highest_perf >= perf_caps.nominal_perf) && 361 + (perf_caps.highest_perf >= perf_caps.lowest_perf)) { 362 + raw_capacity[cpu] = perf_caps.highest_perf; 363 + pr_debug("cpu_capacity: CPU%d cpu_capacity=%u (raw).\n", 364 + cpu, raw_capacity[cpu]); 365 + continue; 366 + } 367 + 368 + pr_err("cpu_capacity: CPU%d missing/invalid highest performance.\n", cpu); 369 + pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n"); 370 + goto exit; 371 + } 372 + 373 + topology_normalize_cpu_scale(); 374 + schedule_work(&update_topology_flags_work); 375 + pr_debug("cpu_capacity: cpu_capacity initialization done\n"); 376 + 377 + exit: 378 + free_raw_capacity(); 379 + } 380 + #endif 381 + 342 382 #ifdef CONFIG_CPU_FREQ 343 383 static cpumask_var_t cpus_to_visit; 344 384 static void parsing_done_workfn(struct work_struct *work); ··· 427 387 int ret; 428 388 429 389 /* 430 - * on ACPI-based systems we need to use the default cpu capacity 431 - * until we have the necessary code to parse the cpu capacity, so 432 - * skip registering cpufreq notifier. 390 + * On ACPI-based systems skip registering cpufreq notifier as cpufreq 391 + * information is not needed for cpu capacity initialization. 433 392 */ 434 393 if (!acpi_disabled || !raw_capacity) 435 394 return -EINVAL;
+4 -2
drivers/clocksource/acpi_pm.c
··· 229 229 int ret; 230 230 231 231 ret = kstrtouint(arg, 16, &base); 232 - if (ret) 233 - return ret; 232 + if (ret) { 233 + pr_warn("PMTMR: invalid 'pmtmr=' value: '%s'\n", arg); 234 + return 1; 235 + } 234 236 235 237 pr_info("PMTMR IOPort override: 0x%04x -> 0x%04x\n", pmtmr_ioport, 236 238 base);
+1
drivers/firmware/Kconfig
··· 40 40 config ARM_SDE_INTERFACE 41 41 bool "ARM Software Delegated Exception Interface (SDEI)" 42 42 depends on ARM64 43 + depends on ACPI_APEI_GHES 43 44 help 44 45 The Software Delegated Exception Interface (SDEI) is an ARM 45 46 standard for registering callbacks from the platform firmware
+2 -11
drivers/firmware/arm_sdei.c
··· 1059 1059 return true; 1060 1060 } 1061 1061 1062 - static int __init sdei_init(void) 1062 + void __init sdei_init(void) 1063 1063 { 1064 1064 struct platform_device *pdev; 1065 1065 int ret; 1066 1066 1067 1067 ret = platform_driver_register(&sdei_driver); 1068 1068 if (ret || !sdei_present_acpi()) 1069 - return ret; 1069 + return; 1070 1070 1071 1071 pdev = platform_device_register_simple(sdei_driver.driver.name, 1072 1072 0, NULL, 0); ··· 1076 1076 pr_info("Failed to register ACPI:SDEI platform device %d\n", 1077 1077 ret); 1078 1078 } 1079 - 1080 - return ret; 1081 1079 } 1082 - 1083 - /* 1084 - * On an ACPI system SDEI needs to be ready before HEST:GHES tries to register 1085 - * its events. ACPI is initialised from a subsys_initcall(), GHES is initialised 1086 - * by device_initcall(). We want to be called in the middle. 1087 - */ 1088 - subsys_initcall_sync(sdei_init); 1089 1080 1090 1081 int sdei_event_handler(struct pt_regs *regs, 1091 1082 struct sdei_registered_event *arg)
+1 -1
drivers/usb/typec/port-mapper.c
··· 59 59 if (!has_acpi_companion(&con->dev)) 60 60 return 0; 61 61 62 - bus_for_each_dev(&acpi_bus_type, NULL, &arg, typec_port_match); 62 + acpi_bus_for_each_dev(typec_port_match, &arg); 63 63 if (!arg.match) 64 64 return 0; 65 65
+2
include/acpi/acpi_bus.h
··· 480 480 /* acpi_device.dev.bus == &acpi_bus_type */ 481 481 extern struct bus_type acpi_bus_type; 482 482 483 + int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data); 484 + 483 485 /* 484 486 * Events 485 487 * ------
+4
include/acpi/actypes.h
··· 507 507 /* Pointer/Integer type conversions */ 508 508 509 509 #define ACPI_TO_POINTER(i) ACPI_CAST_PTR (void, (acpi_size) (i)) 510 + #ifndef ACPI_TO_INTEGER 510 511 #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) 512 + #endif 513 + #ifndef ACPI_OFFSET 511 514 #define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0) 515 + #endif 512 516 #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) 513 517 514 518 /* Optimizations for 4-character (32-bit) acpi_name manipulation */
+3 -1
include/acpi/apei.h
··· 27 27 extern int erst_disable; 28 28 #ifdef CONFIG_ACPI_APEI_GHES 29 29 extern bool ghes_disable; 30 + void __init acpi_ghes_init(void); 30 31 #else 31 32 #define ghes_disable 1 33 + static inline void acpi_ghes_init(void) { } 32 34 #endif 33 35 34 36 #ifdef CONFIG_ACPI_APEI 35 37 void __init acpi_hest_init(void); 36 38 #else 37 - static inline void acpi_hest_init(void) { return; } 39 + static inline void acpi_hest_init(void) { } 38 40 #endif 39 41 40 42 int erst_write(const struct cper_record_header *record);
+5
include/acpi/platform/aclinux.h
··· 114 114 #define acpi_raw_spinlock raw_spinlock_t * 115 115 #define acpi_cpu_flags unsigned long 116 116 117 + #define acpi_uintptr_t uintptr_t 118 + 119 + #define ACPI_TO_INTEGER(p) ((uintptr_t)(p)) 120 + #define ACPI_OFFSET(d, f) offsetof(d, f) 121 + 117 122 /* Use native linux version of acpi_os_allocate_zeroed */ 118 123 119 124 #define USE_NATIVE_ALLOCATE_ZEROED
+3 -2
include/linux/acpi.h
··· 580 580 extern bool osc_sb_apei_support_acked; 581 581 extern bool osc_pc_lpi_support_confirmed; 582 582 extern bool osc_sb_native_usb4_support_confirmed; 583 + extern bool osc_sb_cppc_not_supported; 583 584 584 585 /* USB4 Capabilities */ 585 586 #define OSC_USB_USB3_TUNNELING 0x00000001 ··· 692 691 int acpi_device_modalias(struct device *, char *, int); 693 692 694 693 struct platform_device *acpi_create_platform_device(struct acpi_device *, 695 - struct property_entry *); 694 + const struct property_entry *); 696 695 #define ACPI_PTR(_ptr) (_ptr) 697 696 698 697 static inline void acpi_device_set_enumerated(struct acpi_device *adev) ··· 931 930 932 931 static inline struct platform_device * 933 932 acpi_create_platform_device(struct acpi_device *adev, 934 - struct property_entry *properties) 933 + const struct property_entry *properties) 935 934 { 936 935 return NULL; 937 936 }
+13
include/linux/acpi_agdi.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __ACPI_AGDI_H__ 4 + #define __ACPI_AGDI_H__ 5 + 6 + #include <linux/acpi.h> 7 + 8 + #ifdef CONFIG_ACPI_AGDI 9 + void __init acpi_agdi_init(void); 10 + #else 11 + static inline void acpi_agdi_init(void) {} 12 + #endif 13 + #endif /* __ACPI_AGDI_H__ */
+4
include/linux/arch_topology.h
··· 11 11 void topology_normalize_cpu_scale(void); 12 12 int topology_update_cpu_topology(void); 13 13 14 + #ifdef CONFIG_ACPI_CPPC_LIB 15 + void topology_init_cpu_capacity_cppc(void); 16 + #endif 17 + 14 18 struct device_node; 15 19 bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu); 16 20
+2
include/linux/arm_sdei.h
··· 46 46 /* For use by arch code when CPU hotplug notifiers are not appropriate. */ 47 47 int sdei_mask_local_cpu(void); 48 48 int sdei_unmask_local_cpu(void); 49 + void __init sdei_init(void); 49 50 #else 50 51 static inline int sdei_mask_local_cpu(void) { return 0; } 51 52 static inline int sdei_unmask_local_cpu(void) { return 0; } 53 + static inline void sdei_init(void) { } 52 54 #endif /* CONFIG_ARM_SDE_INTERFACE */ 53 55 54 56