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

Merge branches 'acpi-pm', 'acpi-video', 'acpi-apei' and 'acpi-extlog'

Merge an ACPI power management change, ACPI backlight driver changes, APEI
updates and ACPI extlog driver changes for 6.8-rc1:

- Modify the ACPI LPIT table handling code to avoid u32 multiplication
overflows in state residency computations (Nikita Kiryushin).

- Drop an unused helper function from the ACPI backlight (video) driver
and add a clarifying comment to it (Hans de Goede).

- Update the ACPI backlight driver to avoid using uninitialized memory
in some cases (Nikita Kiryushin).

- Add ACPI backlight quirk for the Colorful X15 AT 23 laptop (Yuluo
Qiu).

- Add support for vendor-defined error types to the ACPI APEI error
injection code (Avadhut Naik).

- Adjust APEI to properly set MF_ACTION_REQUIRED on synchronous memory
failure events, so they are handled differently from the asynchronous
ones (Shuai Xue).

- Fix NULL pointer dereference check in the ACPI extlog driver (Prarit
Bhargava).

- Adjust the ACPI extlog driver to clear the Extended Error Log status
when RAS_CEC handled the error (Tony Luck).

* acpi-pm:
ACPI: LPIT: Avoid u32 multiplication overflow

* acpi-video:
ACPI: video: Add quirk for the Colorful X15 AT 23 Laptop
ACPI: video: check for error while searching for backlight device parent
ACPI: video: Drop should_check_lcd_flag()
ACPI: video: Add comment about acpi_video_backlight_use_native() usage

* acpi-apei:
ACPI: APEI: set memory failure flags as MF_ACTION_REQUIRED on synchronous events
ACPI: APEI: EINJ: Add support for vendor defined error types
platform/chrome: cros_ec_debugfs: Fix permissions for panicinfo
fs: debugfs: Add write functionality to debugfs blobs
ACPI: APEI: EINJ: Refactor available_error_type_show()

* acpi-extlog:
ACPI: extlog: Clear Extended Error Log status when RAS_CEC handled the error
ACPI: extlog: fix NULL pointer dereference check

+130 -100
+9 -3
drivers/acpi/acpi_extlog.c
··· 145 145 static u32 err_seq; 146 146 147 147 estatus = extlog_elog_entry_check(cpu, bank); 148 - if (estatus == NULL || (mce->kflags & MCE_HANDLED_CEC)) 148 + if (!estatus) 149 149 return NOTIFY_DONE; 150 + 151 + if (mce->kflags & MCE_HANDLED_CEC) { 152 + estatus->block_status = 0; 153 + return NOTIFY_DONE; 154 + } 150 155 151 156 memcpy(elog_buf, (void *)estatus, ELOG_ENTRY_LEN); 152 157 /* clear record status to enable BIOS to update it again */ ··· 308 303 static void __exit extlog_exit(void) 309 304 { 310 305 mce_unregister_decode_chain(&extlog_mce_dec); 311 - ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; 312 - if (extlog_l1_addr) 306 + if (extlog_l1_addr) { 307 + ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN; 313 308 acpi_os_unmap_iomem(extlog_l1_addr, l1_size); 309 + } 314 310 if (elog_addr) 315 311 acpi_os_unmap_iomem(elog_addr, elog_size); 316 312 release_mem_region(elog_base, elog_size);
+1 -1
drivers/acpi/acpi_lpit.c
··· 105 105 return; 106 106 107 107 info->frequency = lpit_native->counter_frequency ? 108 - lpit_native->counter_frequency : tsc_khz * 1000; 108 + lpit_native->counter_frequency : mul_u32_u32(tsc_khz, 1000U); 109 109 if (!info->frequency) 110 110 info->frequency = 1; 111 111
+16 -61
drivers/acpi/acpi_video.c
··· 67 67 static bool device_id_scheme = false; 68 68 module_param(device_id_scheme, bool, 0444); 69 69 70 - static int only_lcd = -1; 70 + static int only_lcd; 71 71 module_param(only_lcd, int, 0444); 72 72 73 73 static bool may_report_brightness_keys; ··· 498 498 .matches = { 499 499 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 500 500 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"), 501 + }, 502 + }, 503 + { 504 + .callback = video_set_report_key_events, 505 + .driver_data = (void *)((uintptr_t)REPORT_BRIGHTNESS_KEY_EVENTS), 506 + .ident = "COLORFUL X15 AT 23", 507 + .matches = { 508 + DMI_MATCH(DMI_SYS_VENDOR, "COLORFUL"), 509 + DMI_MATCH(DMI_PRODUCT_NAME, "X15 AT 23"), 501 510 }, 502 511 }, 503 512 /* ··· 1722 1713 return; 1723 1714 count++; 1724 1715 1725 - acpi_get_parent(device->dev->handle, &acpi_parent); 1726 - 1727 - pdev = acpi_get_pci_dev(acpi_parent); 1728 - if (pdev) { 1729 - parent = &pdev->dev; 1730 - pci_dev_put(pdev); 1716 + if (ACPI_SUCCESS(acpi_get_parent(device->dev->handle, &acpi_parent))) { 1717 + pdev = acpi_get_pci_dev(acpi_parent); 1718 + if (pdev) { 1719 + parent = &pdev->dev; 1720 + pci_dev_put(pdev); 1721 + } 1731 1722 } 1732 1723 1733 1724 memset(&props, 0, sizeof(struct backlight_properties)); ··· 2146 2137 return opregion; 2147 2138 } 2148 2139 2149 - /* Check if the chassis-type indicates there is no builtin LCD panel */ 2150 - static bool dmi_is_desktop(void) 2151 - { 2152 - const char *chassis_type; 2153 - unsigned long type; 2154 - 2155 - chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); 2156 - if (!chassis_type) 2157 - return false; 2158 - 2159 - if (kstrtoul(chassis_type, 10, &type) != 0) 2160 - return false; 2161 - 2162 - switch (type) { 2163 - case 0x03: /* Desktop */ 2164 - case 0x04: /* Low Profile Desktop */ 2165 - case 0x05: /* Pizza Box */ 2166 - case 0x06: /* Mini Tower */ 2167 - case 0x07: /* Tower */ 2168 - case 0x10: /* Lunch Box */ 2169 - case 0x11: /* Main Server Chassis */ 2170 - return true; 2171 - } 2172 - 2173 - return false; 2174 - } 2175 - 2176 - /* 2177 - * We're seeing a lot of bogus backlight interfaces on newer machines 2178 - * without a LCD such as desktops, servers and HDMI sticks. Checking the 2179 - * lcd flag fixes this, enable this by default on any machines which are: 2180 - * 1. Win8 ready (where we also prefer the native backlight driver, so 2181 - * normally the acpi_video code should not register there anyways); *and* 2182 - * 2.1 Report a desktop/server DMI chassis-type, or 2183 - * 2.2 Are an ACPI-reduced-hardware platform (and thus won't use the EC for 2184 - backlight control) 2185 - */ 2186 - static bool should_check_lcd_flag(void) 2187 - { 2188 - if (!acpi_osi_is_win8()) 2189 - return false; 2190 - 2191 - if (dmi_is_desktop()) 2192 - return true; 2193 - 2194 - if (acpi_reduced_hardware()) 2195 - return true; 2196 - 2197 - return false; 2198 - } 2199 - 2200 2140 int acpi_video_register(void) 2201 2141 { 2202 2142 int ret = 0; ··· 2158 2200 */ 2159 2201 goto leave; 2160 2202 } 2161 - 2162 - if (only_lcd == -1) 2163 - only_lcd = should_check_lcd_flag(); 2164 2203 2165 2204 dmi_check_system(video_dmi_table); 2166 2205
+48 -23
drivers/acpi/apei/einj.c
··· 73 73 74 74 static u32 vendor_flags; 75 75 static struct debugfs_blob_wrapper vendor_blob; 76 + static struct debugfs_blob_wrapper vendor_errors; 76 77 static char vendor_dev[64]; 77 78 78 79 /* ··· 183 182 return 0; 184 183 } 185 184 185 + static void get_oem_vendor_struct(u64 paddr, int offset, 186 + struct vendor_error_type_extension *v) 187 + { 188 + unsigned long vendor_size; 189 + u64 target_pa = paddr + offset + sizeof(struct vendor_error_type_extension); 190 + 191 + vendor_size = v->length - sizeof(struct vendor_error_type_extension); 192 + 193 + if (vendor_size) 194 + vendor_errors.data = acpi_os_map_memory(target_pa, vendor_size); 195 + 196 + if (vendor_errors.data) 197 + vendor_errors.size = vendor_size; 198 + } 199 + 186 200 static void check_vendor_extension(u64 paddr, 187 201 struct set_error_type_with_address *v5param) 188 202 { ··· 210 194 v = acpi_os_map_iomem(paddr + offset, sizeof(*v)); 211 195 if (!v) 212 196 return; 197 + get_oem_vendor_struct(paddr, offset, v); 213 198 sbdf = v->pcie_sbdf; 214 199 sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n", 215 200 sbdf >> 24, (sbdf >> 16) & 0xff, ··· 594 577 static u64 error_param3; 595 578 static u64 error_param4; 596 579 static struct dentry *einj_debug_dir; 597 - static const char * const einj_error_type_string[] = { 598 - "0x00000001\tProcessor Correctable\n", 599 - "0x00000002\tProcessor Uncorrectable non-fatal\n", 600 - "0x00000004\tProcessor Uncorrectable fatal\n", 601 - "0x00000008\tMemory Correctable\n", 602 - "0x00000010\tMemory Uncorrectable non-fatal\n", 603 - "0x00000020\tMemory Uncorrectable fatal\n", 604 - "0x00000040\tPCI Express Correctable\n", 605 - "0x00000080\tPCI Express Uncorrectable non-fatal\n", 606 - "0x00000100\tPCI Express Uncorrectable fatal\n", 607 - "0x00000200\tPlatform Correctable\n", 608 - "0x00000400\tPlatform Uncorrectable non-fatal\n", 609 - "0x00000800\tPlatform Uncorrectable fatal\n", 610 - "0x00001000\tCXL.cache Protocol Correctable\n", 611 - "0x00002000\tCXL.cache Protocol Uncorrectable non-fatal\n", 612 - "0x00004000\tCXL.cache Protocol Uncorrectable fatal\n", 613 - "0x00008000\tCXL.mem Protocol Correctable\n", 614 - "0x00010000\tCXL.mem Protocol Uncorrectable non-fatal\n", 615 - "0x00020000\tCXL.mem Protocol Uncorrectable fatal\n", 580 + static struct { u32 mask; const char *str; } const einj_error_type_string[] = { 581 + { BIT(0), "Processor Correctable" }, 582 + { BIT(1), "Processor Uncorrectable non-fatal" }, 583 + { BIT(2), "Processor Uncorrectable fatal" }, 584 + { BIT(3), "Memory Correctable" }, 585 + { BIT(4), "Memory Uncorrectable non-fatal" }, 586 + { BIT(5), "Memory Uncorrectable fatal" }, 587 + { BIT(6), "PCI Express Correctable" }, 588 + { BIT(7), "PCI Express Uncorrectable non-fatal" }, 589 + { BIT(8), "PCI Express Uncorrectable fatal" }, 590 + { BIT(9), "Platform Correctable" }, 591 + { BIT(10), "Platform Uncorrectable non-fatal" }, 592 + { BIT(11), "Platform Uncorrectable fatal"}, 593 + { BIT(12), "CXL.cache Protocol Correctable" }, 594 + { BIT(13), "CXL.cache Protocol Uncorrectable non-fatal" }, 595 + { BIT(14), "CXL.cache Protocol Uncorrectable fatal" }, 596 + { BIT(15), "CXL.mem Protocol Correctable" }, 597 + { BIT(16), "CXL.mem Protocol Uncorrectable non-fatal" }, 598 + { BIT(17), "CXL.mem Protocol Uncorrectable fatal" }, 599 + { BIT(31), "Vendor Defined Error Types" }, 616 600 }; 617 601 618 602 static int available_error_type_show(struct seq_file *m, void *v) 619 603 { 620 604 int rc; 621 - u32 available_error_type = 0; 605 + u32 error_type = 0; 622 606 623 - rc = einj_get_available_error_type(&available_error_type); 607 + rc = einj_get_available_error_type(&error_type); 624 608 if (rc) 625 609 return rc; 626 610 for (int pos = 0; pos < ARRAY_SIZE(einj_error_type_string); pos++) 627 - if (available_error_type & BIT(pos)) 628 - seq_puts(m, einj_error_type_string[pos]); 611 + if (error_type & einj_error_type_string[pos].mask) 612 + seq_printf(m, "0x%08x\t%s\n", einj_error_type_string[pos].mask, 613 + einj_error_type_string[pos].str); 629 614 630 615 return 0; 631 616 } ··· 786 767 einj_debug_dir, &vendor_flags); 787 768 } 788 769 770 + if (vendor_errors.size) 771 + debugfs_create_blob("oem_error", 0600, einj_debug_dir, 772 + &vendor_errors); 773 + 789 774 pr_info("Error INJection is initialized.\n"); 790 775 791 776 return 0; ··· 815 792 sizeof(struct einj_parameter); 816 793 817 794 acpi_os_unmap_iomem(einj_param, size); 795 + if (vendor_errors.size) 796 + acpi_os_unmap_memory(vendor_errors.data, vendor_errors.size); 818 797 } 819 798 einj_exec_ctx_init(&ctx); 820 799 apei_exec_post_unmap_gars(&ctx);
+23 -6
drivers/acpi/apei/ghes.c
··· 102 102 } 103 103 104 104 /* 105 + * A platform may describe one error source for the handling of synchronous 106 + * errors (e.g. MCE or SEA), or for handling asynchronous errors (e.g. SCI 107 + * or External Interrupt). On x86, the HEST notifications are always 108 + * asynchronous, so only SEA on ARM is delivered as a synchronous 109 + * notification. 110 + */ 111 + static inline bool is_hest_sync_notify(struct ghes *ghes) 112 + { 113 + u8 notify_type = ghes->generic->notify.type; 114 + 115 + return notify_type == ACPI_HEST_NOTIFY_SEA; 116 + } 117 + 118 + /* 105 119 * This driver isn't really modular, however for the time being, 106 120 * continuing to use module_param is the easiest way to remain 107 121 * compatible with existing boot arg use cases. ··· 503 489 } 504 490 505 491 static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, 506 - int sev) 492 + int sev, bool sync) 507 493 { 508 494 int flags = -1; 509 495 int sec_sev = ghes_severity(gdata->error_severity); ··· 517 503 (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) 518 504 flags = MF_SOFT_OFFLINE; 519 505 if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) 520 - flags = 0; 506 + flags = sync ? MF_ACTION_REQUIRED : 0; 521 507 522 508 if (flags != -1) 523 509 return ghes_do_memory_failure(mem_err->physical_addr, flags); ··· 525 511 return false; 526 512 } 527 513 528 - static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, int sev) 514 + static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, 515 + int sev, bool sync) 529 516 { 530 517 struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); 518 + int flags = sync ? MF_ACTION_REQUIRED : 0; 531 519 bool queued = false; 532 520 int sec_sev, i; 533 521 char *p; ··· 554 538 * and don't filter out 'corrected' error here. 555 539 */ 556 540 if (is_cache && has_pa) { 557 - queued = ghes_do_memory_failure(err_info->physical_fault_addr, 0); 541 + queued = ghes_do_memory_failure(err_info->physical_fault_addr, flags); 558 542 p += err_info->length; 559 543 continue; 560 544 } ··· 682 666 const guid_t *fru_id = &guid_null; 683 667 char *fru_text = ""; 684 668 bool queued = false; 669 + bool sync = is_hest_sync_notify(ghes); 685 670 686 671 sev = ghes_severity(estatus->error_severity); 687 672 apei_estatus_for_each_section(estatus, gdata) { ··· 700 683 atomic_notifier_call_chain(&ghes_report_chain, sev, mem_err); 701 684 702 685 arch_apei_report_mem_error(sev, mem_err); 703 - queued = ghes_handle_memory_failure(gdata, sev); 686 + queued = ghes_handle_memory_failure(gdata, sev, sync); 704 687 } 705 688 else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { 706 689 ghes_handle_aer(gdata); 707 690 } 708 691 else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { 709 - queued = ghes_handle_arm_hw_error(gdata, sev); 692 + queued = ghes_handle_arm_hw_error(gdata, sev, sync); 710 693 } else { 711 694 void *err = acpi_hest_get_payload(gdata); 712 695
+1 -1
drivers/platform/chrome/cros_ec_debugfs.c
··· 454 454 debug_info->panicinfo_blob.data = data; 455 455 debug_info->panicinfo_blob.size = ret; 456 456 457 - debugfs_create_blob("panicinfo", S_IFREG | 0444, debug_info->dir, 457 + debugfs_create_blob("panicinfo", 0444, debug_info->dir, 458 458 &debug_info->panicinfo_blob); 459 459 460 460 return 0;
+23 -5
fs/debugfs/file.c
··· 1100 1100 return r; 1101 1101 } 1102 1102 1103 + static ssize_t write_file_blob(struct file *file, const char __user *user_buf, 1104 + size_t count, loff_t *ppos) 1105 + { 1106 + struct debugfs_blob_wrapper *blob = file->private_data; 1107 + struct dentry *dentry = F_DENTRY(file); 1108 + ssize_t r; 1109 + 1110 + r = debugfs_file_get(dentry); 1111 + if (unlikely(r)) 1112 + return r; 1113 + r = simple_write_to_buffer(blob->data, blob->size, ppos, user_buf, 1114 + count); 1115 + 1116 + debugfs_file_put(dentry); 1117 + return r; 1118 + } 1119 + 1103 1120 static const struct file_operations fops_blob = { 1104 1121 .read = read_file_blob, 1122 + .write = write_file_blob, 1105 1123 .open = simple_open, 1106 1124 .llseek = default_llseek, 1107 1125 }; 1108 1126 1109 1127 /** 1110 - * debugfs_create_blob - create a debugfs file that is used to read a binary blob 1128 + * debugfs_create_blob - create a debugfs file that is used to read and write 1129 + * a binary blob 1111 1130 * @name: a pointer to a string containing the name of the file to create. 1112 - * @mode: the read permission that the file should have (other permissions are 1113 - * masked out) 1131 + * @mode: the permission that the file should have 1114 1132 * @parent: a pointer to the parent dentry for this file. This should be a 1115 1133 * directory dentry if set. If this parameter is %NULL, then the 1116 1134 * file will be created in the root of the debugfs filesystem. ··· 1137 1119 * 1138 1120 * This function creates a file in debugfs with the given name that exports 1139 1121 * @blob->data as a binary blob. If the @mode variable is so set it can be 1140 - * read from. Writing is not supported. 1122 + * read from and written to. 1141 1123 * 1142 1124 * This function will return a pointer to a dentry if it succeeds. This 1143 1125 * pointer must be passed to the debugfs_remove() function when the file is ··· 1152 1134 struct dentry *parent, 1153 1135 struct debugfs_blob_wrapper *blob) 1154 1136 { 1155 - return debugfs_create_file_unsafe(name, mode & 0444, parent, blob, &fops_blob); 1137 + return debugfs_create_file_unsafe(name, mode & 0644, parent, blob, &fops_blob); 1156 1138 } 1157 1139 EXPORT_SYMBOL_GPL(debugfs_create_blob); 1158 1140
+9
include/acpi/video.h
··· 75 75 return __acpi_video_get_backlight_type(false, NULL); 76 76 } 77 77 78 + /* 79 + * This function MUST only be called by GPU drivers to check if the driver 80 + * should register a backlight class device. This function not only checks 81 + * if a GPU native backlight device should be registered it *also* tells 82 + * the ACPI video-detect code that native GPU backlight control is available. 83 + * Therefor calling this from any place other then the GPU driver is wrong! 84 + * To check if GPU native backlight control is used in other places instead use: 85 + * if (acpi_video_get_backlight_type() == acpi_backlight_native) { ... } 86 + */ 78 87 static inline bool acpi_video_backlight_use_native(void) 79 88 { 80 89 return __acpi_video_get_backlight_type(true, NULL) == acpi_backlight_native;