Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6424382 authored by Madhavan Srinivasan's avatar Madhavan Srinivasan Committed by Michael Ellerman
Browse files

powerpc/64s: Add new set of irq_soft_mask_ functions for PMI masking



To support soft-masking of the performance monitor interrupt, a set of
new powerpc_local_irq_pmu_save() and powerpc_local_irq_restore()
functions are added. And powerpc_local_irq_save() implemented, by
adding a new irq_soft_mask manipulation function
irq_soft_mask_or_return().

Local_irq_pmu_* macros are provided to access these
powerpc_local_irq_pmu* functions which includes
trace_hardirqs_on|off() to match what we have in
include/linux/irqflags.h.

Signed-off-by: default avatarMadhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 9aa88188
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -115,6 +115,24 @@ static inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask)
	return flags;
}

static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
{
	unsigned long flags, tmp;

	asm volatile(
		"lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)"
		: "=&r" (flags), "=r" (tmp)
		: "i" (offsetof(struct paca_struct, irq_soft_mask)),
		  "r" (mask)
		: "memory");

#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
	WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED));
#endif

	return flags;
}

static inline unsigned long arch_local_save_flags(void)
{
	return irq_soft_mask_return();
@@ -147,6 +165,55 @@ static inline bool arch_irqs_disabled(void)
	return arch_irqs_disabled_flags(arch_local_save_flags());
}

#ifdef CONFIG_PPC_BOOK3S
/*
 * To support disabling and enabling of irq with PMI, set of
 * new powerpc_local_irq_pmu_save() and powerpc_local_irq_restore()
 * functions are added. These macros are implemented using generic
 * linux local_irq_* code from include/linux/irqflags.h.
 */
#define raw_local_irq_pmu_save(flags)					\
	do {								\
		typecheck(unsigned long, flags);			\
		flags = irq_soft_mask_or_return(IRQS_DISABLED |	\
				IRQS_PMI_DISABLED);			\
	} while(0)

#define raw_local_irq_pmu_restore(flags)				\
	do {								\
		typecheck(unsigned long, flags);			\
		arch_local_irq_restore(flags);				\
	} while(0)

#ifdef CONFIG_TRACE_IRQFLAGS
#define powerpc_local_irq_pmu_save(flags)			\
	 do {							\
		raw_local_irq_pmu_save(flags);			\
		trace_hardirqs_off();				\
	} while(0)
#define powerpc_local_irq_pmu_restore(flags)			\
	do {							\
		if (raw_irqs_disabled_flags(flags)) {		\
			raw_local_irq_pmu_restore(flags);	\
			trace_hardirqs_off();			\
		} else {					\
			trace_hardirqs_on();			\
			raw_local_irq_pmu_restore(flags);	\
		}						\
	} while(0)
#else
#define powerpc_local_irq_pmu_save(flags)			\
	do {							\
		raw_local_irq_pmu_save(flags);			\
	} while(0)
#define powerpc_local_irq_pmu_restore(flags)			\
	do {							\
		raw_local_irq_pmu_restore(flags);		\
	} while (0)
#endif  /* CONFIG_TRACE_IRQFLAGS */

#endif /* CONFIG_PPC_BOOK3S */

#ifdef CONFIG_PPC_BOOK3E
#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory")
#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory")