From 472bc4f2ad164a5aac2e85d891c4faecfc5d62c4 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 4 Apr 2012 13:21:13 +0200 Subject: sparc32: rename sparc_irq_config to sparc_config This struct holds platform specific config and is thus not limited to irq stuff. Do not let the name confuse us to think this is irq only. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 1d13c5bda0b1..30119f662eff 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -512,8 +512,8 @@ void __init sun4d_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); - sparc_irq_config.init_timers = sun4d_init_timers; - sparc_irq_config.build_device_irq = sun4d_build_device_irq; + sparc_config.init_timers = sun4d_init_timers; + sparc_config.build_device_irq = sun4d_build_device_irq; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); -- cgit v1.2.3 From 62f082830d63cf753ed0dab16f8d3b2d0ffc7f43 Mon Sep 17 00:00:00 2001 From: Tkhai Kirill Date: Wed, 4 Apr 2012 21:49:26 +0200 Subject: sparc32: generic clockevent support The kernel uses l14 timers as clockevents. l10 timer is used as clocksource if platform master_l10_counter isn't constantly zero. The clocksource is continuous, so it's possible to use high resolution timers. l10 timer is also used as clockevent on UP configurations. This realization is for sun4m, sun4d, sun4c, microsparc-IIep and LEON platforms. The appropriate LEON changes was made by Konrad Eisele. In case of sun4m's oneshot mode, profile irq is zeroed in smp4m_percpu_timer_interrupt(). It is maybe needless (double, triple etc overflow does nothing). sun4d is able to have oneshot mode too, but I haven't any way to test it. So code of its percpu timer handler is made as much equal to the current code as possible. The patch is tested on sun4m box in SMP mode by me, and tested by Konrad on leon in up mode (leon smp is broken atm - due to other reasons). Signed-off-by: Tkhai Kirill Tested-by: Konrad Eisele [leon up] [sam: revised patch to provide generic support for leon] Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 7 +- arch/sparc/include/asm/cpudata_32.h | 1 - arch/sparc/include/asm/leon.h | 2 +- arch/sparc/include/asm/timer_32.h | 29 +++++ arch/sparc/include/asm/timex_32.h | 1 - arch/sparc/kernel/irq.h | 19 +++- arch/sparc/kernel/kernel.h | 2 - arch/sparc/kernel/leon_kernel.c | 49 +++++++- arch/sparc/kernel/leon_smp.c | 34 +----- arch/sparc/kernel/pcic.c | 48 ++++---- arch/sparc/kernel/smp_32.c | 21 +--- arch/sparc/kernel/sun4c_irq.c | 11 +- arch/sparc/kernel/sun4d_irq.c | 18 ++- arch/sparc/kernel/sun4d_smp.c | 34 ++---- arch/sparc/kernel/sun4m_irq.c | 22 ++-- arch/sparc/kernel/sun4m_smp.c | 38 +++---- arch/sparc/kernel/time_32.c | 215 +++++++++++++++++++++++++++++------- 17 files changed, 362 insertions(+), 189 deletions(-) (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6c0683d3fcba..db4e821b3ed0 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -73,17 +73,12 @@ config BITS default 32 if SPARC32 default 64 if SPARC64 -config ARCH_USES_GETTIMEOFFSET - bool - default y if SPARC32 - config GENERIC_CMOS_UPDATE bool default y config GENERIC_CLOCKEVENTS - bool - default y if SPARC64 + def_bool y config IOMMU_HELPER bool diff --git a/arch/sparc/include/asm/cpudata_32.h b/arch/sparc/include/asm/cpudata_32.h index a4c5a938b936..0300d94c25b3 100644 --- a/arch/sparc/include/asm/cpudata_32.h +++ b/arch/sparc/include/asm/cpudata_32.h @@ -14,7 +14,6 @@ typedef struct { unsigned long udelay_val; unsigned long clock_tick; - unsigned int multiplier; unsigned int counter; #ifdef CONFIG_SMP unsigned int irq_resched_count; diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index a4e457f003ed..cf35a26454c8 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h @@ -323,7 +323,7 @@ extern void leon_update_virq_handling(unsigned int virq, const char *name, int do_ack); extern void leon_clear_clock_irq(void); extern void leon_load_profile_irq(int cpu, unsigned int limit); -extern void leon_init_timers(irq_handler_t counter_fn); +extern void leon_init_timers(void); extern void leon_clear_clock_irq(void); extern void leon_load_profile_irq(int cpu, unsigned int limit); extern void leon_trans_init(struct device_node *dp); diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 1a91e11dd104..e6e66678f470 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h @@ -8,11 +8,40 @@ #ifndef _SPARC_TIMER_H #define _SPARC_TIMER_H +#include +#include + +#include + #include /* For SUN4M_NCPUS */ #include +#define SBUS_CLOCK_RATE 2000000 /* 2MHz */ +#define TIMER_VALUE_SHIFT 9 +#define TIMER_VALUE_MASK 0x3fffff +#define TIMER_LIMIT_BIT (1 << 31) /* Bit 31 in Counter-Timer register */ + +/* The counter timer register has the value offset by 9 bits. + * From sun4m manual: + * When a counter reaches the value in the corresponding limit register, + * the Limit bit is set and the counter is set to 500 nS (i.e. 0x00000200). + * + * To compensate for this add one to the value. + */ +static inline unsigned int timer_value(unsigned int value) +{ + return (value + 1) << TIMER_VALUE_SHIFT; +} + extern __volatile__ unsigned int *master_l10_counter; +extern irqreturn_t notrace timer_interrupt(int dummy, void *dev_id); + +#ifdef CONFIG_SMP +DECLARE_PER_CPU(struct clock_event_device, sparc32_clockevent); +extern void register_percpu_ce(int cpu); +#endif + /* FIXME: Make do_[gs]ettimeofday btfixup calls */ struct timespec; BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv) diff --git a/arch/sparc/include/asm/timex_32.h b/arch/sparc/include/asm/timex_32.h index a254750e4c03..b6ccdb0d6f7d 100644 --- a/arch/sparc/include/asm/timex_32.h +++ b/arch/sparc/include/asm/timex_32.h @@ -12,5 +12,4 @@ typedef unsigned long cycles_t; #define get_cycles() (0) -extern u32 (*do_arch_gettimeoffset)(void); #endif diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 3f6ca4d55dc4..8b946b1bc3b9 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -41,15 +41,32 @@ struct sun4m_irq_global { extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; extern struct sun4m_irq_global __iomem *sun4m_irq_global; +/* The following definitions describe the individual platform features: */ +#define FEAT_L10_CLOCKSOURCE (1 << 0) /* L10 timer is used as a clocksource */ +#define FEAT_L10_CLOCKEVENT (1 << 1) /* L10 timer is used as a clockevent */ +#define FEAT_L14_ONESHOT (1 << 2) /* L14 timer clockevent can oneshot */ + /* * Platform specific configuration * The individual platforms assign their platform * specifics in their init functions. */ struct sparc_config { - void (*init_timers)(irq_handler_t); + void (*init_timers)(void); unsigned int (*build_device_irq)(struct platform_device *op, unsigned int real_irq); + + /* generic clockevent features - see FEAT_* above */ + int features; + + /* clock rate used for clock event timer */ + int clock_rate; + + /* one period for clock source timer */ + unsigned int cs_period; + + /* function to obtain offsett for cs period */ + unsigned int (*get_cycles_offset)(void); }; extern struct sparc_config sparc_config; diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index fd6c36b1df74..8abbad38e34e 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -47,8 +47,6 @@ extern void init_IRQ(void); extern void sun4c_init_IRQ(void); /* sun4m_irq.c */ -extern unsigned int lvl14_resolution; - extern void sun4m_init_IRQ(void); extern void sun4m_unmask_profile_irq(void); extern void sun4m_clear_profile_irq(int cpu); diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index a94122bc0c7b..722650ab83da 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -250,7 +252,38 @@ void leon_update_virq_handling(unsigned int virq, irq_set_chip_data(virq, (void *)mask); } -void __init leon_init_timers(irq_handler_t counter_fn) +static u32 leon_cycles_offset(void) +{ + u32 rld, val, off; + rld = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld); + val = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val); + off = rld - val; + return rld - val; +} + +#ifdef CONFIG_SMP + +/* smp clockevent irq */ +irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused) +{ + struct clock_event_device *ce; + int cpu = smp_processor_id(); + + leon_clear_profile_irq(cpu); + + ce = &per_cpu(sparc32_clockevent, cpu); + + irq_enter(); + if (ce->event_handler) + ce->event_handler(ce); + irq_exit(); + + return IRQ_HANDLED; +} + +#endif /* CONFIG_SMP */ + +void __init leon_init_timers(void) { int irq, eirq; struct device_node *rootnp, *np, *nnp; @@ -260,6 +293,14 @@ void __init leon_init_timers(irq_handler_t counter_fn) int ampopts; int err; + sparc_config.get_cycles_offset = leon_cycles_offset; + sparc_config.cs_period = 1000000 / HZ; + sparc_config.features |= FEAT_L10_CLOCKSOURCE; + +#ifndef CONFIG_SMP + sparc_config.features |= FEAT_L10_CLOCKEVENT; +#endif + leondebug_irq_disable = 0; leon_debug_irqout = 0; master_l10_counter = (unsigned int *)&dummy_master_l10_counter; @@ -369,7 +410,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) leon_eirq_setup(eirq); irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); - err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); + err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); if (err) { printk(KERN_ERR "unable to attach timer IRQ%d\n", irq); prom_halt(); @@ -401,7 +442,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) /* Install per-cpu IRQ handler for broadcasted ticker */ irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq, "per-cpu", 0); - err = request_irq(irq, leon_percpu_timer_interrupt, + err = request_irq(irq, leon_percpu_timer_ce_interrupt, IRQF_PERCPU | IRQF_TIMER, "ticker", NULL); if (err) { @@ -428,7 +469,6 @@ void leon_clear_clock_irq(void) void leon_load_profile_irq(int cpu, unsigned int limit) { - BUG(); } void __init leon_trans_init(struct device_node *dp) @@ -496,6 +536,7 @@ void __init leon_init_IRQ(void) { sparc_config.init_timers = leon_init_timers; sparc_config.build_device_irq = _leon_build_device_irq; + sparc_config.clock_rate = 1000000; BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 1210fde18740..6173f4d82ded 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -42,6 +44,7 @@ #include #include #include +#include #include "kernel.h" @@ -68,8 +71,6 @@ static inline unsigned long do_swap(volatile unsigned long *ptr, return val; } -static void smp_setup_percpu_timer(void); - void __cpuinit leon_callin(void) { int cpuid = hard_smpleon_processor_id(); @@ -79,7 +80,7 @@ void __cpuinit leon_callin(void) leon_configure_cache_smp(); /* Get our local ticker going. */ - smp_setup_percpu_timer(); + register_percpu_ce(cpuid); calibrate_delay(); smp_store_cpu_info(cpuid); @@ -196,7 +197,6 @@ void __init leon_boot_cpus(void) leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); leon_configure_cache_smp(); - smp_setup_percpu_timer(); local_flush_cache_all(); } @@ -489,32 +489,6 @@ void leon_cross_call_irq(void) ccall_info.processors_out[i] = 1; } -irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) -{ - int cpu = smp_processor_id(); - - leon_clear_profile_irq(cpu); - - profile_tick(CPU_PROFILING); - - if (!--prof_counter(cpu)) { - int user = user_mode(get_irq_regs()); - - update_process_times(user); - - prof_counter(cpu) = prof_multiplier(cpu); - } - - return IRQ_HANDLED; -} - -static void __init smp_setup_percpu_timer(void) -{ - int cpu = smp_processor_id(); - - prof_counter(cpu) = prof_multiplier(cpu) = 1; -} - void __init leon_blackbox_id(unsigned *addr) { int rd = *addr & 0x3e000000; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 6edec801e46a..118a3f5806a8 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -703,31 +703,28 @@ static void pcic_clear_clock_irq(void) pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); } -static irqreturn_t pcic_timer_handler (int irq, void *h) +/* CPU frequency is 100 MHz, timer increments every 4 CPU clocks */ +#define USECS_PER_JIFFY (1000000 / HZ) +#define TICK_TIMER_LIMIT ((100 * 1000000 / 4) / HZ) + +static unsigned int pcic_cycles_offset(void) { - pcic_clear_clock_irq(); - xtime_update(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - return IRQ_HANDLED; -} + u32 value, count; -#define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */ -#define TICK_TIMER_LIMIT ((100*1000000/4)/100) + value = readl(pcic0.pcic_regs + PCI_SYS_COUNTER); + count = value & ~PCI_SYS_COUNTER_OVERFLOW; -u32 pci_gettimeoffset(void) -{ + if (value & PCI_SYS_COUNTER_OVERFLOW) + count += TICK_TIMER_LIMIT; /* - * We divide all by 100 + * We divide all by HZ * to have microsecond resolution and to avoid overflow */ - unsigned long count = - readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; - count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); - return count * 1000; -} + count = ((count / HZ) * USECS_PER_JIFFY) / (TICK_TIMER_LIMIT / HZ); + /* Coordinate with the fact that timer_cs rate is 2MHz */ + return count * 2; +} void __init pci_time_init(void) { @@ -736,9 +733,16 @@ void __init pci_time_init(void) int timer_irq, irq; int err; - do_arch_gettimeoffset = pci_gettimeoffset; - - btfixup(); +#ifndef CONFIG_SMP + /* + * It's in SBUS dimension, because timer_cs is in this dimension. + * We take into account this in pcic_cycles_offset() + */ + timer_cs_period = SBUS_CLOCK_RATE / HZ; + sparc_config.features |= FEAT_L10_CLOCKEVENT; +#endif + sparc_config.features |= FEAT_L10_CLOCKSOURCE; + sparc_config.get_cycles_offset = pcic_cycles_offset; writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); /* PROM should set appropriate irq */ @@ -747,7 +751,7 @@ void __init pci_time_init(void) writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), pcic->pcic_regs+PCI_COUNTER_IRQ); irq = pcic_build_device_irq(NULL, timer_irq); - err = request_irq(irq, pcic_timer_handler, + err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); if (err) { prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index f671e7fd6ddc..569a8a9d24a2 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -301,28 +301,9 @@ void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) local_flush_sig_insns(mm, insn_addr); } -extern unsigned int lvl14_resolution; - -/* /proc/profile writes can call this, don't __init it please. */ -static DEFINE_SPINLOCK(prof_setup_lock); - int setup_profiling_timer(unsigned int multiplier) { - int i; - unsigned long flags; - - /* Prevent level14 ticker IRQ flooding. */ - if((!multiplier) || (lvl14_resolution / multiplier) < 500) - return -EINVAL; - - spin_lock_irqsave(&prof_setup_lock, flags); - for_each_possible_cpu(i) { - load_profile_irq(i, lvl14_resolution / multiplier); - prof_multiplier(i) = multiplier; - } - spin_unlock_irqrestore(&prof_setup_lock, flags); - - return 0; + return -EINVAL; } void __init smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index d4e3c832c341..39c64211b1b6 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -174,7 +174,7 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit) /* Errm.. not sure how to do this.. */ } -static void __init sun4c_init_timers(irq_handler_t counter_fn) +static void __init sun4c_init_timers(void) { const struct linux_prom_irqs *prom_irqs; struct device_node *dp; @@ -207,12 +207,16 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) * level 14 timer limit since we are letting the prom handle * them until we have a real console driver so L1-A works. */ - sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); + sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; + sparc_config.features |= + FEAT_L10_CLOCKSOURCE | FEAT_L10_CLOCKEVENT; + sbus_writel(timer_value(sparc_config.cs_period), + &sun4c_timers->l10_limit); master_l10_counter = &sun4c_timers->l10_count; irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri); - err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); + err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); if (err) { prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); prom_halt(); @@ -253,6 +257,7 @@ void __init sun4c_init_IRQ(void) sparc_config.init_timers = sun4c_init_timers; sparc_config.build_device_irq = sun4c_build_device_irq; + sparc_config.clock_rate = SBUS_CLOCK_RATE; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 30119f662eff..abf52654a8bc 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -282,7 +282,8 @@ static void sun4d_clear_clock_irq(void) static void sun4d_load_profile_irq(int cpu, unsigned int limit) { - bw_set_prof_limit(cpu, limit); + unsigned int value = limit ? timer_value(limit) : 0; + bw_set_prof_limit(cpu, value); } static void __init sun4d_load_profile_irqs(void) @@ -423,7 +424,7 @@ static void __init sun4d_fixup_trap_table(void) #endif } -static void __init sun4d_init_timers(irq_handler_t counter_fn) +static void __init sun4d_init_timers(void) { struct device_node *dp; struct resource res; @@ -466,12 +467,20 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) prom_halt(); } - sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); +#ifdef CONFIG_SMP + sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */ +#else + sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */ + sparc_config.features |= FEAT_L10_CLOCKEVENT; +#endif + sparc_config.features |= FEAT_L10_CLOCKSOURCE; + sbus_writel(timer_value(sparc_config.cs_period), + &sun4d_timers->l10_timer_limit); master_l10_counter = &sun4d_timers->l10_cur_count; irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); - err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); + err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); if (err) { prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err); @@ -514,6 +523,7 @@ void __init sun4d_init_IRQ(void) sparc_config.init_timers = sun4d_init_timers; sparc_config.build_device_irq = sun4d_build_device_irq; + sparc_config.clock_rate = SBUS_CLOCK_RATE; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 540b2fec09f0..576fe74d226b 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -6,16 +6,18 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include #include #include +#include +#include +#include +#include #include #include -#include -#include -#include #include "kernel.h" #include "irq.h" @@ -34,7 +36,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon } static void smp4d_ipi_init(void); -static void smp_setup_percpu_timer(void); static unsigned char cpu_leds[32]; @@ -70,7 +71,7 @@ void __cpuinit smp4d_callin(void) * to call the scheduler code. */ /* Get our local ticker going. */ - smp_setup_percpu_timer(); + register_percpu_ce(cpuid); calibrate_delay(); smp_store_cpu_info(cpuid); @@ -123,7 +124,6 @@ void __init smp4d_boot_cpus(void) smp4d_ipi_init(); if (boot_cpu_id) current_set[0] = NULL; - smp_setup_percpu_timer(); local_flush_cache_all(); } @@ -364,6 +364,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) { struct pt_regs *old_regs; int cpu = hard_smp4d_processor_id(); + struct clock_event_device *ce; static int cpu_tick[NR_CPUS]; static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; @@ -379,28 +380,15 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) show_leds(cpu); } - profile_tick(CPU_PROFILING); - - if (!--prof_counter(cpu)) { - int user = user_mode(regs); + ce = &per_cpu(sparc32_clockevent, cpu); - irq_enter(); - update_process_times(user); - irq_exit(); + irq_enter(); + ce->event_handler(ce); + irq_exit(); - prof_counter(cpu) = prof_multiplier(cpu); - } set_irq_regs(old_regs); } -static void __cpuinit smp_setup_percpu_timer(void) -{ - int cpu = hard_smp4d_processor_id(); - - prof_counter(cpu) = prof_multiplier(cpu) = 1; - load_profile_irq(cpu, lvl14_resolution); -} - void __init smp4d_blackbox_id(unsigned *addr) { int rd = *addr & 0x3e000000; diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 0d3a2d8cb266..87908a5b1223 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -318,9 +318,6 @@ struct sun4m_timer_global { static struct sun4m_timer_global __iomem *timers_global; - -unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); - static void sun4m_clear_clock_irq(void) { sbus_readl(&timers_global->l10_limit); @@ -369,10 +366,11 @@ void sun4m_clear_profile_irq(int cpu) static void sun4m_load_profile_irq(int cpu, unsigned int limit) { - sbus_writel(limit, &timers_percpu[cpu]->l14_limit); + unsigned int value = limit ? timer_value(limit) : 0; + sbus_writel(value, &timers_percpu[cpu]->l14_limit); } -static void __init sun4m_init_timers(irq_handler_t counter_fn) +static void __init sun4m_init_timers(void) { struct device_node *dp = of_find_node_by_name(NULL, "counter"); int i, err, len, num_cpu_timers; @@ -402,13 +400,22 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) /* Every per-cpu timer works in timer mode */ sbus_writel(0x00000000, &timers_global->timer_config); - sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); +#ifdef CONFIG_SMP + sparc_config.cs_period = SBUS_CLOCK_RATE * 2; /* 2 seconds */ + sparc_config.features |= FEAT_L14_ONESHOT; +#else + sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec */ + sparc_config.features |= FEAT_L10_CLOCKEVENT; +#endif + sparc_config.features |= FEAT_L10_CLOCKSOURCE; + sbus_writel(timer_value(sparc_config.cs_period), + &timers_global->l10_limit); master_l10_counter = &timers_global->l10_count; irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ); - err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); + err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL); if (err) { printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", err); @@ -480,6 +487,7 @@ void __init sun4m_init_IRQ(void) sparc_config.init_timers = sun4m_init_timers; sparc_config.build_device_irq = sun4m_build_device_irq; + sparc_config.clock_rate = SBUS_CLOCK_RATE; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 02db9a0412ce..29f8ace10b59 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -4,6 +4,7 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include "irq.h" #include "kernel.h" @@ -31,7 +33,6 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) } static void smp4m_ipi_init(void); -static void smp_setup_percpu_timer(void); void __cpuinit smp4m_callin(void) { @@ -42,8 +43,7 @@ void __cpuinit smp4m_callin(void) notify_cpu_starting(cpuid); - /* Get our local ticker going. */ - smp_setup_percpu_timer(); + register_percpu_ce(cpuid); calibrate_delay(); smp_store_cpu_info(cpuid); @@ -87,7 +87,7 @@ void __cpuinit smp4m_callin(void) void __init smp4m_boot_cpus(void) { smp4m_ipi_init(); - smp_setup_percpu_timer(); + sun4m_unmask_profile_irq(); local_flush_cache_all(); } @@ -260,37 +260,25 @@ void smp4m_cross_call_irq(void) void smp4m_percpu_timer_interrupt(struct pt_regs *regs) { struct pt_regs *old_regs; + struct clock_event_device *ce; int cpu = smp_processor_id(); old_regs = set_irq_regs(regs); - sun4m_clear_profile_irq(cpu); + ce = &per_cpu(sparc32_clockevent, cpu); - profile_tick(CPU_PROFILING); + if (ce->mode & CLOCK_EVT_MODE_PERIODIC) + sun4m_clear_profile_irq(cpu); + else + load_profile_irq(cpu, 0); /* Is this needless? */ - if (!--prof_counter(cpu)) { - int user = user_mode(regs); + irq_enter(); + ce->event_handler(ce); + irq_exit(); - irq_enter(); - update_process_times(user); - irq_exit(); - - prof_counter(cpu) = prof_multiplier(cpu); - } set_irq_regs(old_regs); } -static void __cpuinit smp_setup_percpu_timer(void) -{ - int cpu = smp_processor_id(); - - prof_counter(cpu) = prof_multiplier(cpu) = 1; - load_profile_irq(cpu, lvl14_resolution); - - if (cpu == boot_cpu_id) - sun4m_unmask_profile_irq(); -} - static void __init smp4m_blackbox_id(unsigned *addr) { int rd = *addr & 0x3e000000; diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 68e0284bf3f3..89e890bc0941 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -44,9 +46,21 @@ #include #include #include +#include #include "irq.h" +static __cacheline_aligned_in_smp DEFINE_SEQLOCK(timer_cs_lock); +static __volatile__ u64 timer_cs_internal_counter = 0; +static char timer_cs_enabled = 0; + +static struct clock_event_device timer_ce; +static char timer_ce_enabled = 0; + +#ifdef CONFIG_SMP +DEFINE_PER_CPU(struct clock_event_device, sparc32_clockevent); +#endif + DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); @@ -75,36 +89,167 @@ EXPORT_SYMBOL(profile_pc); __volatile__ unsigned int *master_l10_counter; -u32 (*do_arch_gettimeoffset)(void); - int update_persistent_clock(struct timespec now) { return set_rtc_mmss(now.tv_sec); } -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "xtime_update()" routine every clocktick - */ +irqreturn_t notrace timer_interrupt(int dummy, void *dev_id) +{ + if (timer_cs_enabled) { + write_seqlock(&timer_cs_lock); + timer_cs_internal_counter++; + clear_clock_irq(); + write_sequnlock(&timer_cs_lock); + } else { + clear_clock_irq(); + } -#define TICK_SIZE (tick_nsec / 1000) + if (timer_ce_enabled) + timer_ce.event_handler(&timer_ce); -static irqreturn_t timer_interrupt(int dummy, void *dev_id) + return IRQ_HANDLED; +} + +static void timer_ce_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { -#ifndef CONFIG_SMP - profile_tick(CPU_PROFILING); -#endif + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_RESUME: + timer_ce_enabled = 1; + break; + case CLOCK_EVT_MODE_SHUTDOWN: + timer_ce_enabled = 0; + break; + default: + break; + } + smp_mb(); +} + +static __init void setup_timer_ce(void) +{ + struct clock_event_device *ce = &timer_ce; + + BUG_ON(smp_processor_id() != boot_cpu_id); + + ce->name = "timer_ce"; + ce->rating = 100; + ce->features = CLOCK_EVT_FEAT_PERIODIC; + ce->set_mode = timer_ce_set_mode; + ce->cpumask = cpu_possible_mask; + ce->shift = 32; + ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, + ce->shift); + clockevents_register_device(ce); +} - clear_clock_irq(); +static unsigned int sbus_cycles_offset(void) +{ + unsigned int val, offset; - xtime_update(1); + val = *master_l10_counter; + offset = (val >> TIMER_VALUE_SHIFT) & TIMER_VALUE_MASK; -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - return IRQ_HANDLED; + /* Limit hit? */ + if (val & TIMER_LIMIT_BIT) + offset += sparc_config.cs_period; + + return offset; } +static cycle_t timer_cs_read(struct clocksource *cs) +{ + unsigned int seq, offset; + u64 cycles; + + do { + seq = read_seqbegin(&timer_cs_lock); + + cycles = timer_cs_internal_counter; + offset = sparc_config.get_cycles_offset(); + } while (read_seqretry(&timer_cs_lock, seq)); + + /* Count absolute cycles */ + cycles *= sparc_config.cs_period; + cycles += offset; + + return cycles; +} + +static struct clocksource timer_cs = { + .name = "timer_cs", + .rating = 100, + .read = timer_cs_read, + .mask = CLOCKSOURCE_MASK(64), + .shift = 2, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static __init int setup_timer_cs(void) +{ + timer_cs_enabled = 1; + timer_cs.mult = clocksource_hz2mult(sparc_config.clock_rate, + timer_cs.shift); + + return clocksource_register(&timer_cs); +} + +#ifdef CONFIG_SMP +static void percpu_ce_setup(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + int cpu = __first_cpu(evt->cpumask); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + load_profile_irq(cpu, SBUS_CLOCK_RATE / HZ); + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + load_profile_irq(cpu, 0); + break; + default: + break; + } +} + +static int percpu_ce_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + int cpu = __first_cpu(evt->cpumask); + unsigned int next = (unsigned int)delta; + + load_profile_irq(cpu, next); + return 0; +} + +void register_percpu_ce(int cpu) +{ + struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu); + unsigned int features = CLOCK_EVT_FEAT_PERIODIC; + + if (sparc_config.features & FEAT_L14_ONESHOT) + features |= CLOCK_EVT_FEAT_ONESHOT; + + ce->name = "percpu_ce"; + ce->rating = 200; + ce->features = features; + ce->set_mode = percpu_ce_setup; + ce->set_next_event = percpu_ce_set_next_event; + ce->cpumask = cpumask_of(cpu); + ce->shift = 32; + ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, + ce->shift); + ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce); + ce->min_delta_ns = clockevent_delta2ns(100, ce); + + clockevents_register_device(ce); +} +#endif + static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { struct platform_device *pdev = to_platform_device(dev); @@ -195,38 +340,30 @@ static int __init clock_init(void) */ fs_initcall(clock_init); - -u32 sbus_do_gettimeoffset(void) +static void __init sparc32_late_time_init(void) { - unsigned long val = *master_l10_counter; - unsigned long usec = (val >> 10) & 0x1fffff; - - /* Limit hit? */ - if (val & 0x80000000) - usec += 1000000 / HZ; - - return usec * 1000; + if (sparc_config.features & FEAT_L10_CLOCKEVENT) + setup_timer_ce(); + if (sparc_config.features & FEAT_L10_CLOCKSOURCE) + setup_timer_cs(); +#ifdef CONFIG_SMP + register_percpu_ce(smp_processor_id()); +#endif } - -u32 arch_gettimeoffset(void) +static void __init sbus_time_init(void) { - if (unlikely(!do_arch_gettimeoffset)) - return 0; - return do_arch_gettimeoffset(); + sparc_config.get_cycles_offset = sbus_cycles_offset; + sparc_config.init_timers(); } -static void __init sbus_time_init(void) +void __init time_init(void) { - do_arch_gettimeoffset = sbus_do_gettimeoffset; - btfixup(); - sparc_config.init_timers(timer_interrupt); -} + sparc_config.features = 0; + late_time_init = sparc32_late_time_init; -void __init time_init(void) -{ if (pcic_present()) pci_time_init(); else -- cgit v1.2.3 From 41eb17ce9888d759bf327cf0a4e1ea618016be64 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 13 May 2012 15:29:09 +0200 Subject: sparc32: drop unused set_irq_udt Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/kernel/irq.h | 2 -- arch/sparc/kernel/leon_kernel.c | 5 ----- arch/sparc/kernel/sun4d_irq.c | 5 ----- arch/sparc/kernel/sun4m_irq.c | 6 ------ 4 files changed, 18 deletions(-) (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 593e7a583449..b965df4c4b96 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -99,11 +99,9 @@ static inline void load_profile_irq(int cpu, int limit) #ifdef CONFIG_SMP BTFIXUPDEF_CALL(void, set_cpu_int, int, int) BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) -BTFIXUPDEF_CALL(void, set_irq_udt, int) #define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) #define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level) -#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ #define SUN4D_IPI_IRQ 13 diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 722650ab83da..06abbb371263 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -512,10 +512,6 @@ static void leon_clear_ipi(int cpu, int level) LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16); } -static void leon_set_udt(int cpu) -{ -} - void leon_clear_profile_irq(int cpu) { } @@ -546,7 +542,6 @@ void __init leon_init_IRQ(void) #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM); #endif } diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index abf52654a8bc..7796fa511f27 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -252,10 +252,6 @@ static void sun4d_clear_ipi(int cpu, int level) { } -static void sun4d_set_udt(int cpu) -{ -} - /* Setup IRQ distribution scheme. */ void __init sun4d_distribute_irqs(void) { @@ -528,7 +524,6 @@ void __init sun4d_init_IRQ(void) #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP); #endif /* Cannot enable interrupts until OBP ticker is disabled. */ } diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 87908a5b1223..fd8754dcce29 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -292,11 +292,6 @@ static void sun4m_clear_ipi(int cpu, int level) { sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear); } - -static void sun4m_set_udt(int cpu) -{ - sbus_writel(cpu, &sun4m_irq_global->interrupt_target); -} #endif struct sun4m_timer_percpu { @@ -492,7 +487,6 @@ void __init sun4m_init_IRQ(void) #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); #endif /* Cannot enable interrupts until OBP ticker is disabled. */ -- cgit v1.2.3 From 0f031b3f26c5fc019d541e41ae53b32e2dc6a373 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 13 May 2012 15:43:41 +0200 Subject: sparc32: drop unused clear_cpu_int Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/kernel/irq.h | 2 -- arch/sparc/kernel/leon_kernel.c | 8 -------- arch/sparc/kernel/sun4d_irq.c | 5 ----- arch/sparc/kernel/sun4m_irq.c | 6 ------ 4 files changed, 21 deletions(-) (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index b965df4c4b96..e2b5d5c9611e 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -98,10 +98,8 @@ static inline void load_profile_irq(int cpu, int limit) #ifdef CONFIG_SMP BTFIXUPDEF_CALL(void, set_cpu_int, int, int) -BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) #define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) -#define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level) /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ #define SUN4D_IPI_IRQ 13 diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 06abbb371263..e57435f314fe 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -505,13 +505,6 @@ void leon_set_cpu_int(int cpu, int level) LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask); } -static void leon_clear_ipi(int cpu, int level) -{ - unsigned long mask; - mask = get_irqmask(level); - LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16); -} - void leon_clear_profile_irq(int cpu) { } @@ -541,7 +534,6 @@ void __init leon_init_IRQ(void) #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM); #endif } diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 7796fa511f27..15593ee1c120 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -248,10 +248,6 @@ static void sun4d_set_cpu_int(int cpu, int level) sun4d_send_ipi(cpu, level); } -static void sun4d_clear_ipi(int cpu, int level) -{ -} - /* Setup IRQ distribution scheme. */ void __init sun4d_distribute_irqs(void) { @@ -523,7 +519,6 @@ void __init sun4d_init_IRQ(void) #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP); #endif /* Cannot enable interrupts until OBP ticker is disabled. */ } diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index fd8754dcce29..93f46035ce7c 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -287,11 +287,6 @@ static void sun4m_send_ipi(int cpu, int level) { sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set); } - -static void sun4m_clear_ipi(int cpu, int level) -{ - sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear); -} #endif struct sun4m_timer_percpu { @@ -486,7 +481,6 @@ void __init sun4m_init_IRQ(void) #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); #endif /* Cannot enable interrupts until OBP ticker is disabled. */ -- cgit v1.2.3 From 5d83d66635bb1642f3c6a3690c28ff4afdf1ae5f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 13 May 2012 20:49:31 -0700 Subject: sparc32: Move cache and TLB flushes over to method ops. This eliminated most of the remaining users of btfixup. There are some complications because of the special cases we have for sun4d, leon, and some flavors of viking. It was found that there are no cases where a flush_page_for_dma method was not hooked up to something, so the "noflush" iommu methods were removed. Add some documentation to the viking_sun4d_smp_ops to describe exactly the hardware bug which causes us to need special TLB flushing on sun4d. Signed-off-by: David S. Miller --- arch/sparc/include/asm/cacheflush_32.h | 73 ++--- arch/sparc/include/asm/cachetlb_32.h | 29 ++ arch/sparc/include/asm/tlbflush_32.h | 56 +--- arch/sparc/kernel/leon_kernel.c | 2 +- arch/sparc/kernel/leon_smp.c | 26 +- arch/sparc/kernel/smp_32.c | 122 -------- arch/sparc/kernel/sun4d_irq.c | 3 +- arch/sparc/kernel/sun4d_smp.c | 26 +- arch/sparc/kernel/sun4m_irq.c | 2 +- arch/sparc/kernel/sun4m_smp.c | 22 +- arch/sparc/mm/btfixup.c | 11 +- arch/sparc/mm/iommu.c | 38 +-- arch/sparc/mm/srmmu.c | 534 ++++++++++++++++++++++----------- 13 files changed, 466 insertions(+), 478 deletions(-) create mode 100644 arch/sparc/include/asm/cachetlb_32.h (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h index 68431b47a22a..bb014c24f318 100644 --- a/arch/sparc/include/asm/cacheflush_32.h +++ b/arch/sparc/include/asm/cacheflush_32.h @@ -1,56 +1,18 @@ #ifndef _SPARC_CACHEFLUSH_H #define _SPARC_CACHEFLUSH_H -#include /* Common for other includes */ -// #include from pgalloc.h -// #include from pgalloc.h - -// #include -#include - -/* - * Fine grained cache flushing. - */ -#ifdef CONFIG_SMP - -BTFIXUPDEF_CALL(void, local_flush_cache_all, void) -BTFIXUPDEF_CALL(void, local_flush_cache_mm, struct mm_struct *) -BTFIXUPDEF_CALL(void, local_flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long) -BTFIXUPDEF_CALL(void, local_flush_cache_page, struct vm_area_struct *, unsigned long) - -#define local_flush_cache_all() BTFIXUP_CALL(local_flush_cache_all)() -#define local_flush_cache_mm(mm) BTFIXUP_CALL(local_flush_cache_mm)(mm) -#define local_flush_cache_range(vma,start,end) BTFIXUP_CALL(local_flush_cache_range)(vma,start,end) -#define local_flush_cache_page(vma,addr) BTFIXUP_CALL(local_flush_cache_page)(vma,addr) - -BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long) -BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long) - -#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr) -#define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr) - -extern void smp_flush_cache_all(void); -extern void smp_flush_cache_mm(struct mm_struct *mm); -extern void smp_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, - unsigned long end); -extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page); - -extern void smp_flush_page_to_ram(unsigned long page); -extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); - -#endif /* CONFIG_SMP */ - -BTFIXUPDEF_CALL(void, flush_cache_all, void) -BTFIXUPDEF_CALL(void, flush_cache_mm, struct mm_struct *) -BTFIXUPDEF_CALL(void, flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long) -BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long) - -#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)() -#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm) -#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm) -#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end) -#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr) +#include + +#define flush_cache_all() \ + sparc32_cachetlb_ops->cache_all() +#define flush_cache_mm(mm) \ + sparc32_cachetlb_ops->cache_mm(mm) +#define flush_cache_dup_mm(mm) \ + sparc32_cachetlb_ops->cache_mm(mm) +#define flush_cache_range(vma,start,end) \ + sparc32_cachetlb_ops->cache_range(vma, start, end) +#define flush_cache_page(vma,addr,pfn) \ + sparc32_cachetlb_ops->cache_page(vma, addr) #define flush_icache_range(start, end) do { } while (0) #define flush_icache_page(vma, pg) do { } while (0) @@ -67,11 +29,12 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long) memcpy(dst, src, len); \ } while (0) -BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long) -BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long) - -#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr) -#define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr) +#define __flush_page_to_ram(addr) \ + sparc32_cachetlb_ops->page_to_ram(addr) +#define flush_sig_insns(mm,insn_addr) \ + sparc32_cachetlb_ops->sig_insns(mm, insn_addr) +#define flush_page_for_dma(addr) \ + sparc32_cachetlb_ops->page_for_dma(addr) extern void sparc_flush_page_to_ram(struct page *page); diff --git a/arch/sparc/include/asm/cachetlb_32.h b/arch/sparc/include/asm/cachetlb_32.h new file mode 100644 index 000000000000..efb19889a083 --- /dev/null +++ b/arch/sparc/include/asm/cachetlb_32.h @@ -0,0 +1,29 @@ +#ifndef _SPARC_CACHETLB_H +#define _SPARC_CACHETLB_H + +struct mm_struct; +struct vm_area_struct; + +struct sparc32_cachetlb_ops { + void (*cache_all)(void); + void (*cache_mm)(struct mm_struct *); + void (*cache_range)(struct vm_area_struct *, unsigned long, + unsigned long); + void (*cache_page)(struct vm_area_struct *, unsigned long); + + void (*tlb_all)(void); + void (*tlb_mm)(struct mm_struct *); + void (*tlb_range)(struct vm_area_struct *, unsigned long, + unsigned long); + void (*tlb_page)(struct vm_area_struct *, unsigned long); + + void (*page_to_ram)(unsigned long); + void (*sig_insns)(struct mm_struct *, unsigned long); + void (*page_for_dma)(unsigned long); +}; +extern const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops; +#ifdef CONFIG_SMP +extern const struct sparc32_cachetlb_ops *local_ops; +#endif + +#endif /* SPARC_CACHETLB_H */ diff --git a/arch/sparc/include/asm/tlbflush_32.h b/arch/sparc/include/asm/tlbflush_32.h index fe0a71abc9bb..a5c4142130f5 100644 --- a/arch/sparc/include/asm/tlbflush_32.h +++ b/arch/sparc/include/asm/tlbflush_32.h @@ -1,52 +1,16 @@ #ifndef _SPARC_TLBFLUSH_H #define _SPARC_TLBFLUSH_H -#include -// #include - -/* - * TLB flushing: - * - * - flush_tlb() flushes the current mm struct TLBs XXX Exists? - * - flush_tlb_all() flushes all processes TLBs - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(vma, start, end) flushes a range of pages - * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages - */ - -#ifdef CONFIG_SMP - -BTFIXUPDEF_CALL(void, local_flush_tlb_all, void) -BTFIXUPDEF_CALL(void, local_flush_tlb_mm, struct mm_struct *) -BTFIXUPDEF_CALL(void, local_flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long) -BTFIXUPDEF_CALL(void, local_flush_tlb_page, struct vm_area_struct *, unsigned long) - -#define local_flush_tlb_all() BTFIXUP_CALL(local_flush_tlb_all)() -#define local_flush_tlb_mm(mm) BTFIXUP_CALL(local_flush_tlb_mm)(mm) -#define local_flush_tlb_range(vma,start,end) BTFIXUP_CALL(local_flush_tlb_range)(vma,start,end) -#define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr) - -extern void smp_flush_tlb_all(void); -extern void smp_flush_tlb_mm(struct mm_struct *mm); -extern void smp_flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, - unsigned long end); -extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page); - -#endif /* CONFIG_SMP */ - -BTFIXUPDEF_CALL(void, flush_tlb_all, void) -BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *) -BTFIXUPDEF_CALL(void, flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long) -BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long) - -#define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)() -#define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm) -#define flush_tlb_range(vma,start,end) BTFIXUP_CALL(flush_tlb_range)(vma,start,end) -#define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr) - -// #define flush_tlb() flush_tlb_mm(current->active_mm) /* XXX Sure? */ +#include + +#define flush_tlb_all() \ + sparc32_cachetlb_ops->tlb_all() +#define flush_tlb_mm(mm) \ + sparc32_cachetlb_ops->tlb_mm(mm) +#define flush_tlb_range(vma, start, end) \ + sparc32_cachetlb_ops->tlb_range(vma, start, end) +#define flush_tlb_page(vma, addr) \ + sparc32_cachetlb_ops->tlb_page(vma, addr) /* * This is a kludge, until I know better. --zaitcev XXX diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index e57435f314fe..aeb411cd3927 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -427,7 +427,7 @@ void __init leon_init_timers(void) */ local_irq_save(flags); patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ - local_flush_cache_all(); + local_ops->cache_all(); local_irq_restore(flags); } #endif diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 356dfc45cdd0..f3e3630e31a3 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -75,8 +75,8 @@ void __cpuinit leon_callin(void) { int cpuid = hard_smpleon_processor_id(); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); leon_configure_cache_smp(); notify_cpu_starting(cpuid); @@ -87,8 +87,8 @@ void __cpuinit leon_callin(void) calibrate_delay(); smp_store_cpu_info(cpuid); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); /* * Unblock the master CPU _only_ when the scheduler state @@ -99,8 +99,8 @@ void __cpuinit leon_callin(void) */ do_swap(&cpu_callin_map[cpuid], 1); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); /* Fix idle thread fields. */ __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(¤t_set[cpuid]) @@ -143,8 +143,8 @@ void __init leon_configure_cache_smp(void) } } - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); } void leon_smp_setbroadcast(unsigned int mask) @@ -199,7 +199,7 @@ void __init leon_boot_cpus(void) leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); leon_configure_cache_smp(); - local_flush_cache_all(); + local_ops->cache_all(); } @@ -226,7 +226,7 @@ int __cpuinit leon_boot_one_cpu(int i) /* whirrr, whirrr, whirrrrrrrrr... */ printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i, (unsigned int)&leon3_irqctrl_regs->mpstatus); - local_flush_cache_all(); + local_ops->cache_all(); /* Make sure all IRQs are of from the start for this new CPU */ LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0); @@ -251,7 +251,7 @@ int __cpuinit leon_boot_one_cpu(int i) leon_enable_irq_cpu(leon_ipi_irq, i); } - local_flush_cache_all(); + local_ops->cache_all(); return 0; } @@ -271,7 +271,7 @@ void __init leon_smp_done(void) } } *prev = first; - local_flush_cache_all(); + local_ops->cache_all(); /* Free unneeded trap tables */ if (!cpu_present(1)) { @@ -337,7 +337,7 @@ static void __init leon_ipi_init(void) local_irq_save(flags); trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)]; trap_table->inst_three += smpleon_ipi - real_irq_entry; - local_flush_cache_all(); + local_ops->cache_all(); local_irq_restore(flags); for_each_possible_cpu(cpu) { diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 7c11439b44a1..8cd5c79f6193 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -171,128 +171,6 @@ void smp_call_function_interrupt(void) irq_exit(); } -void smp_flush_cache_all(void) -{ - xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); - local_flush_cache_all(); -} - -void smp_flush_tlb_all(void) -{ - xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all)); - local_flush_tlb_all(); -} - -void smp_flush_cache_mm(struct mm_struct *mm) -{ - if(mm->context != NO_CONTEXT) { - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) - xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm); - local_flush_cache_mm(mm); - } -} - -void smp_flush_tlb_mm(struct mm_struct *mm) -{ - if(mm->context != NO_CONTEXT) { - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) { - xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); - if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) - cpumask_copy(mm_cpumask(mm), - cpumask_of(smp_processor_id())); - } - local_flush_tlb_mm(mm); - } -} - -void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != NO_CONTEXT) { - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) - xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end); - local_flush_cache_range(vma, start, end); - } -} - -void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != NO_CONTEXT) { - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) - xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end); - local_flush_tlb_range(vma, start, end); - } -} - -void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - - if(mm->context != NO_CONTEXT) { - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) - xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page); - local_flush_cache_page(vma, page); - } -} - -void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - - if(mm->context != NO_CONTEXT) { - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) - xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page); - local_flush_tlb_page(vma, page); - } -} - -void smp_flush_page_to_ram(unsigned long page) -{ - /* Current theory is that those who call this are the one's - * who have just dirtied their cache with the pages contents - * in kernel space, therefore we only run this on local cpu. - * - * XXX This experiment failed, research further... -DaveM - */ -#if 1 - xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_to_ram), page); -#endif - local_flush_page_to_ram(page); -} - -void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) -{ - cpumask_t cpu_mask; - cpumask_copy(&cpu_mask, mm_cpumask(mm)); - cpumask_clear_cpu(smp_processor_id(), &cpu_mask); - if (!cpumask_empty(&cpu_mask)) - xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr); - local_flush_sig_insns(mm, insn_addr); -} - int setup_profiling_timer(unsigned int multiplier) { return -EINVAL; diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 15593ee1c120..b2fdb3d78c19 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "kernel.h" #include "irq.h" @@ -411,7 +412,7 @@ static void __init sun4d_fixup_trap_table(void) trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; - local_flush_cache_all(); + local_ops->cache_all(); local_irq_restore(flags); #endif } diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 576fe74d226b..f17fd287bf7d 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -10,12 +10,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -60,8 +62,8 @@ void __cpuinit smp4d_callin(void) /* Enable level15 interrupt, disable level14 interrupt for now */ cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); notify_cpu_starting(cpuid); /* @@ -75,13 +77,13 @@ void __cpuinit smp4d_callin(void) calibrate_delay(); smp_store_cpu_info(cpuid); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); /* Allow master to continue. */ sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) barrier(); @@ -101,8 +103,8 @@ void __cpuinit smp4d_callin(void) atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); local_irq_enable(); /* We don't allow PIL 14 yet */ @@ -124,7 +126,7 @@ void __init smp4d_boot_cpus(void) smp4d_ipi_init(); if (boot_cpu_id) current_set[0] = NULL; - local_flush_cache_all(); + local_ops->cache_all(); } int __cpuinit smp4d_boot_one_cpu(int i) @@ -150,7 +152,7 @@ int __cpuinit smp4d_boot_one_cpu(int i) /* whirrr, whirrr, whirrrrrrrrr... */ printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); - local_flush_cache_all(); + local_ops->cache_all(); prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); @@ -168,7 +170,7 @@ int __cpuinit smp4d_boot_one_cpu(int i) return -ENODEV; } - local_flush_cache_all(); + local_ops->cache_all(); return 0; } @@ -185,7 +187,7 @@ void __init smp4d_smp_done(void) prev = &cpu_data(i).next; } *prev = first; - local_flush_cache_all(); + local_ops->cache_all(); /* Ok, they are spinning and ready to go. */ smp_processors_ready = 1; diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 93f46035ce7c..32d3a5ce50f3 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -431,7 +431,7 @@ static void __init sun4m_init_timers(void) trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; - local_flush_cache_all(); + local_ops->cache_all(); local_irq_restore(flags); } #endif diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 29f8ace10b59..afcf6743f0eb 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -8,12 +8,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include "irq.h" #include "kernel.h" @@ -38,8 +40,8 @@ void __cpuinit smp4m_callin(void) { int cpuid = hard_smp_processor_id(); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); notify_cpu_starting(cpuid); @@ -48,8 +50,8 @@ void __cpuinit smp4m_callin(void) calibrate_delay(); smp_store_cpu_info(cpuid); - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); /* * Unblock the master CPU _only_ when the scheduler state @@ -61,8 +63,8 @@ void __cpuinit smp4m_callin(void) swap_ulong(&cpu_callin_map[cpuid], 1); /* XXX: What's up with all the flushes? */ - local_flush_cache_all(); - local_flush_tlb_all(); + local_ops->cache_all(); + local_ops->tlb_all(); /* Fix idle thread fields. */ __asm__ __volatile__("ld [%0], %%g6\n\t" @@ -88,7 +90,7 @@ void __init smp4m_boot_cpus(void) { smp4m_ipi_init(); sun4m_unmask_profile_irq(); - local_flush_cache_all(); + local_ops->cache_all(); } int __cpuinit smp4m_boot_one_cpu(int i) @@ -117,7 +119,7 @@ int __cpuinit smp4m_boot_one_cpu(int i) /* whirrr, whirrr, whirrrrrrrrr... */ printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); - local_flush_cache_all(); + local_ops->cache_all(); prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); /* wheee... it's going... */ @@ -132,7 +134,7 @@ int __cpuinit smp4m_boot_one_cpu(int i) return -ENODEV; } - local_flush_cache_all(); + local_ops->cache_all(); return 0; } @@ -149,7 +151,7 @@ void __init smp4m_smp_done(void) prev = &cpu_data(i).next; } *prev = first; - local_flush_cache_all(); + local_ops->cache_all(); /* Ok, they are spinning and ready to go. */ } diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c index 1b7aa565497e..dcbb7ffcc82e 100644 --- a/arch/sparc/mm/btfixup.c +++ b/arch/sparc/mm/btfixup.c @@ -38,7 +38,6 @@ static char insn_s[] __initdata = "Fixup s %p doesn't refer to an OR at %p[%08x] static char insn_h[] __initdata = "Fixup h %p doesn't refer to a SETHI at %p[%08x]\n"; static char insn_a[] __initdata = "Fixup a %p doesn't refer to a SETHI nor OR at %p[%08x]\n"; static char insn_i[] __initdata = "Fixup i %p doesn't refer to a valid instruction at %p[%08x]\n"; -static char fca_und[] __initdata = "flush_cache_all undefined in btfixup()\n"; static char wrong_setaddr[] __initdata = "Garbled CALL/INT patch at %p[%08x,%08x,%08x]=%08x\n"; #ifdef BTFIXUP_OPTIMIZE_OTHER @@ -75,7 +74,6 @@ void __init btfixup(void) unsigned insn; unsigned *addr; int fmangled = 0; - void (*flush_cacheall)(void); if (!visited) { visited++; @@ -311,13 +309,8 @@ void __init btfixup(void) p = q + count; } #ifdef CONFIG_SMP - flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(local_flush_cache_all); + local_ops->cache_all(); #else - flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(flush_cache_all); + sparc32_cachetlb_ops->cache_all(); #endif - if (!flush_cacheall) { - prom_printf(fca_und); - prom_halt(); - } - (*flush_cacheall)(); } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index c64f81e370aa..720bea2c7fdd 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -39,8 +39,6 @@ /* srmmu.c */ extern int viking_mxcc_present; -BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long) -#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page) extern int flush_page_for_dma_global; static int viking_flush; /* viking.S */ @@ -216,11 +214,6 @@ static u32 iommu_get_scsi_one(struct device *dev, char *vaddr, unsigned int len) return busa + off; } -static __u32 iommu_get_scsi_one_noflush(struct device *dev, char *vaddr, unsigned long len) -{ - return iommu_get_scsi_one(dev, vaddr, len); -} - static __u32 iommu_get_scsi_one_gflush(struct device *dev, char *vaddr, unsigned long len) { flush_page_for_dma(0); @@ -238,19 +231,6 @@ static __u32 iommu_get_scsi_one_pflush(struct device *dev, char *vaddr, unsigned return iommu_get_scsi_one(dev, vaddr, len); } -static void iommu_get_scsi_sgl_noflush(struct device *dev, struct scatterlist *sg, int sz) -{ - int n; - - while (sz != 0) { - --sz; - n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; - sg->dma_length = sg->length; - sg = sg_next(sg); - } -} - static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg, int sz) { int n; @@ -426,17 +406,6 @@ static void iommu_unmap_dma_area(struct device *dev, unsigned long busa, int len } #endif -static const struct sparc32_dma_ops iommu_dma_noflush_ops = { - .get_scsi_one = iommu_get_scsi_one_noflush, - .get_scsi_sgl = iommu_get_scsi_sgl_noflush, - .release_scsi_one = iommu_release_scsi_one, - .release_scsi_sgl = iommu_release_scsi_sgl, -#ifdef CONFIG_SBUS - .map_dma_area = iommu_map_dma_area, - .unmap_dma_area = iommu_unmap_dma_area, -#endif -}; - static const struct sparc32_dma_ops iommu_dma_gflush_ops = { .get_scsi_one = iommu_get_scsi_one_gflush, .get_scsi_sgl = iommu_get_scsi_sgl_gflush, @@ -461,12 +430,7 @@ static const struct sparc32_dma_ops iommu_dma_pflush_ops = { void __init ld_mmu_iommu(void) { - viking_flush = (BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page); - - if (!BTFIXUPVAL_CALL(flush_page_for_dma)) { - /* IO coherent chip */ - sparc32_dma_ops = &iommu_dma_noflush_ops; - } else if (flush_page_for_dma_global) { + if (flush_page_for_dma_global) { /* flush_page_for_dma flushes everything, no matter of what page is it */ sparc32_dma_ops = &iommu_dma_gflush_ops; } else { diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index dc398e5c71a4..cba05fa3fbc7 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -65,24 +65,20 @@ extern unsigned long last_valid_pfn; static pgd_t *srmmu_swapper_pg_dir; +const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops; + #ifdef CONFIG_SMP +const struct sparc32_cachetlb_ops *local_ops; + #define FLUSH_BEGIN(mm) #define FLUSH_END #else -#define FLUSH_BEGIN(mm) if((mm)->context != NO_CONTEXT) { +#define FLUSH_BEGIN(mm) if ((mm)->context != NO_CONTEXT) { #define FLUSH_END } #endif -BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long) -#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page) - int flush_page_for_dma_global = 1; -#ifdef CONFIG_SMP -BTFIXUPDEF_CALL(void, local_flush_page_for_dma, unsigned long) -#define local_flush_page_for_dma(page) BTFIXUP_CALL(local_flush_page_for_dma)(page) -#endif - char *srmmu_name; ctxd_t *srmmu_ctx_table_phys; @@ -1126,7 +1122,7 @@ void __init srmmu_paging_init(void) srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys); #ifdef CONFIG_SMP /* Stop from hanging here... */ - local_flush_tlb_all(); + local_ops->tlb_all(); #else flush_tlb_all(); #endif @@ -1284,6 +1280,20 @@ static void __cpuinit poke_hypersparc(void) clear = srmmu_get_fstatus(); } +static const struct sparc32_cachetlb_ops hypersparc_ops = { + .cache_all = hypersparc_flush_cache_all, + .cache_mm = hypersparc_flush_cache_mm, + .cache_page = hypersparc_flush_cache_page, + .cache_range = hypersparc_flush_cache_range, + .tlb_all = hypersparc_flush_tlb_all, + .tlb_mm = hypersparc_flush_tlb_mm, + .tlb_page = hypersparc_flush_tlb_page, + .tlb_range = hypersparc_flush_tlb_range, + .page_to_ram = hypersparc_flush_page_to_ram, + .sig_insns = hypersparc_flush_sig_insns, + .page_for_dma = hypersparc_flush_page_for_dma, +}; + static void __init init_hypersparc(void) { srmmu_name = "ROSS HyperSparc"; @@ -1292,21 +1302,7 @@ static void __init init_hypersparc(void) init_vac_layout(); is_hypersparc = 1; - - BTFIXUPSET_CALL(flush_cache_all, hypersparc_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, hypersparc_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, hypersparc_flush_cache_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, hypersparc_flush_cache_page, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(flush_tlb_all, hypersparc_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, hypersparc_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(__flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_sig_insns, hypersparc_flush_sig_insns, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP); - + sparc32_cachetlb_ops = &hypersparc_ops; poke_srmmu = poke_hypersparc; @@ -1352,25 +1348,24 @@ static void __cpuinit poke_cypress(void) srmmu_set_mmureg(mreg); } +static const struct sparc32_cachetlb_ops cypress_ops = { + .cache_all = cypress_flush_cache_all, + .cache_mm = cypress_flush_cache_mm, + .cache_page = cypress_flush_cache_page, + .cache_range = cypress_flush_cache_range, + .tlb_all = cypress_flush_tlb_all, + .tlb_mm = cypress_flush_tlb_mm, + .tlb_page = cypress_flush_tlb_page, + .tlb_range = cypress_flush_tlb_range, + .page_to_ram = cypress_flush_page_to_ram, + .sig_insns = cypress_flush_sig_insns, + .page_for_dma = cypress_flush_page_for_dma, +}; + static void __init init_cypress_common(void) { init_vac_layout(); - - BTFIXUPSET_CALL(flush_cache_all, cypress_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, cypress_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, cypress_flush_cache_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, cypress_flush_cache_page, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(flush_tlb_all, cypress_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, cypress_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, cypress_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, cypress_flush_tlb_range, BTFIXUPCALL_NORM); - - - BTFIXUPSET_CALL(__flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP); - + sparc32_cachetlb_ops = &cypress_ops; poke_srmmu = poke_cypress; } @@ -1421,6 +1416,20 @@ static void __cpuinit poke_swift(void) srmmu_set_mmureg(mreg); } +static const struct sparc32_cachetlb_ops swift_ops = { + .cache_all = swift_flush_cache_all, + .cache_mm = swift_flush_cache_mm, + .cache_page = swift_flush_cache_page, + .cache_range = swift_flush_cache_range, + .tlb_all = swift_flush_tlb_all, + .tlb_mm = swift_flush_tlb_mm, + .tlb_page = swift_flush_tlb_page, + .tlb_range = swift_flush_tlb_range, + .page_to_ram = swift_flush_page_to_ram, + .sig_insns = swift_flush_sig_insns, + .page_for_dma = swift_flush_page_for_dma, +}; + #define SWIFT_MASKID_ADDR 0x10003018 static void __init init_swift(void) { @@ -1471,21 +1480,7 @@ static void __init init_swift(void) break; } - BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, swift_flush_cache_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, swift_flush_cache_range, BTFIXUPCALL_NORM); - - - BTFIXUPSET_CALL(flush_tlb_all, swift_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, swift_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(__flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM); - + sparc32_cachetlb_ops = &swift_ops; flush_page_for_dma_global = 0; /* @@ -1618,26 +1613,25 @@ static void __cpuinit poke_turbosparc(void) srmmu_set_mmureg(mreg); } +static const struct sparc32_cachetlb_ops turbosparc_ops = { + .cache_all = turbosparc_flush_cache_all, + .cache_mm = turbosparc_flush_cache_mm, + .cache_page = turbosparc_flush_cache_page, + .cache_range = turbosparc_flush_cache_range, + .tlb_all = turbosparc_flush_tlb_all, + .tlb_mm = turbosparc_flush_tlb_mm, + .tlb_page = turbosparc_flush_tlb_page, + .tlb_range = turbosparc_flush_tlb_range, + .page_to_ram = turbosparc_flush_page_to_ram, + .sig_insns = turbosparc_flush_sig_insns, + .page_for_dma = turbosparc_flush_page_for_dma, +}; + static void __init init_turbosparc(void) { srmmu_name = "Fujitsu TurboSparc"; srmmu_modtype = TurboSparc; - - BTFIXUPSET_CALL(flush_cache_all, turbosparc_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, turbosparc_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, turbosparc_flush_cache_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, turbosparc_flush_cache_range, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(flush_tlb_all, turbosparc_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, turbosparc_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(__flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NORM); - + sparc32_cachetlb_ops = &turbosparc_ops; poke_srmmu = poke_turbosparc; } @@ -1652,6 +1646,20 @@ static void __cpuinit poke_tsunami(void) srmmu_set_mmureg(mreg); } +static const struct sparc32_cachetlb_ops tsunami_ops = { + .cache_all = tsunami_flush_cache_all, + .cache_mm = tsunami_flush_cache_mm, + .cache_page = tsunami_flush_cache_page, + .cache_range = tsunami_flush_cache_range, + .tlb_all = tsunami_flush_tlb_all, + .tlb_mm = tsunami_flush_tlb_mm, + .tlb_page = tsunami_flush_tlb_page, + .tlb_range = tsunami_flush_tlb_range, + .page_to_ram = tsunami_flush_page_to_ram, + .sig_insns = tsunami_flush_sig_insns, + .page_for_dma = tsunami_flush_page_for_dma, +}; + static void __init init_tsunami(void) { /* @@ -1662,22 +1670,7 @@ static void __init init_tsunami(void) srmmu_name = "TI Tsunami"; srmmu_modtype = Tsunami; - - BTFIXUPSET_CALL(flush_cache_all, tsunami_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, tsunami_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, tsunami_flush_cache_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, tsunami_flush_cache_range, BTFIXUPCALL_NORM); - - - BTFIXUPSET_CALL(flush_tlb_all, tsunami_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, tsunami_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, tsunami_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, tsunami_flush_tlb_range, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(__flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_sig_insns, tsunami_flush_sig_insns, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM); - + sparc32_cachetlb_ops = &tsunami_ops; poke_srmmu = poke_tsunami; tsunami_setup_blockops(); @@ -1688,7 +1681,7 @@ static void __cpuinit poke_viking(void) unsigned long mreg = srmmu_get_mmureg(); static int smp_catch; - if(viking_mxcc_present) { + if (viking_mxcc_present) { unsigned long mxcc_control = mxcc_get_creg(); mxcc_control |= (MXCC_CTL_ECE | MXCC_CTL_PRE | MXCC_CTL_MCE); @@ -1725,6 +1718,52 @@ static void __cpuinit poke_viking(void) srmmu_set_mmureg(mreg); } +static struct sparc32_cachetlb_ops viking_ops = { + .cache_all = viking_flush_cache_all, + .cache_mm = viking_flush_cache_mm, + .cache_page = viking_flush_cache_page, + .cache_range = viking_flush_cache_range, + .tlb_all = viking_flush_tlb_all, + .tlb_mm = viking_flush_tlb_mm, + .tlb_page = viking_flush_tlb_page, + .tlb_range = viking_flush_tlb_range, + .page_to_ram = viking_flush_page_to_ram, + .sig_insns = viking_flush_sig_insns, + .page_for_dma = viking_flush_page_for_dma, +}; + +#ifdef CONFIG_SMP +/* On sun4d the cpu broadcasts local TLB flushes, so we can just + * perform the local TLB flush and all the other cpus will see it. + * But, unfortunately, there is a bug in the sun4d XBUS backplane + * that requires that we add some synchronization to these flushes. + * + * The bug is that the fifo which keeps track of all the pending TLB + * broadcasts in the system is an entry or two too small, so if we + * have too many going at once we'll overflow that fifo and lose a TLB + * flush resulting in corruption. + * + * Our workaround is to take a global spinlock around the TLB flushes, + * which guarentees we won't ever have too many pending. It's a big + * hammer, but a semaphore like system to make sure we only have N TLB + * flushes going at once will require SMP locking anyways so there's + * no real value in trying any harder than this. + */ +static struct sparc32_cachetlb_ops viking_sun4d_smp_ops = { + .cache_all = viking_flush_cache_all, + .cache_mm = viking_flush_cache_mm, + .cache_page = viking_flush_cache_page, + .cache_range = viking_flush_cache_range, + .tlb_all = sun4dsmp_flush_tlb_all, + .tlb_mm = sun4dsmp_flush_tlb_mm, + .tlb_page = sun4dsmp_flush_tlb_page, + .tlb_range = sun4dsmp_flush_tlb_range, + .page_to_ram = viking_flush_page_to_ram, + .sig_insns = viking_flush_sig_insns, + .page_for_dma = viking_flush_page_for_dma, +}; +#endif + static void __init init_viking(void) { unsigned long mreg = srmmu_get_mmureg(); @@ -1742,76 +1781,101 @@ static void __init init_viking(void) * This is only necessary because of the new way in * which we use the IOMMU. */ - BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page, BTFIXUPCALL_NORM); - + viking_ops.page_for_dma = viking_flush_page; +#ifdef CONFIG_SMP + viking_sun4d_smp_ops.page_for_dma = viking_flush_page; +#endif flush_page_for_dma_global = 0; } else { srmmu_name = "TI Viking/MXCC"; viking_mxcc_present = 1; - srmmu_cache_pagetables = 1; - - /* MXCC vikings lack the DMA snooping bug. */ - BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page_for_dma, BTFIXUPCALL_NOP); } - BTFIXUPSET_CALL(flush_cache_all, viking_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, viking_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, viking_flush_cache_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, viking_flush_cache_range, BTFIXUPCALL_NORM); - + sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *) + &viking_ops; #ifdef CONFIG_SMP - if (sparc_cpu_model == sun4d) { - BTFIXUPSET_CALL(flush_tlb_all, sun4dsmp_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, sun4dsmp_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, sun4dsmp_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, sun4dsmp_flush_tlb_range, BTFIXUPCALL_NORM); - } else + if (sparc_cpu_model == sun4d) + sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *) + &viking_sun4d_smp_ops; #endif - { - BTFIXUPSET_CALL(flush_tlb_all, viking_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, viking_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, viking_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, viking_flush_tlb_range, BTFIXUPCALL_NORM); - } - - BTFIXUPSET_CALL(__flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_sig_insns, viking_flush_sig_insns, BTFIXUPCALL_NOP); poke_srmmu = poke_viking; } #ifdef CONFIG_SPARC_LEON +static void leon_flush_cache_mm(struct mm_struct *mm) +{ + leon_flush_cache_all(); +} -void __init poke_leonsparc(void) +static void leon_flush_cache_page(struct vm_area_struct *vma, unsigned long page) { + leon_flush_pcache_all(vma, page); } -void __init init_leon(void) +static void leon_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, + unsigned long end) { + leon_flush_cache_all(); +} - srmmu_name = "LEON"; +static void leon_flush_tlb_mm(struct mm_struct *mm) +{ + leon_flush_tlb_all(); +} + +static void leon_flush_tlb_page(struct vm_area_struct *vma, + unsigned long page) +{ + leon_flush_tlb_all(); +} - BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all, - BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, leon_flush_cache_all, - BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, leon_flush_pcache_all, - BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, leon_flush_cache_all, - BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_for_dma, leon_flush_dcache_all, - BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(flush_tlb_all, leon_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, leon_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, leon_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, leon_flush_tlb_all, BTFIXUPCALL_NORM); - - BTFIXUPSET_CALL(__flush_page_to_ram, leon_flush_cache_all, - BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_sig_insns, leon_flush_cache_all, BTFIXUPCALL_NOP); +static void leon_flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, + unsigned long end) +{ + leon_flush_tlb_all(); +} + +static void leon_flush_page_to_ram(unsigned long page) +{ + leon_flush_cache_all(); +} + +static void leon_flush_sig_insns(struct mm_struct *mm, unsigned long page) +{ + leon_flush_cache_all(); +} + +static void leon_flush_page_for_dma(unsigned long page) +{ + leon_flush_dcache_all(); +} + +void __init poke_leonsparc(void) +{ +} + +static const struct sparc32_cachetlb_ops leon_ops = { + .cache_all = leon_flush_cache_all, + .cache_mm = leon_flush_cache_mm, + .cache_page = leon_flush_cache_page, + .cache_range = leon_flush_cache_range, + .tlb_all = leon_flush_tlb_all, + .tlb_mm = leon_flush_tlb_mm, + .tlb_page = leon_flush_tlb_page, + .tlb_range = leon_flush_tlb_range, + .page_to_ram = leon_flush_page_to_ram, + .sig_insns = leon_flush_sig_insns, + .page_for_dma = leon_flush_page_for_dma, +}; +void __init init_leon(void) +{ + srmmu_name = "LEON"; + sparc32_cachetlb_ops = &leon_ops; poke_srmmu = poke_leonsparc; srmmu_cache_pagetables = 0; @@ -1925,10 +1989,152 @@ static void __init get_srmmu_type(void) /* Local cross-calls. */ static void smp_flush_page_for_dma(unsigned long page) { - xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_for_dma), page); - local_flush_page_for_dma(page); + xc1((smpfunc_t) local_ops->page_for_dma, page); + local_ops->page_for_dma(page); +} + +static void smp_flush_cache_all(void) +{ + xc0((smpfunc_t) local_ops->cache_all); + local_ops->cache_all(); +} + +static void smp_flush_tlb_all(void) +{ + xc0((smpfunc_t) local_ops->tlb_all); + local_ops->tlb_all(); +} + +static void smp_flush_cache_mm(struct mm_struct *mm) +{ + if (mm->context != NO_CONTEXT) { + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) + xc1((smpfunc_t) local_ops->cache_mm, (unsigned long) mm); + local_ops->cache_mm(mm); + } +} + +static void smp_flush_tlb_mm(struct mm_struct *mm) +{ + if (mm->context != NO_CONTEXT) { + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) { + xc1((smpfunc_t) local_ops->tlb_mm, (unsigned long) mm); + if (atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) + cpumask_copy(mm_cpumask(mm), + cpumask_of(smp_processor_id())); + } + local_ops->tlb_mm(mm); + } +} + +static void smp_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + + if (mm->context != NO_CONTEXT) { + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) + xc3((smpfunc_t) local_ops->cache_range, + (unsigned long) vma, start, end); + local_ops->cache_range(vma, start, end); + } +} + +static void smp_flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + + if (mm->context != NO_CONTEXT) { + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) + xc3((smpfunc_t) local_ops->tlb_range, + (unsigned long) vma, start, end); + local_ops->tlb_range(vma, start, end); + } } +static void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + + if (mm->context != NO_CONTEXT) { + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) + xc2((smpfunc_t) local_ops->cache_page, + (unsigned long) vma, page); + local_ops->cache_page(vma, page); + } +} + +static void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + + if (mm->context != NO_CONTEXT) { + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) + xc2((smpfunc_t) local_ops->tlb_page, + (unsigned long) vma, page); + local_ops->tlb_page(vma, page); + } +} + +static void smp_flush_page_to_ram(unsigned long page) +{ + /* Current theory is that those who call this are the one's + * who have just dirtied their cache with the pages contents + * in kernel space, therefore we only run this on local cpu. + * + * XXX This experiment failed, research further... -DaveM + */ +#if 1 + xc1((smpfunc_t) local_ops->page_to_ram, page); +#endif + local_ops->page_to_ram(page); +} + +static void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) +{ + cpumask_t cpu_mask; + cpumask_copy(&cpu_mask, mm_cpumask(mm)); + cpumask_clear_cpu(smp_processor_id(), &cpu_mask); + if (!cpumask_empty(&cpu_mask)) + xc2((smpfunc_t) local_ops->sig_insns, + (unsigned long) mm, insn_addr); + local_ops->sig_insns(mm, insn_addr); +} + +static struct sparc32_cachetlb_ops smp_cachetlb_ops = { + .cache_all = smp_flush_cache_all, + .cache_mm = smp_flush_cache_mm, + .cache_page = smp_flush_cache_page, + .cache_range = smp_flush_cache_range, + .tlb_all = smp_flush_tlb_all, + .tlb_mm = smp_flush_tlb_mm, + .tlb_page = smp_flush_tlb_page, + .tlb_range = smp_flush_tlb_range, + .page_to_ram = smp_flush_page_to_ram, + .sig_insns = smp_flush_sig_insns, + .page_for_dma = smp_flush_page_for_dma, +}; #endif /* Load up routines and constants for sun4m and sun4d mmu */ @@ -1942,44 +2148,30 @@ void __init load_mmu(void) #ifdef CONFIG_SMP /* El switcheroo... */ + local_ops = sparc32_cachetlb_ops; - BTFIXUPCOPY_CALL(local_flush_cache_all, flush_cache_all); - BTFIXUPCOPY_CALL(local_flush_cache_mm, flush_cache_mm); - BTFIXUPCOPY_CALL(local_flush_cache_range, flush_cache_range); - BTFIXUPCOPY_CALL(local_flush_cache_page, flush_cache_page); - BTFIXUPCOPY_CALL(local_flush_tlb_all, flush_tlb_all); - BTFIXUPCOPY_CALL(local_flush_tlb_mm, flush_tlb_mm); - BTFIXUPCOPY_CALL(local_flush_tlb_range, flush_tlb_range); - BTFIXUPCOPY_CALL(local_flush_tlb_page, flush_tlb_page); - BTFIXUPCOPY_CALL(local_flush_page_to_ram, __flush_page_to_ram); - BTFIXUPCOPY_CALL(local_flush_sig_insns, flush_sig_insns); - BTFIXUPCOPY_CALL(local_flush_page_for_dma, flush_page_for_dma); - - BTFIXUPSET_CALL(flush_cache_all, smp_flush_cache_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM); - if (sparc_cpu_model != sun4d && - sparc_cpu_model != sparc_leon) { - BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_tlb_page, smp_flush_tlb_page, BTFIXUPCALL_NORM); + if (sparc_cpu_model == sun4d || sparc_cpu_model == sparc_leon) { + smp_cachetlb_ops.tlb_all = local_ops->tlb_all; + smp_cachetlb_ops.tlb_mm = local_ops->tlb_mm; + smp_cachetlb_ops.tlb_range = local_ops->tlb_range; + smp_cachetlb_ops.tlb_page = local_ops->tlb_page; } - BTFIXUPSET_CALL(__flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM); if (poke_srmmu == poke_viking) { /* Avoid unnecessary cross calls. */ - BTFIXUPCOPY_CALL(flush_cache_all, local_flush_cache_all); - BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm); - BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range); - BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page); - BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram); - BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns); - BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma); + smp_cachetlb_ops.cache_all = local_ops->cache_all; + smp_cachetlb_ops.cache_mm = local_ops->cache_mm; + smp_cachetlb_ops.cache_range = local_ops->cache_range; + smp_cachetlb_ops.cache_page = local_ops->cache_page; + + smp_cachetlb_ops.page_to_ram = local_ops->page_to_ram; + smp_cachetlb_ops.sig_insns = local_ops->sig_insns; + smp_cachetlb_ops.page_for_dma = local_ops->page_for_dma; } + + /* It really is const after this point. */ + sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *) + &smp_cachetlb_ops; #endif if (sparc_cpu_model == sun4d) -- cgit v1.2.3 From 4ba22b16bbf354822b7988ec5b4b35774dcd479f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 14 May 2012 15:14:36 +0200 Subject: sparc32: move smp ipi to method ops I ended up renaming set_cpu_int to send_ipi to be consistent all way around. send_ipi was moved to the *_smp.c files so we could call the relevant method direct, without any _ops indirection. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/obio.h | 13 ------------ arch/sparc/include/asm/smp_32.h | 45 +++++++++++++++++++++++++++++------------ arch/sparc/kernel/irq.h | 8 +++++--- arch/sparc/kernel/leon_kernel.c | 19 +++-------------- arch/sparc/kernel/leon_smp.c | 27 +++++++++++++++++-------- arch/sparc/kernel/smp_32.c | 8 +++++--- arch/sparc/kernel/sun4d_irq.c | 8 -------- arch/sparc/kernel/sun4d_smp.c | 34 ++++++++++++++++++++++--------- arch/sparc/kernel/sun4m_irq.c | 14 ------------- arch/sparc/kernel/sun4m_smp.c | 36 ++++++++++++++++----------------- 10 files changed, 107 insertions(+), 105 deletions(-) (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h index 4ade0c8a2c79..910c1d9af1f8 100644 --- a/arch/sparc/include/asm/obio.h +++ b/arch/sparc/include/asm/obio.h @@ -220,19 +220,6 @@ static inline void cc_set_igen(unsigned gen) "i" (ASI_M_MXCC)); } -/* +-------+-------------+-----------+------------------------------------+ - * | bcast | devid | sid | levels mask | - * +-------+-------------+-----------+------------------------------------+ - * 31 30 23 22 15 14 0 - */ -#define IGEN_MESSAGE(bcast, devid, sid, levels) \ - (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels)) - -static inline void sun4d_send_ipi(int cpu, int level) -{ - cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1))); -} - #endif /* !__ASSEMBLY__ */ #endif /* !(_SPARC_OBIO_H) */ diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h index f5b325e731dd..d596061939d1 100644 --- a/arch/sparc/include/asm/smp_32.h +++ b/arch/sparc/include/asm/smp_32.h @@ -58,24 +58,43 @@ struct seq_file; void smp_bogo(struct seq_file *); void smp_info(struct seq_file *); -BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long) -BTFIXUPDEF_CALL(void, smp_ipi_resched, int); -BTFIXUPDEF_CALL(void, smp_ipi_single, int); -BTFIXUPDEF_CALL(void, smp_ipi_mask_one, int); - -#define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4) +struct sparc32_ipi_ops { + void (*cross_call)(smpfunc_t func, cpumask_t mask, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4); + void (*resched)(int cpu); + void (*single)(int cpu); + void (*mask_one)(int cpu); +}; +extern const struct sparc32_ipi_ops *sparc32_ipi_ops; + +static inline void xc0(smpfunc_t func) +{ + sparc32_ipi_ops->cross_call(func, *cpu_online_mask, 0, 0, 0, 0); +} -static inline void xc0(smpfunc_t func) { smp_cross_call(func, *cpu_online_mask, 0, 0, 0, 0); } static inline void xc1(smpfunc_t func, unsigned long arg1) -{ smp_cross_call(func, *cpu_online_mask, arg1, 0, 0, 0); } +{ + sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, 0, 0, 0); +} static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) -{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0); } +{ + sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0); +} + static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, - unsigned long arg3) -{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, 0); } + unsigned long arg3) +{ + sparc32_ipi_ops->cross_call(func, *cpu_online_mask, + arg1, arg2, arg3, 0); +} + static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, - unsigned long arg3, unsigned long arg4) -{ smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, arg4); } + unsigned long arg3, unsigned long arg4) +{ + sparc32_ipi_ops->cross_call(func, *cpu_online_mask, + arg1, arg2, arg3, arg4); +} extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index e2b5d5c9611e..e40ca6c0076a 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -10,6 +10,9 @@ struct irq_bucket { unsigned int pil; }; +#define SUN4M_HARD_INT(x) (0x000000001 << (x)) +#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) + #define SUN4D_MAX_BOARD 10 #define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5) @@ -96,10 +99,9 @@ static inline void load_profile_irq(int cpu, int limit) BTFIXUP_CALL(load_profile_irq)(cpu, limit); } -#ifdef CONFIG_SMP -BTFIXUPDEF_CALL(void, set_cpu_int, int, int) +unsigned long leon_get_irqmask(unsigned int irq); -#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) +#ifdef CONFIG_SMP /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ #define SUN4D_IPI_IRQ 13 diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index aeb411cd3927..1770b3c1cc74 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -86,7 +86,7 @@ void leon_eirq_setup(unsigned int eirq) sparc_leon_eirq = eirq; } -static inline unsigned long get_irqmask(unsigned int irq) +unsigned long leon_get_irqmask(unsigned int irq) { unsigned long mask; @@ -212,7 +212,7 @@ unsigned int leon_build_device_irq(unsigned int real_irq, unsigned long mask; irq = 0; - mask = get_irqmask(real_irq); + mask = leon_get_irqmask(real_irq); if (mask == 0) goto out; @@ -497,14 +497,6 @@ void __init leon_node_init(struct device_node *dp, struct device_node ***nextp) } #ifdef CONFIG_SMP - -void leon_set_cpu_int(int cpu, int level) -{ - unsigned long mask; - mask = get_irqmask(level); - LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask); -} - void leon_clear_profile_irq(int cpu) { } @@ -512,7 +504,7 @@ void leon_clear_profile_irq(int cpu) void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) { unsigned long mask, flags, *addr; - mask = get_irqmask(irq_nr); + mask = leon_get_irqmask(irq_nr); spin_lock_irqsave(&leon_irq_lock, flags); addr = (unsigned long *)LEON_IMASK(cpu); LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask)); @@ -531,11 +523,6 @@ void __init leon_init_IRQ(void) BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq, BTFIXUPCALL_NOP); - -#ifdef CONFIG_SMP - BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM); -#endif - } void __init leon_init(void) diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index faff792d53c8..29325bacba6f 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -346,6 +346,13 @@ static void __init leon_ipi_init(void) } } +static void leon_send_ipi(int cpu, int level) +{ + unsigned long mask; + mask = leon_get_irqmask(level); + LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask); +} + static void leon_ipi_single(int cpu) { struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); @@ -354,7 +361,7 @@ static void leon_ipi_single(int cpu) work->single = 1; /* Generate IRQ on the CPU */ - set_cpu_int(cpu, leon_ipi_irq); + leon_send_ipi(cpu, leon_ipi_irq); } static void leon_ipi_mask_one(int cpu) @@ -365,7 +372,7 @@ static void leon_ipi_mask_one(int cpu) work->msk = 1; /* Generate IRQ on the CPU */ - set_cpu_int(cpu, leon_ipi_irq); + leon_send_ipi(cpu, leon_ipi_irq); } static void leon_ipi_resched(int cpu) @@ -376,7 +383,7 @@ static void leon_ipi_resched(int cpu) work->resched = 1; /* Generate IRQ on the CPU (any IRQ will cause resched) */ - set_cpu_int(cpu, leon_ipi_irq); + leon_send_ipi(cpu, leon_ipi_irq); } void leonsmp_ipi_interrupt(void) @@ -448,7 +455,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, if (cpumask_test_cpu(i, &mask)) { ccall_info.processors_in[i] = 0; ccall_info.processors_out[i] = 0; - set_cpu_int(i, LEON3_IRQ_CROSS_CALL); + leon_send_ipi(i, LEON3_IRQ_CROSS_CALL); } } @@ -491,15 +498,19 @@ void leon_cross_call_irq(void) ccall_info.processors_out[i] = 1; } +static const struct sparc32_ipi_ops leon_ipi_ops = { + .cross_call = leon_cross_call, + .resched = leon_ipi_resched, + .single = leon_ipi_single, + .mask_one = leon_ipi_mask_one, +}; + void __init leon_init_smp(void) { /* Patch ipi15 trap table */ t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m); - BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM); + sparc32_ipi_ops = &leon_ipi_ops; } #endif /* CONFIG_SPARC_LEON */ diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 8cd5c79f6193..57713758079e 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -40,6 +40,8 @@ volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; cpumask_t smp_commenced_mask = CPU_MASK_NONE; +const struct sparc32_ipi_ops *sparc32_ipi_ops; + /* The only guaranteed locking primitive available on all Sparc * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically * places the current byte at the effective address into dest_reg and @@ -124,7 +126,7 @@ void smp_send_reschedule(int cpu) * a single CPU. The trap handler needs only to do trap entry/return * to call schedule. */ - BTFIXUP_CALL(smp_ipi_resched)(cpu); + sparc32_ipi_ops->resched(cpu); } void smp_send_stop(void) @@ -134,7 +136,7 @@ void smp_send_stop(void) void arch_send_call_function_single_ipi(int cpu) { /* trigger one IPI single call on one CPU */ - BTFIXUP_CALL(smp_ipi_single)(cpu); + sparc32_ipi_ops->single(cpu); } void arch_send_call_function_ipi_mask(const struct cpumask *mask) @@ -143,7 +145,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) /* trigger IPI mask call on each CPU */ for_each_cpu(cpu, mask) - BTFIXUP_CALL(smp_ipi_mask_one)(cpu); + sparc32_ipi_ops->mask_one(cpu); } void smp_resched_interrupt(void) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index b2fdb3d78c19..e8e4f1411585 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -244,11 +244,6 @@ struct irq_chip sun4d_irq = { }; #ifdef CONFIG_SMP -static void sun4d_set_cpu_int(int cpu, int level) -{ - sun4d_send_ipi(cpu, level); -} - /* Setup IRQ distribution scheme. */ void __init sun4d_distribute_irqs(void) { @@ -518,8 +513,5 @@ void __init sun4d_init_IRQ(void) sparc_config.build_device_irq = sun4d_build_device_irq; sparc_config.clock_rate = SBUS_CLOCK_RATE; -#ifdef CONFIG_SMP - BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); -#endif /* Cannot enable interrupts until OBP ticker is disabled. */ } diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 38ca0aac2ef2..f9a1a33cbb2c 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -235,7 +235,20 @@ void sun4d_ipi_interrupt(void) } } -static void smp4d_ipi_single(int cpu) +/* +-------+-------------+-----------+------------------------------------+ + * | bcast | devid | sid | levels mask | + * +-------+-------------+-----------+------------------------------------+ + * 31 30 23 22 15 14 0 + */ +#define IGEN_MESSAGE(bcast, devid, sid, levels) \ + (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels)) + +static void sun4d_send_ipi(int cpu, int level) +{ + cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1))); +} + +static void sun4d_ipi_single(int cpu) { struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); @@ -246,7 +259,7 @@ static void smp4d_ipi_single(int cpu) sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); } -static void smp4d_ipi_mask_one(int cpu) +static void sun4d_ipi_mask_one(int cpu) { struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); @@ -257,7 +270,7 @@ static void smp4d_ipi_mask_one(int cpu) sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); } -static void smp4d_ipi_resched(int cpu) +static void sun4d_ipi_resched(int cpu) { struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); @@ -282,7 +295,7 @@ static struct smp_funcall { static DEFINE_SPINLOCK(cross_call_lock); /* Cross calls must be serialized, at least currently. */ -static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, +static void sun4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) { @@ -391,6 +404,13 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) set_irq_regs(old_regs); } +static const struct sparc32_ipi_ops sun4d_ipi_ops = { + .cross_call = sun4d_cross_call, + .resched = sun4d_ipi_resched, + .single = sun4d_ipi_single, + .mask_one = sun4d_ipi_mask_one, +}; + void __init sun4d_init_smp(void) { int i; @@ -398,11 +418,7 @@ void __init sun4d_init_smp(void) /* Patch ipi15 trap table */ t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); - /* And set btfixup... */ - BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM); + sparc32_ipi_ops = &sun4d_ipi_ops; for (i = 0; i < NR_CPUS; i++) { ccall_info.processors_in[i] = 1; diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 32d3a5ce50f3..eb2c277aaf94 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -112,9 +112,6 @@ struct sun4m_handler_data { #define SUN4M_INT_E14 0x00000080 #define SUN4M_INT_E10 0x00080000 -#define SUN4M_HARD_INT(x) (0x000000001 << (x)) -#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) - #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ #define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ @@ -282,13 +279,6 @@ out: return irq; } -#ifdef CONFIG_SMP -static void sun4m_send_ipi(int cpu, int level) -{ - sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set); -} -#endif - struct sun4m_timer_percpu { u32 l14_limit; u32 l14_count; @@ -479,9 +469,5 @@ void __init sun4m_init_IRQ(void) sparc_config.build_device_irq = sun4m_build_device_irq; sparc_config.clock_rate = SBUS_CLOCK_RATE; -#ifdef CONFIG_SMP - BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); -#endif - /* Cannot enable interrupts until OBP ticker is disabled. */ } diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index ff74d33e2709..ee21c4375a90 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -34,8 +34,6 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) return val; } -static void smp4m_ipi_init(void); - void __cpuinit smp4m_callin(void) { int cpuid = hard_smp_processor_id(); @@ -88,7 +86,6 @@ void __cpuinit smp4m_callin(void) */ void __init smp4m_boot_cpus(void) { - smp4m_ipi_init(); sun4m_unmask_profile_irq(); local_ops->cache_all(); } @@ -156,25 +153,24 @@ void __init smp4m_smp_done(void) /* Ok, they are spinning and ready to go. */ } - -/* Initialize IPIs on the SUN4M SMP machine */ -static void __init smp4m_ipi_init(void) +static void sun4m_send_ipi(int cpu, int level) { + sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set); } -static void smp4m_ipi_resched(int cpu) +static void sun4m_ipi_resched(int cpu) { - set_cpu_int(cpu, IRQ_IPI_RESCHED); + sun4m_send_ipi(cpu, IRQ_IPI_RESCHED); } -static void smp4m_ipi_single(int cpu) +static void sun4m_ipi_single(int cpu) { - set_cpu_int(cpu, IRQ_IPI_SINGLE); + sun4m_send_ipi(cpu, IRQ_IPI_SINGLE); } -static void smp4m_ipi_mask_one(int cpu) +static void sun4m_ipi_mask_one(int cpu) { - set_cpu_int(cpu, IRQ_IPI_MASK); + sun4m_send_ipi(cpu, IRQ_IPI_MASK); } static struct smp_funcall { @@ -191,7 +187,7 @@ static struct smp_funcall { static DEFINE_SPINLOCK(cross_call_lock); /* Cross calls must be serialized, at least currently. */ -static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, +static void sun4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) { @@ -218,7 +214,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, if (cpumask_test_cpu(i, &mask)) { ccall_info.processors_in[i] = 0; ccall_info.processors_out[i] = 0; - set_cpu_int(i, IRQ_CROSS_CALL); + sun4m_send_ipi(i, IRQ_CROSS_CALL); } else { ccall_info.processors_in[i] = 1; ccall_info.processors_out[i] = 1; @@ -281,10 +277,14 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) set_irq_regs(old_regs); } +static const struct sparc32_ipi_ops sun4m_ipi_ops = { + .cross_call = sun4m_cross_call, + .resched = sun4m_ipi_resched, + .single = sun4m_ipi_single, + .mask_one = sun4m_ipi_mask_one, +}; + void __init sun4m_init_smp(void) { - BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM); + sparc32_ipi_ops = &sun4m_ipi_ops; } -- cgit v1.2.3 From 08c9388f5816ac9285dce7d07c8867ae1c1e4bcb Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 14 May 2012 17:30:35 +0200 Subject: sparc32: remove remaining users of btfixup Use sparc_config to hold the last two function pointers. There was no point generating dedicated _ops structures only for these. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/leon.h | 4 ---- arch/sparc/kernel/irq.h | 24 +++--------------------- arch/sparc/kernel/leon_kernel.c | 13 +++++-------- arch/sparc/kernel/pcic.c | 5 ++--- arch/sparc/kernel/sun4d_irq.c | 5 ++--- arch/sparc/kernel/sun4m_irq.c | 8 ++++---- arch/sparc/kernel/sun4m_smp.c | 2 +- arch/sparc/kernel/time_32.c | 11 ++++++----- 8 files changed, 23 insertions(+), 49 deletions(-) (limited to 'arch/sparc/kernel/sun4d_irq.c') diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index cf35a26454c8..8095be271825 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h @@ -321,11 +321,7 @@ extern unsigned int leon_build_device_irq(unsigned int real_irq, extern void leon_update_virq_handling(unsigned int virq, irq_flow_handler_t flow_handler, const char *name, int do_ack); -extern void leon_clear_clock_irq(void); -extern void leon_load_profile_irq(int cpu, unsigned int limit); extern void leon_init_timers(void); -extern void leon_clear_clock_irq(void); -extern void leon_load_profile_irq(int cpu, unsigned int limit); extern void leon_trans_init(struct device_node *dp); extern void leon_node_init(struct device_node *dp, struct device_node ***nextp); extern void leon_init_IRQ(void); diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index e40ca6c0076a..f558f710ee51 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h @@ -70,6 +70,9 @@ struct sparc_config { /* function to obtain offsett for cs period */ unsigned int (*get_cycles_offset)(void); + + void (*clear_clock_irq)(void); + void (*load_profile_irq)(int cpu, unsigned int limit); }; extern struct sparc_config sparc_config; @@ -78,27 +81,6 @@ void irq_link(unsigned int irq); void irq_unlink(unsigned int irq); void handler_irq(unsigned int pil, struct pt_regs *regs); -/* Dave Redman (djhr@tadpole.co.uk) - * changed these to function pointers.. it saves cycles and will allow - * the irq dependencies to be split into different files at a later date - * sun4m_irq.c etc so we could reduce the kernel size. - * Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Changed these to btfixup entities... It saves cycles :) - */ - -BTFIXUPDEF_CALL(void, clear_clock_irq, void) -BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) - -static inline void clear_clock_irq(void) -{ - BTFIXUP_CALL(clear_clock_irq)(); -} - -static inline void load_profile_irq(int cpu, int limit) -{ - BTFIXUP_CALL(load_profile_irq)(cpu, limit); -} - unsigned long leon_get_irqmask(unsigned int irq); #ifdef CONFIG_SMP diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 1770b3c1cc74..77c1b916e4dd 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -463,11 +463,11 @@ bad: return; } -void leon_clear_clock_irq(void) +static void leon_clear_clock_irq(void) { } -void leon_load_profile_irq(int cpu, unsigned int limit) +static void leon_load_profile_irq(int cpu, unsigned int limit) { } @@ -517,12 +517,9 @@ void __init leon_init_IRQ(void) { sparc_config.init_timers = leon_init_timers; sparc_config.build_device_irq = _leon_build_device_irq; - sparc_config.clock_rate = 1000000; - - BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, - BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq, - BTFIXUPCALL_NOP); + sparc_config.clock_rate = 1000000; + sparc_config.clear_clock_irq = leon_clear_clock_irq; + sparc_config.load_profile_irq = leon_load_profile_irq; } void __init leon_init(void) diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index f0ec9396a408..ded3f6090c3f 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -880,9 +880,8 @@ static void pcic_load_profile_irq(int cpu, unsigned int limit) void __init sun4m_pci_init_IRQ(void) { sparc_config.build_device_irq = pcic_build_device_irq; - - BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); + sparc_config.clear_clock_irq = pcic_clear_clock_irq; + sparc_config.load_profile_irq = pcic_load_profile_irq; } int pcibios_assign_resource(struct pci_dev *pdev, int resource) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index e8e4f1411585..e490ac9327c7 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -506,12 +506,11 @@ void __init sun4d_init_IRQ(void) { local_irq_disable(); - BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); - sparc_config.init_timers = sun4d_init_timers; sparc_config.build_device_irq = sun4d_build_device_irq; sparc_config.clock_rate = SBUS_CLOCK_RATE; + sparc_config.clear_clock_irq = sun4d_clear_clock_irq; + sparc_config.load_profile_irq = sun4d_load_profile_irq; /* Cannot enable interrupts until OBP ticker is disabled. */ } diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index eb2c277aaf94..c5ade9d27a1d 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -462,12 +462,12 @@ void __init sun4m_init_IRQ(void) if (num_cpu_iregs == 4) sbus_writel(0, &sun4m_irq_global->interrupt_target); - BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); - - sparc_config.init_timers = sun4m_init_timers; + sparc_config.init_timers = sun4m_init_timers; sparc_config.build_device_irq = sun4m_build_device_irq; sparc_config.clock_rate = SBUS_CLOCK_RATE; + sparc_config.clear_clock_irq = sun4m_clear_clock_irq; + sparc_config.load_profile_irq = sun4m_load_profile_irq; + /* Cannot enable interrupts until OBP ticker is disabled. */ } diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index ee21c4375a90..960e8ab47b12 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -268,7 +268,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) if (ce->mode & CLOCK_EVT_MODE_PERIODIC) sun4m_clear_profile_irq(cpu); else - load_profile_irq(cpu, 0); /* Is this needless? */ + sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */ irq_enter(); ce->event_handler(ce); diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 1e25a7ab1ea5..459cf66c143c 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -95,10 +95,10 @@ irqreturn_t notrace timer_interrupt(int dummy, void *dev_id) if (timer_cs_enabled) { write_seqlock(&timer_cs_lock); timer_cs_internal_counter++; - clear_clock_irq(); + sparc_config.clear_clock_irq(); write_sequnlock(&timer_cs_lock); } else { - clear_clock_irq(); + sparc_config.clear_clock_irq(); } if (timer_ce_enabled) @@ -200,12 +200,13 @@ static void percpu_ce_setup(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - load_profile_irq(cpu, SBUS_CLOCK_RATE / HZ); + sparc_config.load_profile_irq(cpu, + SBUS_CLOCK_RATE / HZ); break; case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: - load_profile_irq(cpu, 0); + sparc_config.load_profile_irq(cpu, 0); break; default: break; @@ -218,7 +219,7 @@ static int percpu_ce_set_next_event(unsigned long delta, int cpu = __first_cpu(evt->cpumask); unsigned int next = (unsigned int)delta; - load_profile_irq(cpu, next); + sparc_config.load_profile_irq(cpu, next); return 0; } -- cgit v1.2.3