Commit 2cb54cac authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_work
parents cd03e0b9 7a3182b1
...@@ -487,10 +487,26 @@ CONFIG_VIOPATH=y ...@@ -487,10 +487,26 @@ CONFIG_VIOPATH=y
# #
CONFIG_VT=y CONFIG_VT=y
CONFIG_VT_CONSOLE=y CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_CS is not set
# CONFIG_SERIAL_8250_EXTENDED is not set
# CONFIG_SERIAL_8250_MANY_PORTS is not set
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
# CONFIG_SERIAL_8250_MULTIPORT is not set
# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256 CONFIG_UNIX98_PTY_COUNT=256
CONFIG_HVC_CONSOLE=y CONFIG_HVC_CONSOLE=y
......
...@@ -123,7 +123,8 @@ static void i8259_unmask_irq(unsigned int irq_nr) ...@@ -123,7 +123,8 @@ static void i8259_unmask_irq(unsigned int irq_nr)
static void i8259_end_irq(unsigned int irq) static void i8259_end_irq(unsigned int irq)
{ {
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
irq_desc[irq].action)
i8259_unmask_irq(irq); i8259_unmask_irq(irq);
} }
......
...@@ -169,10 +169,8 @@ setup_irq(unsigned int irq, struct irqaction * new) ...@@ -169,10 +169,8 @@ setup_irq(unsigned int irq, struct irqaction * new)
inline void synchronize_irq(unsigned int irq) inline void synchronize_irq(unsigned int irq)
{ {
while (irq_desc[irq].status & IRQ_INPROGRESS) { while (irq_desc[irq].status & IRQ_INPROGRESS)
barrier();
cpu_relax(); cpu_relax();
}
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -500,7 +498,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -500,7 +498,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
* use the action we have. * use the action we have.
*/ */
action = NULL; action = NULL;
if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
action = desc->action; action = desc->action;
if (!action || !action->handler) { if (!action || !action->handler) {
ppc_spurious_interrupts++; ppc_spurious_interrupts++;
...@@ -527,10 +525,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -527,10 +525,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
a different instance of this same irq, the other processor a different instance of this same irq, the other processor
will take care of it. will take care of it.
*/ */
if (!action) if (unlikely(!action))
goto out; goto out;
/* /*
* Edge triggered interrupts need to remember * Edge triggered interrupts need to remember
* pending events. * pending events.
...@@ -546,12 +543,12 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -546,12 +543,12 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
handle_irq_event(irq, regs, action); handle_irq_event(irq, regs, action);
spin_lock(&desc->lock); spin_lock(&desc->lock);
if (!(desc->status & IRQ_PENDING)) if (likely(!(desc->status & IRQ_PENDING)))
break; break;
desc->status &= ~IRQ_PENDING; desc->status &= ~IRQ_PENDING;
} }
desc->status &= ~IRQ_INPROGRESS;
out: out:
desc->status &= ~IRQ_INPROGRESS;
/* /*
* The ->end() handler has to deal with interrupts which got * The ->end() handler has to deal with interrupts which got
* disabled while the handler was running. * disabled while the handler was running.
...@@ -567,7 +564,6 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -567,7 +564,6 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int do_IRQ(struct pt_regs *regs) int do_IRQ(struct pt_regs *regs)
{ {
int cpu = smp_processor_id();
int irq, first = 1; int irq, first = 1;
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
struct paca_struct *lpaca; struct paca_struct *lpaca;
...@@ -615,9 +611,6 @@ int do_IRQ(struct pt_regs *regs) ...@@ -615,9 +611,6 @@ int do_IRQ(struct pt_regs *regs)
} }
#endif #endif
if (softirq_pending(cpu))
do_softirq();
return 1; /* lets ret_from_int know we can do checks */ return 1; /* lets ret_from_int know we can do checks */
} }
......
...@@ -683,8 +683,8 @@ _GLOBAL(sys_call_table32) ...@@ -683,8 +683,8 @@ _GLOBAL(sys_call_table32)
.llong .sys32_rt_sigtimedwait .llong .sys32_rt_sigtimedwait
.llong .sys32_rt_sigqueueinfo .llong .sys32_rt_sigqueueinfo
.llong .sys32_rt_sigsuspend .llong .sys32_rt_sigsuspend
.llong .sys32_pread .llong .sys32_pread64
.llong .sys32_pwrite /* 180 */ .llong .sys32_pwrite64 /* 180 */
.llong .sys_chown .llong .sys_chown
.llong .sys_getcwd .llong .sys_getcwd
.llong .sys_capget .llong .sys_capget
...@@ -695,7 +695,7 @@ _GLOBAL(sys_call_table32) ...@@ -695,7 +695,7 @@ _GLOBAL(sys_call_table32)
.llong .sys_ni_syscall /* streams2 */ .llong .sys_ni_syscall /* streams2 */
.llong .sys32_vfork .llong .sys32_vfork
.llong .sys32_getrlimit /* 190 */ .llong .sys32_getrlimit /* 190 */
.llong .sys_ni_syscall /* 191 */ /* Unused */ .llong .sys32_readahead
.llong .sys_ni_syscall /* 192 - reserved - mmap2 */ .llong .sys_ni_syscall /* 192 - reserved - mmap2 */
.llong .sys32_truncate64 /* 193 - truncate64 */ .llong .sys32_truncate64 /* 193 - truncate64 */
.llong .sys32_ftruncate64 /* 194 - ftruncate64 */ .llong .sys32_ftruncate64 /* 194 - ftruncate64 */
...@@ -726,11 +726,12 @@ _GLOBAL(sys_call_table32) ...@@ -726,11 +726,12 @@ _GLOBAL(sys_call_table32)
.llong .sys_lremovexattr .llong .sys_lremovexattr
.llong .sys_fremovexattr /* 220 */ .llong .sys_fremovexattr /* 220 */
.llong .sys_futex .llong .sys_futex
.llong .sys_ni_syscall /* reserved for tux */
.llong .sys32_sched_setaffinity .llong .sys32_sched_setaffinity
.llong .sys32_sched_getaffinity .llong .sys32_sched_getaffinity
.llong .sys_ni_syscall /* reserved for security */
.llong .sys_ni_syscall /* 225 - reserved for tux */
.rept NR_syscalls-224 .rept NR_syscalls-225
.llong .sys_ni_syscall .llong .sys_ni_syscall
.endr .endr
#endif #endif
...@@ -928,6 +929,7 @@ _GLOBAL(sys_call_table) ...@@ -928,6 +929,7 @@ _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* streams2 */ .llong .sys_ni_syscall /* streams2 */
.llong .sys_vfork .llong .sys_vfork
.llong .sys_getrlimit /* 190 */ .llong .sys_getrlimit /* 190 */
.llong .sys_readahead
.llong .sys_ni_syscall /* 191 */ /* Unused */ .llong .sys_ni_syscall /* 191 */ /* Unused */
.llong .sys_ni_syscall /* 192 - reserved - mmap2 */ .llong .sys_ni_syscall /* 192 - reserved - mmap2 */
.llong .sys_ni_syscall /* 193 - reserved - truncate64 */ .llong .sys_ni_syscall /* 193 - reserved - truncate64 */
...@@ -959,10 +961,11 @@ _GLOBAL(sys_call_table) ...@@ -959,10 +961,11 @@ _GLOBAL(sys_call_table)
.llong .sys_lremovexattr .llong .sys_lremovexattr
.llong .sys_fremovexattr /* 220 */ .llong .sys_fremovexattr /* 220 */
.llong .sys_futex .llong .sys_futex
.llong .sys_ni_syscall /* reserved for tux */
.llong .sys_sched_setaffinity .llong .sys_sched_setaffinity
.llong .sys_sched_getaffinity .llong .sys_sched_getaffinity
.llong .sys_ni_syscall /* reserved for security */
.llong .sys_ni_syscall /* reserved for tux */
.rept NR_syscalls-224 .rept NR_syscalls-225
.llong .sys_ni_syscall .llong .sys_ni_syscall
.endr .endr
...@@ -576,7 +576,7 @@ void openpic_request_IPIs(void) ...@@ -576,7 +576,7 @@ void openpic_request_IPIs(void)
*/ */
static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED; static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED;
void __init do_openpic_setup_cpu(void) void __devinit do_openpic_setup_cpu(void)
{ {
#ifdef CONFIG_IRQ_ALL_CPUS #ifdef CONFIG_IRQ_ALL_CPUS
int i; int i;
......
...@@ -155,7 +155,7 @@ long plpar_pte_protect(unsigned long flags, ...@@ -155,7 +155,7 @@ long plpar_pte_protect(unsigned long flags,
unsigned long ptex, unsigned long ptex,
unsigned long avpn) unsigned long avpn)
{ {
return plpar_hcall_norets(H_PROTECT, flags, ptex); return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
} }
long plpar_tce_get(unsigned long liobn, long plpar_tce_get(unsigned long liobn,
...@@ -552,6 +552,7 @@ static long pSeries_lpar_insert_hpte(unsigned long hpte_group, ...@@ -552,6 +552,7 @@ static long pSeries_lpar_insert_hpte(unsigned long hpte_group,
int secondary, unsigned long hpteflags, int secondary, unsigned long hpteflags,
int bolted, int large) int bolted, int large)
{ {
/* XXX fix for large page */
unsigned long avpn = vpn >> 11; unsigned long avpn = vpn >> 11;
unsigned long arpn = physRpn_to_absRpn(prpn); unsigned long arpn = physRpn_to_absRpn(prpn);
unsigned long lpar_rc; unsigned long lpar_rc;
...@@ -651,11 +652,10 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp, ...@@ -651,11 +652,10 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long va, int large) unsigned long va, int large)
{ {
unsigned long lpar_rc; unsigned long lpar_rc;
unsigned long flags; unsigned long flags = (newpp & 7) | H_AVPN;
flags = (newpp & 7) | H_AVPN; unsigned long avpn = va >> 23;
unsigned long vpn = va >> PAGE_SHIFT;
lpar_rc = plpar_pte_protect(flags, slot, (vpn >> 4) & ~0x7fUL); lpar_rc = plpar_pte_protect(flags, slot, (avpn << 7));
if (lpar_rc == H_Not_Found) { if (lpar_rc == H_Not_Found) {
udbg_printf("updatepp missed\n"); udbg_printf("updatepp missed\n");
...@@ -748,18 +748,11 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, ...@@ -748,18 +748,11 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
int large, int local) int large, int local)
{ {
unsigned long vpn, avpn; unsigned long avpn = va >> 23;
unsigned long lpar_rc; unsigned long lpar_rc;
unsigned long dummy1, dummy2; unsigned long dummy1, dummy2;
if (large) lpar_rc = plpar_pte_remove(H_AVPN, slot, (avpn << 7), &dummy1,
vpn = va >> LARGE_PAGE_SHIFT;
else
vpn = va >> PAGE_SHIFT;
avpn = vpn >> 11;
lpar_rc = plpar_pte_remove(H_AVPN, slot, (vpn >> 4) & ~0x7fUL, &dummy1,
&dummy2); &dummy2);
if (lpar_rc == H_Not_Found) { if (lpar_rc == H_Not_Found) {
......
...@@ -144,6 +144,7 @@ static interpret_func interpret_root_props; ...@@ -144,6 +144,7 @@ static interpret_func interpret_root_props;
#define FB_MAX 8 #define FB_MAX 8
#endif #endif
static int ppc64_is_smp;
struct prom_t prom = { struct prom_t prom = {
0, /* entry */ 0, /* entry */
......
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/delay.h> #include <linux/delay.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/cache.h> #include <linux/cache.h>
...@@ -53,22 +51,19 @@ ...@@ -53,22 +51,19 @@
#include <asm/machdep.h> #include <asm/machdep.h>
int smp_threads_ready = 0; int smp_threads_ready = 0;
volatile int smp_commenced = 0;
int smp_tb_synchronized = 0;
spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED; spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
unsigned long cache_decay_ticks; unsigned long cache_decay_ticks;
static int max_cpus __initdata = NR_CPUS;
/* initialised so it doesnt end up in bss */ /* initialised so it doesnt end up in bss */
unsigned long cpu_online_map = 0; unsigned long cpu_online_map = 0;
int boot_cpuid = 0; int boot_cpuid = 0;
int ppc64_is_smp = 0;
volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; static struct smp_ops_t *smp_ops;
volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char stab_array[]; extern unsigned char stab_array[];
int start_secondary(void *);
extern int cpu_idle(void *unused); extern int cpu_idle(void *unused);
void smp_call_function_interrupt(void); void smp_call_function_interrupt(void);
void smp_message_pass(int target, int msg, unsigned long data, int wait); void smp_message_pass(int target, int msg, unsigned long data, int wait);
...@@ -86,7 +81,7 @@ struct xics_ipi_struct { ...@@ -86,7 +81,7 @@ struct xics_ipi_struct {
struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
#define smp_message_pass(t,m,d,w) ppc_md.smp_message_pass((t),(m),(d),(w)) #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w))
static inline void set_tb(unsigned int upper, unsigned int lower) static inline void set_tb(unsigned int upper, unsigned int lower)
{ {
...@@ -106,7 +101,6 @@ void iSeries_smp_message_recv( struct pt_regs * regs ) ...@@ -106,7 +101,6 @@ void iSeries_smp_message_recv( struct pt_regs * regs )
for ( msg = 0; msg < 4; ++msg ) for ( msg = 0; msg < 4; ++msg )
if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) ) if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )
smp_message_recv( msg, regs ); smp_message_recv( msg, regs );
} }
static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait) static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait)
...@@ -127,6 +121,7 @@ static void smp_iSeries_message_pass(int target, int msg, unsigned long data, in ...@@ -127,6 +121,7 @@ static void smp_iSeries_message_pass(int target, int msg, unsigned long data, in
} }
} }
#ifdef CONFIG_PPC_ISERIES
static int smp_iSeries_numProcs(void) static int smp_iSeries_numProcs(void)
{ {
unsigned np, i; unsigned np, i;
...@@ -141,24 +136,23 @@ static int smp_iSeries_numProcs(void) ...@@ -141,24 +136,23 @@ static int smp_iSeries_numProcs(void)
} }
return np; return np;
} }
#endif
static void smp_iSeries_probe(void) static int smp_iSeries_probe(void)
{ {
unsigned i; unsigned i;
unsigned np; unsigned np = 0;
struct ItLpPaca * lpPaca; struct ItLpPaca *lpPaca;
np = 0;
for (i=0; i < MAX_PACAS; ++i) { for (i=0; i < MAX_PACAS; ++i) {
lpPaca = paca[i].xLpPacaPtr; lpPaca = paca[i].xLpPacaPtr;
if ( lpPaca->xDynProcStatus < 2 ) { if (lpPaca->xDynProcStatus < 2) {
paca[i].active = 1; paca[i].active = 1;
++np; ++np;
paca[i].next_jiffy_update_tb = paca[0].next_jiffy_update_tb;
} }
} }
smp_tb_synchronized = 1; return np;
} }
static void smp_iSeries_kick_cpu(int nr) static void smp_iSeries_kick_cpu(int nr)
...@@ -194,10 +188,11 @@ static void smp_iSeries_setup_cpu(int nr) ...@@ -194,10 +188,11 @@ static void smp_iSeries_setup_cpu(int nr)
/* This is called very early. */ /* This is called very early. */
void smp_init_iSeries(void) void smp_init_iSeries(void)
{ {
ppc_md.smp_message_pass = smp_iSeries_message_pass; smp_ops = &ppc_md.smp_ops;
ppc_md.smp_probe = smp_iSeries_probe; smp_ops->message_pass = smp_iSeries_message_pass;
ppc_md.smp_kick_cpu = smp_iSeries_kick_cpu; smp_ops->probe = smp_iSeries_probe;
ppc_md.smp_setup_cpu = smp_iSeries_setup_cpu; smp_ops->kick_cpu = smp_iSeries_kick_cpu;
smp_ops->setup_cpu = smp_iSeries_setup_cpu;
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#warning fix for iseries #warning fix for iseries
naca->processorCount = smp_iSeries_numProcs(); naca->processorCount = smp_iSeries_numProcs();
...@@ -229,10 +224,20 @@ smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) ...@@ -229,10 +224,20 @@ smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
} }
} }
static void smp_chrp_probe(void) static int smp_chrp_probe(void)
{ {
if (ppc64_is_smp) int i;
int nr_cpus = 0;
for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i))
nr_cpus++;
}
if (nr_cpus > 1)
openpic_request_IPIs(); openpic_request_IPIs();
return nr_cpus;
} }
static void static void
...@@ -252,78 +257,32 @@ smp_kick_cpu(int nr) ...@@ -252,78 +257,32 @@ smp_kick_cpu(int nr)
/* The processor is currently spinning, waiting /* The processor is currently spinning, waiting
* for the xProcStart field to become non-zero * for the xProcStart field to become non-zero
* After we set xProcStart, the processor will * After we set xProcStart, the processor will
* continue on to secondary_start in iSeries_head.S * continue on to secondary_start
*/ */
paca[nr].xProcStart = 1; paca[nr].xProcStart = 1;
} }
extern struct gettimeofday_struct do_gtod; static void smp_space_timers(unsigned int max_cpus)
static void smp_space_timers()
{ {
int i; int i;
unsigned long offset = tb_ticks_per_jiffy / NR_CPUS; unsigned long offset = tb_ticks_per_jiffy / max_cpus;
unsigned long previous_tb = paca[boot_cpuid].next_jiffy_update_tb;
for (i = 1; i < NR_CPUS; ++i) for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i) && i != boot_cpuid) {
paca[i].next_jiffy_update_tb = paca[i].next_jiffy_update_tb =
paca[i-1].next_jiffy_update_tb + offset; previous_tb + offset;
} previous_tb = paca[i].next_jiffy_update_tb;
static void
smp_chrp_setup_cpu(int cpu_nr)
{
static atomic_t ready = ATOMIC_INIT(1);
static volatile int frozen = 0;
if (naca->platform == PLATFORM_PSERIES_LPAR) {
/* timebases already synced under the hypervisor. */
paca[cpu_nr].next_jiffy_update_tb = tb_last_stamp = get_tb();
if (cpu_nr == boot_cpuid) {
do_gtod.tb_orig_stamp = tb_last_stamp;
/* Should update do_gtod.stamp_xsec.
* For now we leave it which means the time can be some
* number of msecs off until someone does a settimeofday()
*/
}
smp_tb_synchronized = 1;
} else {
if (cpu_nr == boot_cpuid) {
/* wait for all the others */
while (atomic_read(&ready) < num_online_cpus())
barrier();
atomic_set(&ready, 1);
/* freeze the timebase */
rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
mb();
frozen = 1;
set_tb(0, 0);
paca[boot_cpuid].next_jiffy_update_tb = 0;
smp_space_timers();
while (atomic_read(&ready) < num_online_cpus())
barrier();
/* thaw the timebase again */
rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
mb();
frozen = 0;
tb_last_stamp = get_tb();
do_gtod.tb_orig_stamp = tb_last_stamp;
smp_tb_synchronized = 1;
} else {
atomic_inc(&ready);
while (!frozen)
barrier();
set_tb(0, 0);
mb();
atomic_inc(&ready);
while (frozen)
barrier();
} }
} }
}
static void __devinit pSeries_setup_cpu(int cpu)
{
if (OpenPIC_Addr) { if (OpenPIC_Addr) {
do_openpic_setup_cpu(); do_openpic_setup_cpu();
} else { } else {
if (cpu_nr != boot_cpuid) if (cpu != boot_cpuid)
xics_setup_cpu(); xics_setup_cpu();
} }
} }
...@@ -347,26 +306,65 @@ smp_xics_message_pass(int target, int msg, unsigned long data, int wait) ...@@ -347,26 +306,65 @@ smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
} }
} }
static void smp_xics_probe(void) static int smp_xics_probe(void)
{
int i;
int nr_cpus = 0;
for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i))
nr_cpus++;
}
return nr_cpus;
}
static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
static unsigned long timebase = 0;
static void __devinit pSeries_give_timebase(void)
{
spin_lock(&timebase_lock);
rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
timebase = get_tb();
spin_unlock(&timebase_lock);
while (timebase)
barrier();
rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
}
static void __devinit pSeries_take_timebase(void)
{ {
while (!timebase)
barrier();
spin_lock(&timebase_lock);
set_tb(timebase, timebase >> 32);
timebase = 0;
spin_unlock(&timebase_lock);
} }
/* This is called very early */ /* This is called very early */
void smp_init_pSeries(void) void __init smp_init_pSeries(void)
{ {
if(naca->interrupt_controller == IC_OPEN_PIC) { smp_ops = &ppc_md.smp_ops;
ppc_md.smp_message_pass = smp_openpic_message_pass;
ppc_md.smp_probe = smp_chrp_probe; if (naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.smp_kick_cpu = smp_kick_cpu; smp_ops->message_pass = smp_openpic_message_pass;
ppc_md.smp_setup_cpu = smp_chrp_setup_cpu; smp_ops->probe = smp_chrp_probe;
} else { } else {
ppc_md.smp_message_pass = smp_xics_message_pass; smp_ops->message_pass = smp_xics_message_pass;
ppc_md.smp_probe = smp_xics_probe; smp_ops->probe = smp_xics_probe;
ppc_md.smp_kick_cpu = smp_kick_cpu; }
ppc_md.smp_setup_cpu = smp_chrp_setup_cpu;
if (naca->platform == PLATFORM_PSERIES) {
smp_ops->give_timebase = pSeries_give_timebase;
smp_ops->take_timebase = pSeries_take_timebase;
} }
}
smp_ops->kick_cpu = smp_kick_cpu;
smp_ops->setup_cpu = pSeries_setup_cpu;
}
void smp_local_timer_interrupt(struct pt_regs * regs) void smp_local_timer_interrupt(struct pt_regs * regs)
{ {
...@@ -470,7 +468,6 @@ static struct call_data_struct { ...@@ -470,7 +468,6 @@ static struct call_data_struct {
*/ */
int smp_call_function (void (*func) (void *info), void *info, int nonatomic, int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
int wait) int wait)
{ {
struct call_data_struct data; struct call_data_struct data;
int ret = -1, cpus = num_online_cpus()-1; int ret = -1, cpus = num_online_cpus()-1;
...@@ -553,38 +550,41 @@ void smp_call_function_interrupt(void) ...@@ -553,38 +550,41 @@ void smp_call_function_interrupt(void)
atomic_inc(&call_data->finished); atomic_inc(&call_data->finished);
} }
extern unsigned long decr_overclock; extern unsigned long decr_overclock;
extern struct gettimeofday_struct do_gtod;
struct thread_struct *current_set[NR_CPUS] = {&init_thread_union, 0}; struct thread_info *current_set[NR_CPUS];
void __init smp_boot_cpus(void) static void __devinit smp_store_cpu_info(int id)
{ {
int i, cpu_nr = 0; paca[id].pvr = _get_PVR();
struct task_struct *p; }
printk("Entering SMP Mode...\n");
smp_store_cpu_info(boot_cpuid); void __init smp_prepare_cpus(unsigned int max_cpus)
cpu_callin_map[boot_cpuid] = 1; {
int i;
/* XXX buggy - Anton */ /* Fixup boot cpu */
current_thread_info()->cpu = 0; smp_store_cpu_info(smp_processor_id());
cpu_callin_map[smp_processor_id()] = 1;
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
paca[i].prof_counter = 1; paca[i].prof_counter = 1;
paca[i].prof_multiplier = 1; paca[i].prof_multiplier = 1;
if (i != boot_cpuid) { if (i != boot_cpuid) {
void *tmp;
/* /*
* the boot cpu segment table is statically * the boot cpu segment table is statically
* initialized to real address 0x5000. The * initialized to real address 0x5000. The
* Other processor's tables are created and * Other processor's tables are created and
* initialized here. * initialized here.
*/ */
paca[i].xStab_data.virt = (unsigned long)&stab_array[PAGE_SIZE * (i-1)]; tmp = &stab_array[PAGE_SIZE * (i-1)];
memset((void *)paca[i].xStab_data.virt, 0, PAGE_SIZE); memset(tmp, 0, PAGE_SIZE);
paca[i].xStab_data.real = __v2a(paca[i].xStab_data.virt); paca[i].xStab_data.virt = (unsigned long)tmp;
paca[i].default_decr = tb_ticks_per_jiffy / decr_overclock; paca[i].xStab_data.real = (unsigned long)__v2a(tmp);
paca[i].default_decr = tb_ticks_per_jiffy /
decr_overclock;
} }
} }
...@@ -593,153 +593,95 @@ void __init smp_boot_cpus(void) ...@@ -593,153 +593,95 @@ void __init smp_boot_cpus(void)
*/ */
cache_decay_ticks = HZ/100; cache_decay_ticks = HZ/100;
ppc_md.smp_probe(); #ifndef CONFIG_PPC_ISERIES
paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb();
for (i = 0; i < NR_CPUS; i++) {
if (paca[i].active)
cpu_nr++;
}
printk("Probe found %d CPUs\n", cpu_nr);
#ifdef CONFIG_ISERIES /*
smp_space_timers(); * Should update do_gtod.stamp_xsec.
* For now we leave it which means the time can be some
* number of msecs off until someone does a settimeofday()
*/
do_gtod.tb_orig_stamp = tb_last_stamp;
#endif #endif
printk("Waiting for %d CPUs\n", cpu_nr-1); max_cpus = smp_ops->probe();
smp_space_timers(max_cpus);
}
for (i = 1 ; i < NR_CPUS; i++) { int __cpu_up(unsigned int cpu)
int c; {
struct pt_regs regs; struct pt_regs regs;
struct task_struct *p;
if (!paca[i].active) int c;
continue;
if (i == boot_cpuid)
continue;
if (num_online_cpus() >= max_cpus)
break;
/* create a process for the processor */ /* create a process for the processor */
/* we don't care about the values in regs since we'll /* only regs.msr is actually used, and 0 is OK for it */
never reschedule the forked task. */
/* We DO care about one bit in the pt_regs we
pass to do_fork. That is the MSR_FP bit in
regs.msr. If that bit is on, then do_fork
(via copy_thread) will call giveup_fpu.
giveup_fpu will get a pointer to our (current's)
last register savearea via current->thread.regs
and using that pointer will turn off the MSR_FP,
MSR_FE0 and MSR_FE1 bits. At this point, this
pointer is pointing to some arbitrary point within
our stack */
memset(&regs, 0, sizeof(struct pt_regs)); memset(&regs, 0, sizeof(struct pt_regs));
p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0); p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
if (IS_ERR(p)) if (IS_ERR(p))
panic("failed fork for CPU %d", i); panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
init_idle(p, i);
init_idle(p, cpu);
unhash_process(p); unhash_process(p);
paca[i].xCurrent = (u64)p; paca[cpu].xCurrent = (u64)p;
current_set[i] = p->thread_info; current_set[cpu] = p->thread_info;
/* wake up cpus */ /* wake up cpus */
ppc_md.smp_kick_cpu(i); smp_ops->kick_cpu(cpu);
/* /*
* wait to see if the cpu made a callin (is actually up). * wait to see if the cpu made a callin (is actually up).
* use this value that I found through experimentation. * use this value that I found through experimentation.
* -- Cort * -- Cort
*/ */
for ( c = 5000; c && !cpu_callin_map[i] ; c-- ) { for (c = 5000; c && !cpu_callin_map[cpu]; c--)
udelay(100); udelay(100);
}
if ( cpu_callin_map[i] ) if (!cpu_callin_map[cpu]) {
{ printk("Processor %u is stuck.\n", cpu);
printk("Processor %d found.\n", i); return -ENOENT;
/* this sync's the decr's -- Cort */
} else {
printk("Processor %d is stuck.\n", i);
}
} }
/* Setup boot cpu last (important) */ printk("Processor %u found.\n", cpu);
ppc_md.smp_setup_cpu(boot_cpuid);
if (num_online_cpus() < 2) { if (smp_ops->give_timebase)
tb_last_stamp = get_tb(); smp_ops->give_timebase();
smp_tb_synchronized = 1; set_bit(cpu, &cpu_online_map);
} return 0;
} }
void __init smp_commence(void) /* Activate a secondary processor. */
int __devinit start_secondary(void *unused)
{ {
/* unsigned int cpu = smp_processor_id();
* Lets the callin's below out of their loop.
*/
PPCDBG(PPCDBG_SMP, "smp_commence: start\n");
wmb();
smp_commenced = 1;
}
void __init smp_callin(void) atomic_inc(&init_mm.mm_count);
{ current->active_mm = &init_mm;
int cpu = smp_processor_id();
smp_store_cpu_info(cpu); smp_store_cpu_info(cpu);
set_dec(paca[cpu].default_decr); set_dec(paca[cpu].default_decr);
set_bit(smp_processor_id(), &cpu_online_map);
smp_mb();
cpu_callin_map[cpu] = 1; cpu_callin_map[cpu] = 1;
ppc_md.smp_setup_cpu(cpu); smp_ops->setup_cpu(cpu);
if (smp_ops->take_timebase)
smp_ops->take_timebase();
while(!smp_commenced) { /* XXX required? */
barrier();
}
local_irq_enable(); local_irq_enable();
}
/* intel needs this */
void __init initialize_secondary(void)
{
}
/* Activate a secondary processor. */
int start_secondary(void *unused)
{
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
smp_callin();
return cpu_idle(NULL); return cpu_idle(NULL);
} }
void __init smp_setup(char *str, int *ints)
{
}
int setup_profiling_timer(unsigned int multiplier) int setup_profiling_timer(unsigned int multiplier)
{ {
return 0; return 0;
} }
/* this function is called for each processor void smp_cpus_done(unsigned int max_cpus)
*/
void __init smp_store_cpu_info(int id)
{ {
paca[id].pvr = _get_PVR(); smp_ops->setup_cpu(boot_cpuid);
}
static int __init maxcpus(char *str) /* XXX fix this, xics currently relies on it - Anton */
{ smp_threads_ready = 1;
get_option(&str, &max_cpus);
return 1;
} }
__setup("maxcpus=", maxcpus);
...@@ -4438,30 +4438,32 @@ asmlinkage int sys32_vm86(u32 a1, u32 a2, u32 a3, u32 a4) ...@@ -4438,30 +4438,32 @@ asmlinkage int sys32_vm86(u32 a1, u32 a2, u32 a3, u32 a4)
return sys_vm86((int)a1, (int)a2, (int)a3, (int)a4); return sys_vm86((int)a1, (int)a2, (int)a3, (int)a4);
} }
extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count,
loff_t pos);
extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count,
loff_t pos);
extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
size_t count, loff_t pos);
extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
size_t count, loff_t pos);
typedef __kernel_ssize_t32 ssize_t32; typedef __kernel_ssize_t32 ssize_t32;
asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf, ssize_t32 sys32_pread64(unsigned int fd, char *ubuf, __kernel_size_t32 count,
__kernel_size_t32 count, u32 reg6, u32 poshi, u32 poslo) u32 reg6, u32 poshi, u32 poslo)
{ {
return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
} }
asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf, ssize_t32 sys32_pwrite64(unsigned int fd, char *ubuf, __kernel_size_t32 count,
__kernel_size_t32 count, u32 reg6 ,u32 poshi, u32 poslo) u32 reg6 ,u32 poshi, u32 poslo)
{ {
return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
} }
extern ssize_t sys_readahead(int fd, loff_t offset, size_t count);
ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
{
return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
}
extern asmlinkage long sys_truncate(const char * path, unsigned long length); extern asmlinkage long sys_truncate(const char * path, unsigned long length);
extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
......
...@@ -293,9 +293,6 @@ int timer_interrupt(struct pt_regs * regs) ...@@ -293,9 +293,6 @@ int timer_interrupt(struct pt_regs * regs)
irq_exit(); irq_exit();
if (softirq_pending(cpu))
do_softirq();
return 1; return 1;
} }
......
...@@ -128,13 +128,12 @@ void ...@@ -128,13 +128,12 @@ void
SystemResetException(struct pt_regs *regs) SystemResetException(struct pt_regs *regs)
{ {
if (fwnmi_active) { if (fwnmi_active) {
char *msg;
unsigned long *r3 = __va(regs->gpr[3]); /* for FWNMI debug */ unsigned long *r3 = __va(regs->gpr[3]); /* for FWNMI debug */
struct rtas_error_log *errlog; struct rtas_error_log *errlog;
msg = "FWNMI is active with save area at %016lx\n"; udbg_printf("FWNMI is active with save area at %016lx\n", r3);
udbg_printf(msg, r3); printk(msg, r3);
errlog = FWNMI_get_errinfo(regs); errlog = FWNMI_get_errinfo(regs);
FWNMI_release_errinfo();
} }
if (debugger) if (debugger)
......
...@@ -373,7 +373,7 @@ xics_init_IRQ( void ) ...@@ -373,7 +373,7 @@ xics_init_IRQ( void )
if (naca->platform == PLATFORM_PSERIES) { if (naca->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
for (i = 0; i < NR_CPUS; ++i) { for (i = 0; i < NR_CPUS; ++i) {
if (!paca[i].active) if (!cpu_possible(i))
continue; continue;
xics_info.per_cpu[i] = xics_info.per_cpu[i] =
__ioremap((ulong)inodes[i].addr, __ioremap((ulong)inodes[i].addr,
......
...@@ -13,30 +13,86 @@ ...@@ -13,30 +13,86 @@
#include <linux/preempt.h> #include <linux/preempt.h>
typedef struct { typedef struct {
unsigned long __softirq_pending; unsigned int __softirq_pending;
unsigned long __syscall_count; unsigned int __syscall_count;
struct task_struct * __ksoftirqd_task; struct task_struct * __ksoftirqd_task;
unsigned long idle_timestamp; unsigned long idle_timestamp;
} ____cacheline_aligned irq_cpustat_t; } ____cacheline_aligned irq_cpustat_t;
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
#define IRQ_OFFSET 64 /*
* We put the hardirq and softirq counter into the preemption
* counter. The bitmask has the following meaning:
*
* - bits 0-7 are the preemption count (max preemption depth: 256)
* - bits 8-15 are the softirq count (max # of softirqs: 256)
* - bits 16-24 are the hardirq count (max # of hardirqs: 512)
*
* - ( bit 26 is the PREEMPT_ACTIVE flag. )
*
* PREEMPT_MASK: 0x000000ff
* SOFTIRQ_MASK: 0x0000ff00
* HARDIRQ_MASK: 0x01ff0000
*/
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
#define HARDIRQ_BITS 9
#define PREEMPT_SHIFT 0
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
#define __HARDIRQ_MASK(x) ((1UL << (x))-1)
#define PREEMPT_MASK (__HARDIRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
#define SOFTIRQ_MASK (__HARDIRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
#define HARDIRQ_MASK (__HARDIRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
/* /*
* Are we in an interrupt context? Either doing bottom half * The hardirq mask has to be large enough to have
* or hardware interrupt processing? * space for potentially all IRQ sources in the system
* nesting on a single CPU:
*/ */
#define in_interrupt() \ #if (1 << HARDIRQ_BITS) < NR_IRQS
((preempt_count() & ~PREEMPT_ACTIVE) >= IRQ_OFFSET) # error HARDIRQ_BITS is too low!
#endif
/*
* Are we doing bottom half or hardware interrupt processing?
* Are we in a softirq context? Interrupt context?
*/
#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
#define in_irq in_interrupt
#define hardirq_trylock() (!in_interrupt()) #define hardirq_trylock() (!in_interrupt())
#define hardirq_endlock() do { } while (0) #define hardirq_endlock() do { } while (0)
#define irq_enter() (preempt_count() += IRQ_OFFSET) #define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
#define irq_exit() (preempt_count() -= IRQ_OFFSET)
#if CONFIG_PREEMPT
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
#define irq_exit() \
do { \
preempt_count() -= IRQ_EXIT_OFFSET; \
if (!in_interrupt() && softirq_pending(smp_processor_id())) \
do_softirq(); \
preempt_enable_no_resched(); \
} while (0)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
# define synchronize_irq(irq) barrier() # define synchronize_irq(irq) barrier()
...@@ -45,4 +101,13 @@ typedef struct { ...@@ -45,4 +101,13 @@ typedef struct {
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#define show_stack(SP) \
do { \
if (SP) \
print_backtrace(SP); \
else \
print_backtrace(_get_SP()); \
} while (0)
#endif /* __ASM_HARDIRQ_H */ #endif /* __ASM_HARDIRQ_H */
...@@ -20,6 +20,17 @@ struct device_node; ...@@ -20,6 +20,17 @@ struct device_node;
struct TceTable; struct TceTable;
struct rtc_time; struct rtc_time;
#ifdef CONFIG_SMP
struct smp_ops_t {
void (*message_pass)(int target, int msg, unsigned long data, int wait);
int (*probe)(void);
void (*kick_cpu)(int nr);
void (*setup_cpu)(int nr);
void (*take_timebase)(void);
void (*give_timebase)(void);
};
#endif
struct machdep_calls { struct machdep_calls {
/* High use functions in the first cachelines, low use functions /* High use functions in the first cachelines, low use functions
* follow. DRENG collect profile data. * follow. DRENG collect profile data.
...@@ -58,14 +69,6 @@ struct machdep_calls { ...@@ -58,14 +69,6 @@ struct machdep_calls {
void (*tce_free_one)(struct TceTable *tbl, void (*tce_free_one)(struct TceTable *tbl,
long tcenum); long tcenum);
void (*smp_message_pass)(int target,
int msg,
unsigned long data,
int wait);
void (*smp_probe)(void);
void (*smp_kick_cpu)(int nr);
void (*smp_setup_cpu)(int nr);
void (*setup_arch)(void); void (*setup_arch)(void);
/* Optional, may be NULL. */ /* Optional, may be NULL. */
void (*setup_residual)(struct seq_file *m, int cpu_id); void (*setup_residual)(struct seq_file *m, int cpu_id);
...@@ -145,6 +148,11 @@ struct machdep_calls { ...@@ -145,6 +148,11 @@ struct machdep_calls {
/* this is for modules, since _machine can be a define -- Cort */ /* this is for modules, since _machine can be a define -- Cort */
int ppc_machine; int ppc_machine;
#ifdef CONFIG_SMP
/* functions for dealing with other cpus */
struct smp_ops_t smp_ops;
#endif /* CONFIG_SMP */
}; };
extern struct machdep_calls ppc_md; extern struct machdep_calls ppc_md;
......
...@@ -22,7 +22,10 @@ extern plat_pg_data_t plat_node_data[]; ...@@ -22,7 +22,10 @@ extern plat_pg_data_t plat_node_data[];
#define MAX_NUMNODES 4 #define MAX_NUMNODES 4
/* XXX grab this from the device tree - Anton */ /* XXX grab this from the device tree - Anton */
#define PHYSADDR_TO_NID(pa) ((pa) >> 36) #define MEMORY_ZONE_BITS 33
#define CPU_SHIFT_BITS 1
#define PHYSADDR_TO_NID(pa) ((pa) >> MEMORY_ZONE_BITS)
#define PLAT_NODE_DATA(n) (&plat_node_data[(n)]) #define PLAT_NODE_DATA(n) (&plat_node_data[(n)])
#define PLAT_NODE_DATA_STARTNR(n) \ #define PLAT_NODE_DATA_STARTNR(n) \
(PLAT_NODE_DATA(n)->gendata.node_start_mapnr) (PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
...@@ -84,7 +87,7 @@ extern plat_pg_data_t plat_node_data[]; ...@@ -84,7 +87,7 @@ extern plat_pg_data_t plat_node_data[];
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
/* XXX grab this from the device tree - Anton */ /* XXX grab this from the device tree - Anton */
#define cputonode(cpu) ((cpu) >> 3) #define cputonode(cpu) ((cpu) >> CPU_SHIFT_BITS)
#define numa_node_id() cputonode(smp_processor_id()) #define numa_node_id() cputonode(smp_processor_id())
......
...@@ -57,6 +57,7 @@ struct rw_semaphore { ...@@ -57,6 +57,7 @@ struct rw_semaphore {
extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
static inline void init_rwsem(struct rw_semaphore *sem) static inline void init_rwsem(struct rw_semaphore *sem)
{ {
...@@ -73,12 +74,26 @@ static inline void init_rwsem(struct rw_semaphore *sem) ...@@ -73,12 +74,26 @@ static inline void init_rwsem(struct rw_semaphore *sem)
*/ */
static inline void __down_read(struct rw_semaphore *sem) static inline void __down_read(struct rw_semaphore *sem)
{ {
if (atomic_inc_return((atomic_t *)(&sem->count)) >= 0) if (atomic_inc_return((atomic_t *)(&sem->count)) > 0)
smp_wmb(); smp_wmb();
else else
rwsem_down_read_failed(sem); rwsem_down_read_failed(sem);
} }
static inline int __down_read_trylock(struct rw_semaphore *sem)
{
int tmp;
while ((tmp = sem->count) >= 0) {
if (tmp == cmpxchg(&sem->count, tmp,
tmp + RWSEM_ACTIVE_READ_BIAS)) {
smp_wmb();
return 1;
}
}
return 0;
}
/* /*
* lock for writing * lock for writing
*/ */
...@@ -94,6 +109,16 @@ static inline void __down_write(struct rw_semaphore *sem) ...@@ -94,6 +109,16 @@ static inline void __down_write(struct rw_semaphore *sem)
rwsem_down_write_failed(sem); rwsem_down_write_failed(sem);
} }
static inline int __down_write_trylock(struct rw_semaphore *sem)
{
int tmp;
tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
RWSEM_ACTIVE_WRITE_BIAS);
smp_wmb();
return tmp == RWSEM_UNLOCKED_VALUE;
}
/* /*
* unlock after reading * unlock after reading
*/ */
...@@ -126,6 +151,19 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) ...@@ -126,6 +151,19 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
atomic_add(delta, (atomic_t *)(&sem->count)); atomic_add(delta, (atomic_t *)(&sem->count));
} }
/*
* downgrade write lock to read lock
*/
static inline void __downgrade_write(struct rw_semaphore *sem)
{
int tmp;
smp_wmb();
tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
if (tmp < 0)
rwsem_downgrade_wake(sem);
}
/* /*
* implement exchange and add functionality * implement exchange and add functionality
*/ */
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
extern unsigned long cpu_online_map; extern unsigned long cpu_online_map;
extern void smp_message_pass(int target, int msg, unsigned long data, int wait); extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
extern void smp_store_cpu_info(int id);
extern void smp_send_tlb_invalidate(int); extern void smp_send_tlb_invalidate(int);
extern void smp_send_xmon_break(int cpu); extern void smp_send_xmon_break(int cpu);
struct pt_regs; struct pt_regs;
......
...@@ -12,24 +12,16 @@ ...@@ -12,24 +12,16 @@
#include <asm/hardirq.h> #include <asm/hardirq.h>
#define local_bh_disable() \ #define local_bh_disable() \
do { preempt_count() += IRQ_OFFSET; barrier(); } while (0) do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0)
#define __local_bh_enable() \ #define __local_bh_enable() \
do { barrier(); preempt_count() -= IRQ_OFFSET; } while (0) do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
#define local_bh_enable() \ #define local_bh_enable() \
do { \ do { \
if (unlikely((preempt_count() == IRQ_OFFSET) && \
softirq_pending(smp_processor_id()))) { \
__local_bh_enable(); \ __local_bh_enable(); \
if (unlikely(!in_interrupt() && softirq_pending(smp_processor_id()))) \
do_softirq(); \ do_softirq(); \
preempt_check_resched(); \ preempt_check_resched(); \
} else { \
__local_bh_enable(); \
preempt_check_resched(); \
} \
} while (0) } while (0)
#define in_softirq() in_interrupt()
#endif /* __ASM_SOFTIRQ_H */ #endif /* __ASM_SOFTIRQ_H */
...@@ -88,26 +88,18 @@ struct task_struct; ...@@ -88,26 +88,18 @@ struct task_struct;
extern void __switch_to(struct task_struct *, struct task_struct *); extern void __switch_to(struct task_struct *, struct task_struct *);
#define switch_to(prev, next, last) __switch_to((prev), (next)) #define switch_to(prev, next, last) __switch_to((prev), (next))
#define prepare_arch_schedule(prev) do { } while(0)
#define finish_arch_schedule(prev) do { } while(0)
#define prepare_arch_switch(rq) do { } while(0)
#define finish_arch_switch(rq) spin_unlock_irq(&(rq)->lock)
struct thread_struct; struct thread_struct;
extern void _switch(struct thread_struct *prev, struct thread_struct *next); extern void _switch(struct thread_struct *prev, struct thread_struct *next);
struct pt_regs; struct pt_regs;
extern void dump_regs(struct pt_regs *); extern void dump_regs(struct pt_regs *);
#ifndef CONFIG_SMP #define irqs_disabled() \
({ \
#define cli() local_irq_disable() unsigned long flags; \
#define sti() local_irq_enable() local_save_flags(flags); \
#define save_flags(flags) local_save_flags(flags) !(flags & MSR_EE); \
#define restore_flags(flags) local_irq_restore(flags) })
#define save_and_cli(flags) local_irq_save(flags)
#endif /* !CONFIG_SMP */
static __inline__ int __is_processor(unsigned long pv) static __inline__ int __is_processor(unsigned long pv)
{ {
......
...@@ -27,6 +27,8 @@ struct thread_info { ...@@ -27,6 +27,8 @@ struct thread_info {
/* /*
* macros/functions for gaining access to the thread information structure * macros/functions for gaining access to the thread information structure
*
* preempt_count needs to be 1 initially, until the scheduler is functional.
*/ */
#define INIT_THREAD_INFO(tsk) \ #define INIT_THREAD_INFO(tsk) \
{ \ { \
...@@ -34,6 +36,7 @@ struct thread_info { ...@@ -34,6 +36,7 @@ struct thread_info {
exec_domain: &default_exec_domain, \ exec_domain: &default_exec_domain, \
flags: 0, \ flags: 0, \
cpu: 0, \ cpu: 0, \
preempt_count: 1, \
} }
#define init_thread_info (init_thread_union.thread_info) #define init_thread_info (init_thread_union.thread_info)
......
...@@ -200,6 +200,7 @@ ...@@ -200,6 +200,7 @@
#define __NR_putpmsg 188 /* some people actually want streams */ #define __NR_putpmsg 188 /* some people actually want streams */
#define __NR_vfork 189 #define __NR_vfork 189
#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */ #define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
#define __NR_readahead 191
#define __NR_mmap2 192 #define __NR_mmap2 192
#define __NR_truncate64 193 #define __NR_truncate64 193
#define __NR_ftruncate64 194 #define __NR_ftruncate64 194
...@@ -230,15 +231,10 @@ ...@@ -230,15 +231,10 @@
#define __NR_lremovexattr 219 #define __NR_lremovexattr 219
#define __NR_fremovexattr 220 #define __NR_fremovexattr 220
#define __NR_futex 221 #define __NR_futex 221
#define __NR_tux 222 #define __NR_sched_setaffinity 222
#define __NR_sched_setaffinity 223 #define __NR_sched_getaffinity 223
#define __NR_sched_getaffinity 224 #define __NR_security 224
#define __NR_tuxcall 225
#if 0
/* Remind paulus to add these into ppc32 */
__NR_security
__NR_readahead
#endif
#define __NR(n) #n #define __NR(n) #n
......
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