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

Commit c1eeb2de authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar
Browse files

x86: fold apic_ops into genapic



Impact: cleanup

make it simpler, don't need have one extra struct.

v2: fix the sgi_uv build

Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 06cd9a7d
Loading
Loading
Loading
Loading
+31 −66
Original line number Diff line number Diff line
@@ -92,6 +92,12 @@ static inline u32 native_apic_mem_read(u32 reg)
	return *((volatile u32 *)(APIC_BASE + reg));
}

extern void native_apic_wait_icr_idle(void);
extern u32 native_safe_apic_wait_icr_idle(void);
extern void native_apic_icr_write(u32 low, u32 id);
extern u64 native_apic_icr_read(void);

#ifdef CONFIG_X86_X2APIC
static inline void native_apic_msr_write(u32 reg, u32 v)
{
	if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
@@ -112,7 +118,31 @@ static inline u32 native_apic_msr_read(u32 reg)
	return low;
}

#ifdef CONFIG_X86_X2APIC
static inline void native_x2apic_wait_icr_idle(void)
{
	/* no need to wait for icr idle in x2apic */
	return;
}

static inline u32 native_safe_x2apic_wait_icr_idle(void)
{
	/* no need to wait for icr idle in x2apic */
	return 0;
}

static inline void native_x2apic_icr_write(u32 low, u32 id)
{
	wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
}

static inline u64 native_x2apic_icr_read(void)
{
	unsigned long val;

	rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
	return val;
}

extern int x2apic;
extern void check_x2apic(void);
extern void enable_x2apic(void);
@@ -146,47 +176,6 @@ static inline int x2apic_enabled(void)
}
#endif

struct apic_ops {
	u32 (*read)(u32 reg);
	void (*write)(u32 reg, u32 v);
	u64 (*icr_read)(void);
	void (*icr_write)(u32 low, u32 high);
	void (*wait_icr_idle)(void);
	u32 (*safe_wait_icr_idle)(void);
};

extern struct apic_ops *apic_ops;

static inline u32 apic_read(u32 reg)
{
	return apic_ops->read(reg);
}

static inline void apic_write(u32 reg, u32 val)
{
	apic_ops->write(reg, val);
}

static inline u64 apic_icr_read(void)
{
	return apic_ops->icr_read();
}

static inline void apic_icr_write(u32 low, u32 high)
{
	apic_ops->icr_write(low, high);
}

static inline void apic_wait_icr_idle(void)
{
	apic_ops->wait_icr_idle();
}

static inline u32 safe_apic_wait_icr_idle(void)
{
	return apic_ops->safe_wait_icr_idle();
}

extern int get_physical_broadcast(void);

#ifdef CONFIG_X86_X2APIC
@@ -197,18 +186,6 @@ static inline void ack_x2APIC_irq(void)
}
#endif


static inline void ack_APIC_irq(void)
{
	/*
	 * ack_APIC_irq() actually gets compiled as a single instruction
	 * ... yummie.
	 */

	/* Docs say use 0 for future compatibility */
	apic_write(APIC_EOI, 0);
}

extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC(void);
@@ -256,18 +233,6 @@ static inline void disable_local_APIC(void) { }
#define	SET_APIC_ID(x)		(apic->set_apic_id(x))
#else

#ifdef CONFIG_X86_LOCAL_APIC
static inline unsigned default_get_apic_id(unsigned long x)
{
	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));

	if (APIC_XAPIC(ver))
		return (x >> 24) & 0xFF;
	else
		return (x >> 24) & 0x0F;
}
#endif

#endif

#endif /* _ASM_X86_APIC_H */
+61 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

#include <asm/mpspec.h>
#include <asm/atomic.h>
#include <asm/apic.h>

/*
 * Copyright 2004 James Cleverdon, IBM.
@@ -83,10 +84,70 @@ struct genapic {
	void (*smp_callin_clear_local_apic)(void);
	void (*store_NMI_vector)(unsigned short *high, unsigned short *low);
	void (*inquire_remote_apic)(int apicid);

	/* apic ops */
	u32 (*read)(u32 reg);
	void (*write)(u32 reg, u32 v);
	u64 (*icr_read)(void);
	void (*icr_write)(u32 low, u32 high);
	void (*wait_icr_idle)(void);
	u32 (*safe_wait_icr_idle)(void);
};

extern struct genapic *apic;

static inline u32 apic_read(u32 reg)
{
	return apic->read(reg);
}

static inline void apic_write(u32 reg, u32 val)
{
	apic->write(reg, val);
}

static inline u64 apic_icr_read(void)
{
	return apic->icr_read();
}

static inline void apic_icr_write(u32 low, u32 high)
{
	apic->icr_write(low, high);
}

static inline void apic_wait_icr_idle(void)
{
	apic->wait_icr_idle();
}

static inline u32 safe_apic_wait_icr_idle(void)
{
	return apic->safe_wait_icr_idle();
}


static inline void ack_APIC_irq(void)
{
	/*
	 * ack_APIC_irq() actually gets compiled as a single instruction
	 * ... yummie.
	 */

	/* Docs say use 0 for future compatibility */
	apic_write(APIC_EOI, 0);
}

static inline unsigned default_get_apic_id(unsigned long x)
{
	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));

	if (APIC_XAPIC(ver))
		return (x >> 24) & 0xFF;
	else
		return (x >> 24) & 0x0F;
}

/*
 * Warm reset vector default position:
 */
+4 −59
Original line number Diff line number Diff line
@@ -210,18 +210,13 @@ static int modern_apic(void)
	return lapic_get_version() >= 0x14;
}

/*
 * Paravirt kernels also might be using these below ops. So we still
 * use generic apic_read()/apic_write(), which might be pointing to different
 * ops in PARAVIRT case.
 */
void xapic_wait_icr_idle(void)
void native_apic_wait_icr_idle(void)
{
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
		cpu_relax();
}

u32 safe_xapic_wait_icr_idle(void)
u32 native_safe_apic_wait_icr_idle(void)
{
	u32 send_status;
	int timeout;
@@ -237,13 +232,13 @@ u32 safe_xapic_wait_icr_idle(void)
	return send_status;
}

void xapic_icr_write(u32 low, u32 id)
void native_apic_icr_write(u32 low, u32 id)
{
	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id));
	apic_write(APIC_ICR, low);
}

static u64 xapic_icr_read(void)
u64 native_apic_icr_read(void)
{
	u32 icr1, icr2;

@@ -253,54 +248,6 @@ static u64 xapic_icr_read(void)
	return icr1 | ((u64)icr2 << 32);
}

static struct apic_ops xapic_ops = {
	.read = native_apic_mem_read,
	.write = native_apic_mem_write,
	.icr_read = xapic_icr_read,
	.icr_write = xapic_icr_write,
	.wait_icr_idle = xapic_wait_icr_idle,
	.safe_wait_icr_idle = safe_xapic_wait_icr_idle,
};

struct apic_ops __read_mostly *apic_ops = &xapic_ops;
EXPORT_SYMBOL_GPL(apic_ops);

#ifdef CONFIG_X86_X2APIC
static void x2apic_wait_icr_idle(void)
{
	/* no need to wait for icr idle in x2apic */
	return;
}

static u32 safe_x2apic_wait_icr_idle(void)
{
	/* no need to wait for icr idle in x2apic */
	return 0;
}

void x2apic_icr_write(u32 low, u32 id)
{
	wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
}

static u64 x2apic_icr_read(void)
{
	unsigned long val;

	rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
	return val;
}

static struct apic_ops x2apic_ops = {
	.read = native_apic_msr_read,
	.write = native_apic_msr_write,
	.icr_read = x2apic_icr_read,
	.icr_write = x2apic_icr_write,
	.wait_icr_idle = x2apic_wait_icr_idle,
	.safe_wait_icr_idle = safe_x2apic_wait_icr_idle,
};
#endif

/**
 * enable_NMI_through_LVT0 - enable NMI through local vector table 0
 */
@@ -1329,7 +1276,6 @@ void check_x2apic(void)
	if (msr & X2APIC_ENABLE) {
		pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
		x2apic_preenabled = x2apic = 1;
		apic_ops = &x2apic_ops;
	}
}

@@ -1403,7 +1349,6 @@ void __init enable_IR_x2apic(void)

	if (!x2apic) {
		x2apic = 1;
		apic_ops = &x2apic_ops;
		enable_x2apic();
	}

+7 −0
Original line number Diff line number Diff line
@@ -263,4 +263,11 @@ struct genapic apic_bigsmp = {
	.smp_callin_clear_local_apic	= NULL,
	.store_NMI_vector		= NULL,
	.inquire_remote_apic		= default_inquire_remote_apic,

	.read				= native_apic_mem_read,
	.write				= native_apic_mem_write,
	.icr_read			= native_apic_icr_read,
	.icr_write			= native_apic_icr_write,
	.wait_icr_idle			= native_apic_wait_icr_idle,
	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
};
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@
#include <linux/smp.h>
#include <linux/sysdev.h>
#include <linux/sysfs.h>
#include <asm/apic.h>
#include <asm/genapic.h>
#include <asm/mce.h>
#include <asm/msr.h>
#include <asm/percpu.h>
Loading