Skip to content

Commit

Permalink
x86: Add timer_init to x86_init_ops
Browse files Browse the repository at this point in the history
The timer init code is convoluted with several quirks and the paravirt
timer chooser. Figuring out which code path is actually taken is not
for the faint hearted.

Move the numaq TSC quirk to tsc_pre_init x86_init_ops function and
replace the paravirt time chooser and the remaining x86 quirk with a
simple x86_init_ops function.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Thomas Gleixner committed Aug 31, 2009
1 parent 736deca commit 845b394
Show file tree
Hide file tree
Showing 17 changed files with 53 additions and 113 deletions.
5 changes: 0 additions & 5 deletions arch/x86/include/asm/paravirt.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ static inline int set_wallclock(unsigned long nowtime)
return PVOP_CALL1(int, pv_time_ops.set_wallclock, nowtime);
}

static inline void (*choose_time_init(void))(void)
{
return pv_time_ops.time_init;
}

/* The paravirtualized CPUID instruction. */
static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
Expand Down
2 changes: 0 additions & 2 deletions arch/x86/include/asm/paravirt_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ struct pv_lazy_ops {
};

struct pv_time_ops {
void (*time_init)(void);

/* Set and set time of day */
unsigned long (*get_wallclock)(void);
int (*set_wallclock)(unsigned long);
Expand Down
21 changes: 2 additions & 19 deletions arch/x86/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,6 @@

#define COMMAND_LINE_SIZE 2048

#ifndef __ASSEMBLY__

#include <asm/x86_init.h>

/*
* Any setup quirks to be performed?
*/

struct x86_quirks {
int (*arch_pre_time_init)(void);
int (*arch_time_init)(void);
};

extern void x86_quirk_pre_time_init(void);
extern void x86_quirk_time_init(void);

#endif /* __ASSEMBLY__ */

#ifdef __i386__

#include <linux/pfn.h>
Expand All @@ -42,6 +24,7 @@ extern void x86_quirk_time_init(void);

#ifndef __ASSEMBLY__
#include <asm/bootparam.h>
#include <asm/x86_init.h>

/* Interrupt control for vSMPowered x86_64 systems */
#ifdef CONFIG_X86_64
Expand All @@ -60,11 +43,11 @@ static inline void visws_early_detect(void) { }
static inline int is_visws_box(void) { return 0; }
#endif

extern struct x86_quirks *x86_quirks;
extern unsigned long saved_video_mode;

extern void reserve_standard_io_resources(void);
extern void i386_reserve_resources(void);
extern void setup_default_timer_irq(void);

#ifndef _SETUP

Expand Down
1 change: 0 additions & 1 deletion arch/x86/include/asm/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ extern void time_init(void);

#define get_wallclock() native_get_wallclock()
#define set_wallclock(x) native_set_wallclock(x)
#define choose_time_init() hpet_time_init

#endif /* CONFIG_PARAVIRT */

Expand Down
3 changes: 1 addition & 2 deletions arch/x86/include/asm/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ unsigned long native_calibrate_tsc(void);

#ifdef CONFIG_X86_32
extern int timer_ack;
extern irqreturn_t timer_interrupt(int irq, void *dev_id);
#endif /* CONFIG_X86_32 */
#endif
extern int recalibrate_cpu_khz(void);

extern int no_timer_check;
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/include/asm/x86_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,13 @@ struct x86_init_paging {
* struct x86_init_timers - platform specific timer setup
* @setup_perpcu_clockev: set up the per cpu clock event device for the
* boot cpu
* @tsc_pre_init: platform function called before TSC init
* @timer_init: initialize the platform timer (default PIT/HPET)
*/
struct x86_init_timers {
void (*setup_percpu_clockev)(void);
void (*tsc_pre_init)(void);
void (*timer_init)(void);
};

/**
Expand Down
10 changes: 2 additions & 8 deletions arch/x86/kernel/apic/numaq_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,9 @@ void __cpuinit numaq_tsc_disable(void)
}
}

static int __init numaq_pre_time_init(void)
static void __init numaq_tsc_init(void)
{
numaq_tsc_disable();
return 0;
}

static inline int generate_logical_apicid(int quad, int phys_apicid)
Expand Down Expand Up @@ -262,11 +261,6 @@ static void __init smp_read_mpc_oem(struct mpc_table *mpc)
}
}

static struct x86_quirks numaq_x86_quirks __initdata = {
.arch_pre_time_init = numaq_pre_time_init,
.arch_time_init = NULL,
};

static __init void early_check_numaq(void)
{
/*
Expand All @@ -281,13 +275,13 @@ static __init void early_check_numaq(void)
early_get_smp_config();

if (found_numaq) {
x86_quirks = &numaq_x86_quirks;
x86_init.mpparse.mpc_record = numaq_mpc_record;
x86_init.mpparse.setup_ioapic_ids = x86_init_noop;
x86_init.mpparse.mpc_apic_id = mpc_apic_id;
x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem;
x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
x86_init.timers.tsc_pre_init = numaq_tsc_init;
}
}

Expand Down
1 change: 0 additions & 1 deletion arch/x86/kernel/paravirt.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ struct pv_init_ops pv_init_ops = {
};

struct pv_time_ops pv_time_ops = {
.time_init = hpet_time_init,
.get_wallclock = native_get_wallclock,
.set_wallclock = native_set_wallclock,
.sched_clock = native_sched_clock,
Expand Down
43 changes: 0 additions & 43 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,10 +626,6 @@ static int __init setup_elfcorehdr(char *arg)
early_param("elfcorehdr", setup_elfcorehdr);
#endif

static struct x86_quirks default_x86_quirks __initdata;

struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;

#ifdef CONFIG_X86_RESERVE_LOW_64K
static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
{
Expand Down Expand Up @@ -1016,45 +1012,6 @@ void __init setup_arch(char **cmdline_p)

#ifdef CONFIG_X86_32

static struct irqaction irq0 = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
.name = "timer"
};

/**
* x86_quirk_pre_time_init - do any specific initialisations before.
*
**/
void __init x86_quirk_pre_time_init(void)
{
if (x86_quirks->arch_pre_time_init)
x86_quirks->arch_pre_time_init();
}

/**
* x86_quirk_time_init - do any specific initialisations for the system timer.
*
* Description:
* Must plug the system timer interrupt source at HZ into the IRQ listed
* in irq_vectors.h:TIMER_IRQ
**/
void __init x86_quirk_time_init(void)
{
if (x86_quirks->arch_time_init) {
/*
* A nonzero return code does not mean failure, it means
* that the architecture quirk does not want any
* generic (timer) setup to be performed after this:
*/
if (x86_quirks->arch_time_init())
return;
}

irq0.mask = cpumask_of_cpu(0);
setup_irq(0, &irq0);
}

static struct resource video_ram_resource = {
.name = "Video RAM area",
.start = 0xa0000,
Expand Down
34 changes: 23 additions & 11 deletions arch/x86/kernel/time_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ EXPORT_SYMBOL(profile_pc);
* Time Stamp Counter value at the time of the timer interrupt, so that
* we later on can estimate the time of day more exactly.
*/
irqreturn_t timer_interrupt(int irq, void *dev_id)
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
/* Keep nmi watchdog up to date */
inc_irq_stat(irq0_irqs);
Expand Down Expand Up @@ -113,25 +113,37 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}

/* Duplicate of time_init() below, with hpet_enable part added */
static struct irqaction irq0 = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
.name = "timer"
};

void __init setup_default_timer_irq(void)
{
irq0.mask = cpumask_of_cpu(0);
setup_irq(0, &irq0);
}

/* Default timer init function */
void __init hpet_time_init(void)
{
if (!hpet_enable())
setup_pit_timer();
x86_quirk_time_init();
setup_default_timer_irq();
}

static void x86_late_time_init(void)
{
x86_init.timers.timer_init();
}

/*
* This is called directly from init code; we must delay timer setup in the
* HPET case as we can't make the decision to turn on HPET this early in the
* boot process.
*
* The chosen time_init function will usually be hpet_time_init, above, but
* in the case of virtual hardware, an alternative function may be substituted.
* Initialize TSC and delay the periodic timer init to
* late x86_late_time_init() so ioremap works.
*/
void __init time_init(void)
{
x86_quirk_pre_time_init();
tsc_init();
late_time_init = choose_time_init();
late_time_init = x86_late_time_init;
}
9 changes: 7 additions & 2 deletions arch/x86/kernel/time_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/mca.h>
#include <linux/nmi.h>

#include <asm/x86_init.h>
#include <asm/i8253.h>
#include <asm/hpet.h>
#include <asm/vgtod.h>
Expand Down Expand Up @@ -127,9 +128,13 @@ void __init hpet_time_init(void)
setup_irq(0, &irq0);
}

static void x86_late_time_init(void)
{
x86_init.timers.timer_init();
}

void __init time_init(void)
{
tsc_init();

late_time_init = choose_time_init();
late_time_init = x86_late_time_init;
}
2 changes: 2 additions & 0 deletions arch/x86/kernel/tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,8 @@ void __init tsc_init(void)
u64 lpj;
int cpu;

x86_init.timers.tsc_pre_init();

if (!cpu_has_tsc)
return;

Expand Down
20 changes: 5 additions & 15 deletions arch/x86/kernel/visws_quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <asm/setup.h>
#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/time.h>
#include <asm/io.h>

#include <linux/kernel_stat.h>
Expand All @@ -53,7 +54,7 @@ int is_visws_box(void)
return visws_board_type >= 0;
}

static int __init visws_time_init(void)
static void __init visws_time_init(void)
{
printk(KERN_INFO "Starting Cobalt Timer system clock\n");

Expand All @@ -66,11 +67,7 @@ static int __init visws_time_init(void)
/* Enable (unmask) the timer interrupt */
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);

/*
* Zero return means the generic timer setup code will set up
* the standard vector:
*/
return 0;
setup_default_timer_irq();
}

/* Replaces the default init_ISA_irqs in the generic setup */
Expand Down Expand Up @@ -226,10 +223,6 @@ static void __init visws_find_smp_config(unsigned int reserve)

static void visws_trap_init(void);

static struct x86_quirks visws_x86_quirks __initdata = {
.arch_time_init = visws_time_init,
};

void __init visws_early_detect(void)
{
int raw;
Expand All @@ -241,17 +234,14 @@ void __init visws_early_detect(void)
return;

/*
* Install special quirks for timer, interrupt and memory setup:
* Fall back to generic behavior for traps:
* Override generic MP-table parsing:
* Override the default platform setup functions
*/
x86_quirks = &visws_x86_quirks;

x86_init.resources.memory_setup = visws_memory_setup;
x86_init.mpparse.get_smp_config = visws_get_smp_config;
x86_init.mpparse.find_smp_config = visws_find_smp_config;
x86_init.irqs.pre_vector_init = visws_pre_intr_init;
x86_init.irqs.trap_init = visws_trap_init;
x86_init.timers.timer_init = visws_time_init;

/*
* Install reboot quirks:
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/vmi_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ static inline int __init activate_vmi(void)
vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
vmi_timer_ops.cancel_alarm =
vmi_get_function(VMI_CALL_CancelAlarm);
pv_time_ops.time_init = vmi_time_init;
x86_init.timers.timer_init = vmi_time_init;
pv_time_ops.get_wallclock = vmi_get_wallclock;
pv_time_ops.set_wallclock = vmi_set_wallclock;
#ifdef CONFIG_X86_LOCAL_APIC
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/x86_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <asm/setup.h>
#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/time.h>
#include <asm/irq.h>

void __cpuinit x86_init_noop(void) { }
Expand Down Expand Up @@ -58,6 +59,8 @@ struct __initdata x86_init_ops x86_init = {

.timers = {
.setup_percpu_clockev = setup_boot_APIC_clock,
.tsc_pre_init = x86_init_noop,
.timer_init = hpet_time_init,
},
};

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/lguest/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1320,11 +1320,11 @@ __init void lguest_init(void)

/* Time operations */
pv_time_ops.get_wallclock = lguest_get_wallclock;
pv_time_ops.time_init = lguest_time_init;
pv_time_ops.get_tsc_khz = lguest_tsc_khz;

x86_init.resources.memory_setup = lguest_memory_setup;
x86_init.irqs.intr_init = lguest_init_IRQ;
x86_init.timers.timer_init = lguest_time_init;

/*
* Now is a good time to look at the implementations of these functions
Expand Down
Loading

0 comments on commit 845b394

Please sign in to comment.