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

Commit 274cfe59 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Ingo Molnar
Browse files

x86: apic - rearrange functions and comments



Rearrange functions and comments to find differences
easier.

Also use apic_printk in setup_boot_APIC_clock for
64bit mode.

Signed-off-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 24968cfd
Loading
Loading
Loading
Loading
+39 −30
Original line number Original line Diff line number Diff line
@@ -251,6 +251,9 @@ int lapic_get_maxlvt(void)
 * this function twice on the boot CPU, once with a bogus timeout
 * this function twice on the boot CPU, once with a bogus timeout
 * value, second time for real. The other (noncalibrating) CPUs
 * value, second time for real. The other (noncalibrating) CPUs
 * call this function only once, with the real, calibrated value.
 * call this function only once, with the real, calibrated value.
 *
 * We do reads before writes even if unnecessary, to get around the
 * P5 APIC double write bug.
 */
 */
static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
{
{
@@ -279,6 +282,36 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
		apic_write(APIC_TMICT, clocks / APIC_DIVISOR);
		apic_write(APIC_TMICT, clocks / APIC_DIVISOR);
}
}


/*
 * Setup extended LVT, AMD specific (K8, family 10h)
 *
 * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
 * MCE interrupts are supported. Thus MCE offset must be set to 0.
 */

#define APIC_EILVT_LVTOFF_MCE 0
#define APIC_EILVT_LVTOFF_IBS 1

static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
{
	unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;

	apic_write(reg, v);
}

u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
{
	setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
	return APIC_EILVT_LVTOFF_MCE;
}

u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
{
	setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
	return APIC_EILVT_LVTOFF_IBS;
}

/*
/*
 * Program the next event, relative to now
 * Program the next event, relative to now
 */
 */
@@ -298,7 +331,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
	unsigned long flags;
	unsigned long flags;
	unsigned int v;
	unsigned int v;


	/* Lapic used for broadcast ? */
	/* Lapic used as dummy for broadcast ? */
	if (evt->features & CLOCK_EVT_FEAT_DUMMY)
	if (evt->features & CLOCK_EVT_FEAT_DUMMY)
		return;
		return;


@@ -680,35 +713,6 @@ int setup_profiling_timer(unsigned int multiplier)
	return -EINVAL;
	return -EINVAL;
}
}


/*
 * Setup extended LVT, AMD specific (K8, family 10h)
 *
 * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
 * MCE interrupts are supported. Thus MCE offset must be set to 0.
 */

#define APIC_EILVT_LVTOFF_MCE 0
#define APIC_EILVT_LVTOFF_IBS 1

static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
{
	unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
	apic_write(reg, v);
}

u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
{
	setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
	return APIC_EILVT_LVTOFF_MCE;
}

u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
{
	setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
	return APIC_EILVT_LVTOFF_IBS;
}

/*
/*
 * Local APIC start and shutdown
 * Local APIC start and shutdown
 */
 */
@@ -1542,6 +1546,11 @@ void __cpuinit generic_processor_info(int apicid, int version)
#ifdef CONFIG_PM
#ifdef CONFIG_PM


static struct {
static struct {
	/*
	 * 'active' is true if the local APIC was enabled by us and
	 * not the BIOS; this signifies that we are also responsible
	 * for disabling it before entering apm/acpi suspend
	 */
	int active;
	int active;
	/* r/w apic fields */
	/* r/w apic fields */
	unsigned int apic_id;
	unsigned int apic_id;
+38 −10
Original line number Original line Diff line number Diff line
@@ -81,6 +81,9 @@ static void lapic_timer_setup(enum clock_event_mode mode,
static void lapic_timer_broadcast(cpumask_t mask);
static void lapic_timer_broadcast(cpumask_t mask);
static void apic_pm_activate(void);
static void apic_pm_activate(void);


/*
 * The local apic timer can be used for any function which is CPU local.
 */
static struct clock_event_device lapic_clockevent = {
static struct clock_event_device lapic_clockevent = {
	.name		= "lapic",
	.name		= "lapic",
	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
@@ -127,6 +130,11 @@ static int modern_apic(void)
	return lapic_get_version() >= 0x14;
	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 xapic_wait_icr_idle(void)
{
{
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
@@ -175,7 +183,6 @@ static struct apic_ops xapic_ops = {
};
};


struct apic_ops __read_mostly *apic_ops = &xapic_ops;
struct apic_ops __read_mostly *apic_ops = &xapic_ops;

EXPORT_SYMBOL_GPL(apic_ops);
EXPORT_SYMBOL_GPL(apic_ops);


static void x2apic_wait_icr_idle(void)
static void x2apic_wait_icr_idle(void)
@@ -244,6 +251,10 @@ int lapic_get_maxlvt(void)
	return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2;
	return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2;
}
}


/*
 * Local APIC timer
 */

/* Clock divisor is set to 1 */
/* Clock divisor is set to 1 */
#define APIC_DIVISOR 1
#define APIC_DIVISOR 1


@@ -257,7 +268,6 @@ int lapic_get_maxlvt(void)
 * We do reads before writes even if unnecessary, to get around the
 * We do reads before writes even if unnecessary, to get around the
 * P5 APIC double write bug.
 * P5 APIC double write bug.
 */
 */

static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
{
{
	unsigned int lvtt_value, tmp_value;
	unsigned int lvtt_value, tmp_value;
@@ -474,10 +484,10 @@ static int __init calibrate_APIC_clock(void)
void __init setup_boot_APIC_clock(void)
void __init setup_boot_APIC_clock(void)
{
{
	/*
	/*
	 * The local apic timer can be disabled via the kernel commandline.
	 * The local apic timer can be disabled via the kernel
	 * Register the lapic timer as a dummy clock event source on SMP
	 * commandline or from the CPU detection code. Register the lapic
	 * systems, so the broadcast mechanism is used. On UP systems simply
	 * timer as a dummy clock event source on SMP systems, so the
	 * ignore it.
	 * broadcast mechanism is used. On UP systems simply ignore it.
	 */
	 */
	if (disable_apic_timer) {
	if (disable_apic_timer) {
		printk(KERN_INFO "Disabling APIC timer\n");
		printk(KERN_INFO "Disabling APIC timer\n");
@@ -489,7 +499,9 @@ void __init setup_boot_APIC_clock(void)
		return;
		return;
	}
	}


	printk(KERN_INFO "Using local APIC timer interrupts.\n");
	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
		    "calibrating APIC timer ...\n");

	if (calibrate_APIC_clock()) {
	if (calibrate_APIC_clock()) {
		/* No broadcast on UP ! */
		/* No broadcast on UP ! */
		if (num_possible_cpus() > 1)
		if (num_possible_cpus() > 1)
@@ -508,6 +520,7 @@ void __init setup_boot_APIC_clock(void)
		printk(KERN_WARNING "APIC timer registered as dummy,"
		printk(KERN_WARNING "APIC timer registered as dummy,"
			" due to nmi_watchdog=%d!\n", nmi_watchdog);
			" due to nmi_watchdog=%d!\n", nmi_watchdog);


	/* Setup the lapic or request the broadcast */
	setup_APIC_timer();
	setup_APIC_timer();
}
}


@@ -577,6 +590,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
	irq_enter();
	irq_enter();
	local_apic_timer_interrupt();
	local_apic_timer_interrupt();
	irq_exit();
	irq_exit();

	set_irq_regs(old_regs);
	set_irq_regs(old_regs);
}
}


@@ -1248,6 +1262,13 @@ void __init connect_bsp_APIC(void)
	enable_apic_mode();
	enable_apic_mode();
}
}


/**
 * disconnect_bsp_APIC - detach the APIC from the interrupt system
 * @virt_wire_setup:	indicates, whether virtual wire mode is selected
 *
 * Virtual wire mode is necessary to deliver legacy interrupts even when the
 * APIC is disabled.
 */
void disconnect_bsp_APIC(int virt_wire_setup)
void disconnect_bsp_APIC(int virt_wire_setup)
{
{
	/* Go back to Virtual Wire compatibility mode */
	/* Go back to Virtual Wire compatibility mode */
@@ -1347,9 +1368,11 @@ int hard_smp_processor_id(void)
#ifdef CONFIG_PM
#ifdef CONFIG_PM


static struct {
static struct {
	/* 'active' is true if the local APIC was enabled by us and
	/*
	   not the BIOS; this signifies that we are also responsible
	 * 'active' is true if the local APIC was enabled by us and
	   for disabling it before entering apm/acpi suspend */
	 * not the BIOS; this signifies that we are also responsible
	 * for disabling it before entering apm/acpi suspend
	 */
	int active;
	int active;
	/* r/w apic fields */
	/* r/w apic fields */
	unsigned int apic_id;
	unsigned int apic_id;
@@ -1458,6 +1481,11 @@ static int lapic_resume(struct sys_device *dev)
	return 0;
	return 0;
}
}


/*
 * This device has no shutdown method - fully functioning local APICs
 * are needed on every CPU up until machine_halt/restart/poweroff.
 */

static struct sysdev_class lapic_sysclass = {
static struct sysdev_class lapic_sysclass = {
	.name		= "lapic",
	.name		= "lapic",
	.resume		= lapic_resume,
	.resume		= lapic_resume,