Message ID | 20230125-b4-powerpc-rtas-queue-v2-18-9aa6bd058063@linux.ibm.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | RTAS maintenance | expand |
Nathan Lynch via B4 Submission Endpoint <devnull+nathanl.linux.ibm.com@kernel.org> writes: > From: Nathan Lynch <nathanl@linux.ibm.com> > > Users of rtas_token() supply a string argument that can't be validated > at build time. A typo or misspelling has to be caught by inspection or > by observing wrong behavior at runtime. > > Since the core RTAS code now has consolidated the names of all > possible RTAS functions and mapped them to their tokens, token lookup > can be implemented using symbolic constants to index a static array. > > So introduce rtas_function_token(), a replacement API which does that, > along with a rtas_service_present()-equivalent helper, > rtas_function_implemented(). Callers supply an opaque predefined > function handle which is used internally to index the function > table. Typos or other inappropriate arguments yield build errors, and > the function handle is a type that can't be easily confused with RTAS > tokens or other integer types. Why not go all the way and have the rtas_call() signature be: int rtas_call(rtas_fn_handle_t fn, int, int, int *, ...); And have it do the token lookup internally? That way a caller can never inadvertantly pass a random integer to rtas_call(). And instead of eg: error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret); we'd just need: error = rtas_call(RTAS_FN_GET_TIME_OF_DAY, 0, 8, ret); Doing the conversion all at once might be tricky. So maybe we need to add rtas_fn_call() which takes rtas_fn_handle_t so we can convert cases individually? Anyway just a thought. I guess we could merge this as-is and then do a further change to use rtas_fn_handle_t later. > diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h > index 14fe79217c26..fe400438c1fb 100644 > --- a/arch/powerpc/include/asm/rtas.h > +++ b/arch/powerpc/include/asm/rtas.h > @@ -103,6 +103,99 @@ enum rtas_function_index { > rtas_fnidx(WRITE_PCI_CONFIG), > }; > > +/* > + * Opaque handle for client code to refer to RTAS functions. All valid > + * function handles are build-time constants prefixed with RTAS_FN_. > + */ > +typedef struct { > + const enum rtas_function_index index; > +} rtas_fn_handle_t; > + > +#define rtas_fn_handle(x_) ((const rtas_fn_handle_t) { .index = rtas_fnidx(x_), }) > + > +#define RTAS_FN_CHECK_EXCEPTION rtas_fn_handle(CHECK_EXCEPTION) > +#define RTAS_FN_DISPLAY_CHARACTER rtas_fn_handle(DISPLAY_CHARACTER) > +#define RTAS_FN_EVENT_SCAN rtas_fn_handle(EVENT_SCAN) > +#define RTAS_FN_FREEZE_TIME_BASE rtas_fn_handle(FREEZE_TIME_BASE) > +#define RTAS_FN_GET_POWER_LEVEL rtas_fn_handle(GET_POWER_LEVEL) > +#define RTAS_FN_GET_SENSOR_STATE rtas_fn_handle(GET_SENSOR_STATE) > +#define RTAS_FN_GET_TERM_CHAR rtas_fn_handle(GET_TERM_CHAR) > +#define RTAS_FN_GET_TIME_OF_DAY rtas_fn_handle(GET_TIME_OF_DAY) > +#define RTAS_FN_IBM_ACTIVATE_FIRMWARE rtas_fn_handle(IBM_ACTIVATE_FIRMWARE) > +#define RTAS_FN_IBM_CBE_START_PTCAL rtas_fn_handle(IBM_CBE_START_PTCAL) > +#define RTAS_FN_IBM_CBE_STOP_PTCAL rtas_fn_handle(IBM_CBE_STOP_PTCAL) > +#define RTAS_FN_IBM_CHANGE_MSI rtas_fn_handle(IBM_CHANGE_MSI) > +#define RTAS_FN_IBM_CLOSE_ERRINJCT rtas_fn_handle(IBM_CLOSE_ERRINJCT) > +#define RTAS_FN_IBM_CONFIGURE_BRIDGE rtas_fn_handle(IBM_CONFIGURE_BRIDGE) > +#define RTAS_FN_IBM_CONFIGURE_CONNECTOR rtas_fn_handle(IBM_CONFIGURE_CONNECTOR) > +#define RTAS_FN_IBM_CONFIGURE_KERNEL_DUMP rtas_fn_handle(IBM_CONFIGURE_KERNEL_DUMP) > +#define RTAS_FN_IBM_CONFIGURE_PE rtas_fn_handle(IBM_CONFIGURE_PE) > +#define RTAS_FN_IBM_CREATE_PE_DMA_WINDOW rtas_fn_handle(IBM_CREATE_PE_DMA_WINDOW) > +#define RTAS_FN_IBM_DISPLAY_MESSAGE rtas_fn_handle(IBM_DISPLAY_MESSAGE) > +#define RTAS_FN_IBM_ERRINJCT rtas_fn_handle(IBM_ERRINJCT) > +#define RTAS_FN_IBM_EXTI2C rtas_fn_handle(IBM_EXTI2C) > +#define RTAS_FN_IBM_GET_CONFIG_ADDR_INFO rtas_fn_handle(IBM_GET_CONFIG_ADDR_INFO) > +#define RTAS_FN_IBM_GET_CONFIG_ADDR_INFO2 rtas_fn_handle(IBM_GET_CONFIG_ADDR_INFO2) > +#define RTAS_FN_IBM_GET_DYNAMIC_SENSOR_STATE rtas_fn_handle(IBM_GET_DYNAMIC_SENSOR_STATE) > +#define RTAS_FN_IBM_GET_INDICES rtas_fn_handle(IBM_GET_INDICES) > +#define RTAS_FN_IBM_GET_RIO_TOPOLOGY rtas_fn_handle(IBM_GET_RIO_TOPOLOGY) > +#define RTAS_FN_IBM_GET_SYSTEM_PARAMETER rtas_fn_handle(IBM_GET_SYSTEM_PARAMETER) > +#define RTAS_FN_IBM_GET_VPD rtas_fn_handle(IBM_GET_VPD) > +#define RTAS_FN_IBM_GET_XIVE rtas_fn_handle(IBM_GET_XIVE) > +#define RTAS_FN_IBM_INT_OFF rtas_fn_handle(IBM_INT_OFF) > +#define RTAS_FN_IBM_INT_ON rtas_fn_handle(IBM_INT_ON) > +#define RTAS_FN_IBM_IO_QUIESCE_ACK rtas_fn_handle(IBM_IO_QUIESCE_ACK) > +#define RTAS_FN_IBM_LPAR_PERFTOOLS rtas_fn_handle(IBM_LPAR_PERFTOOLS) > +#define RTAS_FN_IBM_MANAGE_FLASH_IMAGE rtas_fn_handle(IBM_MANAGE_FLASH_IMAGE) > +#define RTAS_FN_IBM_MANAGE_STORAGE_PRESERVATION rtas_fn_handle(IBM_MANAGE_STORAGE_PRESERVATION) > +#define RTAS_FN_IBM_NMI_INTERLOCK rtas_fn_handle(IBM_NMI_INTERLOCK) > +#define RTAS_FN_IBM_NMI_REGISTER rtas_fn_handle(IBM_NMI_REGISTER) > +#define RTAS_FN_IBM_OPEN_ERRINJCT rtas_fn_handle(IBM_OPEN_ERRINJCT) > +#define RTAS_FN_IBM_OPEN_SRIOV_ALLOW_UNFREEZE rtas_fn_handle(IBM_OPEN_SRIOV_ALLOW_UNFREEZE) > +#define RTAS_FN_IBM_OPEN_SRIOV_MAP_PE_NUMBER rtas_fn_handle(IBM_OPEN_SRIOV_MAP_PE_NUMBER) > +#define RTAS_FN_IBM_OS_TERM rtas_fn_handle(IBM_OS_TERM) > +#define RTAS_FN_IBM_PARTNER_CONTROL rtas_fn_handle(IBM_PARTNER_CONTROL) > +#define RTAS_FN_IBM_PHYSICAL_ATTESTATION rtas_fn_handle(IBM_PHYSICAL_ATTESTATION) > +#define RTAS_FN_IBM_PLATFORM_DUMP rtas_fn_handle(IBM_PLATFORM_DUMP) > +#define RTAS_FN_IBM_POWER_OFF_UPS rtas_fn_handle(IBM_POWER_OFF_UPS) > +#define RTAS_FN_IBM_QUERY_INTERRUPT_SOURCE_NUMBER rtas_fn_handle(IBM_QUERY_INTERRUPT_SOURCE_NUMBER) > +#define RTAS_FN_IBM_QUERY_PE_DMA_WINDOW rtas_fn_handle(IBM_QUERY_PE_DMA_WINDOW) > +#define RTAS_FN_IBM_READ_PCI_CONFIG rtas_fn_handle(IBM_READ_PCI_CONFIG) > +#define RTAS_FN_IBM_READ_SLOT_RESET_STATE rtas_fn_handle(IBM_READ_SLOT_RESET_STATE) > +#define RTAS_FN_IBM_READ_SLOT_RESET_STATE2 rtas_fn_handle(IBM_READ_SLOT_RESET_STATE2) > +#define RTAS_FN_IBM_REMOVE_PE_DMA_WINDOW rtas_fn_handle(IBM_REMOVE_PE_DMA_WINDOW) > +#define RTAS_FN_IBM_RESET_PE_DMA_WINDOWS rtas_fn_handle(IBM_RESET_PE_DMA_WINDOWS) > +#define RTAS_FN_IBM_SCAN_LOG_DUMP rtas_fn_handle(IBM_SCAN_LOG_DUMP) > +#define RTAS_FN_IBM_SET_DYNAMIC_INDICATOR rtas_fn_handle(IBM_SET_DYNAMIC_INDICATOR) > +#define RTAS_FN_IBM_SET_EEH_OPTION rtas_fn_handle(IBM_SET_EEH_OPTION) > +#define RTAS_FN_IBM_SET_SLOT_RESET rtas_fn_handle(IBM_SET_SLOT_RESET) > +#define RTAS_FN_IBM_SET_SYSTEM_PARAMETER rtas_fn_handle(IBM_SET_SYSTEM_PARAMETER) > +#define RTAS_FN_IBM_SET_XIVE rtas_fn_handle(IBM_SET_XIVE) > +#define RTAS_FN_IBM_SLOT_ERROR_DETAIL rtas_fn_handle(IBM_SLOT_ERROR_DETAIL) > +#define RTAS_FN_IBM_SUSPEND_ME rtas_fn_handle(IBM_SUSPEND_ME) > +#define RTAS_FN_IBM_TUNE_DMA_PARMS rtas_fn_handle(IBM_TUNE_DMA_PARMS) > +#define RTAS_FN_IBM_UPDATE_FLASH_64_AND_REBOOT rtas_fn_handle(IBM_UPDATE_FLASH_64_AND_REBOOT) > +#define RTAS_FN_IBM_UPDATE_NODES rtas_fn_handle(IBM_UPDATE_NODES) > +#define RTAS_FN_IBM_UPDATE_PROPERTIES rtas_fn_handle(IBM_UPDATE_PROPERTIES) > +#define RTAS_FN_IBM_VALIDATE_FLASH_IMAGE rtas_fn_handle(IBM_VALIDATE_FLASH_IMAGE) > +#define RTAS_FN_IBM_WRITE_PCI_CONFIG rtas_fn_handle(IBM_WRITE_PCI_CONFIG) > +#define RTAS_FN_NVRAM_FETCH rtas_fn_handle(NVRAM_FETCH) > +#define RTAS_FN_NVRAM_STORE rtas_fn_handle(NVRAM_STORE) > +#define RTAS_FN_POWER_OFF rtas_fn_handle(POWER_OFF) > +#define RTAS_FN_PUT_TERM_CHAR rtas_fn_handle(PUT_TERM_CHAR) > +#define RTAS_FN_QUERY_CPU_STOPPED_STATE rtas_fn_handle(QUERY_CPU_STOPPED_STATE) > +#define RTAS_FN_READ_PCI_CONFIG rtas_fn_handle(READ_PCI_CONFIG) > +#define RTAS_FN_RTAS_LAST_ERROR rtas_fn_handle(RTAS_LAST_ERROR) > +#define RTAS_FN_SET_INDICATOR rtas_fn_handle(SET_INDICATOR) > +#define RTAS_FN_SET_POWER_LEVEL rtas_fn_handle(SET_POWER_LEVEL) > +#define RTAS_FN_SET_TIME_FOR_POWER_ON rtas_fn_handle(SET_TIME_FOR_POWER_ON) > +#define RTAS_FN_SET_TIME_OF_DAY rtas_fn_handle(SET_TIME_OF_DAY) > +#define RTAS_FN_START_CPU rtas_fn_handle(START_CPU) > +#define RTAS_FN_STOP_SELF rtas_fn_handle(STOP_SELF) > +#define RTAS_FN_SYSTEM_REBOOT rtas_fn_handle(SYSTEM_REBOOT) > +#define RTAS_FN_THAW_TIME_BASE rtas_fn_handle(THAW_TIME_BASE) > +#define RTAS_FN_WRITE_PCI_CONFIG rtas_fn_handle(WRITE_PCI_CONFIG) > + > #define RTAS_UNKNOWN_SERVICE (-1) > #define RTAS_INSTANTIATE_MAX (1ULL<<30) /* Don't instantiate rtas at/above this value */ > > @@ -309,6 +402,11 @@ extern void (*rtas_flash_term_hook)(int); > > extern struct rtas_t rtas; > > +s32 rtas_function_token(const rtas_fn_handle_t handle); > +static inline bool rtas_function_implemented(const rtas_fn_handle_t handle) > +{ > + return rtas_function_token(handle) != RTAS_UNKNOWN_SERVICE; > +} > extern int rtas_token(const char *service); > extern int rtas_service_present(const char *service); > extern int rtas_call(int token, int, int, int *, ...); > diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c > index 41c430dc40c2..17e59306ce63 100644 > --- a/arch/powerpc/kernel/rtas.c > +++ b/arch/powerpc/kernel/rtas.c > @@ -453,6 +453,26 @@ static struct rtas_function rtas_function_table[] __ro_after_init = { > }, > }; > > +/** > + * rtas_function_token() - RTAS function token lookup. > + * @handle: Function handle, e.g. RTAS_FN_EVENT_SCAN. > + * > + * Context: Any context. > + * Return: the token value for the function if implemented by this platform, > + * otherwise RTAS_UNKNOWN_SERVICE. > + */ > +s32 rtas_function_token(const rtas_fn_handle_t handle) > +{ > + const size_t index = handle.index; > + const bool out_of_bounds = index >= ARRAY_SIZE(rtas_function_table); > + > + if (WARN_ONCE(out_of_bounds, "invalid function index %zu", index)) > + return RTAS_UNKNOWN_SERVICE; This needs: + // If RTAS is not present or not initialised (yet) return unknown + if (!rtas.dev) + return RTAS_UNKNOWN_SERVICE; + Otherwise powernv breaks because it looks up tokens and gets back 0, because we never got as far as rtas_function_table_init() (to set all the tokens to RTAS_UNKNOWN_SERVICE), because we bailed out at the start of rtas_initialize() when we found no /rtas node. > + return rtas_function_table[index].token; > +} > +EXPORT_SYMBOL_GPL(rtas_function_token); > + > static int rtas_function_cmp(const void *a, const void *b) > { > const struct rtas_function *f1 = a; cheers
Michael Ellerman <mpe@ellerman.id.au> writes: > Nathan Lynch via B4 Submission Endpoint > <devnull+nathanl.linux.ibm.com@kernel.org> writes: >> From: Nathan Lynch <nathanl@linux.ibm.com> >> >> Users of rtas_token() supply a string argument that can't be validated >> at build time. A typo or misspelling has to be caught by inspection or >> by observing wrong behavior at runtime. >> >> Since the core RTAS code now has consolidated the names of all >> possible RTAS functions and mapped them to their tokens, token lookup >> can be implemented using symbolic constants to index a static array. >> >> So introduce rtas_function_token(), a replacement API which does that, >> along with a rtas_service_present()-equivalent helper, >> rtas_function_implemented(). Callers supply an opaque predefined >> function handle which is used internally to index the function >> table. Typos or other inappropriate arguments yield build errors, and >> the function handle is a type that can't be easily confused with RTAS >> tokens or other integer types. > > Why not go all the way and have the rtas_call() signature be: > > int rtas_call(rtas_fn_handle_t fn, int, int, int *, ...); > > > And have it do the token lookup internally? That way a caller can never > inadvertantly pass a random integer to rtas_call(). > > And instead of eg: > > error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret); > > we'd just need: > > error = rtas_call(RTAS_FN_GET_TIME_OF_DAY, 0, 8, ret); > > > Doing the conversion all at once might be tricky. So maybe we need to add > rtas_fn_call() which takes rtas_fn_handle_t so we can convert cases individually? > > Anyway just a thought. I guess we could merge this as-is and then do a > further change to use rtas_fn_handle_t later. You read my mind :-) But I want to go further and make the eventual replacement for rtas_call() non-variadic, which will eliminate another class of usage error. Getting more ambitious: the ideal situation IMO would be that every use of rtas_call() or its replacement is tidily contained in a C function in kernel/rtas.c, where complexities like retries and error code translation can be performed in a uniform way. Anyway, a transition away from rtas_call(), whatever form it takes, probably needs to happen incrementally. >> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c >> index 41c430dc40c2..17e59306ce63 100644 >> --- a/arch/powerpc/kernel/rtas.c >> +++ b/arch/powerpc/kernel/rtas.c >> @@ -453,6 +453,26 @@ static struct rtas_function rtas_function_table[] __ro_after_init = { >> }, >> }; >> >> +/** >> + * rtas_function_token() - RTAS function token lookup. >> + * @handle: Function handle, e.g. RTAS_FN_EVENT_SCAN. >> + * >> + * Context: Any context. >> + * Return: the token value for the function if implemented by this platform, >> + * otherwise RTAS_UNKNOWN_SERVICE. >> + */ >> +s32 rtas_function_token(const rtas_fn_handle_t handle) >> +{ >> + const size_t index = handle.index; >> + const bool out_of_bounds = index >= ARRAY_SIZE(rtas_function_table); >> + >> + if (WARN_ONCE(out_of_bounds, "invalid function index %zu", index)) >> + return RTAS_UNKNOWN_SERVICE; > > This needs: > > + // If RTAS is not present or not initialised (yet) return unknown > + if (!rtas.dev) > + return RTAS_UNKNOWN_SERVICE; > + > > Otherwise powernv breaks because it looks up tokens and gets back 0, > because we never got as far as rtas_function_table_init() (to set all the > tokens to RTAS_UNKNOWN_SERVICE), because we bailed out at the start of > rtas_initialize() when we found no /rtas node. Oh! OK, thanks.
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 14fe79217c26..fe400438c1fb 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -103,6 +103,99 @@ enum rtas_function_index { rtas_fnidx(WRITE_PCI_CONFIG), }; +/* + * Opaque handle for client code to refer to RTAS functions. All valid + * function handles are build-time constants prefixed with RTAS_FN_. + */ +typedef struct { + const enum rtas_function_index index; +} rtas_fn_handle_t; + +#define rtas_fn_handle(x_) ((const rtas_fn_handle_t) { .index = rtas_fnidx(x_), }) + +#define RTAS_FN_CHECK_EXCEPTION rtas_fn_handle(CHECK_EXCEPTION) +#define RTAS_FN_DISPLAY_CHARACTER rtas_fn_handle(DISPLAY_CHARACTER) +#define RTAS_FN_EVENT_SCAN rtas_fn_handle(EVENT_SCAN) +#define RTAS_FN_FREEZE_TIME_BASE rtas_fn_handle(FREEZE_TIME_BASE) +#define RTAS_FN_GET_POWER_LEVEL rtas_fn_handle(GET_POWER_LEVEL) +#define RTAS_FN_GET_SENSOR_STATE rtas_fn_handle(GET_SENSOR_STATE) +#define RTAS_FN_GET_TERM_CHAR rtas_fn_handle(GET_TERM_CHAR) +#define RTAS_FN_GET_TIME_OF_DAY rtas_fn_handle(GET_TIME_OF_DAY) +#define RTAS_FN_IBM_ACTIVATE_FIRMWARE rtas_fn_handle(IBM_ACTIVATE_FIRMWARE) +#define RTAS_FN_IBM_CBE_START_PTCAL rtas_fn_handle(IBM_CBE_START_PTCAL) +#define RTAS_FN_IBM_CBE_STOP_PTCAL rtas_fn_handle(IBM_CBE_STOP_PTCAL) +#define RTAS_FN_IBM_CHANGE_MSI rtas_fn_handle(IBM_CHANGE_MSI) +#define RTAS_FN_IBM_CLOSE_ERRINJCT rtas_fn_handle(IBM_CLOSE_ERRINJCT) +#define RTAS_FN_IBM_CONFIGURE_BRIDGE rtas_fn_handle(IBM_CONFIGURE_BRIDGE) +#define RTAS_FN_IBM_CONFIGURE_CONNECTOR rtas_fn_handle(IBM_CONFIGURE_CONNECTOR) +#define RTAS_FN_IBM_CONFIGURE_KERNEL_DUMP rtas_fn_handle(IBM_CONFIGURE_KERNEL_DUMP) +#define RTAS_FN_IBM_CONFIGURE_PE rtas_fn_handle(IBM_CONFIGURE_PE) +#define RTAS_FN_IBM_CREATE_PE_DMA_WINDOW rtas_fn_handle(IBM_CREATE_PE_DMA_WINDOW) +#define RTAS_FN_IBM_DISPLAY_MESSAGE rtas_fn_handle(IBM_DISPLAY_MESSAGE) +#define RTAS_FN_IBM_ERRINJCT rtas_fn_handle(IBM_ERRINJCT) +#define RTAS_FN_IBM_EXTI2C rtas_fn_handle(IBM_EXTI2C) +#define RTAS_FN_IBM_GET_CONFIG_ADDR_INFO rtas_fn_handle(IBM_GET_CONFIG_ADDR_INFO) +#define RTAS_FN_IBM_GET_CONFIG_ADDR_INFO2 rtas_fn_handle(IBM_GET_CONFIG_ADDR_INFO2) +#define RTAS_FN_IBM_GET_DYNAMIC_SENSOR_STATE rtas_fn_handle(IBM_GET_DYNAMIC_SENSOR_STATE) +#define RTAS_FN_IBM_GET_INDICES rtas_fn_handle(IBM_GET_INDICES) +#define RTAS_FN_IBM_GET_RIO_TOPOLOGY rtas_fn_handle(IBM_GET_RIO_TOPOLOGY) +#define RTAS_FN_IBM_GET_SYSTEM_PARAMETER rtas_fn_handle(IBM_GET_SYSTEM_PARAMETER) +#define RTAS_FN_IBM_GET_VPD rtas_fn_handle(IBM_GET_VPD) +#define RTAS_FN_IBM_GET_XIVE rtas_fn_handle(IBM_GET_XIVE) +#define RTAS_FN_IBM_INT_OFF rtas_fn_handle(IBM_INT_OFF) +#define RTAS_FN_IBM_INT_ON rtas_fn_handle(IBM_INT_ON) +#define RTAS_FN_IBM_IO_QUIESCE_ACK rtas_fn_handle(IBM_IO_QUIESCE_ACK) +#define RTAS_FN_IBM_LPAR_PERFTOOLS rtas_fn_handle(IBM_LPAR_PERFTOOLS) +#define RTAS_FN_IBM_MANAGE_FLASH_IMAGE rtas_fn_handle(IBM_MANAGE_FLASH_IMAGE) +#define RTAS_FN_IBM_MANAGE_STORAGE_PRESERVATION rtas_fn_handle(IBM_MANAGE_STORAGE_PRESERVATION) +#define RTAS_FN_IBM_NMI_INTERLOCK rtas_fn_handle(IBM_NMI_INTERLOCK) +#define RTAS_FN_IBM_NMI_REGISTER rtas_fn_handle(IBM_NMI_REGISTER) +#define RTAS_FN_IBM_OPEN_ERRINJCT rtas_fn_handle(IBM_OPEN_ERRINJCT) +#define RTAS_FN_IBM_OPEN_SRIOV_ALLOW_UNFREEZE rtas_fn_handle(IBM_OPEN_SRIOV_ALLOW_UNFREEZE) +#define RTAS_FN_IBM_OPEN_SRIOV_MAP_PE_NUMBER rtas_fn_handle(IBM_OPEN_SRIOV_MAP_PE_NUMBER) +#define RTAS_FN_IBM_OS_TERM rtas_fn_handle(IBM_OS_TERM) +#define RTAS_FN_IBM_PARTNER_CONTROL rtas_fn_handle(IBM_PARTNER_CONTROL) +#define RTAS_FN_IBM_PHYSICAL_ATTESTATION rtas_fn_handle(IBM_PHYSICAL_ATTESTATION) +#define RTAS_FN_IBM_PLATFORM_DUMP rtas_fn_handle(IBM_PLATFORM_DUMP) +#define RTAS_FN_IBM_POWER_OFF_UPS rtas_fn_handle(IBM_POWER_OFF_UPS) +#define RTAS_FN_IBM_QUERY_INTERRUPT_SOURCE_NUMBER rtas_fn_handle(IBM_QUERY_INTERRUPT_SOURCE_NUMBER) +#define RTAS_FN_IBM_QUERY_PE_DMA_WINDOW rtas_fn_handle(IBM_QUERY_PE_DMA_WINDOW) +#define RTAS_FN_IBM_READ_PCI_CONFIG rtas_fn_handle(IBM_READ_PCI_CONFIG) +#define RTAS_FN_IBM_READ_SLOT_RESET_STATE rtas_fn_handle(IBM_READ_SLOT_RESET_STATE) +#define RTAS_FN_IBM_READ_SLOT_RESET_STATE2 rtas_fn_handle(IBM_READ_SLOT_RESET_STATE2) +#define RTAS_FN_IBM_REMOVE_PE_DMA_WINDOW rtas_fn_handle(IBM_REMOVE_PE_DMA_WINDOW) +#define RTAS_FN_IBM_RESET_PE_DMA_WINDOWS rtas_fn_handle(IBM_RESET_PE_DMA_WINDOWS) +#define RTAS_FN_IBM_SCAN_LOG_DUMP rtas_fn_handle(IBM_SCAN_LOG_DUMP) +#define RTAS_FN_IBM_SET_DYNAMIC_INDICATOR rtas_fn_handle(IBM_SET_DYNAMIC_INDICATOR) +#define RTAS_FN_IBM_SET_EEH_OPTION rtas_fn_handle(IBM_SET_EEH_OPTION) +#define RTAS_FN_IBM_SET_SLOT_RESET rtas_fn_handle(IBM_SET_SLOT_RESET) +#define RTAS_FN_IBM_SET_SYSTEM_PARAMETER rtas_fn_handle(IBM_SET_SYSTEM_PARAMETER) +#define RTAS_FN_IBM_SET_XIVE rtas_fn_handle(IBM_SET_XIVE) +#define RTAS_FN_IBM_SLOT_ERROR_DETAIL rtas_fn_handle(IBM_SLOT_ERROR_DETAIL) +#define RTAS_FN_IBM_SUSPEND_ME rtas_fn_handle(IBM_SUSPEND_ME) +#define RTAS_FN_IBM_TUNE_DMA_PARMS rtas_fn_handle(IBM_TUNE_DMA_PARMS) +#define RTAS_FN_IBM_UPDATE_FLASH_64_AND_REBOOT rtas_fn_handle(IBM_UPDATE_FLASH_64_AND_REBOOT) +#define RTAS_FN_IBM_UPDATE_NODES rtas_fn_handle(IBM_UPDATE_NODES) +#define RTAS_FN_IBM_UPDATE_PROPERTIES rtas_fn_handle(IBM_UPDATE_PROPERTIES) +#define RTAS_FN_IBM_VALIDATE_FLASH_IMAGE rtas_fn_handle(IBM_VALIDATE_FLASH_IMAGE) +#define RTAS_FN_IBM_WRITE_PCI_CONFIG rtas_fn_handle(IBM_WRITE_PCI_CONFIG) +#define RTAS_FN_NVRAM_FETCH rtas_fn_handle(NVRAM_FETCH) +#define RTAS_FN_NVRAM_STORE rtas_fn_handle(NVRAM_STORE) +#define RTAS_FN_POWER_OFF rtas_fn_handle(POWER_OFF) +#define RTAS_FN_PUT_TERM_CHAR rtas_fn_handle(PUT_TERM_CHAR) +#define RTAS_FN_QUERY_CPU_STOPPED_STATE rtas_fn_handle(QUERY_CPU_STOPPED_STATE) +#define RTAS_FN_READ_PCI_CONFIG rtas_fn_handle(READ_PCI_CONFIG) +#define RTAS_FN_RTAS_LAST_ERROR rtas_fn_handle(RTAS_LAST_ERROR) +#define RTAS_FN_SET_INDICATOR rtas_fn_handle(SET_INDICATOR) +#define RTAS_FN_SET_POWER_LEVEL rtas_fn_handle(SET_POWER_LEVEL) +#define RTAS_FN_SET_TIME_FOR_POWER_ON rtas_fn_handle(SET_TIME_FOR_POWER_ON) +#define RTAS_FN_SET_TIME_OF_DAY rtas_fn_handle(SET_TIME_OF_DAY) +#define RTAS_FN_START_CPU rtas_fn_handle(START_CPU) +#define RTAS_FN_STOP_SELF rtas_fn_handle(STOP_SELF) +#define RTAS_FN_SYSTEM_REBOOT rtas_fn_handle(SYSTEM_REBOOT) +#define RTAS_FN_THAW_TIME_BASE rtas_fn_handle(THAW_TIME_BASE) +#define RTAS_FN_WRITE_PCI_CONFIG rtas_fn_handle(WRITE_PCI_CONFIG) + #define RTAS_UNKNOWN_SERVICE (-1) #define RTAS_INSTANTIATE_MAX (1ULL<<30) /* Don't instantiate rtas at/above this value */ @@ -309,6 +402,11 @@ extern void (*rtas_flash_term_hook)(int); extern struct rtas_t rtas; +s32 rtas_function_token(const rtas_fn_handle_t handle); +static inline bool rtas_function_implemented(const rtas_fn_handle_t handle) +{ + return rtas_function_token(handle) != RTAS_UNKNOWN_SERVICE; +} extern int rtas_token(const char *service); extern int rtas_service_present(const char *service); extern int rtas_call(int token, int, int, int *, ...); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 41c430dc40c2..17e59306ce63 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -453,6 +453,26 @@ static struct rtas_function rtas_function_table[] __ro_after_init = { }, }; +/** + * rtas_function_token() - RTAS function token lookup. + * @handle: Function handle, e.g. RTAS_FN_EVENT_SCAN. + * + * Context: Any context. + * Return: the token value for the function if implemented by this platform, + * otherwise RTAS_UNKNOWN_SERVICE. + */ +s32 rtas_function_token(const rtas_fn_handle_t handle) +{ + const size_t index = handle.index; + const bool out_of_bounds = index >= ARRAY_SIZE(rtas_function_table); + + if (WARN_ONCE(out_of_bounds, "invalid function index %zu", index)) + return RTAS_UNKNOWN_SERVICE; + + return rtas_function_table[index].token; +} +EXPORT_SYMBOL_GPL(rtas_function_token); + static int rtas_function_cmp(const void *a, const void *b) { const struct rtas_function *f1 = a; @@ -1011,7 +1031,7 @@ static int ibm_errinjct_token; * @....: List of @nargs input parameters. * * Invokes the RTAS function indicated by @token, which the caller - * should obtain via rtas_token(). + * should obtain via rtas_function_token(). * * The @nargs and @nret arguments must match the number of input and * output parameters specified for the RTAS function.