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

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

Pull more ACPI updates from Rafael Wysocki:
"These make additional changes to the platform profile interface merged
recently and add support for the FPDT ACPI table.

Specifics:

- Rearrange Kconfig handling of ACPI_PLATFORM_PROFILE, add
"balanced-performance" to the list of supported platform profiles
and fix up some file references in a comment (Maximilian Luz).

- Add support for parsing the ACPI Firmware Performance Data Table
(FPDT) and exposing the data from there via sysfs (Zhang Rui)"

* tag 'acpi-5.12-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI: platform: Add balanced-performance platform profile
ACPI: platform: Fix file references in comment
ACPI: platform: Hide ACPI_PLATFORM_PROFILE option
ACPI: tables: introduce support for FPDT table

+334 -27
+43
Documentation/ABI/testing/sysfs-firmware-acpi
··· 1 + What: /sys/firmware/acpi/fpdt/ 2 + Date: Jan 2021 3 + Contact: Zhang Rui <rui.zhang@intel.com> 4 + Description: 5 + ACPI Firmware Performance Data Table (FPDT) provides 6 + information for firmware performance data for system boot, 7 + S3 suspend and S3 resume. This sysfs entry contains the 8 + performance data retrieved from the FPDT. 9 + 10 + boot: 11 + firmware_start_ns: Timer value logged at the beginning 12 + of firmware image execution. In nanoseconds. 13 + bootloader_load_ns: Timer value logged just prior to 14 + loading the OS boot loader into memory. 15 + In nanoseconds. 16 + bootloader_launch_ns: Timer value logged just prior to 17 + launching the currently loaded OS boot loader 18 + image. In nanoseconds. 19 + exitbootservice_start_ns: Timer value logged at the 20 + point when the OS loader calls the 21 + ExitBootServices function for UEFI compatible 22 + firmware. In nanoseconds. 23 + exitbootservice_end_ns: Timer value logged at the point 24 + just prior to the OS loader gaining control 25 + back from the ExitBootServices function for 26 + UEFI compatible firmware. In nanoseconds. 27 + suspend: 28 + suspend_start_ns: Timer value recorded at the previous 29 + OS write to SLP_TYP upon entry to S3. In 30 + nanoseconds. 31 + suspend_end_ns: Timer value recorded at the previous 32 + firmware write to SLP_TYP used to trigger 33 + hardware entry to S3. In nanoseconds. 34 + resume: 35 + resume_count: A count of the number of S3 resume cycles 36 + since the last full boot sequence. 37 + resume_avg_ns: Average timer value of all resume cycles 38 + logged since the last full boot sequence, 39 + including the most recent resume. In nanoseconds. 40 + resume_prev_ns: Timer recorded at the end of the previous 41 + platform runtime firmware S3 resume, just prior to 42 + handoff to the OS waking vector. In nanoseconds. 43 + 1 44 What: /sys/firmware/acpi/bgrt/ 2 45 Date: January 2012 3 46 Contact: Matthew Garrett <mjg@redhat.com>
+11 -7
Documentation/ABI/testing/sysfs-platform_profile
··· 5 5 6 6 Drivers must use the following standard profile-names: 7 7 8 - ============ ============================================ 9 - low-power Low power consumption 10 - cool Cooler operation 11 - quiet Quieter operation 12 - balanced Balance between low power consumption and performance 13 - performance High performance operation 14 - ============ ============================================ 8 + ==================== ======================================== 9 + low-power Low power consumption 10 + cool Cooler operation 11 + quiet Quieter operation 12 + balanced Balance between low power consumption 13 + and performance 14 + balanced-performance Balance between performance and low 15 + power consumption with a slight bias 16 + towards performance 17 + performance High performance operation 18 + ==================== ======================================== 15 19 16 20 Userspace may expect drivers to offer more than one of these 17 21 standard profile names.
+9 -15
drivers/acpi/Kconfig
··· 87 87 This table provides information about the configuration of the 88 88 earlycon console. 89 89 90 + config ACPI_FPDT 91 + bool "ACPI Firmware Performance Data Table (FPDT) support" 92 + depends on X86_64 93 + help 94 + Enable support for the Firmware Performance Data Table (FPDT). 95 + This table provides information on the timing of the system 96 + boot, S3 suspend and S3 resume firmware code paths. 97 + 90 98 config ACPI_LPIT 91 99 bool 92 100 depends on X86_64 ··· 335 327 the module will be called thermal. 336 328 337 329 config ACPI_PLATFORM_PROFILE 338 - tristate "ACPI Platform Profile Driver" 339 - default m 340 - help 341 - This driver adds support for platform-profiles on platforms that 342 - support it. 343 - 344 - Platform-profiles can be used to control the platform behaviour. For 345 - example whether to operate in a lower power mode, in a higher 346 - power performance mode or between the two. 347 - 348 - This driver provides the sysfs interface and is used as the registration 349 - point for platform specific drivers. 350 - 351 - Which profiles are supported is determined on a per-platform basis and 352 - should be obtained from the platform specific driver. 330 + tristate 353 331 354 332 config ACPI_CUSTOM_DSDT_FILE 355 333 string "Custom DSDT Table file to include"
+1
drivers/acpi/Makefile
··· 57 57 acpi-$(CONFIG_X86) += x86/s2idle.o 58 58 acpi-$(CONFIG_DEBUG_FS) += debugfs.o 59 59 acpi-y += acpi_lpat.o 60 + acpi-$(CONFIG_ACPI_FPDT) += acpi_fpdt.o 60 61 acpi-$(CONFIG_ACPI_LPIT) += acpi_lpit.o 61 62 acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o 62 63 acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o
+264
drivers/acpi/acpi_fpdt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * FPDT support for exporting boot and suspend/resume performance data 5 + * 6 + * Copyright (C) 2021 Intel Corporation. All rights reserved. 7 + */ 8 + 9 + #define pr_fmt(fmt) "ACPI FPDT: " fmt 10 + 11 + #include <linux/acpi.h> 12 + 13 + /* 14 + * FPDT contains ACPI table header and a number of fpdt_subtable_entries. 15 + * Each fpdt_subtable_entry points to a subtable: FBPT or S3PT. 16 + * Each FPDT subtable (FBPT/S3PT) is composed of a fpdt_subtable_header 17 + * and a number of fpdt performance records. 18 + * Each FPDT performance record is composed of a fpdt_record_header and 19 + * performance data fields, for boot or suspend or resume phase. 20 + */ 21 + enum fpdt_subtable_type { 22 + SUBTABLE_FBPT, 23 + SUBTABLE_S3PT, 24 + }; 25 + 26 + struct fpdt_subtable_entry { 27 + u16 type; /* refer to enum fpdt_subtable_type */ 28 + u8 length; 29 + u8 revision; 30 + u32 reserved; 31 + u64 address; /* physical address of the S3PT/FBPT table */ 32 + }; 33 + 34 + struct fpdt_subtable_header { 35 + u32 signature; 36 + u32 length; 37 + }; 38 + 39 + enum fpdt_record_type { 40 + RECORD_S3_RESUME, 41 + RECORD_S3_SUSPEND, 42 + RECORD_BOOT, 43 + }; 44 + 45 + struct fpdt_record_header { 46 + u16 type; /* refer to enum fpdt_record_type */ 47 + u8 length; 48 + u8 revision; 49 + }; 50 + 51 + struct resume_performance_record { 52 + struct fpdt_record_header header; 53 + u32 resume_count; 54 + u64 resume_prev; 55 + u64 resume_avg; 56 + } __attribute__((packed)); 57 + 58 + struct boot_performance_record { 59 + struct fpdt_record_header header; 60 + u32 reserved; 61 + u64 firmware_start; 62 + u64 bootloader_load; 63 + u64 bootloader_launch; 64 + u64 exitbootservice_start; 65 + u64 exitbootservice_end; 66 + } __attribute__((packed)); 67 + 68 + struct suspend_performance_record { 69 + struct fpdt_record_header header; 70 + u64 suspend_start; 71 + u64 suspend_end; 72 + } __attribute__((packed)); 73 + 74 + 75 + static struct resume_performance_record *record_resume; 76 + static struct suspend_performance_record *record_suspend; 77 + static struct boot_performance_record *record_boot; 78 + 79 + #define FPDT_ATTR(phase, name) \ 80 + static ssize_t name##_show(struct kobject *kobj, \ 81 + struct kobj_attribute *attr, char *buf) \ 82 + { \ 83 + return sprintf(buf, "%llu\n", record_##phase->name); \ 84 + } \ 85 + static struct kobj_attribute name##_attr = \ 86 + __ATTR(name##_ns, 0444, name##_show, NULL) 87 + 88 + FPDT_ATTR(resume, resume_prev); 89 + FPDT_ATTR(resume, resume_avg); 90 + FPDT_ATTR(suspend, suspend_start); 91 + FPDT_ATTR(suspend, suspend_end); 92 + FPDT_ATTR(boot, firmware_start); 93 + FPDT_ATTR(boot, bootloader_load); 94 + FPDT_ATTR(boot, bootloader_launch); 95 + FPDT_ATTR(boot, exitbootservice_start); 96 + FPDT_ATTR(boot, exitbootservice_end); 97 + 98 + static ssize_t resume_count_show(struct kobject *kobj, 99 + struct kobj_attribute *attr, char *buf) 100 + { 101 + return sprintf(buf, "%u\n", record_resume->resume_count); 102 + } 103 + 104 + static struct kobj_attribute resume_count_attr = 105 + __ATTR_RO(resume_count); 106 + 107 + static struct attribute *resume_attrs[] = { 108 + &resume_count_attr.attr, 109 + &resume_prev_attr.attr, 110 + &resume_avg_attr.attr, 111 + NULL 112 + }; 113 + 114 + static const struct attribute_group resume_attr_group = { 115 + .attrs = resume_attrs, 116 + .name = "resume", 117 + }; 118 + 119 + static struct attribute *suspend_attrs[] = { 120 + &suspend_start_attr.attr, 121 + &suspend_end_attr.attr, 122 + NULL 123 + }; 124 + 125 + static const struct attribute_group suspend_attr_group = { 126 + .attrs = suspend_attrs, 127 + .name = "suspend", 128 + }; 129 + 130 + static struct attribute *boot_attrs[] = { 131 + &firmware_start_attr.attr, 132 + &bootloader_load_attr.attr, 133 + &bootloader_launch_attr.attr, 134 + &exitbootservice_start_attr.attr, 135 + &exitbootservice_end_attr.attr, 136 + NULL 137 + }; 138 + 139 + static const struct attribute_group boot_attr_group = { 140 + .attrs = boot_attrs, 141 + .name = "boot", 142 + }; 143 + 144 + static struct kobject *fpdt_kobj; 145 + 146 + static int fpdt_process_subtable(u64 address, u32 subtable_type) 147 + { 148 + struct fpdt_subtable_header *subtable_header; 149 + struct fpdt_record_header *record_header; 150 + char *signature = (subtable_type == SUBTABLE_FBPT ? "FBPT" : "S3PT"); 151 + u32 length, offset; 152 + int result; 153 + 154 + subtable_header = acpi_os_map_memory(address, sizeof(*subtable_header)); 155 + if (!subtable_header) 156 + return -ENOMEM; 157 + 158 + if (strncmp((char *)&subtable_header->signature, signature, 4)) { 159 + pr_info(FW_BUG "subtable signature and type mismatch!\n"); 160 + return -EINVAL; 161 + } 162 + 163 + length = subtable_header->length; 164 + acpi_os_unmap_memory(subtable_header, sizeof(*subtable_header)); 165 + 166 + subtable_header = acpi_os_map_memory(address, length); 167 + if (!subtable_header) 168 + return -ENOMEM; 169 + 170 + offset = sizeof(*subtable_header); 171 + while (offset < length) { 172 + record_header = (void *)subtable_header + offset; 173 + offset += record_header->length; 174 + 175 + switch (record_header->type) { 176 + case RECORD_S3_RESUME: 177 + if (subtable_type != SUBTABLE_S3PT) { 178 + pr_err(FW_BUG "Invalid record %d for subtable %s\n", 179 + record_header->type, signature); 180 + return -EINVAL; 181 + } 182 + if (record_resume) { 183 + pr_err("Duplicate resume performance record found.\n"); 184 + continue; 185 + } 186 + record_resume = (struct resume_performance_record *)record_header; 187 + result = sysfs_create_group(fpdt_kobj, &resume_attr_group); 188 + if (result) 189 + return result; 190 + break; 191 + case RECORD_S3_SUSPEND: 192 + if (subtable_type != SUBTABLE_S3PT) { 193 + pr_err(FW_BUG "Invalid %d for subtable %s\n", 194 + record_header->type, signature); 195 + continue; 196 + } 197 + if (record_suspend) { 198 + pr_err("Duplicate suspend performance record found.\n"); 199 + continue; 200 + } 201 + record_suspend = (struct suspend_performance_record *)record_header; 202 + result = sysfs_create_group(fpdt_kobj, &suspend_attr_group); 203 + if (result) 204 + return result; 205 + break; 206 + case RECORD_BOOT: 207 + if (subtable_type != SUBTABLE_FBPT) { 208 + pr_err(FW_BUG "Invalid %d for subtable %s\n", 209 + record_header->type, signature); 210 + return -EINVAL; 211 + } 212 + if (record_boot) { 213 + pr_err("Duplicate boot performance record found.\n"); 214 + continue; 215 + } 216 + record_boot = (struct boot_performance_record *)record_header; 217 + result = sysfs_create_group(fpdt_kobj, &boot_attr_group); 218 + if (result) 219 + return result; 220 + break; 221 + 222 + default: 223 + pr_err(FW_BUG "Invalid record %d found.\n", record_header->type); 224 + return -EINVAL; 225 + } 226 + } 227 + return 0; 228 + } 229 + 230 + static int __init acpi_init_fpdt(void) 231 + { 232 + acpi_status status; 233 + struct acpi_table_header *header; 234 + struct fpdt_subtable_entry *subtable; 235 + u32 offset = sizeof(*header); 236 + 237 + status = acpi_get_table(ACPI_SIG_FPDT, 0, &header); 238 + 239 + if (ACPI_FAILURE(status)) 240 + return 0; 241 + 242 + fpdt_kobj = kobject_create_and_add("fpdt", acpi_kobj); 243 + if (!fpdt_kobj) 244 + return -ENOMEM; 245 + 246 + while (offset < header->length) { 247 + subtable = (void *)header + offset; 248 + switch (subtable->type) { 249 + case SUBTABLE_FBPT: 250 + case SUBTABLE_S3PT: 251 + fpdt_process_subtable(subtable->address, 252 + subtable->type); 253 + break; 254 + default: 255 + pr_info(FW_BUG "Invalid subtable type %d found.\n", 256 + subtable->type); 257 + break; 258 + } 259 + offset += sizeof(*subtable); 260 + } 261 + return 0; 262 + } 263 + 264 + fs_initcall(acpi_init_fpdt);
+1
drivers/acpi/platform_profile.c
··· 17 17 [PLATFORM_PROFILE_COOL] = "cool", 18 18 [PLATFORM_PROFILE_QUIET] = "quiet", 19 19 [PLATFORM_PROFILE_BALANCED] = "balanced", 20 + [PLATFORM_PROFILE_BALANCED_PERFORMANCE] = "balanced-performance", 20 21 [PLATFORM_PROFILE_PERFORMANCE] = "performance", 21 22 }; 22 23 static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST);
+2 -2
drivers/platform/x86/Kconfig
··· 450 450 depends on BACKLIGHT_CLASS_DEVICE 451 451 depends on ACPI_VIDEO || ACPI_VIDEO = n 452 452 depends on ACPI_WMI || ACPI_WMI = n 453 - depends on ACPI_PLATFORM_PROFILE 453 + select ACPI_PLATFORM_PROFILE 454 454 select INPUT_SPARSEKMAP 455 455 select NEW_LEDS 456 456 select LEDS_CLASS ··· 484 484 depends on RFKILL || RFKILL = n 485 485 depends on ACPI_VIDEO || ACPI_VIDEO = n 486 486 depends on BACKLIGHT_CLASS_DEVICE 487 - depends on ACPI_PLATFORM_PROFILE 487 + select ACPI_PLATFORM_PROFILE 488 488 select HWMON 489 489 select NVRAM 490 490 select NEW_LEDS
+3 -3
include/linux/platform_profile.h
··· 12 12 #include <linux/bitops.h> 13 13 14 14 /* 15 - * If more options are added please update profile_names 16 - * array in platform-profile.c and sysfs-platform-profile.rst 17 - * documentation. 15 + * If more options are added please update profile_names array in 16 + * platform_profile.c and sysfs-platform_profile documentation. 18 17 */ 19 18 20 19 enum platform_profile_option { ··· 21 22 PLATFORM_PROFILE_COOL, 22 23 PLATFORM_PROFILE_QUIET, 23 24 PLATFORM_PROFILE_BALANCED, 25 + PLATFORM_PROFILE_BALANCED_PERFORMANCE, 24 26 PLATFORM_PROFILE_PERFORMANCE, 25 27 PLATFORM_PROFILE_LAST, /*must always be last */ 26 28 };