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.

ACPI: APEI: GHES: Extract helper functions for error status handling

Refactors the GHES driver by extracting common functionality into
reusable helper functions:

1. ghes_has_active_errors() - Checks if any error sources in a given list
have active errors
2. ghes_map_error_status() - Maps error status address to virtual address
3. ghes_unmap_error_status() - Unmaps error status virtual address
4. Use `guard(rcu)()` instead of explicit `rcu_read_lock()`/`rcu_read_unlock()`.

These helpers eliminate code duplication in the NMI path and prepare for
similar usage in the SEA path in a subsequent patch.

No functional change intended.

Tested-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
Link: https://patch.msgid.link/20260112032239.30023-3-xueshuai@linux.alibaba.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Shuai Xue and committed by
Rafael J. Wysocki
feb2d380 f2edc1fb

+68 -21
+68 -21
drivers/acpi/apei/ghes.c
··· 1434 1434 return ret; 1435 1435 } 1436 1436 1437 + /** 1438 + * ghes_has_active_errors - Check if there are active errors in error sources 1439 + * @ghes_list: List of GHES entries to check for active errors 1440 + * 1441 + * This function iterates through all GHES entries in the given list and 1442 + * checks if any of them has active error status by reading the error 1443 + * status register. 1444 + * 1445 + * Return: true if at least one source has active error, false otherwise. 1446 + */ 1447 + static bool __maybe_unused ghes_has_active_errors(struct list_head *ghes_list) 1448 + { 1449 + struct ghes *ghes; 1450 + 1451 + guard(rcu)(); 1452 + list_for_each_entry_rcu(ghes, ghes_list, list) { 1453 + if (ghes->error_status_vaddr && 1454 + readl(ghes->error_status_vaddr)) 1455 + return true; 1456 + } 1457 + 1458 + return false; 1459 + } 1460 + 1461 + /** 1462 + * ghes_map_error_status - Map error status address to virtual address 1463 + * @ghes: pointer to GHES structure 1464 + * 1465 + * Reads the error status address from ACPI HEST table and maps it to a virtual 1466 + * address that can be accessed by the kernel. 1467 + * 1468 + * Return: 0 on success, error code on failure. 1469 + */ 1470 + static int __maybe_unused ghes_map_error_status(struct ghes *ghes) 1471 + { 1472 + struct acpi_hest_generic *g = ghes->generic; 1473 + u64 paddr; 1474 + int rc; 1475 + 1476 + rc = apei_read(&paddr, &g->error_status_address); 1477 + if (rc) 1478 + return rc; 1479 + 1480 + ghes->error_status_vaddr = 1481 + acpi_os_ioremap(paddr, sizeof(ghes->estatus->block_status)); 1482 + if (!ghes->error_status_vaddr) 1483 + return -EINVAL; 1484 + 1485 + return 0; 1486 + } 1487 + 1488 + /** 1489 + * ghes_unmap_error_status - Unmap error status virtual address 1490 + * @ghes: pointer to GHES structure 1491 + * 1492 + * Unmaps the error status address if it was previously mapped. 1493 + */ 1494 + static void __maybe_unused ghes_unmap_error_status(struct ghes *ghes) 1495 + { 1496 + if (ghes->error_status_vaddr) { 1497 + iounmap(ghes->error_status_vaddr); 1498 + ghes->error_status_vaddr = NULL; 1499 + } 1500 + } 1501 + 1437 1502 #ifdef CONFIG_ACPI_APEI_SEA 1438 1503 static LIST_HEAD(ghes_sea); 1439 1504 ··· 1549 1484 static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) 1550 1485 { 1551 1486 static DEFINE_RAW_SPINLOCK(ghes_notify_lock_nmi); 1552 - bool active_error = false; 1553 1487 int ret = NMI_DONE; 1554 - struct ghes *ghes; 1555 1488 1556 - rcu_read_lock(); 1557 - list_for_each_entry_rcu(ghes, &ghes_nmi, list) { 1558 - if (ghes->error_status_vaddr && readl(ghes->error_status_vaddr)) { 1559 - active_error = true; 1560 - break; 1561 - } 1562 - } 1563 - rcu_read_unlock(); 1564 - 1565 - if (!active_error) 1489 + if (!ghes_has_active_errors(&ghes_nmi)) 1566 1490 return ret; 1567 1491 1568 1492 if (!atomic_add_unless(&ghes_in_nmi, 1, 1)) ··· 1568 1514 1569 1515 static int ghes_nmi_add(struct ghes *ghes) 1570 1516 { 1571 - struct acpi_hest_generic *g = ghes->generic; 1572 - u64 paddr; 1573 1517 int rc; 1574 1518 1575 - rc = apei_read(&paddr, &g->error_status_address); 1519 + rc = ghes_map_error_status(ghes); 1576 1520 if (rc) 1577 1521 return rc; 1578 - 1579 - ghes->error_status_vaddr = acpi_os_ioremap(paddr, sizeof(ghes->estatus->block_status)); 1580 - if (!ghes->error_status_vaddr) 1581 - return -EINVAL; 1582 1522 1583 1523 mutex_lock(&ghes_list_mutex); 1584 1524 if (list_empty(&ghes_nmi)) ··· 1591 1543 unregister_nmi_handler(NMI_LOCAL, "ghes"); 1592 1544 mutex_unlock(&ghes_list_mutex); 1593 1545 1594 - if (ghes->error_status_vaddr) 1595 - iounmap(ghes->error_status_vaddr); 1546 + ghes_unmap_error_status(ghes); 1596 1547 1597 1548 /* 1598 1549 * To synchronize with NMI handler, ghes can only be