Commit e98bae75 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6: (28 commits)
  sparc32: fix build, fix missing cpu_relax declaration
  SCHED_TTWU_QUEUE is not longer needed since sparc32 now implements IPI
  sparc32,leon: Remove unnecessary page_address calls in LEON DMA API.
  sparc: convert old cpumask API into new one
  sparc32, sun4d: Implemented SMP IPIs support for SUN4D machines
  sparc32, sun4m: Implemented SMP IPIs support for SUN4M machines
  sparc32,leon: Implemented SMP IPIs for LEON CPU
  sparc32: implement SMP IPIs using the generic functions
  sparc32,leon: SMP power down implementation
  sparc32,leon: added some SMP comments
  sparc: add {read,write}*_be routines
  sparc32,leon: don't rely on bootloader to mask IRQs
  sparc32,leon: operate on boot-cpu IRQ controller registers
  sparc32: always define boot_cpu_id
  sparc32: removed unused code, implemented by generic code
  sparc32: avoid build warning at mm/percpu.c:1647
  sparc32: always register a PROM based early console
  sparc32: probe for cpu info only during startup
  sparc: consolidate show_cpuinfo in cpu.c
  sparc32,leon: implement genirq CPU affinity
  ...
parents 4b382d06 f400bdb1
...@@ -25,6 +25,10 @@ config SPARC ...@@ -25,6 +25,10 @@ config SPARC
select HAVE_DMA_ATTRS select HAVE_DMA_ATTRS
select HAVE_DMA_API_DEBUG select HAVE_DMA_API_DEBUG
select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL
select HAVE_GENERIC_HARDIRQS
select GENERIC_HARDIRQS_NO_DEPRECATED
select GENERIC_IRQ_SHOW
select USE_GENERIC_SMP_HELPERS if SMP
config SPARC32 config SPARC32
def_bool !64BIT def_bool !64BIT
...@@ -43,15 +47,12 @@ config SPARC64 ...@@ -43,15 +47,12 @@ config SPARC64
select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_SYSCALL_TRACEPOINTS select HAVE_SYSCALL_TRACEPOINTS
select USE_GENERIC_SMP_HELPERS if SMP
select RTC_DRV_CMOS select RTC_DRV_CMOS
select RTC_DRV_BQ4802 select RTC_DRV_BQ4802
select RTC_DRV_SUN4V select RTC_DRV_SUN4V
select RTC_DRV_STARFIRE select RTC_DRV_STARFIRE
select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC select PERF_USE_VMALLOC
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_SHOW
select IRQ_PREFLOW_FASTEOI select IRQ_PREFLOW_FASTEOI
config ARCH_DEFCONFIG config ARCH_DEFCONFIG
......
...@@ -16,6 +16,10 @@ typedef struct { ...@@ -16,6 +16,10 @@ typedef struct {
unsigned long clock_tick; unsigned long clock_tick;
unsigned int multiplier; unsigned int multiplier;
unsigned int counter; unsigned int counter;
#ifdef CONFIG_SMP
unsigned int irq_resched_count;
unsigned int irq_call_count;
#endif
int prom_node; int prom_node;
int mid; int mid;
int next; int next;
...@@ -23,5 +27,6 @@ typedef struct { ...@@ -23,5 +27,6 @@ typedef struct {
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data); DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu)) #define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
#define local_cpu_data() __get_cpu_var(__cpu_data)
#endif /* _SPARC_CPUDATA_H */ #endif /* _SPARC_CPUDATA_H */
...@@ -281,28 +281,27 @@ static inline void sun_fd_enable_dma(void) ...@@ -281,28 +281,27 @@ static inline void sun_fd_enable_dma(void)
pdma_areasize = pdma_size; pdma_areasize = pdma_size;
} }
/* Our low-level entry point in arch/sparc/kernel/entry.S */ extern int sparc_floppy_request_irq(unsigned int irq,
extern int sparc_floppy_request_irq(int irq, unsigned long flags, irq_handler_t irq_handler);
irq_handler_t irq_handler);
static int sun_fd_request_irq(void) static int sun_fd_request_irq(void)
{ {
static int once = 0; static int once = 0;
int error;
if(!once) { if (!once) {
once = 1; once = 1;
error = sparc_floppy_request_irq(FLOPPY_IRQ, return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt);
IRQF_DISABLED, } else {
floppy_interrupt); return 0;
return ((error == 0) ? 0 : -1); }
} else return 0;
} }
static struct linux_prom_registers fd_regs[2]; static struct linux_prom_registers fd_regs[2];
static int sun_floppy_init(void) static int sun_floppy_init(void)
{ {
struct platform_device *op;
struct device_node *dp;
char state[128]; char state[128];
phandle tnode, fd_node; phandle tnode, fd_node;
int num_regs; int num_regs;
...@@ -310,7 +309,6 @@ static int sun_floppy_init(void) ...@@ -310,7 +309,6 @@ static int sun_floppy_init(void)
use_virtual_dma = 1; use_virtual_dma = 1;
FLOPPY_IRQ = 11;
/* Forget it if we aren't on a machine that could possibly /* Forget it if we aren't on a machine that could possibly
* ever have a floppy drive. * ever have a floppy drive.
*/ */
...@@ -349,6 +347,26 @@ static int sun_floppy_init(void) ...@@ -349,6 +347,26 @@ static int sun_floppy_init(void)
sun_fdc = (struct sun_flpy_controller *) sun_fdc = (struct sun_flpy_controller *)
of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
/* Look up irq in platform_device.
* We try "SUNW,fdtwo" and "fd"
*/
for_each_node_by_name(dp, "SUNW,fdtwo") {
op = of_find_device_by_node(dp);
if (op)
break;
}
if (!op) {
for_each_node_by_name(dp, "fd") {
op = of_find_device_by_node(dp);
if (op)
break;
}
}
if (!op)
goto no_sun_fdc;
FLOPPY_IRQ = op->archdata.irqs[0];
/* Last minute sanity check... */ /* Last minute sanity check... */
if(sun_fdc->status_82072 == 0xff) { if(sun_fdc->status_82072 == 0xff) {
sun_fdc = NULL; sun_fdc = NULL;
......
...@@ -5,4 +5,17 @@ ...@@ -5,4 +5,17 @@
#else #else
#include <asm/io_32.h> #include <asm/io_32.h>
#endif #endif
/*
* Defines used for both SPARC32 and SPARC64
*/
/* Big endian versions of memory read/write routines */
#define readb_be(__addr) __raw_readb(__addr)
#define readw_be(__addr) __raw_readw(__addr)
#define readl_be(__addr) __raw_readl(__addr)
#define writeb_be(__b, __addr) __raw_writeb(__b, __addr)
#define writel_be(__w, __addr) __raw_writel(__w, __addr)
#define writew_be(__l, __addr) __raw_writew(__l, __addr)
#endif #endif
...@@ -6,7 +6,11 @@ ...@@ -6,7 +6,11 @@
#ifndef _SPARC_IRQ_H #ifndef _SPARC_IRQ_H
#define _SPARC_IRQ_H #define _SPARC_IRQ_H
#define NR_IRQS 16 /* Allocated number of logical irq numbers.
* sun4d boxes (ss2000e) should be OK with ~32.
* Be on the safe side and make room for 64
*/
#define NR_IRQS 64
#include <linux/interrupt.h> #include <linux/interrupt.h>
......
...@@ -52,29 +52,6 @@ ...@@ -52,29 +52,6 @@
#define LEON_DIAGF_VALID 0x2000 #define LEON_DIAGF_VALID 0x2000
#define LEON_DIAGF_VALID_SHIFT 13 #define LEON_DIAGF_VALID_SHIFT 13
/*
* Interrupt Sources
*
* The interrupt source numbers directly map to the trap type and to
* the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers.
*/
#define LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR 1
#define LEON_INTERRUPT_UART_1_RX_TX 2
#define LEON_INTERRUPT_UART_0_RX_TX 3
#define LEON_INTERRUPT_EXTERNAL_0 4
#define LEON_INTERRUPT_EXTERNAL_1 5
#define LEON_INTERRUPT_EXTERNAL_2 6
#define LEON_INTERRUPT_EXTERNAL_3 7
#define LEON_INTERRUPT_TIMER1 8
#define LEON_INTERRUPT_TIMER2 9
#define LEON_INTERRUPT_EMPTY1 10
#define LEON_INTERRUPT_EMPTY2 11
#define LEON_INTERRUPT_OPEN_ETH 12
#define LEON_INTERRUPT_EMPTY4 13
#define LEON_INTERRUPT_EMPTY5 14
#define LEON_INTERRUPT_EMPTY6 15
/* irq masks */ /* irq masks */
#define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */ #define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */
#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */ #define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */
...@@ -183,7 +160,6 @@ static inline void leon_srmmu_enabletlb(void) ...@@ -183,7 +160,6 @@ static inline void leon_srmmu_enabletlb(void)
/* macro access for leon_readnobuffer_reg() */ /* macro access for leon_readnobuffer_reg() */
#define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x)) #define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x))
extern void sparc_leon_eirq_register(int eirq);
extern void leon_init(void); extern void leon_init(void);
extern void leon_switch_mm(void); extern void leon_switch_mm(void);
extern void leon_init_IRQ(void); extern void leon_init_IRQ(void);
...@@ -239,8 +215,8 @@ static inline int sparc_leon3_cpuid(void) ...@@ -239,8 +215,8 @@ static inline int sparc_leon3_cpuid(void)
#endif /*!__ASSEMBLY__*/ #endif /*!__ASSEMBLY__*/
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
# define LEON3_IRQ_RESCHEDULE 13 # define LEON3_IRQ_IPI_DEFAULT 13
# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) # define LEON3_IRQ_TICKER (leon3_ticker_irq)
# define LEON3_IRQ_CROSS_CALL 15 # define LEON3_IRQ_CROSS_CALL 15
#endif #endif
...@@ -339,9 +315,9 @@ struct leon2_cacheregs { ...@@ -339,9 +315,9 @@ struct leon2_cacheregs {
#include <linux/interrupt.h> #include <linux/interrupt.h>
struct device_node; struct device_node;
extern int sparc_leon_eirq_get(int eirq, int cpu); extern unsigned int leon_build_device_irq(unsigned int real_irq,
extern irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id); irq_flow_handler_t flow_handler,
extern void sparc_leon_eirq_register(int eirq); const char *name, int do_ack);
extern void leon_clear_clock_irq(void); extern void leon_clear_clock_irq(void);
extern void leon_load_profile_irq(int cpu, unsigned int limit); 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(irq_handler_t counter_fn);
...@@ -358,6 +334,7 @@ extern void leon3_getCacheRegs(struct leon3_cacheregs *regs); ...@@ -358,6 +334,7 @@ extern void leon3_getCacheRegs(struct leon3_cacheregs *regs);
extern int leon_flush_needed(void); extern int leon_flush_needed(void);
extern void leon_switch_mm(void); extern void leon_switch_mm(void);
extern int srmmu_swprobe_trace; extern int srmmu_swprobe_trace;
extern int leon3_ticker_irq;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern int leon_smp_nrcpus(void); extern int leon_smp_nrcpus(void);
...@@ -366,17 +343,19 @@ extern void leon_smp_done(void); ...@@ -366,17 +343,19 @@ extern void leon_smp_done(void);
extern void leon_boot_cpus(void); extern void leon_boot_cpus(void);
extern int leon_boot_one_cpu(int i); extern int leon_boot_one_cpu(int i);
void leon_init_smp(void); void leon_init_smp(void);
extern void cpu_probe(void);
extern void cpu_idle(void); extern void cpu_idle(void);
extern void init_IRQ(void); extern void init_IRQ(void);
extern void cpu_panic(void); extern void cpu_panic(void);
extern int __leon_processor_id(void); extern int __leon_processor_id(void);
void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
extern unsigned int real_irq_entry[], smpleon_ticker[]; extern unsigned int real_irq_entry[];
extern unsigned int smpleon_ipi[];
extern unsigned int patchme_maybe_smp_msg[]; extern unsigned int patchme_maybe_smp_msg[];
extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
extern unsigned int linux_trap_ipi15_sun4m[]; extern unsigned int linux_trap_ipi15_sun4m[];
extern int leon_ipi_irq;
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
......
...@@ -29,11 +29,17 @@ struct linux_pcic { ...@@ -29,11 +29,17 @@ struct linux_pcic {
int pcic_imdim; int pcic_imdim;
}; };
extern int pcic_probe(void); #ifdef CONFIG_PCI
/* Erm... MJ redefined pcibios_present() so that it does not work early. */
extern int pcic_present(void); extern int pcic_present(void);
extern int pcic_probe(void);
extern void pci_time_init(void);
extern void sun4m_pci_init_IRQ(void); extern void sun4m_pci_init_IRQ(void);
#else
static inline int pcic_present(void) { return 0; }
static inline int pcic_probe(void) { return 0; }
static inline void pci_time_init(void) {}
static inline void sun4m_pci_init_IRQ(void) {}
#endif
#endif #endif
/* Size of PCI I/O space which we relocate. */ /* Size of PCI I/O space which we relocate. */
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
* Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/ */
#include <linux/const.h>
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm-generic/4level-fixup.h> #include <asm-generic/4level-fixup.h>
...@@ -456,9 +458,9 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, ...@@ -456,9 +458,9 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma,
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
#define VMALLOC_START 0xfe600000 #define VMALLOC_START _AC(0xfe600000,UL)
/* XXX Alter this when I get around to fixing sun4c - Anton */ /* XXX Alter this when I get around to fixing sun4c - Anton */
#define VMALLOC_END 0xffc00000 #define VMALLOC_END _AC(0xffc00000,UL)
/* We provide our own get_unmapped_area to cope with VA holes for userland */ /* We provide our own get_unmapped_area to cope with VA holes for userland */
......
...@@ -699,6 +699,9 @@ extern pmd_t swapper_low_pmd_dir[2048]; ...@@ -699,6 +699,9 @@ extern pmd_t swapper_low_pmd_dir[2048];
extern void paging_init(void); extern void paging_init(void);
extern unsigned long find_ecache_flush_span(unsigned long size); extern unsigned long find_ecache_flush_span(unsigned long size);
struct seq_file;
extern void mmu_info(struct seq_file *);
/* These do nothing with the way I have things setup. */ /* These do nothing with the way I have things setup. */
#define mmu_lockarea(vaddr, len) (vaddr) #define mmu_lockarea(vaddr, len) (vaddr)
#define mmu_unlockarea(vaddr, len) do { } while(0) #define mmu_unlockarea(vaddr, len) do { } while(0)
......
...@@ -11,4 +11,16 @@ ...@@ -11,4 +11,16 @@
# define COMMAND_LINE_SIZE 256 # define COMMAND_LINE_SIZE 256
#endif #endif
#ifdef __KERNEL__
#ifdef CONFIG_SPARC32
/* The CPU that was used for booting
* Only sun4d + leon may have boot_cpu_id != 0
*/
extern unsigned char boot_cpu_id;
extern unsigned char boot_cpu_id4;
#endif
#endif /* __KERNEL__ */
#endif /* _SPARC_SETUP_H */ #endif /* _SPARC_SETUP_H */
...@@ -50,42 +50,38 @@ void smp_callin(void); ...@@ -50,42 +50,38 @@ void smp_callin(void);
void smp_boot_cpus(void); void smp_boot_cpus(void);
void smp_store_cpu_info(int); void smp_store_cpu_info(int);
void smp_resched_interrupt(void);
void smp_call_function_single_interrupt(void);
void smp_call_function_interrupt(void);
struct seq_file; struct seq_file;
void smp_bogo(struct seq_file *); void smp_bogo(struct seq_file *);
void smp_info(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_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long)
BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void) BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
BTFIXUPDEF_CALL(void, smp_ipi_resched, int);
BTFIXUPDEF_CALL(void, smp_ipi_single, int);
BTFIXUPDEF_CALL(void, smp_ipi_mask_one, int);
BTFIXUPDEF_BLACKBOX(hard_smp_processor_id) BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
BTFIXUPDEF_BLACKBOX(load_current) BTFIXUPDEF_BLACKBOX(load_current)
#define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4) #define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4)
static inline void xc0(smpfunc_t func) { smp_cross_call(func, cpu_online_map, 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) static inline void xc1(smpfunc_t func, unsigned long arg1)
{ smp_cross_call(func, cpu_online_map, arg1, 0, 0, 0); } { smp_cross_call(func, *cpu_online_mask, arg1, 0, 0, 0); }
static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
{ smp_cross_call(func, cpu_online_map, arg1, arg2, 0, 0); } { smp_cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0); }
static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
unsigned long arg3) unsigned long arg3)
{ smp_cross_call(func, cpu_online_map, arg1, arg2, arg3, 0); } { smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, 0); }
static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
unsigned long arg3, unsigned long arg4) unsigned long arg3, unsigned long arg4)
{ smp_cross_call(func, cpu_online_map, arg1, arg2, arg3, arg4); } { smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, arg4); }
static inline int smp_call_function(void (*func)(void *info), void *info, int wait)
{
xc1((smpfunc_t)func, (unsigned long)info);
return 0;
}
static inline int smp_call_function_single(int cpuid, void (*func) (void *info), extern void arch_send_call_function_single_ipi(int cpu);
void *info, int wait) extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
{
smp_cross_call((smpfunc_t)func, cpumask_of_cpu(cpuid),
(unsigned long) info, 0, 0, 0);
return 0;
}
static inline int cpu_logical_map(int cpu) static inline int cpu_logical_map(int cpu)
{ {
...@@ -135,6 +131,11 @@ static inline int hard_smp_processor_id(void) ...@@ -135,6 +131,11 @@ static inline int hard_smp_processor_id(void)
__asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t" __asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t"
"nop; nop" : "nop; nop" :
"=&r" (cpuid)); "=&r" (cpuid));
- leon
__asm__ __volatile__( "rd %asr17, %0\n\t"
"srl %0, 0x1c, %0\n\t"
"nop\n\t" :
"=&r" (cpuid));
See btfixup.h and btfixupprep.c to understand how a blackbox works. See btfixup.h and btfixupprep.c to understand how a blackbox works.
*/ */
__asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t" __asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
......
...@@ -49,6 +49,10 @@ extern void cpu_play_dead(void); ...@@ -49,6 +49,10 @@ extern void cpu_play_dead(void);
extern void smp_fetch_global_regs(void); extern void smp_fetch_global_regs(void);
struct seq_file;
void smp_bogo(struct seq_file *);
void smp_info(struct seq_file *);
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
extern int __cpu_disable(void); extern int __cpu_disable(void);
extern void __cpu_die(unsigned int cpu); extern void __cpu_die(unsigned int cpu);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/psr.h> #include <asm/psr.h>
#include <asm/processor.h> /* for cpu_relax */
#define arch_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0) #define arch_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
......
...@@ -15,11 +15,6 @@ ...@@ -15,11 +15,6 @@
#include <linux/irqflags.h> #include <linux/irqflags.h>
static inline unsigned int probe_irq_mask(unsigned long val)
{
return 0;
}
/* /*
* Sparc (general) CPU types * Sparc (general) CPU types
*/ */
......
...@@ -29,10 +29,6 @@ enum sparc_cpu { ...@@ -29,10 +29,6 @@ enum sparc_cpu {
/* This cannot ever be a sun4c :) That's just history. */ /* This cannot ever be a sun4c :) That's just history. */
#define ARCH_SUN4C 0 #define ARCH_SUN4C 0
extern const char *sparc_cpu_type;
extern const char *sparc_fpu_type;
extern const char *sparc_pmu_type;
extern char reboot_command[]; extern char reboot_command[];
/* These are here in an effort to more fully work around Spitfire Errata /* These are here in an effort to more fully work around Spitfire Errata
......
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
st %scratch, [%cur_reg + TI_W_SAVED]; st %scratch, [%cur_reg + TI_W_SAVED];
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Results of LOAD_CURRENT() after BTFIXUP for SUN4M, SUN4D & LEON (comments) */
#define LOAD_CURRENT4M(dest_reg, idreg) \ #define LOAD_CURRENT4M(dest_reg, idreg) \
rd %tbr, %idreg; \ rd %tbr, %idreg; \
sethi %hi(current_set), %dest_reg; \ sethi %hi(current_set), %dest_reg; \
...@@ -118,6 +119,14 @@ ...@@ -118,6 +119,14 @@
or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \
ld [%idreg + %dest_reg], %dest_reg; ld [%idreg + %dest_reg], %dest_reg;
#define LOAD_CURRENT_LEON(dest_reg, idreg) \
rd %asr17, %idreg; \
sethi %hi(current_set), %dest_reg; \
srl %idreg, 0x1c, %idreg; \
or %dest_reg, %lo(current_set), %dest_reg; \
sll %idreg, 0x2, %idreg; \
ld [%idreg + %dest_reg], %dest_reg;
/* Blackbox - take care with this... - check smp4m and smp4d before changing this. */ /* Blackbox - take care with this... - check smp4m and smp4d before changing this. */
#define LOAD_CURRENT(dest_reg, idreg) \ #define LOAD_CURRENT(dest_reg, idreg) \
sethi %hi(___b_load_current), %idreg; \ sethi %hi(___b_load_current), %idreg; \
......
...@@ -71,10 +71,6 @@ obj-$(CONFIG_SPARC64) += pcr.o ...@@ -71,10 +71,6 @@ obj-$(CONFIG_SPARC64) += pcr.o
obj-$(CONFIG_SPARC64) += nmi.o obj-$(CONFIG_SPARC64) += nmi.o
obj-$(CONFIG_SPARC64_SMP) += cpumap.o obj-$(CONFIG_SPARC64_SMP) += cpumap.o
# sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation
obj-$(CONFIG_SPARC32) += devres.o
devres-y := ../../../kernel/irq/devres.o
obj-y += dma.o obj-y += dma.o
obj-$(CONFIG_SPARC32_PCI) += pcic.o obj-$(CONFIG_SPARC32_PCI) += pcic.o
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/ */
#include <linux/seq_file.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -11,7 +12,9 @@ ...@@ -11,7 +12,9 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/pgtable.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/setup.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/head.h> #include <asm/head.h>
#include <asm/psr.h> #include <asm/psr.h>
...@@ -23,6 +26,9 @@ ...@@ -23,6 +26,9 @@
DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
EXPORT_PER_CPU_SYMBOL(__cpu_data); EXPORT_PER_CPU_SYMBOL(__cpu_data);
int ncpus_probed;
unsigned int fsr_storage;
struct cpu_info { struct cpu_info {
int psr_vers; int psr_vers;
const char *name; const char *name;
...@@ -247,13 +253,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { ...@@ -247,13 +253,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
* machine type value into consideration too. I will fix this. * machine type value into consideration too. I will fix this.
*/ */
const char *sparc_cpu_type; static const char *sparc_cpu_type;
const char *sparc_fpu_type; static const char *sparc_fpu_type;
const char *sparc_pmu_type; const char *sparc_pmu_type;
unsigned int fsr_storage;
static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) static void __init set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
{ {
const struct manufacturer_info *manuf; const struct manufacturer_info *manuf;
int i; int i;
...@@ -313,7 +318,123 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) ...@@ -313,7 +318,123 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
} }
#ifdef CONFIG_SPARC32 #ifdef CONFIG_SPARC32
void __cpuinit cpu_probe(void) static int show_cpuinfo(struct seq_file *m, void *__unused)
{
seq_printf(m,
"cpu\t\t: %s\n"
"fpu\t\t: %s\n"
"promlib\t\t: Version %d Revision %d\n"
"prom\t\t: %d.%d\n"
"type\t\t: %s\n"
"ncpus probed\t: %d\n"
"ncpus active\t: %d\n"
#ifndef CONFIG_SMP
"CPU0Bogo\t: %lu.%02lu\n"
"CPU0ClkTck\t: %ld\n"
#endif
,
sparc_cpu_type,
sparc_fpu_type ,
romvec->pv_romvers,
prom_rev,
romvec->pv_printrev >> 16,
romvec->pv_printrev & 0xffff,
&cputypval[0],
ncpus_probed,
num_online_cpus()
#ifndef CONFIG_SMP
, cpu_data(0).udelay_val/(500000/HZ),
(cpu_data(0).udelay_val/(5000/HZ)) % 100,
cpu_data(0).clock_tick
#endif
);
#ifdef CONFIG_SMP
smp_bogo(m);
#endif
mmu_info(m);
#ifdef CONFIG_SMP
smp_info(m);
#endif
return 0;
}
#endif /* CONFIG_SPARC32 */
#ifdef CONFIG_SPARC64
unsigned int dcache_parity_tl1_occurred;
unsigned int icache_parity_tl1_occurred;
static int show_cpuinfo(struct seq_file *m, void *__unused)
{
seq_printf(m,
"cpu\t\t: %s\n"
"fpu\t\t: %s\n"
"pmu\t\t: %s\n"
"prom\t\t: %s\n"
"type\t\t: %s\n"
"ncpus probed\t: %d\n"
"ncpus active\t: %d\n"
"D$ parity tl1\t: %u\n"
"I$ parity tl1\t: %u\n"
#ifndef CONFIG_SMP
"Cpu0ClkTck\t: %016lx\n"
#endif
,
sparc_cpu_type,
sparc_fpu_type,
sparc_pmu_type,
prom_version,
((tlb_type == hypervisor) ?
"sun4v" :
"sun4u"),
ncpus_probed,
num_online_cpus(),
dcache_parity_tl1_occurred,
icache_parity_tl1_occurred
#ifndef CONFIG_SMP
, cpu_data(0).clock_tick
#endif
);
#ifdef CONFIG_SMP
smp_bogo(m);
#endif
mmu_info(m);
#ifdef CONFIG_SMP
smp_info(m);
#endif
return 0;
}
#endif /* CONFIG_SPARC64 */
static void *c_start(struct seq_file *m, loff_t *pos)
{
/* The pointer we are returning is arbitrary,
* it just has to be non-NULL and not IS_ERR
* in the success case.
*/
return *pos == 0 ? &c_start : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
return c_start(m, pos);
}
static void c_stop(struct seq_file *m, void *v)
{
}
const struct seq_operations cpuinfo_op = {
.start =c_start,
.next = c_next,
.stop = c_stop,
.show = show_cpuinfo,
};
#ifdef CONFIG_SPARC32
static int __init cpu_type_probe(void)
{ {
int psr_impl, psr_vers, fpu_vers; int psr_impl, psr_vers, fpu_vers;
int psr; int psr;
...@@ -332,8 +453,12 @@ void __cpuinit cpu_probe(void) ...@@ -332,8 +453,12 @@ void __cpuinit cpu_probe(void)
put_psr(psr); put_psr(psr);
set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers);
return 0;
} }
#else #endif /* CONFIG_SPARC32 */
#ifdef CONFIG_SPARC64
static void __init sun4v_cpu_probe(void) static void __init sun4v_cpu_probe(void)
{ {
switch (sun4v_chip_type) { switch (sun4v_chip_type) {
...@@ -374,6 +499,6 @@ static int __init cpu_type_probe(void) ...@@ -374,6 +499,6 @@ static int __init cpu_type_probe(void)
} }
return 0; return 0;
} }
#endif /* CONFIG_SPARC64 */
early_initcall(cpu_type_probe); early_initcall(cpu_type_probe);
#endif
...@@ -202,7 +202,7 @@ static struct cpuinfo_tree *build_cpuinfo_tree(void) ...@@ -202,7 +202,7 @@ static struct cpuinfo_tree *build_cpuinfo_tree(void)
new_tree->total_nodes = n; new_tree->total_nodes = n;
memcpy(&new_tree->level, tmp_level, sizeof(tmp_level)); memcpy(&new_tree->level, tmp_level, sizeof(tmp_level));
prev_cpu = cpu = first_cpu(cpu_online_map); prev_cpu = cpu = cpumask_first(cpu_online_mask);
/* Initialize all levels in the tree with the first CPU */ /* Initialize all levels in the tree with the first CPU */
for (level = CPUINFO_LVL_PROC; level >= CPUINFO_LVL_ROOT; level--) { for (level = CPUINFO_LVL_PROC; level >= CPUINFO_LVL_ROOT; level--) {
...@@ -381,7 +381,7 @@ static int simple_map_to_cpu(unsigned int index) ...@@ -381,7 +381,7 @@ static int simple_map_to_cpu(unsigned int index)
} }
/* Impossible, since num_online_cpus() <= num_possible_cpus() */ /* Impossible, since num_online_cpus() <= num_possible_cpus() */
return first_cpu(cpu_online_map); return cpumask_first(cpu_online_mask);
} }
static int _map_to_cpu(unsigned int index) static int _map_to_cpu(unsigned int index)
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/cpudata.h> #include <asm/cpudata.h>
extern void cpu_probe(void);
extern void clock_stop_probe(void); /* tadpole.c */ extern void clock_stop_probe(void); /* tadpole.c */
extern void sun4c_probe_memerr_reg(void); extern void sun4c_probe_memerr_reg(void);
...@@ -115,7 +114,7 @@ int cpu_get_hwmid(phandle prom_node) ...@@ -115,7 +114,7 @@ int cpu_get_hwmid(phandle prom_node)
void __init device_scan(void) void __init device_scan(void)
{ {
prom_printf("Booting Linux...\n"); printk(KERN_NOTICE "Booting Linux...\n");
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
{ {
...@@ -133,7 +132,6 @@ void __init device_scan(void) ...@@ -133,7 +132,6 @@ void __init device_scan(void)
} }
#endif /* !CONFIG_SMP */ #endif /* !CONFIG_SMP */
cpu_probe();
{ {
extern void auxio_probe(void); extern void auxio_probe(void);
extern void auxio_power_probe(void); extern void auxio_power_probe(void);
......
...@@ -497,7 +497,7 @@ static void dr_cpu_init_response(struct ds_data *resp, u64 req_num, ...@@ -497,7 +497,7 @@ static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
tag->num_records = ncpus; tag->num_records = ncpus;
i = 0; i = 0;
for_each_cpu_mask(cpu, *mask) { for_each_cpu(cpu, mask) {
ent[i].cpu = cpu; ent[i].cpu = cpu;
ent[i].result = DR_CPU_RES_OK; ent[i].result = DR_CPU_RES_OK;
ent[i].stat = default_stat; ent[i].stat = default_stat;
...@@ -534,7 +534,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp, ...@@ -534,7 +534,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp,
int resp_len, ncpus, cpu; int resp_len, ncpus, cpu;
unsigned long flags; unsigned long flags;
ncpus = cpus_weight(*mask); ncpus = cpumask_weight(mask);
resp_len = dr_cpu_size_response(ncpus); resp_len = dr_cpu_size_response(ncpus);
resp = kzalloc(resp_len, GFP_KERNEL); resp = kzalloc(resp_len, GFP_KERNEL);
if (!resp) if (!resp)
...@@ -547,7 +547,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp, ...@@ -547,7 +547,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp,
mdesc_populate_present_mask(mask); mdesc_populate_present_mask(mask);
mdesc_fill_in_cpu_data(mask); mdesc_fill_in_cpu_data(mask);
for_each_cpu_mask(cpu, *mask) { for_each_cpu(cpu, mask) {
int err; int err;
printk(KERN_INFO "ds-%llu: Starting cpu %d...\n", printk(KERN_INFO "ds-%llu: Starting cpu %d...\n",
...@@ -593,7 +593,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp, ...@@ -593,7 +593,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp,
int resp_len, ncpus, cpu; int resp_len, ncpus, cpu;
unsigned long flags; unsigned long flags;
ncpus = cpus_weight(*mask); ncpus = cpumask_weight(mask);
resp_len = dr_cpu_size_response(ncpus); resp_len = dr_cpu_size_response(ncpus);
resp = kzalloc(resp_len, GFP_KERNEL); resp = kzalloc(resp_len, GFP_KERNEL);
if (!resp) if (!resp)
...@@ -603,7 +603,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp, ...@@ -603,7 +603,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp,
resp_len, ncpus, mask, resp_len, ncpus, mask,
DR_CPU_STAT_UNCONFIGURED); DR_CPU_STAT_UNCONFIGURED);
for_each_cpu_mask(cpu, *mask) { for_each_cpu(cpu, mask) {
int err; int err;
printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n", printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n",
...@@ -649,13 +649,13 @@ static void __cpuinit dr_cpu_data(struct ds_info *dp, ...@@ -649,13 +649,13 @@ static void __cpuinit dr_cpu_data(struct ds_info *dp,
purge_dups(cpu_list, tag->num_records); purge_dups(cpu_list, tag->num_records);
cpus_clear(mask); cpumask_clear(&mask);
for (i = 0; i < tag->num_records; i++) { for (i = 0; i < tag->num_records; i++) {
if (cpu_list[i] == CPU_SENTINEL) if (cpu_list[i] == CPU_SENTINEL)
continue; continue;
if (cpu_list[i] < nr_cpu_ids) if (cpu_list[i] < nr_cpu_ids)
cpu_set(cpu_list[i], mask); cpumask_set_cpu(cpu_list[i], &mask);
} }
if (tag->type == DR_CPU_CONFIGURE) if (tag->type == DR_CPU_CONFIGURE)
......
...@@ -269,19 +269,22 @@ smp4m_ticker: ...@@ -269,19 +269,22 @@ smp4m_ticker:
/* Here is where we check for possible SMP IPI passed to us /* Here is where we check for possible SMP IPI passed to us
* on some level other than 15 which is the NMI and only used * on some level other than 15 which is the NMI and only used
* for cross calls. That has a separate entry point below. * for cross calls. That has a separate entry point below.
*
* IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*.
*/ */
maybe_smp4m_msg: maybe_smp4m_msg:
GET_PROCESSOR4M_ID(o3) GET_PROCESSOR4M_ID(o3)
sethi %hi(sun4m_irq_percpu), %l5 sethi %hi(sun4m_irq_percpu), %l5
sll %o3, 2, %o3 sll %o3, 2, %o3
or %l5, %lo(sun4m_irq_percpu), %o5 or %l5, %lo(sun4m_irq_percpu), %o5
sethi %hi(0x40000000), %o2 sethi %hi(0x70000000), %o2 ! Check all soft-IRQs
ld [%o5 + %o3], %o1 ld [%o5 + %o3], %o1
ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
andcc %o3, %o2, %g0 andcc %o3, %o2, %g0
be,a smp4m_ticker be,a smp4m_ticker
cmp %l7, 14 cmp %l7, 14
st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 /* Soft-IRQ IPI */
st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x70000000
WRITE_PAUSE WRITE_PAUSE
ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
WRITE_PAUSE WRITE_PAUSE
...@@ -290,9 +293,27 @@ maybe_smp4m_msg: ...@@ -290,9 +293,27 @@ maybe_smp4m_msg:
WRITE_PAUSE WRITE_PAUSE
wr %l4, PSR_ET, %psr wr %l4, PSR_ET, %psr
WRITE_PAUSE WRITE_PAUSE
call smp_reschedule_irq sll %o2, 28, %o2 ! shift for simpler checks below
maybe_smp4m_msg_check_single:
andcc %o2, 0x1, %g0
beq,a maybe_smp4m_msg_check_mask
andcc %o2, 0x2, %g0
call smp_call_function_single_interrupt
nop nop
andcc %o2, 0x2, %g0
maybe_smp4m_msg_check_mask:
beq,a maybe_smp4m_msg_check_resched
andcc %o2, 0x4, %g0
call smp_call_function_interrupt
nop
andcc %o2, 0x4, %g0
maybe_smp4m_msg_check_resched:
/* rescheduling is done in RESTORE_ALL regardless, but incr stats */
beq,a maybe_smp4m_msg_out
nop
call smp_resched_interrupt
nop
maybe_smp4m_msg_out:
RESTORE_ALL RESTORE_ALL
.align 4 .align 4
...@@ -401,18 +422,18 @@ linux_trap_ipi15_sun4d: ...@@ -401,18 +422,18 @@ linux_trap_ipi15_sun4d:
1: b,a 1b 1: b,a 1b
#ifdef CONFIG_SPARC_LEON #ifdef CONFIG_SPARC_LEON
.globl smpleon_ipi
.globl smpleon_ticker .extern leon_ipi_interrupt
/* SMP per-cpu ticker interrupts are handled specially. */ /* SMP per-cpu IPI interrupts are handled specially. */
smpleon_ticker: smpleon_ipi:
SAVE_ALL SAVE_ALL
or %l0, PSR_PIL, %g2 or %l0, PSR_PIL, %g2
wr %g2, 0x0, %psr wr %g2, 0x0, %psr
WRITE_PAUSE WRITE_PAUSE
wr %g2, PSR_ET, %psr wr %g2, PSR_ET, %psr
WRITE_PAUSE WRITE_PAUSE
call leon_percpu_timer_interrupt call leonsmp_ipi_interrupt
add %sp, STACKFRAME_SZ, %o0 add %sp, STACKFRAME_SZ, %o1 ! pt_regs
wr %l0, PSR_ET, %psr wr %l0, PSR_ET, %psr
WRITE_PAUSE WRITE_PAUSE
RESTORE_ALL RESTORE_ALL
......
...@@ -810,30 +810,24 @@ found_version: ...@@ -810,30 +810,24 @@ found_version:
got_prop: got_prop:
#ifdef CONFIG_SPARC_LEON #ifdef CONFIG_SPARC_LEON
/* no cpu-type check is needed, it is a SPARC-LEON */ /* no cpu-type check is needed, it is a SPARC-LEON */
#ifdef CONFIG_SMP
ba leon_smp_init
nop
.global leon_smp_init sethi %hi(boot_cpu_id), %g2 ! boot-cpu index
leon_smp_init:
sethi %hi(boot_cpu_id), %g1 ! master always 0
stb %g0, [%g1 + %lo(boot_cpu_id)]
sethi %hi(boot_cpu_id4), %g1 ! master always 0
stb %g0, [%g1 + %lo(boot_cpu_id4)]
rd %asr17,%g1 #ifdef CONFIG_SMP
srl %g1,28,%g1 ldub [%g2 + %lo(boot_cpu_id)], %g1
cmp %g1, 0xff ! unset means first CPU
bne leon_smp_cpu_startup ! continue only with master
nop
#endif
/* Get CPU-ID from most significant 4-bit of ASR17 */
rd %asr17, %g1
srl %g1, 28, %g1
cmp %g0,%g1 /* Update boot_cpu_id only on boot cpu */
beq sun4c_continue_boot !continue with master stub %g1, [%g2 + %lo(boot_cpu_id)]
nop
ba leon_smp_cpu_startup
nop
#else
ba sun4c_continue_boot ba sun4c_continue_boot
nop nop
#endif
#endif #endif
set cputypval, %o2 set cputypval, %o2
ldub [%o2 + 0x4], %l1 ldub [%o2 + 0x4], %l1
...@@ -893,9 +887,6 @@ sun4d_init: ...@@ -893,9 +887,6 @@ sun4d_init:
sta %g4, [%g0] ASI_M_VIKING_TMP1 sta %g4, [%g0] ASI_M_VIKING_TMP1
sethi %hi(boot_cpu_id), %g5 sethi %hi(boot_cpu_id), %g5
stb %g4, [%g5 + %lo(boot_cpu_id)] stb %g4, [%g5 + %lo(boot_cpu_id)]
sll %g4, 2, %g4
sethi %hi(boot_cpu_id4), %g5
stb %g4, [%g5 + %lo(boot_cpu_id4)]
#endif #endif
/* Fall through to sun4m_init */ /* Fall through to sun4m_init */
...@@ -1024,14 +1015,28 @@ sun4c_continue_boot: ...@@ -1024,14 +1015,28 @@ sun4c_continue_boot:
bl 1b bl 1b
add %o0, 0x1, %o0 add %o0, 0x1, %o0
/* If boot_cpu_id has not been setup by machine specific
* init-code above we default it to zero.
*/
sethi %hi(boot_cpu_id), %g2
ldub [%g2 + %lo(boot_cpu_id)], %g3
cmp %g3, 0xff
bne 1f
nop
mov %g0, %g3
stub %g3, [%g2 + %lo(boot_cpu_id)]
1: /* boot_cpu_id set. calculate boot_cpu_id4 = boot_cpu_id*4 */
sll %g3, 2, %g3
sethi %hi(boot_cpu_id4), %g2
stub %g3, [%g2 + %lo(boot_cpu_id4)]
/* Initialize the uwinmask value for init task just in case. /* Initialize the uwinmask value for init task just in case.
* But first make current_set[boot_cpu_id] point to something useful. * But first make current_set[boot_cpu_id] point to something useful.
*/ */
set init_thread_union, %g6 set init_thread_union, %g6
set current_set, %g2 set current_set, %g2
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
sethi %hi(boot_cpu_id4), %g3
ldub [%g3 + %lo(boot_cpu_id4)], %g3
st %g6, [%g2] st %g6, [%g2]
add %g2, %g3, %g2 add %g2, %g3, %g2
#endif #endif
......
...@@ -50,10 +50,15 @@ ...@@ -50,10 +50,15 @@
#include <asm/io-unit.h> #include <asm/io-unit.h>
#include <asm/leon.h> #include <asm/leon.h>
/* This function must make sure that caches and memory are coherent after DMA
* On LEON systems without cache snooping it flushes the entire D-CACHE.
*/
#ifndef CONFIG_SPARC_LEON #ifndef CONFIG_SPARC_LEON
#define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ static inline void dma_make_coherent(unsigned long pa, unsigned long len)
{
}
#else #else
static inline void mmu_inval_dma_area(void *va, unsigned long len) static inline void dma_make_coherent(unsigned long pa, unsigned long len)
{ {
if (!sparc_leon3_snooping_enabled()) if (!sparc_leon3_snooping_enabled())
leon_flush_dcache_all(); leon_flush_dcache_all();
...@@ -284,7 +289,6 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, ...@@ -284,7 +289,6 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total); printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
goto err_nova; goto err_nova;
} }
mmu_inval_dma_area((void *)va, len_total);
// XXX The mmu_map_dma_area does this for us below, see comments. // XXX The mmu_map_dma_area does this for us below, see comments.
// sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
...@@ -336,7 +340,6 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p, ...@@ -336,7 +340,6 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
release_resource(res); release_resource(res);
kfree(res); kfree(res);
/* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */
pgv = virt_to_page(p); pgv = virt_to_page(p);
mmu_unmap_dma_area(dev, ba, n); mmu_unmap_dma_area(dev, ba, n);
...@@ -463,7 +466,6 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len, ...@@ -463,7 +466,6 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len,
printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
goto err_nova; goto err_nova;
} }
mmu_inval_dma_area(va, len_total);
sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
...@@ -489,7 +491,6 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p, ...@@ -489,7 +491,6 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
dma_addr_t ba) dma_addr_t ba)
{ {
struct resource *res; struct resource *res;
void *pgp;
if ((res = _sparc_find_resource(&_sparc_dvma, if ((res = _sparc_find_resource(&_sparc_dvma,
(unsigned long)p)) == NULL) { (unsigned long)p)) == NULL) {
...@@ -509,14 +510,12 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p, ...@@ -509,14 +510,12 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
return; return;
} }
pgp = phys_to_virt(ba); /* bus_to_virt actually */ dma_make_coherent(ba, n);
mmu_inval_dma_area(pgp, n);
sparc_unmapiorange((unsigned long)p, n); sparc_unmapiorange((unsigned long)p, n);
release_resource(res); release_resource(res);
kfree(res); kfree(res);
free_pages((unsigned long)phys_to_virt(ba), get_order(n));
free_pages((unsigned long)pgp, get_order(n));
} }
/* /*
...@@ -535,7 +534,7 @@ static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size, ...@@ -535,7 +534,7 @@ static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
enum dma_data_direction dir, struct dma_attrs *attrs) enum dma_data_direction dir, struct dma_attrs *attrs)
{ {
if (dir != PCI_DMA_TODEVICE) if (dir != PCI_DMA_TODEVICE)
mmu_inval_dma_area(phys_to_virt(ba), PAGE_ALIGN(size)); dma_make_coherent(ba, PAGE_ALIGN(size));
} }
/* Map a set of buffers described by scatterlist in streaming /* Map a set of buffers described by scatterlist in streaming
...@@ -562,8 +561,7 @@ static int pci32_map_sg(struct device *device, struct scatterlist *sgl, ...@@ -562,8 +561,7 @@ static int pci32_map_sg(struct device *device, struct scatterlist *sgl,
/* IIep is write-through, not flushing. */ /* IIep is write-through, not flushing. */
for_each_sg(sgl, sg, nents, n) { for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL); sg->dma_address = sg_phys(sg);
sg->dma_address = virt_to_phys(sg_virt(sg));
sg->dma_length = sg->length; sg->dma_length = sg->length;
} }
return nents; return nents;
...@@ -582,9 +580,7 @@ static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl, ...@@ -582,9 +580,7 @@ static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl,
if (dir != PCI_DMA_TODEVICE) { if (dir != PCI_DMA_TODEVICE) {
for_each_sg(sgl, sg, nents, n) { for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL); dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
mmu_inval_dma_area(page_address(sg_page(sg)),
PAGE_ALIGN(sg->length));
} }
} }
} }
...@@ -603,8 +599,7 @@ static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba, ...@@ -603,8 +599,7 @@ static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
if (dir != PCI_DMA_TODEVICE) { if (dir != PCI_DMA_TODEVICE) {
mmu_inval_dma_area(phys_to_virt(ba), dma_make_coherent(ba, PAGE_ALIGN(size));
PAGE_ALIGN(size));
} }
} }
...@@ -612,8 +607,7 @@ static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba, ...@@ -612,8 +607,7 @@ static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
if (dir != PCI_DMA_TODEVICE) { if (dir != PCI_DMA_TODEVICE) {
mmu_inval_dma_area(phys_to_virt(ba), dma_make_coherent(ba, PAGE_ALIGN(size));
PAGE_ALIGN(size));
} }
} }
...@@ -631,9 +625,7 @@ static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, ...@@ -631,9 +625,7 @@ static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
if (dir != PCI_DMA_TODEVICE) { if (dir != PCI_DMA_TODEVICE) {
for_each_sg(sgl, sg, nents, n) { for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL); dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
mmu_inval_dma_area(page_address(sg_page(sg)),
PAGE_ALIGN(sg->length));
} }
} }
} }
...@@ -646,9 +638,7 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist * ...@@ -646,9 +638,7 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist *
if (dir != PCI_DMA_TODEVICE) { if (dir != PCI_DMA_TODEVICE) {
for_each_sg(sgl, sg, nents, n) { for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL); dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
mmu_inval_dma_area(page_address(sg_page(sg)),
PAGE_ALIGN(sg->length));
} }
} }
} }
......
...@@ -2,6 +2,23 @@ ...@@ -2,6 +2,23 @@
#include <asm/btfixup.h> #include <asm/btfixup.h>
struct irq_bucket {
struct irq_bucket *next;
unsigned int real_irq;
unsigned int irq;
unsigned int pil;
};
#define SUN4D_MAX_BOARD 10
#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5)
/* Map between the irq identifier used in hw to the
* irq_bucket. The map is sufficient large to hold
* the sun4d hw identifiers.
*/
extern struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
/* sun4m specific type definitions */ /* sun4m specific type definitions */
/* This maps direct to CPU specific interrupt registers */ /* This maps direct to CPU specific interrupt registers */
...@@ -35,6 +52,10 @@ struct sparc_irq_config { ...@@ -35,6 +52,10 @@ struct sparc_irq_config {
}; };
extern struct sparc_irq_config sparc_irq_config; extern struct sparc_irq_config sparc_irq_config;
unsigned int irq_alloc(unsigned int real_irq, unsigned int pil);
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) /* Dave Redman (djhr@tadpole.co.uk)
* changed these to function pointers.. it saves cycles and will allow * changed these to function pointers.. it saves cycles and will allow
...@@ -44,33 +65,9 @@ extern struct sparc_irq_config sparc_irq_config; ...@@ -44,33 +65,9 @@ extern struct sparc_irq_config sparc_irq_config;
* Changed these to btfixup entities... It saves cycles :) * Changed these to btfixup entities... It saves cycles :)
*/ */
BTFIXUPDEF_CALL(void, disable_irq, unsigned int)
BTFIXUPDEF_CALL(void, enable_irq, unsigned int)
BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int)
BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int)
BTFIXUPDEF_CALL(void, clear_clock_irq, void) BTFIXUPDEF_CALL(void, clear_clock_irq, void)
BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int)
static inline void __disable_irq(unsigned int irq)
{
BTFIXUP_CALL(disable_irq)(irq);
}
static inline void __enable_irq(unsigned int irq)
{
BTFIXUP_CALL(enable_irq)(irq);
}
static inline void disable_pil_irq(unsigned int irq)
{
BTFIXUP_CALL(disable_pil_irq)(irq);
}
static inline void enable_pil_irq(unsigned int irq)
{
BTFIXUP_CALL(enable_pil_irq)(irq);
}
static inline void clear_clock_irq(void) static inline void clear_clock_irq(void)
{ {
BTFIXUP_CALL(clear_clock_irq)(); BTFIXUP_CALL(clear_clock_irq)();
...@@ -89,4 +86,10 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int) ...@@ -89,4 +86,10 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int)
#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) #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 clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level)
#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) #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 14
extern void sun4d_ipi_interrupt(void);
#endif #endif
This diff is collapsed.
...@@ -224,13 +224,13 @@ static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity) ...@@ -224,13 +224,13 @@ static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity)
int cpuid; int cpuid;
cpumask_copy(&mask, affinity); cpumask_copy(&mask, affinity);
if (cpus_equal(mask, cpu_online_map)) { if (cpumask_equal(&mask, cpu_online_mask)) {
cpuid = map_to_cpu(irq); cpuid = map_to_cpu(irq);
} else { } else {
cpumask_t tmp; cpumask_t tmp;
cpus_and(tmp, cpu_online_map, mask); cpumask_and(&tmp, cpu_online_mask, &mask);
cpuid = cpus_empty(tmp) ? map_to_cpu(irq) : first_cpu(tmp); cpuid = cpumask_empty(&tmp) ? map_to_cpu(irq) : cpumask_first(&tmp);
} }
return cpuid; return cpuid;
......
...@@ -6,11 +6,9 @@ ...@@ -6,11 +6,9 @@
#include <asm/traps.h> #include <asm/traps.h>
/* cpu.c */ /* cpu.c */
extern const char *sparc_cpu_type;
extern const char *sparc_pmu_type; extern const char *sparc_pmu_type;
extern const char *sparc_fpu_type;
extern unsigned int fsr_storage; extern unsigned int fsr_storage;
extern int ncpus_probed;
#ifdef CONFIG_SPARC32 #ifdef CONFIG_SPARC32
/* cpu.c */ /* cpu.c */
...@@ -37,6 +35,7 @@ extern void sun4c_init_IRQ(void); ...@@ -37,6 +35,7 @@ extern void sun4c_init_IRQ(void);
extern unsigned int lvl14_resolution; extern unsigned int lvl14_resolution;
extern void sun4m_init_IRQ(void); extern void sun4m_init_IRQ(void);
extern void sun4m_unmask_profile_irq(void);
extern void sun4m_clear_profile_irq(int cpu); extern void sun4m_clear_profile_irq(int cpu);
/* sun4d_irq.c */ /* sun4d_irq.c */
......
This diff is collapsed.
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/of.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -29,6 +30,7 @@ ...@@ -29,6 +30,7 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/irq_regs.h> #include <asm/irq_regs.h>
#include <asm/traps.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -50,9 +52,12 @@ ...@@ -50,9 +52,12 @@
extern ctxd_t *srmmu_ctx_table_phys; extern ctxd_t *srmmu_ctx_table_phys;
static int smp_processors_ready; static int smp_processors_ready;
extern volatile unsigned long cpu_callin_map[NR_CPUS]; extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
extern cpumask_t smp_commenced_mask; extern cpumask_t smp_commenced_mask;
void __init leon_configure_cache_smp(void); void __init leon_configure_cache_smp(void);
static void leon_ipi_init(void);
/* IRQ number of LEON IPIs */
int leon_ipi_irq = LEON3_IRQ_IPI_DEFAULT;
static inline unsigned long do_swap(volatile unsigned long *ptr, static inline unsigned long do_swap(volatile unsigned long *ptr,
unsigned long val) unsigned long val)
...@@ -94,8 +99,6 @@ void __cpuinit leon_callin(void) ...@@ -94,8 +99,6 @@ void __cpuinit leon_callin(void)
local_flush_cache_all(); local_flush_cache_all();
local_flush_tlb_all(); local_flush_tlb_all();
cpu_probe();
/* Fix idle thread fields. */ /* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid]) __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(&current_set[cpuid])
: "memory" /* paranoid */); : "memory" /* paranoid */);
...@@ -104,11 +107,11 @@ void __cpuinit leon_callin(void) ...@@ -104,11 +107,11 @@ void __cpuinit leon_callin(void)
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
while (!cpu_isset(cpuid, smp_commenced_mask)) while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
mb(); mb();
local_irq_enable(); local_irq_enable();
cpu_set(cpuid, cpu_online_map); set_cpu_online(cpuid, true);
} }
/* /*
...@@ -179,13 +182,16 @@ void __init leon_boot_cpus(void) ...@@ -179,13 +182,16 @@ void __init leon_boot_cpus(void)
int nrcpu = leon_smp_nrcpus(); int nrcpu = leon_smp_nrcpus();
int me = smp_processor_id(); int me = smp_processor_id();
/* Setup IPI */
leon_ipi_init();
printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x\n", (unsigned int)me, printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x\n", (unsigned int)me,
(unsigned int)nrcpu, (unsigned int)NR_CPUS, (unsigned int)nrcpu, (unsigned int)NR_CPUS,
(unsigned int)&(leon3_irqctrl_regs->mpstatus)); (unsigned int)&(leon3_irqctrl_regs->mpstatus));
leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, me); leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, me);
leon_enable_irq_cpu(LEON3_IRQ_TICKER, me); leon_enable_irq_cpu(LEON3_IRQ_TICKER, me);
leon_enable_irq_cpu(LEON3_IRQ_RESCHEDULE, me); leon_enable_irq_cpu(leon_ipi_irq, me);
leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
...@@ -220,6 +226,10 @@ int __cpuinit leon_boot_one_cpu(int i) ...@@ -220,6 +226,10 @@ int __cpuinit leon_boot_one_cpu(int i)
(unsigned int)&leon3_irqctrl_regs->mpstatus); (unsigned int)&leon3_irqctrl_regs->mpstatus);
local_flush_cache_all(); local_flush_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);
/* Wake one CPU */
LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpstatus), 1 << i); LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpstatus), 1 << i);
/* wheee... it's going... */ /* wheee... it's going... */
...@@ -236,7 +246,7 @@ int __cpuinit leon_boot_one_cpu(int i) ...@@ -236,7 +246,7 @@ int __cpuinit leon_boot_one_cpu(int i)
} else { } else {
leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, i); leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, i);
leon_enable_irq_cpu(LEON3_IRQ_TICKER, i); leon_enable_irq_cpu(LEON3_IRQ_TICKER, i);
leon_enable_irq_cpu(LEON3_IRQ_RESCHEDULE, i); leon_enable_irq_cpu(leon_ipi_irq, i);
} }
local_flush_cache_all(); local_flush_cache_all();
...@@ -262,21 +272,21 @@ void __init leon_smp_done(void) ...@@ -262,21 +272,21 @@ void __init leon_smp_done(void)
local_flush_cache_all(); local_flush_cache_all();
/* Free unneeded trap tables */ /* Free unneeded trap tables */
if (!cpu_isset(1, cpu_present_map)) { if (!cpu_present(1)) {
ClearPageReserved(virt_to_page(&trapbase_cpu1)); ClearPageReserved(virt_to_page(&trapbase_cpu1));
init_page_count(virt_to_page(&trapbase_cpu1)); init_page_count(virt_to_page(&trapbase_cpu1));
free_page((unsigned long)&trapbase_cpu1); free_page((unsigned long)&trapbase_cpu1);
totalram_pages++; totalram_pages++;
num_physpages++; num_physpages++;
} }
if (!cpu_isset(2, cpu_present_map)) { if (!cpu_present(2)) {
ClearPageReserved(virt_to_page(&trapbase_cpu2)); ClearPageReserved(virt_to_page(&trapbase_cpu2));
init_page_count(virt_to_page(&trapbase_cpu2)); init_page_count(virt_to_page(&trapbase_cpu2));
free_page((unsigned long)&trapbase_cpu2); free_page((unsigned long)&trapbase_cpu2);
totalram_pages++; totalram_pages++;
num_physpages++; num_physpages++;
} }
if (!cpu_isset(3, cpu_present_map)) { if (!cpu_present(3)) {
ClearPageReserved(virt_to_page(&trapbase_cpu3)); ClearPageReserved(virt_to_page(&trapbase_cpu3));
init_page_count(virt_to_page(&trapbase_cpu3)); init_page_count(virt_to_page(&trapbase_cpu3));
free_page((unsigned long)&trapbase_cpu3); free_page((unsigned long)&trapbase_cpu3);
...@@ -292,6 +302,99 @@ void leon_irq_rotate(int cpu) ...@@ -292,6 +302,99 @@ void leon_irq_rotate(int cpu)
{ {
} }
struct leon_ipi_work {
int single;
int msk;
int resched;
};
static DEFINE_PER_CPU_SHARED_ALIGNED(struct leon_ipi_work, leon_ipi_work);
/* Initialize IPIs on the LEON, in order to save IRQ resources only one IRQ
* is used for all three types of IPIs.
*/
static void __init leon_ipi_init(void)
{
int cpu, len;
struct leon_ipi_work *work;
struct property *pp;
struct device_node *rootnp;
struct tt_entry *trap_table;
unsigned long flags;
/* Find IPI IRQ or stick with default value */
rootnp = of_find_node_by_path("/ambapp0");
if (rootnp) {
pp = of_find_property(rootnp, "ipi_num", &len);
if (pp && (*(int *)pp->value))
leon_ipi_irq = *(int *)pp->value;
}
printk(KERN_INFO "leon: SMP IPIs at IRQ %d\n", leon_ipi_irq);
/* Adjust so that we jump directly to smpleon_ipi */
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_irq_restore(flags);
for_each_possible_cpu(cpu) {
work = &per_cpu(leon_ipi_work, cpu);
work->single = work->msk = work->resched = 0;
}
}
static void leon_ipi_single(int cpu)
{
struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
/* Mark work */
work->single = 1;
/* Generate IRQ on the CPU */
set_cpu_int(cpu, leon_ipi_irq);
}
static void leon_ipi_mask_one(int cpu)
{
struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
/* Mark work */
work->msk = 1;
/* Generate IRQ on the CPU */
set_cpu_int(cpu, leon_ipi_irq);
}
static void leon_ipi_resched(int cpu)
{
struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu);
/* Mark work */
work->resched = 1;
/* Generate IRQ on the CPU (any IRQ will cause resched) */
set_cpu_int(cpu, leon_ipi_irq);
}
void leonsmp_ipi_interrupt(void)
{
struct leon_ipi_work *work = &__get_cpu_var(leon_ipi_work);
if (work->single) {
work->single = 0;
smp_call_function_single_interrupt();
}
if (work->msk) {
work->msk = 0;
smp_call_function_interrupt();
}
if (work->resched) {
work->resched = 0;
smp_resched_interrupt();
}
}
static struct smp_funcall { static struct smp_funcall {
smpfunc_t func; smpfunc_t func;
unsigned long arg1; unsigned long arg1;
...@@ -337,10 +440,10 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -337,10 +440,10 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
{ {
register int i; register int i;
cpu_clear(smp_processor_id(), mask); cpumask_clear_cpu(smp_processor_id(), &mask);
cpus_and(mask, cpu_online_map, mask); cpumask_and(&mask, cpu_online_mask, &mask);
for (i = 0; i <= high; i++) { for (i = 0; i <= high; i++) {
if (cpu_isset(i, mask)) { if (cpumask_test_cpu(i, &mask)) {
ccall_info.processors_in[i] = 0; ccall_info.processors_in[i] = 0;
ccall_info.processors_out[i] = 0; ccall_info.processors_out[i] = 0;
set_cpu_int(i, LEON3_IRQ_CROSS_CALL); set_cpu_int(i, LEON3_IRQ_CROSS_CALL);
...@@ -354,7 +457,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -354,7 +457,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
i = 0; i = 0;
do { do {
if (!cpu_isset(i, mask)) if (!cpumask_test_cpu(i, &mask))
continue; continue;
while (!ccall_info.processors_in[i]) while (!ccall_info.processors_in[i])
...@@ -363,7 +466,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -363,7 +466,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
i = 0; i = 0;
do { do {
if (!cpu_isset(i, mask)) if (!cpumask_test_cpu(i, &mask))
continue; continue;
while (!ccall_info.processors_out[i]) while (!ccall_info.processors_out[i])
...@@ -386,27 +489,23 @@ void leon_cross_call_irq(void) ...@@ -386,27 +489,23 @@ void leon_cross_call_irq(void)
ccall_info.processors_out[i] = 1; ccall_info.processors_out[i] = 1;
} }
void leon_percpu_timer_interrupt(struct pt_regs *regs) irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused)
{ {
struct pt_regs *old_regs;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
old_regs = set_irq_regs(regs);
leon_clear_profile_irq(cpu); leon_clear_profile_irq(cpu);
profile_tick(CPU_PROFILING); profile_tick(CPU_PROFILING);
if (!--prof_counter(cpu)) { if (!--prof_counter(cpu)) {
int user = user_mode(regs); int user = user_mode(get_irq_regs());
irq_enter();
update_process_times(user); update_process_times(user);
irq_exit();
prof_counter(cpu) = prof_multiplier(cpu); prof_counter(cpu) = prof_multiplier(cpu);
} }
set_irq_regs(old_regs);
return IRQ_HANDLED;
} }
static void __init smp_setup_percpu_timer(void) static void __init smp_setup_percpu_timer(void)
...@@ -449,6 +548,9 @@ void __init leon_init_smp(void) ...@@ -449,6 +548,9 @@ void __init leon_init_smp(void)
BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id, BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
BTFIXUPCALL_NORM); 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);
} }
#endif /* CONFIG_SPARC_LEON */ #endif /* CONFIG_SPARC_LEON */
...@@ -768,7 +768,7 @@ static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handl ...@@ -768,7 +768,7 @@ static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handl
cpuid, NR_CPUS); cpuid, NR_CPUS);
continue; continue;
} }
if (!cpu_isset(cpuid, *mask)) if (!cpumask_test_cpu(cpuid, mask))
continue; continue;
#endif #endif
......
...@@ -622,8 +622,9 @@ static unsigned int __init build_one_device_irq(struct platform_device *op, ...@@ -622,8 +622,9 @@ static unsigned int __init build_one_device_irq(struct platform_device *op,
out: out:
nid = of_node_to_nid(dp); nid = of_node_to_nid(dp);
if (nid != -1) { if (nid != -1) {
cpumask_t numa_mask = *cpumask_of_node(nid); cpumask_t numa_mask;
cpumask_copy(&numa_mask, cpumask_of_node(nid));
irq_set_affinity(irq, &numa_mask); irq_set_affinity(irq, &numa_mask);
} }
......
...@@ -284,8 +284,9 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm, ...@@ -284,8 +284,9 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm,
nid = pbm->numa_node; nid = pbm->numa_node;
if (nid != -1) { if (nid != -1) {
cpumask_t numa_mask = *cpumask_of_node(nid); cpumask_t numa_mask;
cpumask_copy(&numa_mask, cpumask_of_node(nid));
irq_set_affinity(irq, &numa_mask); irq_set_affinity(irq, &numa_mask);
} }
err = request_irq(irq, sparc64_msiq_interrupt, 0, err = request_irq(irq, sparc64_msiq_interrupt, 0,
......
...@@ -164,6 +164,9 @@ void __iomem *pcic_regs; ...@@ -164,6 +164,9 @@ void __iomem *pcic_regs;
volatile int pcic_speculative; volatile int pcic_speculative;
volatile int pcic_trapped; volatile int pcic_trapped;
/* forward */
unsigned int pcic_build_device_irq(struct platform_device *op,
unsigned int real_irq);
#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
...@@ -523,6 +526,7 @@ static void ...@@ -523,6 +526,7 @@ static void
pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
{ {
struct pcic_ca2irq *p; struct pcic_ca2irq *p;
unsigned int real_irq;
int i, ivec; int i, ivec;
char namebuf[64]; char namebuf[64];
...@@ -551,26 +555,25 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) ...@@ -551,26 +555,25 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
i = p->pin; i = p->pin;
if (i >= 0 && i < 4) { if (i >= 0 && i < 4) {
ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
dev->irq = ivec >> (i << 2) & 0xF; real_irq = ivec >> (i << 2) & 0xF;
} else if (i >= 4 && i < 8) { } else if (i >= 4 && i < 8) {
ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
dev->irq = ivec >> ((i-4) << 2) & 0xF; real_irq = ivec >> ((i-4) << 2) & 0xF;
} else { /* Corrupted map */ } else { /* Corrupted map */
printk("PCIC: BAD PIN %d\n", i); for (;;) {} printk("PCIC: BAD PIN %d\n", i); for (;;) {}
} }
/* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */ /* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */
/* /* real_irq means PROM did not bother to program the upper
* dev->irq=0 means PROM did not bother to program the upper
* half of PCIC. This happens on JS-E with PROM 3.11, for instance. * half of PCIC. This happens on JS-E with PROM 3.11, for instance.
*/ */
if (dev->irq == 0 || p->force) { if (real_irq == 0 || p->force) {
if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */
printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
} }
printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n",
p->irq, p->pin, dev->bus->number, dev->devfn); p->irq, p->pin, dev->bus->number, dev->devfn);
dev->irq = p->irq; real_irq = p->irq;
i = p->pin; i = p->pin;
if (i >= 4) { if (i >= 4) {
...@@ -584,7 +587,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) ...@@ -584,7 +587,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
ivec |= p->irq << (i << 2); ivec |= p->irq << (i << 2);
writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO);
} }
} }
dev->irq = pcic_build_device_irq(NULL, real_irq);
} }
/* /*
...@@ -729,6 +733,7 @@ void __init pci_time_init(void) ...@@ -729,6 +733,7 @@ void __init pci_time_init(void)
struct linux_pcic *pcic = &pcic0; struct linux_pcic *pcic = &pcic0;
unsigned long v; unsigned long v;
int timer_irq, irq; int timer_irq, irq;
int err;
do_arch_gettimeoffset = pci_gettimeoffset; do_arch_gettimeoffset = pci_gettimeoffset;
...@@ -740,9 +745,10 @@ void __init pci_time_init(void) ...@@ -740,9 +745,10 @@ void __init pci_time_init(void)
timer_irq = PCI_COUNTER_IRQ_SYS(v); timer_irq = PCI_COUNTER_IRQ_SYS(v);
writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
pcic->pcic_regs+PCI_COUNTER_IRQ); pcic->pcic_regs+PCI_COUNTER_IRQ);
irq = request_irq(timer_irq, pcic_timer_handler, irq = pcic_build_device_irq(NULL, timer_irq);
(IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); err = request_irq(irq, pcic_timer_handler,
if (irq) { IRQF_TIMER, "timer", NULL);
if (err) {
prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
prom_halt(); prom_halt();
} }
...@@ -803,50 +809,73 @@ static inline unsigned long get_irqmask(int irq_nr) ...@@ -803,50 +809,73 @@ static inline unsigned long get_irqmask(int irq_nr)
return 1 << irq_nr; return 1 << irq_nr;
} }
static void pcic_disable_irq(unsigned int irq_nr) static void pcic_mask_irq(struct irq_data *data)
{ {
unsigned long mask, flags; unsigned long mask, flags;
mask = get_irqmask(irq_nr); mask = (unsigned long)data->chip_data;
local_irq_save(flags); local_irq_save(flags);
writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
local_irq_restore(flags); local_irq_restore(flags);
} }
static void pcic_enable_irq(unsigned int irq_nr) static void pcic_unmask_irq(struct irq_data *data)
{ {
unsigned long mask, flags; unsigned long mask, flags;
mask = get_irqmask(irq_nr); mask = (unsigned long)data->chip_data;
local_irq_save(flags); local_irq_save(flags);
writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
local_irq_restore(flags); local_irq_restore(flags);
} }
static void pcic_load_profile_irq(int cpu, unsigned int limit) static unsigned int pcic_startup_irq(struct irq_data *data)
{ {
printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); irq_link(data->irq);
pcic_unmask_irq(data);
return 0;
} }
/* We assume the caller has disabled local interrupts when these are called, static struct irq_chip pcic_irq = {
* or else very bizarre behavior will result. .name = "pcic",
*/ .irq_startup = pcic_startup_irq,
static void pcic_disable_pil_irq(unsigned int pil) .irq_mask = pcic_mask_irq,
.irq_unmask = pcic_unmask_irq,
};
unsigned int pcic_build_device_irq(struct platform_device *op,
unsigned int real_irq)
{ {
writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); unsigned int irq;
unsigned long mask;
irq = 0;
mask = get_irqmask(real_irq);
if (mask == 0)
goto out;
irq = irq_alloc(real_irq, real_irq);
if (irq == 0)
goto out;
irq_set_chip_and_handler_name(irq, &pcic_irq,
handle_level_irq, "PCIC");
irq_set_chip_data(irq, (void *)mask);
out:
return irq;
} }
static void pcic_enable_pil_irq(unsigned int pil)
static void pcic_load_profile_irq(int cpu, unsigned int limit)
{ {
writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);
} }
void __init sun4m_pci_init_IRQ(void) void __init sun4m_pci_init_IRQ(void)
{ {
BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM); sparc_irq_config.build_device_irq = pcic_build_device_irq;
BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/pcr.h> #include <asm/pcr.h>
#include "kernel.h"
#include "kstack.h" #include "kstack.h"
/* Sparc64 chips have two performance counters, 32-bits each, with /* Sparc64 chips have two performance counters, 32-bits each, with
......
...@@ -128,8 +128,16 @@ void cpu_idle(void) ...@@ -128,8 +128,16 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
while(1) { while(1) {
while (!need_resched()) #ifdef CONFIG_SPARC_LEON
cpu_relax(); if (pm_idle) {
while (!need_resched())
(*pm_idle)();
} else
#endif
{
while (!need_resched())
cpu_relax();
}
preempt_enable_no_resched(); preempt_enable_no_resched();
schedule(); schedule();
preempt_disable(); preempt_disable();
......
...@@ -326,7 +326,6 @@ void __init of_console_init(void) ...@@ -326,7 +326,6 @@ void __init of_console_init(void)
of_console_options = NULL; of_console_options = NULL;
} }
prom_printf(msg, of_console_path);
printk(msg, of_console_path); printk(msg, of_console_path);
} }
......
...@@ -103,16 +103,20 @@ static unsigned int boot_flags __initdata = 0; ...@@ -103,16 +103,20 @@ static unsigned int boot_flags __initdata = 0;
/* Exported for mm/init.c:paging_init. */ /* Exported for mm/init.c:paging_init. */
unsigned long cmdline_memory_size __initdata = 0; unsigned long cmdline_memory_size __initdata = 0;
/* which CPU booted us (0xff = not set) */
unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */
unsigned char boot_cpu_id4; /* boot_cpu_id << 2 */
static void static void
prom_console_write(struct console *con, const char *s, unsigned n) prom_console_write(struct console *con, const char *s, unsigned n)
{ {
prom_write(s, n); prom_write(s, n);
} }
static struct console prom_debug_console = { static struct console prom_early_console = {
.name = "debug", .name = "earlyprom",
.write = prom_console_write, .write = prom_console_write,
.flags = CON_PRINTBUFFER, .flags = CON_PRINTBUFFER | CON_BOOT,
.index = -1, .index = -1,
}; };
...@@ -133,8 +137,7 @@ static void __init process_switch(char c) ...@@ -133,8 +137,7 @@ static void __init process_switch(char c)
prom_halt(); prom_halt();
break; break;
case 'p': case 'p':
/* Use PROM debug console. */ /* Just ignore, this behavior is now the default. */
register_console(&prom_debug_console);
break; break;
default: default:
printk("Unknown boot switch (-%c)\n", c); printk("Unknown boot switch (-%c)\n", c);
...@@ -215,6 +218,10 @@ void __init setup_arch(char **cmdline_p) ...@@ -215,6 +218,10 @@ void __init setup_arch(char **cmdline_p)
strcpy(boot_command_line, *cmdline_p); strcpy(boot_command_line, *cmdline_p);
parse_early_param(); parse_early_param();
boot_flags_init(*cmdline_p);
register_console(&prom_early_console);
/* Set sparc_cpu_model */ /* Set sparc_cpu_model */
sparc_cpu_model = sun_unknown; sparc_cpu_model = sun_unknown;
if (!strcmp(&cputypval[0], "sun4 ")) if (!strcmp(&cputypval[0], "sun4 "))
...@@ -265,7 +272,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -265,7 +272,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_DUMMY_CONSOLE #ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con; conswitchp = &dummy_con;
#endif #endif
boot_flags_init(*cmdline_p);
idprom_init(); idprom_init();
if (ARCH_SUN4C) if (ARCH_SUN4C)
...@@ -311,75 +317,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -311,75 +317,6 @@ void __init setup_arch(char **cmdline_p)
smp_setup_cpu_possible_map(); smp_setup_cpu_possible_map();
} }
static int ncpus_probed;
static int show_cpuinfo(struct seq_file *m, void *__unused)
{
seq_printf(m,
"cpu\t\t: %s\n"
"fpu\t\t: %s\n"
"promlib\t\t: Version %d Revision %d\n"
"prom\t\t: %d.%d\n"
"type\t\t: %s\n"
"ncpus probed\t: %d\n"
"ncpus active\t: %d\n"
#ifndef CONFIG_SMP
"CPU0Bogo\t: %lu.%02lu\n"
"CPU0ClkTck\t: %ld\n"
#endif
,
sparc_cpu_type,
sparc_fpu_type ,
romvec->pv_romvers,
prom_rev,
romvec->pv_printrev >> 16,
romvec->pv_printrev & 0xffff,
&cputypval[0],
ncpus_probed,
num_online_cpus()
#ifndef CONFIG_SMP
, cpu_data(0).udelay_val/(500000/HZ),
(cpu_data(0).udelay_val/(5000/HZ)) % 100,
cpu_data(0).clock_tick
#endif
);
#ifdef CONFIG_SMP
smp_bogo(m);
#endif
mmu_info(m);
#ifdef CONFIG_SMP
smp_info(m);
#endif
return 0;
}
static void *c_start(struct seq_file *m, loff_t *pos)
{
/* The pointer we are returning is arbitrary,
* it just has to be non-NULL and not IS_ERR
* in the success case.
*/
return *pos == 0 ? &c_start : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
return c_start(m, pos);
}
static void c_stop(struct seq_file *m, void *v)
{
}
const struct seq_operations cpuinfo_op = {
.start =c_start,
.next = c_next,
.stop = c_stop,
.show = show_cpuinfo,
};
extern int stop_a_enabled; extern int stop_a_enabled;
void sun_do_break(void) void sun_do_break(void)
......
...@@ -339,84 +339,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -339,84 +339,6 @@ void __init setup_arch(char **cmdline_p)
paging_init(); paging_init();
} }
/* BUFFER is PAGE_SIZE bytes long. */
extern void smp_info(struct seq_file *);
extern void smp_bogo(struct seq_file *);
extern void mmu_info(struct seq_file *);
unsigned int dcache_parity_tl1_occurred;
unsigned int icache_parity_tl1_occurred;
int ncpus_probed;
static int show_cpuinfo(struct seq_file *m, void *__unused)
{
seq_printf(m,
"cpu\t\t: %s\n"
"fpu\t\t: %s\n"
"pmu\t\t: %s\n"
"prom\t\t: %s\n"
"type\t\t: %s\n"
"ncpus probed\t: %d\n"
"ncpus active\t: %d\n"
"D$ parity tl1\t: %u\n"
"I$ parity tl1\t: %u\n"
#ifndef CONFIG_SMP
"Cpu0ClkTck\t: %016lx\n"
#endif
,
sparc_cpu_type,
sparc_fpu_type,
sparc_pmu_type,
prom_version,
((tlb_type == hypervisor) ?
"sun4v" :
"sun4u"),
ncpus_probed,
num_online_cpus(),
dcache_parity_tl1_occurred,
icache_parity_tl1_occurred
#ifndef CONFIG_SMP
, cpu_data(0).clock_tick
#endif
);
#ifdef CONFIG_SMP
smp_bogo(m);
#endif
mmu_info(m);
#ifdef CONFIG_SMP
smp_info(m);
#endif
return 0;
}
static void *c_start(struct seq_file *m, loff_t *pos)
{
/* The pointer we are returning is arbitrary,
* it just has to be non-NULL and not IS_ERR
* in the success case.
*/
return *pos == 0 ? &c_start : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
return c_start(m, pos);
}
static void c_stop(struct seq_file *m, void *v)
{
}
const struct seq_operations cpuinfo_op = {
.start =c_start,
.next = c_next,
.stop = c_stop,
.show = show_cpuinfo,
};
extern int stop_a_enabled; extern int stop_a_enabled;
void sun_do_break(void) void sun_do_break(void)
......
...@@ -37,8 +37,6 @@ ...@@ -37,8 +37,6 @@
#include "irq.h" #include "irq.h"
volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
unsigned char boot_cpu_id = 0;
unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
cpumask_t smp_commenced_mask = CPU_MASK_NONE; cpumask_t smp_commenced_mask = CPU_MASK_NONE;
...@@ -130,14 +128,57 @@ struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 }; ...@@ -130,14 +128,57 @@ struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 };
void smp_send_reschedule(int cpu) void smp_send_reschedule(int cpu)
{ {
/* /*
* XXX missing reschedule IPI, see scheduler_ipi() * CPU model dependent way of implementing IPI generation targeting
* a single CPU. The trap handler needs only to do trap entry/return
* to call schedule.
*/ */
BTFIXUP_CALL(smp_ipi_resched)(cpu);
} }
void smp_send_stop(void) 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);
}
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
int cpu;
/* trigger IPI mask call on each CPU */
for_each_cpu(cpu, mask)
BTFIXUP_CALL(smp_ipi_mask_one)(cpu);
}
void smp_resched_interrupt(void)
{
irq_enter();
scheduler_ipi();
local_cpu_data().irq_resched_count++;
irq_exit();
/* re-schedule routine called by interrupt return code. */
}
void smp_call_function_single_interrupt(void)
{
irq_enter();
generic_smp_call_function_single_interrupt();
local_cpu_data().irq_call_count++;
irq_exit();
}
void smp_call_function_interrupt(void)
{
irq_enter();
generic_smp_call_function_interrupt();
local_cpu_data().irq_call_count++;
irq_exit();
}
void smp_flush_cache_all(void) void smp_flush_cache_all(void)
{ {
xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all));
...@@ -153,9 +194,10 @@ void smp_flush_tlb_all(void) ...@@ -153,9 +194,10 @@ void smp_flush_tlb_all(void)
void smp_flush_cache_mm(struct mm_struct *mm) void smp_flush_cache_mm(struct mm_struct *mm)
{ {
if(mm->context != NO_CONTEXT) { if(mm->context != NO_CONTEXT) {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) 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); xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm);
local_flush_cache_mm(mm); local_flush_cache_mm(mm);
} }
...@@ -164,9 +206,10 @@ void smp_flush_cache_mm(struct mm_struct *mm) ...@@ -164,9 +206,10 @@ void smp_flush_cache_mm(struct mm_struct *mm)
void smp_flush_tlb_mm(struct mm_struct *mm) void smp_flush_tlb_mm(struct mm_struct *mm)
{ {
if(mm->context != NO_CONTEXT) { if(mm->context != NO_CONTEXT) {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) { 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); xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
cpumask_copy(mm_cpumask(mm), cpumask_copy(mm_cpumask(mm),
...@@ -182,9 +225,10 @@ void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start, ...@@ -182,9 +225,10 @@ void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
if (mm->context != NO_CONTEXT) { if (mm->context != NO_CONTEXT) {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) 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); xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end);
local_flush_cache_range(vma, start, end); local_flush_cache_range(vma, start, end);
} }
...@@ -196,9 +240,10 @@ void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, ...@@ -196,9 +240,10 @@ void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
if (mm->context != NO_CONTEXT) { if (mm->context != NO_CONTEXT) {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) 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); xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end);
local_flush_tlb_range(vma, start, end); local_flush_tlb_range(vma, start, end);
} }
...@@ -209,9 +254,10 @@ void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page) ...@@ -209,9 +254,10 @@ void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
if(mm->context != NO_CONTEXT) { if(mm->context != NO_CONTEXT) {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) 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); xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page);
local_flush_cache_page(vma, page); local_flush_cache_page(vma, page);
} }
...@@ -222,19 +268,15 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) ...@@ -222,19 +268,15 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
if(mm->context != NO_CONTEXT) { if(mm->context != NO_CONTEXT) {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) 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); xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page);
local_flush_tlb_page(vma, page); local_flush_tlb_page(vma, page);
} }
} }
void smp_reschedule_irq(void)
{
set_need_resched();
}
void smp_flush_page_to_ram(unsigned long page) void smp_flush_page_to_ram(unsigned long page)
{ {
/* Current theory is that those who call this are the one's /* Current theory is that those who call this are the one's
...@@ -251,9 +293,10 @@ void smp_flush_page_to_ram(unsigned long page) ...@@ -251,9 +293,10 @@ void smp_flush_page_to_ram(unsigned long page)
void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
{ {
cpumask_t cpu_mask = *mm_cpumask(mm); cpumask_t cpu_mask;
cpu_clear(smp_processor_id(), cpu_mask); cpumask_copy(&cpu_mask, mm_cpumask(mm));
if (!cpus_empty(cpu_mask)) 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); xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr);
local_flush_sig_insns(mm, insn_addr); local_flush_sig_insns(mm, insn_addr);
} }
...@@ -407,7 +450,7 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -407,7 +450,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
}; };
if (!ret) { if (!ret) {
cpu_set(cpu, smp_commenced_mask); cpumask_set_cpu(cpu, &smp_commenced_mask);
while (!cpu_online(cpu)) while (!cpu_online(cpu))
mb(); mb();
} }
......
...@@ -121,11 +121,11 @@ void __cpuinit smp_callin(void) ...@@ -121,11 +121,11 @@ void __cpuinit smp_callin(void)
/* inform the notifiers about the new cpu */ /* inform the notifiers about the new cpu */
notify_cpu_starting(cpuid); notify_cpu_starting(cpuid);
while (!cpu_isset(cpuid, smp_commenced_mask)) while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
rmb(); rmb();
ipi_call_lock_irq(); ipi_call_lock_irq();
cpu_set(cpuid, cpu_online_map); set_cpu_online(cpuid, true);
ipi_call_unlock_irq(); ipi_call_unlock_irq();
/* idle thread is expected to have preempt disabled */ /* idle thread is expected to have preempt disabled */
...@@ -785,7 +785,7 @@ static void xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask ...@@ -785,7 +785,7 @@ static void xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask
/* Send cross call to all processors mentioned in MASK_P /* Send cross call to all processors mentioned in MASK_P
* except self. Really, there are only two cases currently, * except self. Really, there are only two cases currently,
* "&cpu_online_map" and "&mm->cpu_vm_mask". * "cpu_online_mask" and "mm_cpumask(mm)".
*/ */
static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 data2, const cpumask_t *mask) static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 data2, const cpumask_t *mask)
{ {
...@@ -797,7 +797,7 @@ static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 d ...@@ -797,7 +797,7 @@ static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 d
/* Send cross call to all processors except self. */ /* Send cross call to all processors except self. */
static void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2) static void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2)
{ {
smp_cross_call_masked(func, ctx, data1, data2, &cpu_online_map); smp_cross_call_masked(func, ctx, data1, data2, cpu_online_mask);
} }
extern unsigned long xcall_sync_tick; extern unsigned long xcall_sync_tick;
...@@ -805,7 +805,7 @@ extern unsigned long xcall_sync_tick; ...@@ -805,7 +805,7 @@ extern unsigned long xcall_sync_tick;
static void smp_start_sync_tick_client(int cpu) static void smp_start_sync_tick_client(int cpu)
{ {
xcall_deliver((u64) &xcall_sync_tick, 0, 0, xcall_deliver((u64) &xcall_sync_tick, 0, 0,
&cpumask_of_cpu(cpu)); cpumask_of(cpu));
} }
extern unsigned long xcall_call_function; extern unsigned long xcall_call_function;
...@@ -820,7 +820,7 @@ extern unsigned long xcall_call_function_single; ...@@ -820,7 +820,7 @@ extern unsigned long xcall_call_function_single;
void arch_send_call_function_single_ipi(int cpu) void arch_send_call_function_single_ipi(int cpu)
{ {
xcall_deliver((u64) &xcall_call_function_single, 0, 0, xcall_deliver((u64) &xcall_call_function_single, 0, 0,
&cpumask_of_cpu(cpu)); cpumask_of(cpu));
} }
void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)
...@@ -918,7 +918,7 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) ...@@ -918,7 +918,7 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
} }
if (data0) { if (data0) {
xcall_deliver(data0, __pa(pg_addr), xcall_deliver(data0, __pa(pg_addr),
(u64) pg_addr, &cpumask_of_cpu(cpu)); (u64) pg_addr, cpumask_of(cpu));
#ifdef CONFIG_DEBUG_DCFLUSH #ifdef CONFIG_DEBUG_DCFLUSH
atomic_inc(&dcpage_flushes_xcall); atomic_inc(&dcpage_flushes_xcall);
#endif #endif
...@@ -954,7 +954,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) ...@@ -954,7 +954,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
} }
if (data0) { if (data0) {
xcall_deliver(data0, __pa(pg_addr), xcall_deliver(data0, __pa(pg_addr),
(u64) pg_addr, &cpu_online_map); (u64) pg_addr, cpu_online_mask);
#ifdef CONFIG_DEBUG_DCFLUSH #ifdef CONFIG_DEBUG_DCFLUSH
atomic_inc(&dcpage_flushes_xcall); atomic_inc(&dcpage_flushes_xcall);
#endif #endif
...@@ -1197,32 +1197,32 @@ void __devinit smp_fill_in_sib_core_maps(void) ...@@ -1197,32 +1197,32 @@ void __devinit smp_fill_in_sib_core_maps(void)
for_each_present_cpu(i) { for_each_present_cpu(i) {
unsigned int j; unsigned int j;
cpus_clear(cpu_core_map[i]); cpumask_clear(&cpu_core_map[i]);
if (cpu_data(i).core_id == 0) { if (cpu_data(i).core_id == 0) {
cpu_set(i, cpu_core_map[i]); cpumask_set_cpu(i, &cpu_core_map[i]);
continue; continue;
} }
for_each_present_cpu(j) { for_each_present_cpu(j) {
if (cpu_data(i).core_id == if (cpu_data(i).core_id ==
cpu_data(j).core_id) cpu_data(j).core_id)
cpu_set(j, cpu_core_map[i]); cpumask_set_cpu(j, &cpu_core_map[i]);
} }
} }
for_each_present_cpu(i) { for_each_present_cpu(i) {
unsigned int j; unsigned int j;
cpus_clear(per_cpu(cpu_sibling_map, i)); cpumask_clear(&per_cpu(cpu_sibling_map, i));
if (cpu_data(i).proc_id == -1) { if (cpu_data(i).proc_id == -1) {
cpu_set(i, per_cpu(cpu_sibling_map, i)); cpumask_set_cpu(i, &per_cpu(cpu_sibling_map, i));
continue; continue;
} }
for_each_present_cpu(j) { for_each_present_cpu(j) {
if (cpu_data(i).proc_id == if (cpu_data(i).proc_id ==
cpu_data(j).proc_id) cpu_data(j).proc_id)
cpu_set(j, per_cpu(cpu_sibling_map, i)); cpumask_set_cpu(j, &per_cpu(cpu_sibling_map, i));
} }
} }
} }
...@@ -1232,10 +1232,10 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -1232,10 +1232,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
int ret = smp_boot_one_cpu(cpu); int ret = smp_boot_one_cpu(cpu);
if (!ret) { if (!ret) {
cpu_set(cpu, smp_commenced_mask); cpumask_set_cpu(cpu, &smp_commenced_mask);
while (!cpu_isset(cpu, cpu_online_map)) while (!cpu_online(cpu))
mb(); mb();
if (!cpu_isset(cpu, cpu_online_map)) { if (!cpu_online(cpu)) {
ret = -ENODEV; ret = -ENODEV;
} else { } else {
/* On SUN4V, writes to %tick and %stick are /* On SUN4V, writes to %tick and %stick are
...@@ -1269,7 +1269,7 @@ void cpu_play_dead(void) ...@@ -1269,7 +1269,7 @@ void cpu_play_dead(void)
tb->nonresum_mondo_pa, 0); tb->nonresum_mondo_pa, 0);
} }
cpu_clear(cpu, smp_commenced_mask); cpumask_clear_cpu(cpu, &smp_commenced_mask);
membar_safe("#Sync"); membar_safe("#Sync");
local_irq_disable(); local_irq_disable();
...@@ -1290,13 +1290,13 @@ int __cpu_disable(void) ...@@ -1290,13 +1290,13 @@ int __cpu_disable(void)
cpuinfo_sparc *c; cpuinfo_sparc *c;
int i; int i;
for_each_cpu_mask(i, cpu_core_map[cpu]) for_each_cpu(i, &cpu_core_map[cpu])
cpu_clear(cpu, cpu_core_map[i]); cpumask_clear_cpu(cpu, &cpu_core_map[i]);
cpus_clear(cpu_core_map[cpu]); cpumask_clear(&cpu_core_map[cpu]);
for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) for_each_cpu(i, &per_cpu(cpu_sibling_map, cpu))
cpu_clear(cpu, per_cpu(cpu_sibling_map, i)); cpumask_clear_cpu(cpu, &per_cpu(cpu_sibling_map, i));
cpus_clear(per_cpu(cpu_sibling_map, cpu)); cpumask_clear(&per_cpu(cpu_sibling_map, cpu));
c = &cpu_data(cpu); c = &cpu_data(cpu);
...@@ -1313,7 +1313,7 @@ int __cpu_disable(void) ...@@ -1313,7 +1313,7 @@ int __cpu_disable(void)
local_irq_disable(); local_irq_disable();
ipi_call_lock(); ipi_call_lock();
cpu_clear(cpu, cpu_online_map); set_cpu_online(cpu, false);
ipi_call_unlock(); ipi_call_unlock();
cpu_map_rebuild(); cpu_map_rebuild();
...@@ -1327,11 +1327,11 @@ void __cpu_die(unsigned int cpu) ...@@ -1327,11 +1327,11 @@ void __cpu_die(unsigned int cpu)
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
smp_rmb(); smp_rmb();
if (!cpu_isset(cpu, smp_commenced_mask)) if (!cpumask_test_cpu(cpu, &smp_commenced_mask))
break; break;
msleep(100); msleep(100);
} }
if (cpu_isset(cpu, smp_commenced_mask)) { if (cpumask_test_cpu(cpu, &smp_commenced_mask)) {
printk(KERN_ERR "CPU %u didn't die...\n", cpu); printk(KERN_ERR "CPU %u didn't die...\n", cpu);
} else { } else {
#if defined(CONFIG_SUN_LDOMS) #if defined(CONFIG_SUN_LDOMS)
...@@ -1341,7 +1341,7 @@ void __cpu_die(unsigned int cpu) ...@@ -1341,7 +1341,7 @@ void __cpu_die(unsigned int cpu)
do { do {
hv_err = sun4v_cpu_stop(cpu); hv_err = sun4v_cpu_stop(cpu);
if (hv_err == HV_EOK) { if (hv_err == HV_EOK) {
cpu_clear(cpu, cpu_present_map); set_cpu_present(cpu, false);
break; break;
} }
} while (--limit > 0); } while (--limit > 0);
...@@ -1362,7 +1362,7 @@ void __init smp_cpus_done(unsigned int max_cpus) ...@@ -1362,7 +1362,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
void smp_send_reschedule(int cpu) void smp_send_reschedule(int cpu)
{ {
xcall_deliver((u64) &xcall_receive_signal, 0, 0, xcall_deliver((u64) &xcall_receive_signal, 0, 0,
&cpumask_of_cpu(cpu)); cpumask_of(cpu));
} }
void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
......
...@@ -65,62 +65,94 @@ ...@@ -65,62 +65,94 @@
*/ */
unsigned char __iomem *interrupt_enable; unsigned char __iomem *interrupt_enable;
static void sun4c_disable_irq(unsigned int irq_nr) static void sun4c_mask_irq(struct irq_data *data)
{ {
unsigned long flags; unsigned long mask = (unsigned long)data->chip_data;
unsigned char current_mask, new_mask;
if (mask) {
local_irq_save(flags); unsigned long flags;
irq_nr &= (NR_IRQS - 1);
current_mask = sbus_readb(interrupt_enable); local_irq_save(flags);
switch (irq_nr) { mask = sbus_readb(interrupt_enable) & ~mask;
case 1: sbus_writeb(mask, interrupt_enable);
new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
break;
case 8:
new_mask = ((current_mask) & (~(SUN4C_INT_E8)));
break;
case 10:
new_mask = ((current_mask) & (~(SUN4C_INT_E10)));
break;
case 14:
new_mask = ((current_mask) & (~(SUN4C_INT_E14)));
break;
default:
local_irq_restore(flags); local_irq_restore(flags);
return;
} }
sbus_writeb(new_mask, interrupt_enable);
local_irq_restore(flags);
} }
static void sun4c_enable_irq(unsigned int irq_nr) static void sun4c_unmask_irq(struct irq_data *data)
{ {
unsigned long flags; unsigned long mask = (unsigned long)data->chip_data;
unsigned char current_mask, new_mask;
if (mask) {
local_irq_save(flags); unsigned long flags;
irq_nr &= (NR_IRQS - 1);
current_mask = sbus_readb(interrupt_enable); local_irq_save(flags);
switch (irq_nr) { mask = sbus_readb(interrupt_enable) | mask;
case 1: sbus_writeb(mask, interrupt_enable);
new_mask = ((current_mask) | SUN4C_INT_E1);
break;
case 8:
new_mask = ((current_mask) | SUN4C_INT_E8);
break;
case 10:
new_mask = ((current_mask) | SUN4C_INT_E10);
break;
case 14:
new_mask = ((current_mask) | SUN4C_INT_E14);
break;
default:
local_irq_restore(flags); local_irq_restore(flags);
return;
} }
sbus_writeb(new_mask, interrupt_enable); }
local_irq_restore(flags);
static unsigned int sun4c_startup_irq(struct irq_data *data)
{
irq_link(data->irq);
sun4c_unmask_irq(data);
return 0;
}
static void sun4c_shutdown_irq(struct irq_data *data)
{
sun4c_mask_irq(data);
irq_unlink(data->irq);
}
static struct irq_chip sun4c_irq = {
.name = "sun4c",
.irq_startup = sun4c_startup_irq,
.irq_shutdown = sun4c_shutdown_irq,
.irq_mask = sun4c_mask_irq,
.irq_unmask = sun4c_unmask_irq,
};
static unsigned int sun4c_build_device_irq(struct platform_device *op,
unsigned int real_irq)
{
unsigned int irq;
if (real_irq >= 16) {
prom_printf("Bogus sun4c IRQ %u\n", real_irq);
prom_halt();
}
irq = irq_alloc(real_irq, real_irq);
if (irq) {
unsigned long mask = 0UL;
switch (real_irq) {
case 1:
mask = SUN4C_INT_E1;
break;
case 8:
mask = SUN4C_INT_E8;
break;
case 10:
mask = SUN4C_INT_E10;
break;
case 14:
mask = SUN4C_INT_E14;
break;
default:
/* All the rest are either always enabled,
* or are for signalling software interrupts.
*/
break;
}
irq_set_chip_and_handler_name(irq, &sun4c_irq,
handle_level_irq, "level");
irq_set_chip_data(irq, (void *)mask);
}
return irq;
} }
struct sun4c_timer_info { struct sun4c_timer_info {
...@@ -144,8 +176,9 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit) ...@@ -144,8 +176,9 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit)
static void __init sun4c_init_timers(irq_handler_t counter_fn) static void __init sun4c_init_timers(irq_handler_t counter_fn)
{ {
const struct linux_prom_irqs *irq; const struct linux_prom_irqs *prom_irqs;
struct device_node *dp; struct device_node *dp;
unsigned int irq;
const u32 *addr; const u32 *addr;
int err; int err;
...@@ -163,9 +196,9 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) ...@@ -163,9 +196,9 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
sun4c_timers = (void __iomem *) (unsigned long) addr[0]; sun4c_timers = (void __iomem *) (unsigned long) addr[0];
irq = of_get_property(dp, "intr", NULL); prom_irqs = of_get_property(dp, "intr", NULL);
of_node_put(dp); of_node_put(dp);
if (!irq) { if (!prom_irqs) {
prom_printf("sun4c_init_timers: No intr property\n"); prom_printf("sun4c_init_timers: No intr property\n");
prom_halt(); prom_halt();
} }
...@@ -178,15 +211,15 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) ...@@ -178,15 +211,15 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
master_l10_counter = &sun4c_timers->l10_count; master_l10_counter = &sun4c_timers->l10_count;
err = request_irq(irq[0].pri, counter_fn, irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri);
(IRQF_DISABLED | SA_STATIC_ALLOC), err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
"timer", NULL);
if (err) { if (err) {
prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
prom_halt(); prom_halt();
} }
sun4c_disable_irq(irq[1].pri); /* disable timer interrupt */
sun4c_mask_irq(irq_get_irq_data(irq));
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -215,14 +248,11 @@ void __init sun4c_init_IRQ(void) ...@@ -215,14 +248,11 @@ void __init sun4c_init_IRQ(void)
interrupt_enable = (void __iomem *) (unsigned long) addr[0]; interrupt_enable = (void __iomem *) (unsigned long) addr[0];
BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
sparc_irq_config.init_timers = sun4c_init_timers; sparc_irq_config.init_timers = sun4c_init_timers;
sparc_irq_config.build_device_irq = sun4c_build_device_irq;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
......
This diff is collapsed.
...@@ -32,6 +32,7 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon ...@@ -32,6 +32,7 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
return val; return val;
} }
static void smp4d_ipi_init(void);
static void smp_setup_percpu_timer(void); static void smp_setup_percpu_timer(void);
static unsigned char cpu_leds[32]; static unsigned char cpu_leds[32];
...@@ -80,8 +81,6 @@ void __cpuinit smp4d_callin(void) ...@@ -80,8 +81,6 @@ void __cpuinit smp4d_callin(void)
local_flush_cache_all(); local_flush_cache_all();
local_flush_tlb_all(); local_flush_tlb_all();
cpu_probe();
while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
barrier(); barrier();
...@@ -105,7 +104,7 @@ void __cpuinit smp4d_callin(void) ...@@ -105,7 +104,7 @@ void __cpuinit smp4d_callin(void)
local_irq_enable(); /* We don't allow PIL 14 yet */ local_irq_enable(); /* We don't allow PIL 14 yet */
while (!cpu_isset(cpuid, smp_commenced_mask)) while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
barrier(); barrier();
spin_lock_irqsave(&sun4d_imsk_lock, flags); spin_lock_irqsave(&sun4d_imsk_lock, flags);
...@@ -120,6 +119,7 @@ void __cpuinit smp4d_callin(void) ...@@ -120,6 +119,7 @@ void __cpuinit smp4d_callin(void)
*/ */
void __init smp4d_boot_cpus(void) void __init smp4d_boot_cpus(void)
{ {
smp4d_ipi_init();
if (boot_cpu_id) if (boot_cpu_id)
current_set[0] = NULL; current_set[0] = NULL;
smp_setup_percpu_timer(); smp_setup_percpu_timer();
...@@ -191,6 +191,80 @@ void __init smp4d_smp_done(void) ...@@ -191,6 +191,80 @@ void __init smp4d_smp_done(void)
sun4d_distribute_irqs(); sun4d_distribute_irqs();
} }
/* Memory structure giving interrupt handler information about IPI generated */
struct sun4d_ipi_work {
int single;
int msk;
int resched;
};
static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work);
/* Initialize IPIs on the SUN4D SMP machine */
static void __init smp4d_ipi_init(void)
{
int cpu;
struct sun4d_ipi_work *work;
printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ);
for_each_possible_cpu(cpu) {
work = &per_cpu(sun4d_ipi_work, cpu);
work->single = work->msk = work->resched = 0;
}
}
void sun4d_ipi_interrupt(void)
{
struct sun4d_ipi_work *work = &__get_cpu_var(sun4d_ipi_work);
if (work->single) {
work->single = 0;
smp_call_function_single_interrupt();
}
if (work->msk) {
work->msk = 0;
smp_call_function_interrupt();
}
if (work->resched) {
work->resched = 0;
smp_resched_interrupt();
}
}
static void smp4d_ipi_single(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
/* Mark work */
work->single = 1;
/* Generate IRQ on the CPU */
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}
static void smp4d_ipi_mask_one(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
/* Mark work */
work->msk = 1;
/* Generate IRQ on the CPU */
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}
static void smp4d_ipi_resched(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
/* Mark work */
work->resched = 1;
/* Generate IRQ on the CPU (any IRQ will cause resched) */
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}
static struct smp_funcall { static struct smp_funcall {
smpfunc_t func; smpfunc_t func;
unsigned long arg1; unsigned long arg1;
...@@ -239,10 +313,10 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -239,10 +313,10 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
{ {
register int i; register int i;
cpu_clear(smp_processor_id(), mask); cpumask_clear_cpu(smp_processor_id(), &mask);
cpus_and(mask, cpu_online_map, mask); cpumask_and(&mask, cpu_online_mask, &mask);
for (i = 0; i <= high; i++) { for (i = 0; i <= high; i++) {
if (cpu_isset(i, mask)) { if (cpumask_test_cpu(i, &mask)) {
ccall_info.processors_in[i] = 0; ccall_info.processors_in[i] = 0;
ccall_info.processors_out[i] = 0; ccall_info.processors_out[i] = 0;
sun4d_send_ipi(i, IRQ_CROSS_CALL); sun4d_send_ipi(i, IRQ_CROSS_CALL);
...@@ -255,7 +329,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -255,7 +329,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
i = 0; i = 0;
do { do {
if (!cpu_isset(i, mask)) if (!cpumask_test_cpu(i, &mask))
continue; continue;
while (!ccall_info.processors_in[i]) while (!ccall_info.processors_in[i])
barrier(); barrier();
...@@ -263,7 +337,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -263,7 +337,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
i = 0; i = 0;
do { do {
if (!cpu_isset(i, mask)) if (!cpumask_test_cpu(i, &mask))
continue; continue;
while (!ccall_info.processors_out[i]) while (!ccall_info.processors_out[i])
barrier(); barrier();
...@@ -356,6 +430,9 @@ void __init sun4d_init_smp(void) ...@@ -356,6 +430,9 @@ void __init sun4d_init_smp(void)
BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, 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);
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
ccall_info.processors_in[i] = 1; ccall_info.processors_in[i] = 1;
......
...@@ -100,6 +100,11 @@ ...@@ -100,6 +100,11 @@
struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
struct sun4m_irq_global __iomem *sun4m_irq_global; struct sun4m_irq_global __iomem *sun4m_irq_global;
struct sun4m_handler_data {
bool percpu;
long mask;
};
/* Dave Redman (djhr@tadpole.co.uk) /* Dave Redman (djhr@tadpole.co.uk)
* The sun4m interrupt registers. * The sun4m interrupt registers.
*/ */
...@@ -142,9 +147,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; ...@@ -142,9 +147,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global;
#define OBP_INT_LEVEL_VME 0x40 #define OBP_INT_LEVEL_VME 0x40
#define SUN4M_TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) #define SUN4M_TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10)
#define SUM4M_PROFILE_IRQ (OBP_INT_LEVEL_ONBOARD | 14) #define SUN4M_PROFILE_IRQ (OBP_INT_LEVEL_ONBOARD | 14)
static unsigned long irq_mask[0x50] = { static unsigned long sun4m_imask[0x50] = {
/* 0x00 - SMP */ /* 0x00 - SMP */
0, SUN4M_SOFT_INT(1), 0, SUN4M_SOFT_INT(1),
SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3),
...@@ -169,7 +174,7 @@ static unsigned long irq_mask[0x50] = { ...@@ -169,7 +174,7 @@ static unsigned long irq_mask[0x50] = {
SUN4M_INT_VIDEO, SUN4M_INT_MODULE, SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
(SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, SUN4M_INT_AUDIO, SUN4M_INT_E14, SUN4M_INT_MODULE_ERR,
/* 0x30 - sbus */ /* 0x30 - sbus */
0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
...@@ -182,105 +187,110 @@ static unsigned long irq_mask[0x50] = { ...@@ -182,105 +187,110 @@ static unsigned long irq_mask[0x50] = {
0, SUN4M_INT_VME(6), 0, 0 0, SUN4M_INT_VME(6), 0, 0
}; };
static unsigned long sun4m_get_irqmask(unsigned int irq) static void sun4m_mask_irq(struct irq_data *data)
{ {
unsigned long mask; struct sun4m_handler_data *handler_data = data->handler_data;
int cpu = smp_processor_id();
if (irq < 0x50)
mask = irq_mask[irq];
else
mask = 0;
if (!mask) if (handler_data->mask) {
printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n", unsigned long flags;
irq);
return mask; local_irq_save(flags);
if (handler_data->percpu) {
sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->set);
} else {
sbus_writel(handler_data->mask, &sun4m_irq_global->mask_set);
}
local_irq_restore(flags);
}
} }
static void sun4m_disable_irq(unsigned int irq_nr) static void sun4m_unmask_irq(struct irq_data *data)
{ {
unsigned long mask, flags; struct sun4m_handler_data *handler_data = data->handler_data;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
mask = sun4m_get_irqmask(irq_nr); if (handler_data->mask) {
local_irq_save(flags); unsigned long flags;
if (irq_nr > 15)
sbus_writel(mask, &sun4m_irq_global->mask_set);
else
sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
local_irq_restore(flags);
}
static void sun4m_enable_irq(unsigned int irq_nr)
{
unsigned long mask, flags;
int cpu = smp_processor_id();
/* Dreadful floppy hack. When we use 0x2b instead of
* 0x0b the system blows (it starts to whistle!).
* So we continue to use 0x0b. Fixme ASAP. --P3
*/
if (irq_nr != 0x0b) {
mask = sun4m_get_irqmask(irq_nr);
local_irq_save(flags);
if (irq_nr > 15)
sbus_writel(mask, &sun4m_irq_global->mask_clear);
else
sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
local_irq_restore(flags);
} else {
local_irq_save(flags); local_irq_save(flags);
sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); if (handler_data->percpu) {
sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear);
} else {
sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear);
}
local_irq_restore(flags); local_irq_restore(flags);
} }
} }
static unsigned long cpu_pil_to_imask[16] = { static unsigned int sun4m_startup_irq(struct irq_data *data)
/*0*/ 0x00000000, {
/*1*/ 0x00000000, irq_link(data->irq);
/*2*/ SUN4M_INT_SBUS(0) | SUN4M_INT_VME(0), sun4m_unmask_irq(data);
/*3*/ SUN4M_INT_SBUS(1) | SUN4M_INT_VME(1), return 0;
/*4*/ SUN4M_INT_SCSI, }
/*5*/ SUN4M_INT_SBUS(2) | SUN4M_INT_VME(2),
/*6*/ SUN4M_INT_ETHERNET,
/*7*/ SUN4M_INT_SBUS(3) | SUN4M_INT_VME(3),
/*8*/ SUN4M_INT_VIDEO,
/*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR,
/*10*/ SUN4M_INT_REALTIME,
/*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY,
/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS,
/*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO,
/*14*/ SUN4M_INT_E14,
/*15*/ SUN4M_INT_ERROR,
};
/* We assume the caller has disabled local interrupts when these are called, static void sun4m_shutdown_irq(struct irq_data *data)
* or else very bizarre behavior will result.
*/
static void sun4m_disable_pil_irq(unsigned int pil)
{ {
sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); sun4m_mask_irq(data);
irq_unlink(data->irq);
} }
static void sun4m_enable_pil_irq(unsigned int pil) static struct irq_chip sun4m_irq = {
.name = "sun4m",
.irq_startup = sun4m_startup_irq,
.irq_shutdown = sun4m_shutdown_irq,
.irq_mask = sun4m_mask_irq,
.irq_unmask = sun4m_unmask_irq,
};
static unsigned int sun4m_build_device_irq(struct platform_device *op,
unsigned int real_irq)
{ {
sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); struct sun4m_handler_data *handler_data;
unsigned int irq;
unsigned int pil;
if (real_irq >= OBP_INT_LEVEL_VME) {
prom_printf("Bogus sun4m IRQ %u\n", real_irq);
prom_halt();
}
pil = (real_irq & 0xf);
irq = irq_alloc(real_irq, pil);
if (irq == 0)
goto out;
handler_data = irq_get_handler_data(irq);
if (unlikely(handler_data))
goto out;
handler_data = kzalloc(sizeof(struct sun4m_handler_data), GFP_ATOMIC);
if (unlikely(!handler_data)) {
prom_printf("IRQ: kzalloc(sun4m_handler_data) failed.\n");
prom_halt();
}
handler_data->mask = sun4m_imask[real_irq];
handler_data->percpu = real_irq < OBP_INT_LEVEL_ONBOARD;
irq_set_chip_and_handler_name(irq, &sun4m_irq,
handle_level_irq, "level");
irq_set_handler_data(irq, handler_data);
out:
return irq;
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void sun4m_send_ipi(int cpu, int level) static void sun4m_send_ipi(int cpu, int level)
{ {
unsigned long mask = sun4m_get_irqmask(level); sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
} }
static void sun4m_clear_ipi(int cpu, int level) static void sun4m_clear_ipi(int cpu, int level)
{ {
unsigned long mask = sun4m_get_irqmask(level); sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear);
sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
} }
static void sun4m_set_udt(int cpu) static void sun4m_set_udt(int cpu)
...@@ -343,7 +353,15 @@ void sun4m_nmi(struct pt_regs *regs) ...@@ -343,7 +353,15 @@ void sun4m_nmi(struct pt_regs *regs)
prom_halt(); prom_halt();
} }
/* Exported for sun4m_smp.c */ void sun4m_unmask_profile_irq(void)
{
unsigned long flags;
local_irq_save(flags);
sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear);
local_irq_restore(flags);
}
void sun4m_clear_profile_irq(int cpu) void sun4m_clear_profile_irq(int cpu)
{ {
sbus_readl(&timers_percpu[cpu]->l14_limit); sbus_readl(&timers_percpu[cpu]->l14_limit);
...@@ -358,6 +376,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) ...@@ -358,6 +376,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
{ {
struct device_node *dp = of_find_node_by_name(NULL, "counter"); struct device_node *dp = of_find_node_by_name(NULL, "counter");
int i, err, len, num_cpu_timers; int i, err, len, num_cpu_timers;
unsigned int irq;
const u32 *addr; const u32 *addr;
if (!dp) { if (!dp) {
...@@ -384,8 +403,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) ...@@ -384,8 +403,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
master_l10_counter = &timers_global->l10_count; master_l10_counter = &timers_global->l10_count;
err = request_irq(SUN4M_TIMER_IRQ, counter_fn, irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
(IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
if (err) { if (err) {
printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
err); err);
...@@ -452,14 +472,11 @@ void __init sun4m_init_IRQ(void) ...@@ -452,14 +472,11 @@ void __init sun4m_init_IRQ(void)
if (num_cpu_iregs == 4) if (num_cpu_iregs == 4)
sbus_writel(0, &sun4m_irq_global->interrupt_target); sbus_writel(0, &sun4m_irq_global->interrupt_target);
BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
sparc_irq_config.init_timers = sun4m_init_timers; sparc_irq_config.init_timers = sun4m_init_timers;
sparc_irq_config.build_device_irq = sun4m_build_device_irq;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include "irq.h" #include "irq.h"
#include "kernel.h" #include "kernel.h"
#define IRQ_IPI_SINGLE 12
#define IRQ_IPI_MASK 13
#define IRQ_IPI_RESCHED 14
#define IRQ_CROSS_CALL 15 #define IRQ_CROSS_CALL 15
static inline unsigned long static inline unsigned long
...@@ -26,6 +29,7 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) ...@@ -26,6 +29,7 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
return val; return val;
} }
static void smp4m_ipi_init(void);
static void smp_setup_percpu_timer(void); static void smp_setup_percpu_timer(void);
void __cpuinit smp4m_callin(void) void __cpuinit smp4m_callin(void)
...@@ -59,8 +63,6 @@ void __cpuinit smp4m_callin(void) ...@@ -59,8 +63,6 @@ void __cpuinit smp4m_callin(void)
local_flush_cache_all(); local_flush_cache_all();
local_flush_tlb_all(); local_flush_tlb_all();
cpu_probe();
/* Fix idle thread fields. */ /* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t" __asm__ __volatile__("ld [%0], %%g6\n\t"
: : "r" (&current_set[cpuid]) : : "r" (&current_set[cpuid])
...@@ -70,7 +72,7 @@ void __cpuinit smp4m_callin(void) ...@@ -70,7 +72,7 @@ void __cpuinit smp4m_callin(void)
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
while (!cpu_isset(cpuid, smp_commenced_mask)) while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
mb(); mb();
local_irq_enable(); local_irq_enable();
...@@ -83,6 +85,7 @@ void __cpuinit smp4m_callin(void) ...@@ -83,6 +85,7 @@ void __cpuinit smp4m_callin(void)
*/ */
void __init smp4m_boot_cpus(void) void __init smp4m_boot_cpus(void)
{ {
smp4m_ipi_init();
smp_setup_percpu_timer(); smp_setup_percpu_timer();
local_flush_cache_all(); local_flush_cache_all();
} }
...@@ -150,18 +153,25 @@ void __init smp4m_smp_done(void) ...@@ -150,18 +153,25 @@ void __init smp4m_smp_done(void)
/* Ok, they are spinning and ready to go. */ /* Ok, they are spinning and ready to go. */
} }
/* At each hardware IRQ, we get this called to forward IRQ reception
* to the next processor. The caller must disable the IRQ level being /* Initialize IPIs on the SUN4M SMP machine */
* serviced globally so that there are no double interrupts received. static void __init smp4m_ipi_init(void)
* {
* XXX See sparc64 irq.c. }
*/
void smp4m_irq_rotate(int cpu) static void smp4m_ipi_resched(int cpu)
{
set_cpu_int(cpu, IRQ_IPI_RESCHED);
}
static void smp4m_ipi_single(int cpu)
{ {
int next = cpu_data(cpu).next; set_cpu_int(cpu, IRQ_IPI_SINGLE);
}
if (next != cpu) static void smp4m_ipi_mask_one(int cpu)
set_irq_udt(next); {
set_cpu_int(cpu, IRQ_IPI_MASK);
} }
static struct smp_funcall { static struct smp_funcall {
...@@ -199,10 +209,10 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -199,10 +209,10 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
{ {
register int i; register int i;
cpu_clear(smp_processor_id(), mask); cpumask_clear_cpu(smp_processor_id(), &mask);
cpus_and(mask, cpu_online_map, mask); cpumask_and(&mask, cpu_online_mask, &mask);
for (i = 0; i < ncpus; i++) { for (i = 0; i < ncpus; i++) {
if (cpu_isset(i, mask)) { if (cpumask_test_cpu(i, &mask)) {
ccall_info.processors_in[i] = 0; ccall_info.processors_in[i] = 0;
ccall_info.processors_out[i] = 0; ccall_info.processors_out[i] = 0;
set_cpu_int(i, IRQ_CROSS_CALL); set_cpu_int(i, IRQ_CROSS_CALL);
...@@ -218,7 +228,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -218,7 +228,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
i = 0; i = 0;
do { do {
if (!cpu_isset(i, mask)) if (!cpumask_test_cpu(i, &mask))
continue; continue;
while (!ccall_info.processors_in[i]) while (!ccall_info.processors_in[i])
barrier(); barrier();
...@@ -226,7 +236,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, ...@@ -226,7 +236,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
i = 0; i = 0;
do { do {
if (!cpu_isset(i, mask)) if (!cpumask_test_cpu(i, &mask))
continue; continue;
while (!ccall_info.processors_out[i]) while (!ccall_info.processors_out[i])
barrier(); barrier();
...@@ -277,7 +287,7 @@ static void __cpuinit smp_setup_percpu_timer(void) ...@@ -277,7 +287,7 @@ static void __cpuinit smp_setup_percpu_timer(void)
load_profile_irq(cpu, lvl14_resolution); load_profile_irq(cpu, lvl14_resolution);
if (cpu == boot_cpu_id) if (cpu == boot_cpu_id)
enable_pil_irq(14); sun4m_unmask_profile_irq();
} }
static void __init smp4m_blackbox_id(unsigned *addr) static void __init smp4m_blackbox_id(unsigned *addr)
...@@ -306,4 +316,7 @@ void __init sun4m_init_smp(void) ...@@ -306,4 +316,7 @@ void __init sun4m_init_smp(void)
BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, 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);
} }
...@@ -103,9 +103,10 @@ static unsigned long run_on_cpu(unsigned long cpu, ...@@ -103,9 +103,10 @@ static unsigned long run_on_cpu(unsigned long cpu,
unsigned long (*func)(unsigned long), unsigned long (*func)(unsigned long),
unsigned long arg) unsigned long arg)
{ {
cpumask_t old_affinity = current->cpus_allowed; cpumask_t old_affinity;
unsigned long ret; unsigned long ret;
cpumask_copy(&old_affinity, tsk_cpus_allowed(current));
/* should return -EINVAL to userspace */ /* should return -EINVAL to userspace */
if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
return 0; return 0;
......
...@@ -228,14 +228,10 @@ static void __init sbus_time_init(void) ...@@ -228,14 +228,10 @@ static void __init sbus_time_init(void)
void __init time_init(void) void __init time_init(void)
{ {
#ifdef CONFIG_PCI if (pcic_present())
extern void pci_time_init(void);
if (pcic_present()) {
pci_time_init(); pci_time_init();
return; else
} sbus_time_init();
#endif
sbus_time_init();
} }
......
...@@ -237,7 +237,7 @@ static unsigned int us2e_freq_get(unsigned int cpu) ...@@ -237,7 +237,7 @@ static unsigned int us2e_freq_get(unsigned int cpu)
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return 0; return 0;
cpus_allowed = current->cpus_allowed; cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
set_cpus_allowed_ptr(current, cpumask_of(cpu)); set_cpus_allowed_ptr(current, cpumask_of(cpu));
clock_tick = sparc64_get_clock_tick(cpu) / 1000; clock_tick = sparc64_get_clock_tick(cpu) / 1000;
...@@ -258,7 +258,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index) ...@@ -258,7 +258,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index)
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return; return;
cpus_allowed = current->cpus_allowed; cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
set_cpus_allowed_ptr(current, cpumask_of(cpu)); set_cpus_allowed_ptr(current, cpumask_of(cpu));
new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000; new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000;
......
...@@ -85,7 +85,7 @@ static unsigned int us3_freq_get(unsigned int cpu) ...@@ -85,7 +85,7 @@ static unsigned int us3_freq_get(unsigned int cpu)
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return 0; return 0;
cpus_allowed = current->cpus_allowed; cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
set_cpus_allowed_ptr(current, cpumask_of(cpu)); set_cpus_allowed_ptr(current, cpumask_of(cpu));
reg = read_safari_cfg(); reg = read_safari_cfg();
...@@ -105,7 +105,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) ...@@ -105,7 +105,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return; return;
cpus_allowed = current->cpus_allowed; cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current));
set_cpus_allowed_ptr(current, cpumask_of(cpu)); set_cpus_allowed_ptr(current, cpumask_of(cpu));
new_freq = sparc64_get_clock_tick(cpu) / 1000; new_freq = sparc64_get_clock_tick(cpu) / 1000;
......
...@@ -15,7 +15,6 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o ...@@ -15,7 +15,6 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
lib-$(CONFIG_SPARC32) += copy_user.o locks.o lib-$(CONFIG_SPARC32) += copy_user.o locks.o
lib-y += atomic_$(BITS).o lib-y += atomic_$(BITS).o
lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
lib-$(CONFIG_SPARC32) += rwsem_32.o
lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o
......
/*
* Assembly part of rw semaphores.
*
* Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
*/
#include <asm/ptrace.h>
#include <asm/psr.h>
.section .sched.text, "ax"
.align 4
.globl ___down_read
___down_read:
rd %psr, %g3
nop
nop
nop
or %g3, PSR_PIL, %g7
wr %g7, 0, %psr
nop
nop
nop
#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
ld [%g1], %g7
sub %g7, 1, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
sub %g7, 1, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
add %g7, 1, %g7
nop
nop
subcc %g7, 1, %g7
bneg 3f
nop
2: jmpl %o7, %g0
mov %g4, %o7
3: save %sp, -64, %sp
mov %g1, %l1
mov %g4, %l4
bcs 4f
mov %g5, %l5
call down_read_failed
mov %l1, %o0
mov %l1, %g1
mov %l4, %g4
ba ___down_read
restore %l5, %g0, %g5
4: call down_read_failed_biased
mov %l1, %o0
mov %l1, %g1
mov %l4, %g4
ba 2b
restore %l5, %g0, %g5
.globl ___down_write
___down_write:
rd %psr, %g3
nop
nop
nop
or %g3, PSR_PIL, %g7
wr %g7, 0, %psr
sethi %hi(0x01000000), %g2
nop
nop
#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
ld [%g1], %g7
sub %g7, %g2, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
sub %g7, %g2, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
add %g7, %g2, %g7
nop
nop
subcc %g7, %g2, %g7
bne 3f
nop
2: jmpl %o7, %g0
mov %g4, %o7
3: save %sp, -64, %sp
mov %g1, %l1
mov %g4, %l4
bcs 4f
mov %g5, %l5
call down_write_failed
mov %l1, %o0
mov %l1, %g1
mov %l4, %g4
ba ___down_write
restore %l5, %g0, %g5
4: call down_write_failed_biased
mov %l1, %o0
mov %l1, %g1
mov %l4, %g4
ba 2b
restore %l5, %g0, %g5
.text
.globl ___up_read
___up_read:
rd %psr, %g3
nop
nop
nop
or %g3, PSR_PIL, %g7
wr %g7, 0, %psr
nop
nop
nop
#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
ld [%g1], %g7
add %g7, 1, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
add %g7, 1, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
nop
nop
nop
cmp %g7, 0
be 3f
nop
2: jmpl %o7, %g0
mov %g4, %o7
3: save %sp, -64, %sp
mov %g1, %l1
mov %g4, %l4
mov %g5, %l5
clr %o1
call __rwsem_wake
mov %l1, %o0
mov %l1, %g1
mov %l4, %g4
ba 2b
restore %l5, %g0, %g5
.globl ___up_write
___up_write:
rd %psr, %g3
nop
nop
nop
or %g3, PSR_PIL, %g7
wr %g7, 0, %psr
sethi %hi(0x01000000), %g2
nop
nop
#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
ld [%g1], %g7
add %g7, %g2, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
add %g7, %g2, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
sub %g7, %g2, %g7
nop
nop
addcc %g7, %g2, %g7
bcs 3f
nop
2: jmpl %o7, %g0
mov %g4, %o7
3: save %sp, -64, %sp
mov %g1, %l1
mov %g4, %l4
mov %g5, %l5
mov %g7, %o1
call __rwsem_wake
mov %l1, %o0
mov %l1, %g1
mov %l4, %g4
ba 2b
restore %l5, %g0, %g5
...@@ -862,7 +862,7 @@ static void init_node_masks_nonnuma(void) ...@@ -862,7 +862,7 @@ static void init_node_masks_nonnuma(void)
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
numa_cpu_lookup_table[i] = 0; numa_cpu_lookup_table[i] = 0;
numa_cpumask_lookup_table[0] = CPU_MASK_ALL; cpumask_setall(&numa_cpumask_lookup_table[0]);
} }
#ifdef CONFIG_NEED_MULTIPLE_NODES #ifdef CONFIG_NEED_MULTIPLE_NODES
...@@ -1080,7 +1080,7 @@ static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md, ...@@ -1080,7 +1080,7 @@ static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md,
{ {
u64 arc; u64 arc;
cpus_clear(*mask); cpumask_clear(mask);
mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) { mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) {
u64 target = mdesc_arc_target(md, arc); u64 target = mdesc_arc_target(md, arc);
...@@ -1091,7 +1091,7 @@ static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md, ...@@ -1091,7 +1091,7 @@ static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md,
continue; continue;
id = mdesc_get_property(md, target, "id", NULL); id = mdesc_get_property(md, target, "id", NULL);
if (*id < nr_cpu_ids) if (*id < nr_cpu_ids)
cpu_set(*id, *mask); cpumask_set_cpu(*id, mask);
} }
} }
...@@ -1153,13 +1153,13 @@ static int __init numa_parse_mdesc_group(struct mdesc_handle *md, u64 grp, ...@@ -1153,13 +1153,13 @@ static int __init numa_parse_mdesc_group(struct mdesc_handle *md, u64 grp,
numa_parse_mdesc_group_cpus(md, grp, &mask); numa_parse_mdesc_group_cpus(md, grp, &mask);
for_each_cpu_mask(cpu, mask) for_each_cpu(cpu, &mask)
numa_cpu_lookup_table[cpu] = index; numa_cpu_lookup_table[cpu] = index;
numa_cpumask_lookup_table[index] = mask; cpumask_copy(&numa_cpumask_lookup_table[index], &mask);
if (numa_debug) { if (numa_debug) {
printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index); printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index);
for_each_cpu_mask(cpu, mask) for_each_cpu(cpu, &mask)
printk("%d ", cpu); printk("%d ", cpu);
printk("]\n"); printk("]\n");
} }
...@@ -1218,7 +1218,7 @@ static int __init numa_parse_jbus(void) ...@@ -1218,7 +1218,7 @@ static int __init numa_parse_jbus(void)
index = 0; index = 0;
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
numa_cpu_lookup_table[cpu] = index; numa_cpu_lookup_table[cpu] = index;
numa_cpumask_lookup_table[index] = cpumask_of_cpu(cpu); cpumask_copy(&numa_cpumask_lookup_table[index], cpumask_of(cpu));
node_masks[index].mask = ~((1UL << 36UL) - 1UL); node_masks[index].mask = ~((1UL << 36UL) - 1UL);
node_masks[index].val = cpu << 36UL; node_masks[index].val = cpu << 36UL;
......
...@@ -827,11 +827,6 @@ config SCHED_AUTOGROUP ...@@ -827,11 +827,6 @@ config SCHED_AUTOGROUP
desktop applications. Task group autogeneration is currently based desktop applications. Task group autogeneration is currently based
upon task session. upon task session.
config SCHED_TTWU_QUEUE
bool
depends on !SPARC32
default y
config MM_OWNER config MM_OWNER
bool bool
......
...@@ -2564,7 +2564,7 @@ static void ttwu_queue(struct task_struct *p, int cpu) ...@@ -2564,7 +2564,7 @@ static void ttwu_queue(struct task_struct *p, int cpu)
{ {
struct rq *rq = cpu_rq(cpu); struct rq *rq = cpu_rq(cpu);
#if defined(CONFIG_SMP) && defined(CONFIG_SCHED_TTWU_QUEUE) #if defined(CONFIG_SMP)
if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) { if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) {
ttwu_queue_remote(p, cpu); ttwu_queue_remote(p, cpu);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment