mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-28 00:19:36 +00:00

SDEI usually initialize with the ACPI table, but on platforms where ACPI is not used, the SDEI feature can still be used to handle specific firmware calls or other customized purposes. Therefore, it is not necessary for ARM_SDE_INTERFACE to depend on ACPI_APEI_GHES. In commitdc4e8c07e9
("ACPI: APEI: explicit init of HEST and GHES in acpi_init()"), to make APEI ready earlier, sdei_init was moved into acpi_ghes_init instead of being a standalone initcall, adding ACPI_APEI_GHES dependency to ARM_SDE_INTERFACE. This restricts the flexibility and usability of SDEI. This patch corrects the dependency in Kconfig and splits sdei_init() into two separate functions: sdei_init() and acpi_sdei_init(). sdei_init() will be called by arch_initcall and will only initialize the platform driver, while acpi_sdei_init() will initialize the device from acpi_ghes_init() when ACPI is ready. This allows the initialization of SDEI without ACPI_APEI_GHES enabled. Fixes:dc4e8c07e9
("ACPI: APEI: explicit init of HEST and GHES in apci_init()") Cc: Shuai Xue <xueshuai@linux.alibaba.com> Signed-off-by: Huang Yiwei <quic_hyiwei@quicinc.com> Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://lore.kernel.org/r/20250507045757.2658795-1-quic_hyiwei@quicinc.com Signed-off-by: Will Deacon <will@kernel.org>
87 lines
2.7 KiB
C
87 lines
2.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
// Copyright (C) 2017 Arm Ltd.
|
|
#ifndef __LINUX_ARM_SDEI_H
|
|
#define __LINUX_ARM_SDEI_H
|
|
|
|
#include <uapi/linux/arm_sdei.h>
|
|
|
|
#include <acpi/ghes.h>
|
|
|
|
#ifdef CONFIG_ARM_SDE_INTERFACE
|
|
#include <asm/sdei.h>
|
|
#endif
|
|
|
|
/* Arch code should override this to set the entry point from firmware... */
|
|
#ifndef sdei_arch_get_entry_point
|
|
#define sdei_arch_get_entry_point(conduit) (0)
|
|
#endif
|
|
|
|
/*
|
|
* When an event occurs sdei_event_handler() will call a user-provided callback
|
|
* like this in NMI context on the CPU that received the event.
|
|
*/
|
|
typedef int (sdei_event_callback)(u32 event, struct pt_regs *regs, void *arg);
|
|
|
|
/*
|
|
* Register your callback to claim an event. The event must be described
|
|
* by firmware.
|
|
*/
|
|
int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg);
|
|
|
|
/*
|
|
* Calls to sdei_event_unregister() may return EINPROGRESS. Keep calling
|
|
* it until it succeeds.
|
|
*/
|
|
int sdei_event_unregister(u32 event_num);
|
|
|
|
int sdei_event_enable(u32 event_num);
|
|
int sdei_event_disable(u32 event_num);
|
|
|
|
/* GHES register/unregister helpers */
|
|
int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
|
|
sdei_event_callback *critical_cb);
|
|
int sdei_unregister_ghes(struct ghes *ghes);
|
|
|
|
#ifdef CONFIG_ARM_SDE_INTERFACE
|
|
/* For use by arch code when CPU hotplug notifiers are not appropriate. */
|
|
int sdei_mask_local_cpu(void);
|
|
int sdei_unmask_local_cpu(void);
|
|
void __init acpi_sdei_init(void);
|
|
void sdei_handler_abort(void);
|
|
#else
|
|
static inline int sdei_mask_local_cpu(void) { return 0; }
|
|
static inline int sdei_unmask_local_cpu(void) { return 0; }
|
|
static inline void acpi_sdei_init(void) { }
|
|
static inline void sdei_handler_abort(void) { }
|
|
#endif /* CONFIG_ARM_SDE_INTERFACE */
|
|
|
|
|
|
/*
|
|
* This struct represents an event that has been registered. The driver
|
|
* maintains a list of all events, and which ones are registered. (Private
|
|
* events have one entry in the list, but are registered on each CPU).
|
|
* A pointer to this struct is passed to firmware, and back to the event
|
|
* handler. The event handler can then use this to invoke the registered
|
|
* callback, without having to walk the list.
|
|
*
|
|
* For CPU private events, this structure is per-cpu.
|
|
*/
|
|
struct sdei_registered_event {
|
|
/* For use by arch code: */
|
|
struct pt_regs interrupted_regs;
|
|
|
|
sdei_event_callback *callback;
|
|
void *callback_arg;
|
|
u32 event_num;
|
|
u8 priority;
|
|
};
|
|
|
|
/* The arch code entry point should then call this when an event arrives. */
|
|
int notrace sdei_event_handler(struct pt_regs *regs,
|
|
struct sdei_registered_event *arg);
|
|
|
|
/* arch code may use this to retrieve the extra registers. */
|
|
int sdei_api_event_context(u32 query, u64 *result);
|
|
|
|
#endif /* __LINUX_ARM_SDEI_H */
|