/* * SPDX-License-Identifier: GPL-2.0 * * Copyright (C) 2016 Philippe Gerum . */ #ifndef __ASM_GENERIC_IRQ_PIPELINE_H #define __ASM_GENERIC_IRQ_PIPELINE_H #include #include #ifdef CONFIG_IRQ_PIPELINE unsigned long inband_irq_save(void); void inband_irq_restore(unsigned long flags); void inband_irq_enable(void); void inband_irq_disable(void); int inband_irqs_disabled(void); #define hard_cond_local_irq_enable() hard_local_irq_enable() #define hard_cond_local_irq_disable() hard_local_irq_disable() #define hard_cond_local_irq_save() hard_local_irq_save() #define hard_cond_local_irq_restore(__flags) hard_local_irq_restore(__flags) #define hard_local_irq_save() native_irq_save() #define hard_local_irq_restore(__flags) native_irq_restore(__flags) #define hard_local_irq_enable() native_irq_enable() #define hard_local_irq_disable() native_irq_disable() #define hard_local_save_flags() native_save_flags() #define hard_irqs_disabled() native_irqs_disabled() #define hard_irqs_disabled_flags(__flags) native_irqs_disabled_flags(__flags) void irq_pipeline_nmi_enter(void); void irq_pipeline_nmi_exit(void); /* Swap then merge virtual and hardware interrupt states. */ #define irqs_merge_flags(__flags, __stalled) \ ({ \ unsigned long __combo = \ arch_irqs_virtual_to_native_flags(__stalled) | \ arch_irqs_native_to_virtual_flags(__flags); \ __combo; \ }) /* Extract swap virtual and hardware interrupt states. */ #define irqs_split_flags(__combo, __stall_r) \ ({ \ unsigned long __virt = (__combo); \ *(__stall_r) = hard_irqs_disabled_flags(__combo); \ __virt &= ~arch_irqs_virtual_to_native_flags(*(__stall_r)); \ arch_irqs_virtual_to_native_flags(__virt); \ }) #define hard_local_irq_sync() native_irq_sync() #else /* !CONFIG_IRQ_PIPELINE */ #define hard_local_save_flags() ({ unsigned long __flags; \ raw_local_save_flags(__flags); __flags; }) #define hard_local_irq_enable() raw_local_irq_enable() #define hard_local_irq_disable() raw_local_irq_disable() #define hard_local_irq_save() ({ unsigned long __flags; \ raw_local_irq_save(__flags); __flags; }) #define hard_local_irq_restore(__flags) raw_local_irq_restore(__flags) #define hard_cond_local_irq_enable() do { } while(0) #define hard_cond_local_irq_disable() do { } while(0) #define hard_cond_local_irq_save() 0 #define hard_cond_local_irq_restore(__flags) do { (void)(__flags); } while(0) #define hard_irqs_disabled() irqs_disabled() #define hard_irqs_disabled_flags(__flags) raw_irqs_disabled_flags(__flags) static inline void irq_pipeline_nmi_enter(void) { } static inline void irq_pipeline_nmi_exit(void) { } #define hard_local_irq_sync() do { } while (0) #endif /* !CONFIG_IRQ_PIPELINE */ #ifdef CONFIG_DEBUG_IRQ_PIPELINE void check_inband_stage(void); #define check_hard_irqs_disabled() \ WARN_ON_ONCE(!hard_irqs_disabled()) #else static inline void check_inband_stage(void) { } static inline int check_hard_irqs_disabled(void) { return 0; } #endif extern bool irq_pipeline_oopsing; static __always_inline bool irqs_pipelined(void) { return IS_ENABLED(CONFIG_IRQ_PIPELINE); } static __always_inline bool irq_pipeline_debug(void) { return IS_ENABLED(CONFIG_DEBUG_IRQ_PIPELINE) && !irq_pipeline_oopsing; } static __always_inline bool irq_pipeline_debug_locking(void) { return IS_ENABLED(CONFIG_DEBUG_HARD_LOCKS); } #endif /* __ASM_GENERIC_IRQ_PIPELINE_H */