[PATCH v2] powerpc/powernv: Cache OPAL check_token() results
From: Shivang Upadhyay <hidden>
Date: 2026-06-26 12:36:00
Also in:
lkml
Subsystem:
linux for powerpc (32-bit and 64-bit), the rest · Maintainers:
Madhavan Srinivasan, Michael Ellerman, Linus Torvalds
`opal_check_token()` function is used to determine if a specific OPAL firmware call is supported on the current platform. This check is performed frequently during boot and runtime, resulting in unnecessary firmware calls for the same token values. Add a caching layer for the opal_check_token() OPAL call to avoid repeated firmware calls for token availability checks. This reduces firmware call overhead during boot. Testing with buildroot images shows OPAL calls reduced from 35578 to 28983, before console bring-up. Signed-off-by: Shivang Upadhyay <redacted> --- Changelog: * v1: https://lore.kernel.org/all/20260601112520.161605-1-shivangu@linux.ibm.com/ (local) - implemented tri-state check as suggestd by Sourabh. - made the implementation more clear. --- arch/powerpc/include/asm/opal.h | 1 + arch/powerpc/platforms/powernv/opal-call.c | 2 +- arch/powerpc/platforms/powernv/opal.c | 30 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 0a398265ba04..e7e11479122b 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h@@ -156,6 +156,7 @@ int64_t opal_pci_next_error(uint64_t phb_id, __be64 *first_frozen_pe, int64_t opal_pci_poll(uint64_t id); int64_t opal_return_cpu(void); int64_t opal_check_token(uint64_t token); +int64_t opal_check_token_call(uint64_t token); int64_t opal_reinit_cpus(uint64_t flags); int64_t opal_xscom_read(uint32_t gcid, uint64_t pcb_addr, __be64 *val);
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 021b0ec29e24..00325c189e69 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c@@ -207,7 +207,7 @@ OPAL_CALL(opal_validate_flash, OPAL_FLASH_VALIDATE); OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE); OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); OPAL_CALL(opal_resync_timebase, OPAL_RESYNC_TIMEBASE); -OPAL_CALL(opal_check_token, OPAL_CHECK_TOKEN); +OPAL_CALL(opal_check_token_call, OPAL_CHECK_TOKEN); OPAL_CALL(opal_dump_init, OPAL_DUMP_INIT); OPAL_CALL(opal_dump_info, OPAL_DUMP_INFO); OPAL_CALL(opal_dump_info2, OPAL_DUMP_INFO2);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 1946dbdc9fa1..1e9cb5271ee7 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c@@ -1125,6 +1125,36 @@ EXPORT_SYMBOL_GPL(opal_flash_read); EXPORT_SYMBOL_GPL(opal_flash_write); EXPORT_SYMBOL_GPL(opal_flash_erase); EXPORT_SYMBOL_GPL(opal_prd_msg); + +/** + * opal_check_token - Check if an OPAL call token is supported + * @token: OPAL token number to check + * + * Returns 1 if supported, 0 if not. + */ +int64_t opal_check_token(uint64_t token) +{ + static u8 token_cache[OPAL_LAST]; + enum { + SUPP_UNKNOWN = 0, + PRESENT, + ABSENT + }; + + if (token > OPAL_LAST) + return 0; + + if (token_cache[token] == SUPP_UNKNOWN) { + /* Do the actual opal_call here */ + if (opal_check_token_call(token)) { + token_cache[token] = PRESENT; + } else { + token_cache[token] = ABSENT; + } + } + + return (token_cache[token] == PRESENT); +} EXPORT_SYMBOL_GPL(opal_check_token); /* Convert a region of vmalloc memory to an opal sg list */
--
2.54.0