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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull ACPI fix from Rafael Wysocki:
"This fixes EINJV2 support introduced during the 6.17 cycle by
unbreaking the initialization broken by a previous attempted fix,
adding sanity checks for data coming from the platform firmware, and
updating the code to handle injecting legacy error types on an EINJV2
capable systems properly (Tony Luck)"

* tag 'acpi-6.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI: APEI: EINJ: Fix EINJV2 initialization and injection

+41 -23
+41 -23
drivers/acpi/apei/einj-core.c
··· 182 182 183 183 static void __iomem *einj_param; 184 184 static u32 v5param_size; 185 + static u32 v66param_size; 185 186 static bool is_v2; 186 187 187 188 static void einj_exec_ctx_init(struct apei_exec_context *ctx) ··· 284 283 acpi_os_unmap_iomem(p, sizeof(v)); 285 284 } 286 285 286 + static u32 einjv2_init(struct einjv2_extension_struct *e) 287 + { 288 + if (e->revision != 1) { 289 + pr_info("Unknown v2 extension revision %u\n", e->revision); 290 + return 0; 291 + } 292 + if (e->length < sizeof(*e) || e->length > PAGE_SIZE) { 293 + pr_info(FW_BUG "Bad1 v2 extension length %u\n", e->length); 294 + return 0; 295 + } 296 + if ((e->length - sizeof(*e)) % sizeof(e->component_arr[0])) { 297 + pr_info(FW_BUG "Bad2 v2 extension length %u\n", e->length); 298 + return 0; 299 + } 300 + 301 + return (e->length - sizeof(*e)) / sizeof(e->component_arr[0]); 302 + } 303 + 287 304 static void __iomem *einj_get_parameter_address(void) 288 305 { 289 306 int i; ··· 329 310 v5param_size = sizeof(v5param); 330 311 p = acpi_os_map_iomem(pa_v5, sizeof(*p)); 331 312 if (p) { 332 - int offset, len; 333 - 334 313 memcpy_fromio(&v5param, p, v5param_size); 335 314 acpi5 = 1; 336 315 check_vendor_extension(pa_v5, &v5param); 337 - if (is_v2 && available_error_type & ACPI65_EINJV2_SUPP) { 338 - len = v5param.einjv2_struct.length; 339 - offset = offsetof(struct einjv2_extension_struct, component_arr); 340 - max_nr_components = (len - offset) / 341 - sizeof(v5param.einjv2_struct.component_arr[0]); 342 - /* 343 - * The first call to acpi_os_map_iomem above does not include the 344 - * component array, instead it is used to read and calculate maximum 345 - * number of components supported by the system. Below, the mapping 346 - * is expanded to include the component array. 347 - */ 316 + if (available_error_type & ACPI65_EINJV2_SUPP) { 317 + struct einjv2_extension_struct *e; 318 + 319 + e = &v5param.einjv2_struct; 320 + max_nr_components = einjv2_init(e); 321 + 322 + /* remap including einjv2_extension_struct */ 348 323 acpi_os_unmap_iomem(p, v5param_size); 349 - offset = offsetof(struct set_error_type_with_address, einjv2_struct); 350 - v5param_size = offset + struct_size(&v5param.einjv2_struct, 351 - component_arr, max_nr_components); 352 - p = acpi_os_map_iomem(pa_v5, v5param_size); 324 + v66param_size = v5param_size - sizeof(*e) + e->length; 325 + p = acpi_os_map_iomem(pa_v5, v66param_size); 353 326 } 327 + 354 328 return p; 355 329 } 356 330 } ··· 539 527 u64 param3, u64 param4) 540 528 { 541 529 struct apei_exec_context ctx; 530 + u32 param_size = is_v2 ? v66param_size : v5param_size; 542 531 u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; 543 532 int i, rc; 544 533 ··· 552 539 if (acpi5) { 553 540 struct set_error_type_with_address *v5param; 554 541 555 - v5param = kmalloc(v5param_size, GFP_KERNEL); 542 + v5param = kmalloc(param_size, GFP_KERNEL); 556 543 if (!v5param) 557 544 return -ENOMEM; 558 545 559 - memcpy_fromio(v5param, einj_param, v5param_size); 546 + memcpy_fromio(v5param, einj_param, param_size); 560 547 v5param->type = type; 561 548 if (type & ACPI5_VENDOR_BIT) { 562 549 switch (vendor_flags) { ··· 614 601 break; 615 602 } 616 603 } 617 - memcpy_toio(einj_param, v5param, v5param_size); 604 + memcpy_toio(einj_param, v5param, param_size); 618 605 kfree(v5param); 619 606 } else { 620 607 rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE); ··· 1145 1132 struct apei_exec_context ctx; 1146 1133 1147 1134 if (einj_param) { 1148 - acpi_size size = (acpi5) ? 1149 - v5param_size : 1150 - sizeof(struct einj_parameter); 1135 + acpi_size size; 1136 + 1137 + if (v66param_size) 1138 + size = v66param_size; 1139 + else if (acpi5) 1140 + size = v5param_size; 1141 + else 1142 + size = sizeof(struct einj_parameter); 1151 1143 1152 1144 acpi_os_unmap_iomem(einj_param, size); 1153 1145 if (vendor_errors.size)