diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 00dd309b6682..cee82b473dc5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -581,7 +581,7 @@ config ACPI_VIOT config ACPI_PRMT bool "Platform Runtime Mechanism Support" - depends on EFI && (X86_64 || ARM64) + depends on EFI_RUNTIME_WRAPPERS && (X86_64 || ARM64) default y help Platform Runtime Mechanism (PRM) is a firmware interface exposing a diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 71b9adaaf33b..7020584096bf 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -260,9 +260,9 @@ static acpi_status acpi_platformrt_space_handler(u32 function, context.static_data_buffer = handler->static_data_buffer_addr; context.mmio_ranges = module->mmio_info; - status = efi_call_virt_pointer(handler, handler_addr, - handler->acpi_param_buffer_addr, - &context); + status = efi_call_acpi_prm_handler(handler->handler_addr, + handler->acpi_param_buffer_addr, + &context); if (status == EFI_SUCCESS) { buffer->prm_status = PRM_HANDLER_SUCCESS; } else { diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index afe9248cc5bc..e89484af9740 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -108,6 +108,12 @@ union efi_rts_args { u64 *max_size; int *reset_type; } QUERY_CAPSULE_CAPS; + + struct { + efi_status_t (__efiapi *acpi_prm_handler)(u64, void *); + u64 param_buffer_addr; + void *context; + } ACPI_PRM_HANDLER; }; struct efi_runtime_work efi_rts_work; @@ -283,6 +289,13 @@ static void efi_call_rts(struct work_struct *work) args->QUERY_CAPSULE_CAPS.max_size, args->QUERY_CAPSULE_CAPS.reset_type); break; + case EFI_ACPI_PRM_HANDLER: +#ifdef CONFIG_ACPI_PRMT + status = arch_efi_call_virt(args, ACPI_PRM_HANDLER.acpi_prm_handler, + args->ACPI_PRM_HANDLER.param_buffer_addr, + args->ACPI_PRM_HANDLER.context); + break; +#endif default: /* * Ideally, we should never reach here because a caller of this @@ -560,3 +573,21 @@ void efi_native_runtime_setup(void) efi.update_capsule = virt_efi_update_capsule; efi.query_capsule_caps = virt_efi_query_capsule_caps; } + +#ifdef CONFIG_ACPI_PRMT + +efi_status_t +efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *), + u64 param_buffer_addr, void *context) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_queue_work(ACPI_PRM_HANDLER, handler_addr, + param_buffer_addr, context); + up(&efi_runtime_lock); + return status; +} + +#endif diff --git a/include/linux/efi.h b/include/linux/efi.h index e0b346b014df..5a1e39df8b26 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1228,6 +1228,10 @@ extern int efi_tpm_final_log_size; extern unsigned long rci2_table_phys; +efi_status_t +efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *), + u64 param_buffer_addr, void *context); + /* * efi_runtime_service() function identifiers. * "NONE" is used by efi_recover_from_page_fault() to check if the page @@ -1247,6 +1251,7 @@ enum efi_rts_ids { EFI_RESET_SYSTEM, EFI_UPDATE_CAPSULE, EFI_QUERY_CAPSULE_CAPS, + EFI_ACPI_PRM_HANDLER, }; union efi_rts_args;