summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/entry.S7
-rw-r--r--arch/alpha/kernel/pci_iommu.c3
-rw-r--r--arch/alpha/kernel/setup.c3
-rw-r--r--arch/alpha/kernel/signal.c110
-rw-r--r--arch/alpha/kernel/systbls.S32
-rw-r--r--arch/alpha/lib/Makefile3
-rw-r--r--arch/alpha/lib/fls.c38
-rw-r--r--arch/arm/kernel/armksyms.c2
-rw-r--r--arch/arm/kernel/stacktrace.c2
-rw-r--r--arch/arm/mach-at91/board-dk.c2
-rw-r--r--arch/arm/mach-at91/board-kb9202.c2
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9rlek.c2
-rw-r--r--arch/arm/mach-footbridge/cats-pci.c2
-rw-r--r--arch/arm/mach-imx/generic.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2400.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2800.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x00.c2
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c2
-rw-r--r--arch/arm/mach-ixp23xx/pci.c2
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c2
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig3
-rw-r--r--arch/arm/mach-ixp4xx/common.c2
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c4
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c24
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c4
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c3
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c37
-rw-r--r--arch/arm/mach-s3c2410/bast.h2
-rw-r--r--arch/arm/mach-s3c2410/mach-amlm5900.c2
-rw-r--r--arch/arm/mach-s3c2412/s3c2412.c24
-rw-r--r--arch/arm/mach-s3c2443/clock.c3
-rw-r--r--arch/arm/mach-sa1100/neponset.c4
-rw-r--r--arch/arm/mm/Kconfig5
-rw-r--r--arch/arm/mm/Makefile1
-rw-r--r--arch/arm/mm/proc-v7.S2
-rw-r--r--arch/arm/mm/tlb-v7.S88
-rw-r--r--arch/arm/nwfpe/softfloat.h3
-rw-r--r--arch/arm/oprofile/op_model_mpcore.c9
-rw-r--r--arch/i386/kernel/smpboot.c5
-rw-r--r--arch/m68k/Kconfig13
-rw-r--r--arch/m68k/Makefile1
-rw-r--r--arch/m68k/kernel/Makefile3
-rw-r--r--arch/m68k/kernel/module.c31
-rw-r--r--arch/m68k/kernel/module.lds7
-rw-r--r--arch/m68k/kernel/setup.c37
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds5
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds5
-rw-r--r--arch/m68k/mm/init.c119
-rw-r--r--arch/m68k/mm/memory.c73
-rw-r--r--arch/m68k/mm/motorola.c104
-rw-r--r--arch/m68k/sun3/config.c2
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/boot/dts/lite5200.dts2
-rw-r--r--arch/powerpc/boot/dts/lite5200b.dts2
-rw-r--r--arch/powerpc/mm/pgtable_32.c2
-rw-r--r--arch/powerpc/platforms/chrp/pegasos_eth.c2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c2
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig4
-rw-r--r--arch/ppc/kernel/entry.S18
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c2
-rw-r--r--arch/ppc/mm/hashtable.S20
-rw-r--r--arch/ppc/mm/pgtable.c2
-rw-r--r--arch/s390/hypfs/hypfs_diag.c17
-rw-r--r--arch/s390/kernel/debug.c22
-rw-r--r--arch/s390/kernel/setup.c4
-rw-r--r--arch/s390/kernel/smp.c6
-rw-r--r--arch/sh/Makefile2
-rw-r--r--arch/sh/drivers/dma/dma-api.c1
-rw-r--r--arch/sh/kernel/cf-enabler.c6
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S1
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c1
-rw-r--r--arch/sh/kernel/smp.c2
-rw-r--r--arch/sh/kernel/timers/timer.c5
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.c1
-rw-r--r--arch/sparc/Kconfig7
-rw-r--r--arch/sparc/kernel/time.c4
-rw-r--r--arch/sparc/lib/atomic32.c15
-rw-r--r--arch/sparc64/Kconfig6
-rw-r--r--arch/sparc64/kernel/Makefile4
-rw-r--r--arch/sparc64/kernel/devices.c196
-rw-r--r--arch/sparc64/kernel/entry.S647
-rw-r--r--arch/sparc64/kernel/head.S31
-rw-r--r--arch/sparc64/kernel/hvapi.c5
-rw-r--r--arch/sparc64/kernel/irq.c83
-rw-r--r--arch/sparc64/kernel/itlb_miss.S4
-rw-r--r--arch/sparc64/kernel/mdesc.c619
-rw-r--r--arch/sparc64/kernel/pci.c54
-rw-r--r--arch/sparc64/kernel/pci_sabre.c7
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c54
-rw-r--r--arch/sparc64/kernel/power.c2
-rw-r--r--arch/sparc64/kernel/process.c4
-rw-r--r--arch/sparc64/kernel/prom.c148
-rw-r--r--arch/sparc64/kernel/setup.c18
-rw-r--r--arch/sparc64/kernel/smp.c155
-rw-r--r--arch/sparc64/kernel/sstate.c104
-rw-r--r--arch/sparc64/kernel/sun4v_ivec.S30
-rw-r--r--arch/sparc64/kernel/time.c47
-rw-r--r--arch/sparc64/kernel/traps.c27
-rw-r--r--arch/sparc64/mm/init.c90
-rw-r--r--arch/sparc64/prom/misc.c19
102 files changed, 2515 insertions, 840 deletions
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index c95e95e1ab0..debc8f03886 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -391,11 +391,10 @@ $work_resched:
bne $2, $work_resched
$work_notifysig:
- mov $sp, $17
+ mov $sp, $16
br $1, do_switch_stack
- mov $5, $21
- mov $sp, $18
- mov $31, $16
+ mov $sp, $17
+ mov $5, $18
jsr $26, do_notify_resume
bsr $1, undo_switch_stack
br restore_all
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 6e7d1fe6e93..28c84e55feb 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -7,6 +7,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
+#include <linux/log2.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
@@ -53,7 +54,7 @@ size_for_memory(unsigned long max)
{
unsigned long mem = max_low_pfn << PAGE_SHIFT;
if (mem < max)
- max = 1UL << ceil_log2(mem);
+ max = roundup_pow_of_two(mem);
return max;
}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 915f26345c4..bd5e68cd61e 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -43,6 +43,7 @@
#include <linux/notifier.h>
#include <asm/setup.h>
#include <asm/io.h>
+#include <linux/log2.h>
extern struct atomic_notifier_head panic_notifier_list;
static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
@@ -1303,7 +1304,7 @@ external_cache_probe(int minsize, int width)
long size = minsize, maxsize = MAX_BCACHE_SIZE * 2;
if (maxsize > (max_low_pfn + 1) << PAGE_SHIFT)
- maxsize = 1 << (floor_log2(max_low_pfn + 1) + PAGE_SHIFT);
+ maxsize = 1 << (ilog2(max_low_pfn + 1) + PAGE_SHIFT);
/* Get the first block cached. */
read_mem_block(__va(0), stride, size);
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 7f64aa767d5..410af4f3140 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -32,8 +32,8 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage void ret_from_sys_call(void);
-static int do_signal(sigset_t *, struct pt_regs *, struct switch_stack *,
- unsigned long, unsigned long);
+static void do_signal(struct pt_regs *, struct switch_stack *,
+ unsigned long, unsigned long);
/*
@@ -146,11 +146,9 @@ sys_rt_sigaction(int sig, const struct sigaction __user *act,
asmlinkage int
do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
{
- sigset_t oldset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- oldset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
@@ -160,19 +158,17 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
regs->r0 = EINTR;
regs->r19 = 1;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&oldset, regs, sw, 0, 0))
- return -EINTR;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage int
do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
struct pt_regs *regs, struct switch_stack *sw)
{
- sigset_t oldset, set;
+ sigset_t set;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
@@ -182,7 +178,7 @@ do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
- oldset = current->blocked;
+ current->saved_sigmask = current->blocked;
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
@@ -192,12 +188,10 @@ do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
regs->r0 = EINTR;
regs->r19 = 1;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&oldset, regs, sw, 0, 0))
- return -EINTR;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage int
@@ -436,7 +430,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
return err;
}
-static void
+static int
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
struct pt_regs *regs, struct switch_stack * sw)
{
@@ -481,13 +475,14 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
current->comm, current->pid, frame, regs->pc, regs->r26);
#endif
- return;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
-static void
+static int
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
{
@@ -543,34 +538,38 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->pc, regs->r26);
#endif
- return;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
/*
* OK, we're invoking a handler.
*/
-static inline void
+static inline int
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
{
+ int ret;
+
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs, sw);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
else
- setup_frame(sig, ka, oldset, regs, sw);
+ ret = setup_frame(sig, ka, oldset, regs, sw);
- if (ka->sa.sa_flags & SA_RESETHAND)
- ka->sa.sa_handler = SIG_DFL;
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ return ret;
}
static inline void
@@ -611,30 +610,42 @@ syscall_restart(unsigned long r0, unsigned long r19,
* restart. "r0" is also used as an indicator whether we can restart at
* all (if we get here from anything but a syscall return, it will be 0)
*/
-static int
-do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
+static void
+do_signal(struct pt_regs * regs, struct switch_stack * sw,
unsigned long r0, unsigned long r19)
{
siginfo_t info;
int signr;
unsigned long single_stepping = ptrace_cancel_bpt(current);
struct k_sigaction ka;
+ sigset_t *oldset;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
/* This lets the debugger run, ... */
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
/* ... so re-check the single stepping. */
single_stepping |= ptrace_cancel_bpt(current);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- if (r0) syscall_restart(r0, r19, regs, &ka);
- handle_signal(signr, &ka, &info, oldset, regs, sw);
+ if (r0)
+ syscall_restart(r0, r19, regs, &ka);
+ if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
+ /* A signal was successfully delivered, and the
+ saved sigmask was stored on the signal frame,
+ and will be restored by sigreturn. So we can
+ simply clear the restore sigmask flag. */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
if (single_stepping)
ptrace_set_bpt(current); /* re-set bpt */
- return 1;
+ return;
}
if (r0) {
@@ -654,17 +665,22 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
break;
}
}
+
+ /* If there's no signal to deliver, we just restore the saved mask. */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+
if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */
-
- return 0;
}
void
-do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
- struct switch_stack *sw, unsigned long r0,
- unsigned long r19, unsigned long thread_info_flags)
+do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
+ unsigned long thread_info_flags,
+ unsigned long r0, unsigned long r19)
{
- if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(oldset, regs, sw, r0, r19);
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs, sw, r0, r19);
}
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index f6cfe8ce3f9..79de99e32c3 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -465,6 +465,38 @@ sys_call_table:
.quad sys_inotify_init
.quad sys_inotify_add_watch /* 445 */
.quad sys_inotify_rm_watch
+ .quad sys_fdatasync
+ .quad sys_kexec_load
+ .quad sys_migrate_pages
+ .quad sys_openat /* 450 */
+ .quad sys_mkdirat
+ .quad sys_mknodat
+ .quad sys_fchownat
+ .quad sys_futimesat
+ .quad sys_fstatat64 /* 455 */
+ .quad sys_unlinkat
+ .quad sys_renameat
+ .quad sys_linkat
+ .quad sys_symlinkat
+ .quad sys_readlinkat /* 460 */
+ .quad sys_fchmodat
+ .quad sys_faccessat
+ .quad sys_pselect6
+ .quad sys_ppoll
+ .quad sys_unshare /* 465 */
+ .quad sys_set_robust_list
+ .quad sys_get_robust_list
+ .quad sys_splice
+ .quad sys_sync_file_range
+ .quad sys_tee /* 470 */
+ .quad sys_vmsplice
+ .quad sys_move_pages
+ .quad sys_getcpu
+ .quad sys_epoll_pwait
+ .quad sys_utimensat /* 475 */
+ .quad sys_signalfd
+ .quad sys_timerfd
+ .quad sys_eventfd
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index ea098f3b629..266f78e1307 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -37,7 +37,8 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
$(ev6-y)clear_page.o \
$(ev6-y)copy_page.o \
fpreg.o \
- callback_srm.o srm_puts.o srm_printk.o
+ callback_srm.o srm_puts.o srm_printk.o \
+ fls.o
lib-$(CONFIG_SMP) += dec_and_lock.o
diff --git a/arch/alpha/lib/fls.c b/arch/alpha/lib/fls.c
new file mode 100644
index 00000000000..7ad84ea0acf
--- /dev/null
+++ b/arch/alpha/lib/fls.c
@@ -0,0 +1,38 @@
+/*
+ * arch/alpha/lib/fls.c
+ */
+
+#include <linux/module.h>
+#include <asm/bitops.h>
+
+/* This is fls(x)-1, except zero is held to zero. This allows most
+ efficent input into extbl, plus it allows easy handling of fls(0)=0. */
+
+const unsigned char __flsm1_tab[256] =
+{
+ 0,
+ 0,
+ 1, 1,
+ 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+};
+
+EXPORT_SYMBOL(__flsm1_tab);
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 9179e822031..f73d62e8ab6 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -57,7 +57,7 @@ extern void fp_enter(void);
#define EXPORT_SYMBOL_ALIAS(sym,orig) \
EXPORT_CRC_ALIAS(sym) \
static const struct kernel_symbol __ksymtab_##sym \
- __attribute_used__ __attribute__((section("__ksymtab"))) = \
+ __used __attribute__((section("__ksymtab"))) = \
{ (unsigned long)&orig, #sym };
/*
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 8b63ad89d0a..ae31deb2d06 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -13,7 +13,7 @@ int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
/*
* Check current frame pointer is within bounds
*/
- if ((fp - 12) < low || fp + 4 >= high)
+ if (fp < (low + 12) || fp + 4 >= high)
break;
frame = (struct stackframe *)(fp - 12);
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
index 6043c38c0a9..af497896a96 100644
--- a/arch/arm/mach-at91/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -132,7 +132,7 @@ static struct mtd_partition __initdata dk_nand_partition[] = {
},
};
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
{
*num_partitions = ARRAY_SIZE(dk_nand_partition);
return dk_nand_partition;
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 76f6e1e553e..7d9b1a278fd 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -96,7 +96,7 @@ static struct mtd_partition __initdata kb9202_nand_partition[] = {
},
};
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
{
*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
return kb9202_nand_partition;
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 1f0c8a400b3..26ca8ab3f62 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -178,7 +178,7 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
},
};
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
{
*num_partitions = ARRAY_SIZE(ek_nand_partition);
return ek_nand_partition;
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index f57458559fb..c164c8e58ae 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -180,7 +180,7 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
},
};
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
{
*num_partitions = ARRAY_SIZE(ek_nand_partition);
return ek_nand_partition;
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 30c79aca84d..9b61320f295 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -87,7 +87,7 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
},
};
-static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
{
*num_partitions = ARRAY_SIZE(ek_nand_partition);
return ek_nand_partition;
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
index 4f984fde737..35eb232a649 100644
--- a/arch/arm/mach-footbridge/cats-pci.c
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -45,7 +45,7 @@ static struct hw_pci cats_pci __initdata = {
.postinit = dc21285_postinit,
};
-static int cats_pci_init(void)
+static int __init cats_pci_init(void)
{
if (machine_is_cats())
pci_common_init(&cats_pci);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 7a7fa51ec62..1c474cf709c 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -201,7 +201,6 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
{
imx_mmc_device.dev.platform_data = info;
}
-EXPORT_SYMBOL(imx_set_mmc_info);
static struct imxfb_mach_info imx_fb_info;
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index 0fdd03ab36e..ce7c15c7300 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -164,7 +164,7 @@ int __init ixdp2400_pci_init(void)
subsys_initcall(ixdp2400_pci_init);
-void ixdp2400_init_irq(void)
+void __init ixdp2400_init_irq(void)
{
ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
}
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index 70d247f09a7..14f09b80ab7 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -279,7 +279,7 @@ int __init ixdp2800_pci_init(void)
subsys_initcall(ixdp2800_pci_init);
-void ixdp2800_init_irq(void)
+void __init ixdp2800_init_irq(void)
{
ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
}
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 011065b967b..73c651e83d9 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -145,7 +145,7 @@ static struct irq_chip ixdp2x00_cpld_irq_chip = {
.unmask = ixdp2x00_irq_unmask
};
-void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
+void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
{
unsigned int irq;
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index 7a86a2516ea..c41a6b5a0ac 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -124,7 +124,7 @@ static struct irq_chip ixdp2351_intb_chip = {
.unmask = ixdp2351_intb_unmask
};
-void ixdp2351_init_irq(void)
+void __init ixdp2351_init_irq(void)
{
int irq;
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index ac7d43d23c2..227f808dc0e 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -284,7 +284,7 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-void ixp23xx_pci_slave_init(void)
+void __init ixp23xx_pci_slave_init(void)
{
ixp23xx_pci_common_init();
}
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index d06e21b70de..e35644961aa 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -110,7 +110,7 @@ static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
return NO_IRQ;
}
-static void roadrunner_pci_preinit(void)
+static void __init roadrunner_pci_preinit(void)
{
set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 9715ef506c2..060909870b5 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -104,9 +104,6 @@ config MACH_DSMG600
DSM-G600 RevA device. For more information on this platform,
see http://www.nslu2-linux.org/wiki/DSMG600/HomePage
-#
-# Avila and IXDP share the same source for now. Will change in future
-#
config ARCH_IXDP4XX
bool
depends on ARCH_IXDP425 || MACH_IXDP465 || MACH_KIXRP435
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 64685da1462..8112f726ffa 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -283,7 +283,7 @@ static struct irqaction ixp4xx_timer_irq = {
.handler = ixp4xx_timer_interrupt,
};
-static void __init ixp4xx_timer_init(void)
+void __init ixp4xx_timer_init(void)
{
/* Reset/disable counter */
*IXP4XX_OSRT1 = 0;
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index 7bc94f3def1..ad2e5b97966 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -25,10 +25,6 @@
#include <asm/mach/pci.h>
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
void __init coyote_pci_preinit(void)
{
set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 1caff65e22c..1e75e105c4f 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -18,6 +18,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
+#include <asm/mach/time.h>
static struct flash_platform_data dsmg600_flash_data = {
.map_name = "cfi_probe",
@@ -128,6 +129,19 @@ static void dsmg600_power_off(void)
gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
}
+static void __init dsmg600_timer_init(void)
+{
+ /* The xtal on this machine is non-standard. */
+ ixp4xx_timer_freq = DSMG600_FREQ;
+
+ /* Call standard timer_init function. */
+ ixp4xx_timer_init();
+}
+
+static struct sys_timer dsmg600_timer = {
+ .init = dsmg600_timer_init,
+};
+
static void __init dsmg600_init(void)
{
ixp4xx_sys_init();
@@ -155,21 +169,13 @@ static void __init dsmg600_init(void)
#endif
}
-static void __init dsmg600_fixup(struct machine_desc *desc,
- struct tag *tags, char **cmdline, struct meminfo *mi)
-{
- /* The xtal on this machine is non-standard. */
- ixp4xx_timer_freq = DSMG600_FREQ;
-}
-
MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
/* Maintainer: www.nslu2-linux.org */
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
- .fixup = dsmg600_fixup,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
- .timer = &ixp4xx_timer,
+ .timer = &dsmg600_timer,
.init_machine = dsmg600_init,
MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index 509a95a692a..d1e75b7dc3b 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -23,10 +23,6 @@
#include <asm/mach/pci.h>
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
void __init ixdpg425_pci_preinit(void)
{
set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 9a31444d921..78a17413cec 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -155,7 +155,8 @@ static void __init nas100d_init(void)
pm_power_off = nas100d_power_off;
- /* This is only useful on a modified machine, but it is valuable
+ /*
+ * This is only useful on a modified machine, but it is valuable
* to have it first in order to see debug messages, and so that
* it does *not* get removed if platform_add_devices fails!
*/
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 162c266e5f8..9bf8ccbcacc 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -22,6 +22,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
+#include <asm/mach/time.h>
static struct flash_platform_data nslu2_flash_data = {
.map_name = "cfi_probe",
@@ -49,26 +50,26 @@ static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = {
static struct resource nslu2_led_resources[] = {
{
.name = "ready", /* green led */
- .start = NSLU2_LED_GRN,
- .end = NSLU2_LED_GRN,
+ .start = NSLU2_LED_GRN_GPIO,
+ .end = NSLU2_LED_GRN_GPIO,
.flags = IXP4XX_GPIO_HIGH,
},
{
.name = "status", /* red led */
- .start = NSLU2_LED_RED,
- .end = NSLU2_LED_RED,
+ .start = NSLU2_LED_RED_GPIO,
+ .end = NSLU2_LED_RED_GPIO,
.flags = IXP4XX_GPIO_HIGH,
},
{
.name = "disk-1",
- .start = NSLU2_LED_DISK1,
- .end = NSLU2_LED_DISK1,
+ .start = NSLU2_LED_DISK1_GPIO,
+ .end = NSLU2_LED_DISK1_GPIO,
.flags = IXP4XX_GPIO_LOW,
},
{
.name = "disk-2",
- .start = NSLU2_LED_DISK2,
- .end = NSLU2_LED_DISK2,
+ .start = NSLU2_LED_DISK2_GPIO,
+ .end = NSLU2_LED_DISK2_GPIO,
.flags = IXP4XX_GPIO_LOW,
},
};
@@ -157,10 +158,21 @@ static void nslu2_power_off(void)
gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
}
-static void __init nslu2_init(void)
+static void __init nslu2_timer_init(void)
{
- ixp4xx_timer_freq = NSLU2_FREQ;
+ /* The xtal on this machine is non-standard. */
+ ixp4xx_timer_freq = NSLU2_FREQ;
+
+ /* Call standard timer_init function. */
+ ixp4xx_timer_init();
+}
+static struct sys_timer nslu2_timer = {
+ .init = nslu2_timer_init,
+};
+
+static void __init nslu2_init(void)
+{
ixp4xx_sys_init();
nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
@@ -169,7 +181,8 @@ static void __init nslu2_init(void)
pm_power_off = nslu2_power_off;
- /* This is only useful on a modified machine, but it is valuable
+ /*
+ * This is only useful on a modified machine, but it is valuable
* to have it first in order to see debug messages, and so that
* it does *not* get removed if platform_add_devices fails!
*/
@@ -185,6 +198,6 @@ MACHINE_START(NSLU2, "Linksys NSLU2")
.boot_params = 0x00000100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
- .timer = &ixp4xx_timer,
+ .timer = &nslu2_timer,
.init_machine = nslu2_init,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/bast.h b/arch/arm/mach-s3c2410/bast.h
deleted file mode 100644
index e98543742eb..00000000000
--- a/arch/arm/mach-s3c2410/bast.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/bast.h
-extern void bast_init_irq(void);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index bc308ceb91c..435adcce648 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -160,7 +160,7 @@ static struct platform_device *amlm5900_devices[] __initdata = {
#endif
};
-void __init amlm5900_map_io(void)
+static void __init amlm5900_map_io(void)
{
s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
s3c24xx_init_clocks(0);
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index c602aa39f9c..782b5814ced 100644
--- a/arch/arm/mach-s3c2412/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/sysdev.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
@@ -29,6 +30,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/arch/reset.h>
#include <asm/arch/idle.h>
#include <asm/arch/regs-clock.h>
@@ -38,6 +40,7 @@
#include <asm/arch/regs-gpioj.h>
#include <asm/arch/regs-dsc.h>
#include <asm/arch/regs-spi.h>
+#include <asm/arch/regs-s3c2412.h>
#include <asm/plat-s3c24xx/s3c2412.h>
#include <asm/plat-s3c24xx/cpu.h>
@@ -106,6 +109,23 @@ static void s3c2412_idle(void)
cpu_do_idle();
}
+static void s3c2412_hard_reset(void)
+{
+ /* errata "Watch-dog/Software Reset Problem" specifies that
+ * this reset must be done with the SYSCLK sourced from
+ * EXTCLK instead of FOUT to avoid a glitch in the reset
+ * mechanism.
+ *
+ * See the watchdog section of the S3C2412 manual for more
+ * information on this fix.
+ */
+
+ __raw_writel(0x00, S3C2412_CLKSRC);
+ __raw_writel(S3C2412_SWRST_RESET, S3C2412_SWRST);
+
+ mdelay(1);
+}
+
/* s3c2412_map_io
*
* register the standard cpu IO areas, and any passed in from the
@@ -122,6 +142,10 @@ void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
s3c24xx_idle = s3c2412_idle;
+ /* set custom reset hook */
+
+ s3c24xx_reset_hook = s3c2412_hard_reset;
+
/* register our io-tables */
iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 5955efb5de8..58402948c47 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -394,7 +394,7 @@ static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
return 0;
}
-struct clk clk_usb_bus_host = {
+static struct clk clk_usb_bus_host = {
.name = "usb-bus-host-parent",
.id = -1,
.parent = &clk_esysclk,
@@ -758,7 +758,6 @@ static struct clk init_clocks[] = {
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_CFC,
- .ctrlbit = S3C2443_HCLKCON_HSMMC,
}, {
.name = "ssmc",
.id = -1,
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index d7c038a0256..4cbf9468f65 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -139,12 +139,12 @@ static u_int neponset_get_mctrl(struct uart_port *port)
return ret;
}
-static struct sa1100_port_fns neponset_port_fns __initdata = {
+static struct sa1100_port_fns neponset_port_fns __devinitdata = {
.set_mctrl = neponset_set_mctrl,
.get_mctrl = neponset_get_mctrl,
};
-static int neponset_probe(struct platform_device *dev)
+static int __devinit neponset_probe(struct platform_device *dev)
{
sa1100_register_uart_fns(&neponset_port_fns);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5f472a8b406..e7904bc92c7 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -379,7 +379,7 @@ config CPU_V7
select CPU_CP15_MMU
select CPU_HAS_ASID
select CPU_COPY_V6 if MMU
- select CPU_TLB_V6 if MMU
+ select CPU_TLB_V7 if MMU
# Figure out what processor architecture version we should be using.
# This defines the compiler instruction set which depends on the machine type.
@@ -498,6 +498,9 @@ config CPU_TLB_V4WBI
config CPU_TLB_V6
bool
+config CPU_TLB_V7
+ bool
+
endif
config CPU_HAS_ASID
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index b5bd335ff14..762702765fc 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o
obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o
+obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o
obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o
obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index dd823dd4a37..718f4782ee8 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -256,7 +256,7 @@ __v7_proc_info:
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
.long cpu_v7_name
.long v7_processor_functions
- .long v6wbi_tlb_fns
+ .long v7wbi_tlb_fns
.long v6_user_fns
.long v7_cache_fns
.size __v7_proc_info, . - __v7_proc_info
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
new file mode 100644
index 00000000000..b56dda8052f
--- /dev/null
+++ b/arch/arm/mm/tlb-v7.S
@@ -0,0 +1,88 @@
+/*
+ * linux/arch/arm/mm/tlb-v7.S
+ *
+ * Copyright (C) 1997-2002 Russell King
+ * Modified for ARMv7 by Catalin Marinas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ARM architecture version 6 TLB handling functions.
+ * These assume a split I/D TLB.
+ */
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+/*
+ * v7wbi_flush_user_tlb_range(start, end, vma)
+ *
+ * Invalidate a range of TLB entries in the specified address space.
+ *
+ * - start - start address (may not be aligned)
+ * - end - end address (exclusive, may not be aligned)
+ * - vma - vma_struct describing address range
+ *
+ * It is assumed that:
+ * - the "Invalidate single entry" instruction will invalidate
+ * both the I and the D TLBs on Harvard-style TLBs
+ */
+ENTRY(v7wbi_flush_user_tlb_range)
+ vma_vm_mm r3, r2 @ get vma->vm_mm
+ mmid r3, r3 @ get vm_mm->context.id
+ dsb
+ mov r0, r0, lsr #PAGE_SHIFT @ align address
+ mov r1, r1, lsr #PAGE_SHIFT
+ asid r3, r3 @ mask ASID
+ orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA
+ mov r1, r1, lsl #PAGE_SHIFT
+ vma_vm_flags r2, r2 @ get vma->vm_flags
+1:
+ mcr p15, 0, r0, c8, c6, 1 @ TLB invalidate D MVA (was 1)
+ tst r2, #VM_EXEC @ Executable area ?
+ mcrne p15, 0, r0, c8, c5, 1 @ TLB invalidate I MVA (was 1)
+ add r0, r0, #PAGE_SZ
+ cmp r0, r1
+ blo 1b
+ mov ip, #0
+ mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
+ dsb
+ mov pc, lr
+
+/*
+ * v7wbi_flush_kern_tlb_range(start,end)
+ *
+ * Invalidate a range of kernel TLB entries
+ *
+ * - start - start address (may not be aligned)
+ * - end - end address (exclusive, may not be aligned)
+ */
+ENTRY(v7wbi_flush_kern_tlb_range)
+ dsb
+ mov r0, r0, lsr #PAGE_SHIFT @ align address
+ mov r1, r1, lsr #PAGE_SHIFT
+ mov r0, r0, lsl #PAGE_SHIFT
+ mov r1, r1, lsl #PAGE_SHIFT
+1:
+ mcr p15, 0, r0, c8, c6, 1 @ TLB invalidate D MVA
+ mcr p15, 0, r0, c8, c5, 1 @ TLB invalidate I MVA
+ add r0, r0, #PAGE_SZ
+ cmp r0, r1
+ blo 1b
+ mov r2, #0
+ mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
+ dsb
+ isb
+ mov pc, lr
+
+ .section ".text.init", #alloc, #execinstr
+
+ .type v7wbi_tlb_fns, #object
+ENTRY(v7wbi_tlb_fns)
+ .long v7wbi_flush_user_tlb_range
+ .long v7wbi_flush_kern_tlb_range
+ .long v6wbi_tlb_flags
+ .size v7wbi_tlb_fns, . - v7wbi_tlb_fns
diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h
index 0a3067452cd..260fe29d73f 100644
--- a/arch/arm/nwfpe/softfloat.h
+++ b/arch/arm/nwfpe/softfloat.h
@@ -273,4 +273,7 @@ static inline flag float64_lt_nocheck(float64 a, float64 b)
extern flag float32_is_nan( float32 a );
extern flag float64_is_nan( float64 a );
+extern int32 float64_to_uint32( struct roundingData *roundData, float64 a );
+extern int32 float64_to_uint32_round_to_zero( float64 a );
+
#endif
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
index 89850071824..7791da791f5 100644
--- a/arch/arm/oprofile/op_model_mpcore.c
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -257,8 +257,13 @@ static void em_stop(void)
*/
static void em_route_irq(int irq, unsigned int cpu)
{
- irq_desc[irq].affinity = cpumask_of_cpu(cpu);
- irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
+ struct irq_desc *desc = irq_desc + irq;
+ cpumask_t mask = cpumask_of_cpu(cpu);
+
+ spin_lock_irq(&desc->lock);
+ desc->affinity = mask;
+ desc->chip->set_affinity(irq, mask);
+ spin_unlock_irq(&desc->lock);
}
static int em_setup(void)
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 08f07a74a9d..88baed1e7e8 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -943,10 +943,9 @@ exit:
static void smp_tune_scheduling(void)
{
- unsigned long cachesize; /* kB */
-
if (cpu_khz) {
- cachesize = boot_cpu_data.x86_cache_size;
+ /* cache size in kB */
+ long cachesize = boot_cpu_data.x86_cache_size;
if (cachesize > 0)
max_cache_size = cachesize * 1024;
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b8536c7c087..85cdd23b044 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -355,8 +355,9 @@ config RMW_INSNS
adventurous.
config SINGLE_MEMORY_CHUNK
- bool "Use one physical chunk of memory only"
- depends on ADVANCED && !SUN3
+ bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
+ default y if SUN3
+ select NEED_MULTIPLE_NODES
help
Ignore all but the first contiguous chunk of physical memory for VM
purposes. This will save a few bytes kernel size and may speed up
@@ -377,6 +378,14 @@ config 060_WRITETHROUGH
is hardwired on. The 53c710 SCSI driver is known to suffer from
this problem.
+config ARCH_DISCONTIGMEM_ENABLE
+ def_bool !SINGLE_MEMORY_CHUNK
+
+config NODES_SHIFT
+ int
+ default "3"
+ depends on !SINGLE_MEMORY_CHUNK
+
source "mm/Kconfig"
endmenu
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index c20831a7e1a..aa383a5ea7a 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -19,6 +19,7 @@ COMPILE_ARCH = $(shell uname -m)
# override top level makefile
AS += -m68020
LDFLAGS := -m m68kelf
+LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
ifneq ($(COMPILE_ARCH),$(ARCH))
# prefix for cross-compiling binaries
CROSS_COMPILE = m68k-linux-gnu-
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 0b68ab8d63d..a806208c7fb 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -9,13 +9,12 @@ else
endif
extra-y += vmlinux.lds
-obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \
+obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
devres-y = ../../../kernel/irq/devres.o
obj-$(CONFIG_PCI) += bios32.o
-obj-$(CONFIG_MODULES) += module.o
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
EXTRA_AFLAGS := -traditional
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
index 3b1a2ff61dd..774862bc697 100644
--- a/arch/m68k/kernel/module.c
+++ b/arch/m68k/kernel/module.c
@@ -1,3 +1,9 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
#include <linux/moduleloader.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
@@ -11,6 +17,8 @@
#define DEBUGP(fmt...)
#endif
+#ifdef CONFIG_MODULES
+
void *module_alloc(unsigned long size)
{
if (size == 0)
@@ -118,11 +126,32 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
- struct module *me)
+ struct module *mod)
{
+ module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
+
return 0;
}
void module_arch_cleanup(struct module *mod)
{
}
+
+#endif /* CONFIG_MODULES */
+
+void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+ struct m68k_fixup_info *end)
+{
+ struct m68k_fixup_info *fixup;
+
+ for (fixup = start; fixup < end; fixup++) {
+ switch (fixup->type) {
+ case m68k_fixup_memoffset:
+ *(u32 *)fixup->addr = m68k_memoffset;
+ break;
+ case m68k_fixup_vnode_shift:
+ *(u16 *)fixup->addr += m68k_virt_to_node_shift;
+ break;
+ }
+ }
+}
diff --git a/arch/m68k/kernel/module.lds b/arch/m68k/kernel/module.lds
new file mode 100644
index 00000000000..fda94fa3824
--- /dev/null
+++ b/arch/m68k/kernel/module.lds
@@ -0,0 +1,7 @@
+SECTIONS {
+ .m68k_fixup : {
+ __start_fixup = .;
+ *(.m68k_fixup)
+ __stop_fixup = .;
+ }
+}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 61031935669..215c7bd4392 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -60,14 +60,12 @@ extern unsigned long availmem;
int m68k_num_memory;
int m68k_realnum_memory;
EXPORT_SYMBOL(m68k_realnum_memory);
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
unsigned long m68k_memoffset;
EXPORT_SYMBOL(m68k_memoffset);
-#endif
struct mem_info m68k_memory[NUM_MEMINFO];
EXPORT_SYMBOL(m68k_memory);
-static struct mem_info m68k_ramdisk;
+struct mem_info m68k_ramdisk;
static char m68k_command_line[CL_SIZE];
@@ -208,9 +206,6 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
void __init setup_arch(char **cmdline_p)
{
extern int _etext, _edata, _end;
-#ifndef CONFIG_SUN3
- unsigned long endmem, startmem;
-#endif
int i;
/* The bootinfo is located right after the kernel bss */
@@ -320,30 +315,16 @@ void __init setup_arch(char **cmdline_p)
panic("No configuration setup");
}
-#ifndef CONFIG_SUN3
- startmem= m68k_memory[0].addr;
- endmem = startmem + m68k_memory[0].size;
- high_memory = (void *)PAGE_OFFSET;
- for (i = 0; i < m68k_num_memory; i++) {
- m68k_memory[i].size &= MASK_256K;
- if (m68k_memory[i].addr < startmem)
- startmem = m68k_memory[i].addr;
- if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
- endmem = m68k_memory[i].addr+m68k_memory[i].size;
- high_memory += m68k_memory[i].size;
- }
-
- availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
- startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
-
- for (i = 0; i < m68k_num_memory; i++)
- free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
-
- reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
+ paging_init();
+#ifndef CONFIG_SUN3
+ for (i = 1; i < m68k_num_memory; i++)
+ free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
+ m68k_memory[i].size);
#ifdef CONFIG_BLK_DEV_INITRD
if (m68k_ramdisk.size) {
- reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
+ reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
+ m68k_ramdisk.addr, m68k_ramdisk.size);
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
initrd_end = initrd_start + m68k_ramdisk.size;
printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
@@ -362,8 +343,6 @@ void __init setup_arch(char **cmdline_p)
#endif /* !CONFIG_SUN3 */
- paging_init();
-
/* set ISA defs early as possible */
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
#if defined(CONFIG_Q40)
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index 78f139226a1..40f02b128f2 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -60,6 +60,11 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ .m68k_fixup : {
+ __start_fixup = .;
+ *(.m68k_fixup)
+ __stop_fixup = .;
+ }
SECURITY_INIT
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(8192);
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index c8999b2db23..f06425b6d20 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -54,6 +54,11 @@ __init_begin = .;
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ .m68k_fixup : {
+ __start_fixup = .;
+ *(.m68k_fixup)
+ __stop_fixup = .;
+ }
SECURITY_INIT
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(8192);
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index ab90213e5c5..f1de19e1dde 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -7,6 +7,7 @@
* to motorola.c and sun3mmu.c
*/
+#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -31,6 +32,37 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];
+
+pg_data_t pg_data_map[MAX_NUMNODES];
+EXPORT_SYMBOL(pg_data_map);
+
+int m68k_virt_to_node_shift;
+
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+pg_data_t *pg_data_table[65];
+EXPORT_SYMBOL(pg_data_table);
+#endif
+
+void m68k_setup_node(int node)
+{
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+ struct mem_info *info = m68k_memory + node;
+ int i, end;
+
+ i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
+ end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
+ for (; i <= end; i++) {
+ if (pg_data_table[i])
+ printk("overlap at %u for chunk %u\n", i, node);
+ pg_data_table[i] = pg_data_map + node;
+ }
+#endif
+ pg_data_map[node].bdata = bootmem_data + node;
+ node_set_online(node);
+}
+
+
/*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
@@ -40,52 +72,51 @@ void *empty_zero_page;
void show_mem(void)
{
- unsigned long i;
- int free = 0, total = 0, reserved = 0, shared = 0;
- int cached = 0;
-
- printk("\nMem-info:\n");
- show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- i = max_mapnr;
- while (i-- > 0) {
- total++;
- if (PageReserved(mem_map+i))
- reserved++;
- else if (PageSwapCache(mem_map+i))
- cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
- shared += page_count(mem_map+i) - 1;
- }
- printk("%d pages of RAM\n",total);
- printk("%d free pages\n",free);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
- printk("%d pages swap cached\n",cached);
+ pg_data_t *pgdat;
+ int free = 0, total = 0, reserved = 0, shared = 0;
+ int cached = 0;
+ int i;
+
+ printk("\nMem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ for_each_online_pgdat(pgdat) {
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat->node_mem_map + i;
+ total++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (!page_count(page))
+ free++;
+ else
+ shared += page_count(page) - 1;
+ }
+ }
+ printk("%d pages of RAM\n",total);
+ printk("%d free pages\n",free);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
}
extern void init_pointer_table(unsigned long ptable);
/* References to section boundaries */
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
+extern char _text[], _etext[];
+extern char __init_begin[], __init_end[];
extern pmd_t *zero_pgtable;
void __init mem_init(void)
{
+ pg_data_t *pgdat;
int codepages = 0;
int datapages = 0;
int initpages = 0;
- unsigned long tmp;
-#ifndef CONFIG_SUN3
int i;
-#endif
-
- max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);
#ifdef CONFIG_ATARI
if (MACH_IS_ATARI)
@@ -93,19 +124,25 @@ void __init mem_init(void)
#endif
/* this will put all memory onto the freelists */
- totalram_pages = free_all_bootmem();
-
- for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
- if (PageReserved(virt_to_page(tmp))) {
- if (tmp >= (unsigned long)&_text
- && tmp < (unsigned long)&_etext)
+ totalram_pages = num_physpages = 0;
+ for_each_online_pgdat(pgdat) {
+ num_physpages += pgdat->node_present_pages;
+
+ totalram_pages += free_all_bootmem_node(pgdat);
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat->node_mem_map + i;
+ char *addr = page_to_virt(page);
+
+ if (!PageReserved(page))
+ continue;
+ if (addr >= _text &&
+ addr < _etext)
codepages++;
- else if (tmp >= (unsigned long) &__init_begin
- && tmp < (unsigned long) &__init_end)
+ else if (addr >= __init_begin &&
+ addr < __init_end)
initpages++;
else
datapages++;
- continue;
}
}
@@ -124,7 +161,7 @@ void __init mem_init(void)
printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
(unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
- max_mapnr << (PAGE_SHIFT-10),
+ totalram_pages << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 13c0b4ad01e..b7473525b43 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -127,67 +127,6 @@ int free_pointer_table (pmd_t *ptable)
return 0;
}
-#ifdef DEBUG_INVALID_PTOV
-int mm_inv_cnt = 5;
-#endif
-
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-/*
- * The following two routines map from a physical address to a kernel
- * virtual address and vice versa.
- */
-unsigned long mm_vtop(unsigned long vaddr)
-{
- int i=0;
- unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;
-
- do {
- if (voff < m68k_memory[i].size) {
-#ifdef DEBUGPV
- printk ("VTOP(%p)=%lx\n", vaddr,
- m68k_memory[i].addr + voff);
-#endif
- return m68k_memory[i].addr + voff;
- }
- voff -= m68k_memory[i].size;
- } while (++i < m68k_num_memory);
-
- /* As a special case allow `__pa(high_memory)'. */
- if (voff == 0)
- return m68k_memory[i-1].addr + m68k_memory[i-1].size;
-
- return -1;
-}
-EXPORT_SYMBOL(mm_vtop);
-
-unsigned long mm_ptov (unsigned long paddr)
-{
- int i = 0;
- unsigned long poff, voff = PAGE_OFFSET;
-
- do {
- poff = paddr - m68k_memory[i].addr;
- if (poff < m68k_memory[i].size) {
-#ifdef DEBUGPV
- printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
-#endif
- return poff + voff;
- }
- voff += m68k_memory[i].size;
- } while (++i < m68k_num_memory);
-
-#ifdef DEBUG_INVALID_PTOV
- if (mm_inv_cnt > 0) {
- mm_inv_cnt--;
- printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
- paddr, __builtin_return_address(0));
- }
-#endif
- return -1;
-}
-EXPORT_SYMBOL(mm_ptov);
-#endif
-
/* invalidate page in both caches */
static inline void clear040(unsigned long paddr)
{
@@ -354,15 +293,3 @@ void cache_push (unsigned long paddr, int len)
}
EXPORT_SYMBOL(cache_push);
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-int mm_end_of_chunk (unsigned long addr, int len)
-{
- int i;
-
- for (i = 0; i < m68k_num_memory; i++)
- if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
- return 1;
- return 0;
-}
-EXPORT_SYMBOL(mm_end_of_chunk);
-#endif
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index afcccdc6ad4..7d571a2b44d 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -43,6 +43,11 @@ unsigned long mm_cachebits;
EXPORT_SYMBOL(mm_cachebits);
#endif
+/* size of memory already mapped in head.S */
+#define INIT_MAPPED_SIZE (4UL<<20)
+
+extern unsigned long availmem;
+
static pte_t * __init kernel_page_table(void)
{
pte_t *ptablep;
@@ -98,19 +103,20 @@ static pmd_t * __init kernel_ptr_table(void)
return last_pgtable;
}
-static unsigned long __init
-map_chunk (unsigned long addr, long size)
+static void __init map_node(int node)
{
#define PTRTREESIZE (256*1024)
#define ROOTTREESIZE (32*1024*1024)
- static unsigned long virtaddr = PAGE_OFFSET;
- unsigned long physaddr;
+ unsigned long physaddr, virtaddr, size;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
- physaddr = (addr | m68k_supervisor_cachemode |
- _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+ size = m68k_memory[node].size;
+ physaddr = m68k_memory[node].addr;
+ virtaddr = (unsigned long)phys_to_virt(physaddr);
+ physaddr |= m68k_supervisor_cachemode |
+ _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY;
if (CPU_IS_040_OR_060)
physaddr |= _PAGE_GLOBAL040;
@@ -190,8 +196,6 @@ map_chunk (unsigned long addr, long size)
#ifdef DEBUG
printk("\n");
#endif
-
- return virtaddr;
}
/*
@@ -200,15 +204,16 @@ map_chunk (unsigned long addr, long size)
*/
void __init paging_init(void)
{
- int chunk;
- unsigned long mem_avail = 0;
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+ unsigned long min_addr, max_addr;
+ unsigned long addr, size, end;
+ int i;
#ifdef DEBUG
{
extern unsigned long availmem;
- printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
- kernel_pg_dir, availmem, start_mem, end_mem);
+ printk ("start of paging_init (%p, %lx)\n",
+ kernel_pg_dir, availmem);
}
#endif
@@ -222,24 +227,62 @@ void __init paging_init(void)
pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
}
+ min_addr = m68k_memory[0].addr;
+ max_addr = min_addr + m68k_memory[0].size;
+ for (i = 1; i < m68k_num_memory;) {
+ if (m68k_memory[i].addr < min_addr) {
+ printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
+ m68k_memory[i].addr, m68k_memory[i].size);
+ printk("Fix your bootloader or use a memfile to make use of this area!\n");
+ m68k_num_memory--;
+ memmove(m68k_memory + i, m68k_memory + i + 1,
+ (m68k_num_memory - i) * sizeof(struct mem_info));
+ continue;
+ }
+ addr = m68k_memory[i].addr + m68k_memory[i].size;
+ if (addr > max_addr)
+ max_addr = addr;
+ i++;
+ }
+ m68k_memoffset = min_addr - PAGE_OFFSET;
+ m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6;
+
+ module_fixup(NULL, __start_fixup, __stop_fixup);
+ flush_icache();
+
+ high_memory = phys_to_virt(max_addr);
+
+ min_low_pfn = availmem >> PAGE_SHIFT;
+ max_low_pfn = max_addr >> PAGE_SHIFT;
+
+ for (i = 0; i < m68k_num_memory; i++) {
+ addr = m68k_memory[i].addr;
+ end = addr + m68k_memory[i].size;
+ m68k_setup_node(i);
+ availmem = PAGE_ALIGN(availmem);
+ availmem += init_bootmem_node(NODE_DATA(i),
+ availmem >> PAGE_SHIFT,
+ addr >> PAGE_SHIFT,
+ end >> PAGE_SHIFT);
+ }
+
/*
* Map the physical memory available into the kernel virtual
- * address space. It may allocate some memory for page
- * tables and thus modify availmem.
+ * address space. First initialize the bootmem allocator with
+ * the memory we already mapped, so map_node() has something
+ * to allocate.
*/
+ addr = m68k_memory[0].addr;
+ size = m68k_memory[0].size;
+ free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
+ map_node(0);
+ if (size > INIT_MAPPED_SIZE)
+ free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
- for (chunk = 0; chunk < m68k_num_memory; chunk++) {
- mem_avail = map_chunk (m68k_memory[chunk].addr,
- m68k_memory[chunk].size);
-
- }
+ for (i = 1; i < m68k_num_memory; i++)
+ map_node(i);
flush_tlb_all();
-#ifdef DEBUG
- printk ("memory available is %ldKB\n", mem_avail >> 10);
- printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
- start_mem, end_mem);
-#endif
/*
* initialize the bad page table and bad page to point
@@ -256,14 +299,11 @@ void __init paging_init(void)
#ifdef DEBUG
printk ("before free_area_init\n");
#endif
- zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
- (mach_max_dma_address+1) : (unsigned long)high_memory);
- zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
-
- zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
- zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
-
- free_area_init(zones_size);
+ for (i = 0; i < m68k_num_memory; i++) {
+ zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
+ free_area_init_node(i, pg_data_map + i, zones_size,
+ m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+ }
}
extern char __init_begin, __init_end;
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 4851b8437a8..c0fbd278fbb 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -21,6 +21,7 @@
#include <asm/contregs.h>
#include <asm/movs.h>
#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/sun3-head.h>
#include <asm/sun3mmu.h>
#include <asm/rtc.h>
@@ -127,6 +128,7 @@ void __init sun3_bootmem_alloc(unsigned long memory_start, unsigned long memory_
high_memory = (void *)memory_end;
availmem = memory_start;
+ m68k_setup_node(0);
availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 56d3c0dcd2b..5eaeafd30bd 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -118,6 +118,7 @@ config GENERIC_BUG
depends on BUG
config SYS_SUPPORTS_APM_EMULATION
+ default y if PMAC_APM_EMU
bool
config DEFAULT_UIMAGE
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index eae68ab1177..d29308fe4c2 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -67,7 +67,7 @@
interrupt-controller;
#interrupt-cells = <3>;
device_type = "interrupt-controller";
- compatible = "mpc5200_pic";
+ compatible = "mpc5200-pic";
reg = <500 80>;
built-in;
};
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 5185625a941..f242531f045 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -67,7 +67,7 @@
interrupt-controller;
#interrupt-cells = <3>;
device_type = "interrupt-controller";
- compatible = "mpc5200b-pic\0mpc5200_pic";
+ compatible = "mpc5200b-pic\0mpc5200-pic";
reg = <500 80>;
built-in;
};
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index d8232b7a08f..f6ae1a57d65 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -93,7 +93,7 @@ void pgd_free(pgd_t *pgd)
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
pte_t *pte;
extern int mem_init_done;
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 71045677559..5bcc58d9a4d 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -169,7 +169,7 @@ static int Enable_SRAM(void)
/***********/
/***********/
-int mv643xx_eth_add_pds(void)
+static int __init mv643xx_eth_add_pds(void)
{
int ret = 0;
static struct pci_device_id pci_marvell_mv64360[] = {
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index a410bc76a8a..07b1c4ec428 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -384,7 +384,7 @@ int boot_part;
static dev_t boot_dev;
#ifdef CONFIG_SCSI
-void __init note_scsi_host(struct device_node *node, void *host)
+void note_scsi_host(struct device_node *node, void *host)
{
int l;
char *p;
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 887739f3bad..f611d344a12 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -5,15 +5,13 @@
config UCC_SLOW
bool
default n
- select UCC
help
This option provides qe_lib support to UCC slow
protocols: UART, BISYNC, QMC
config UCC_FAST
bool
- default n
- select UCC
+ default y if UCC_GETH
help
This option provides qe_lib support to UCC fast
protocols: HDLC, Ethernet, ATM, transparent
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index ab64256110b..fba7ca17a67 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -596,7 +596,11 @@ fast_exception_return:
mr r12,r4 /* restart at exc_exit_restart */
b 2b
- .comm fee_restarts,4
+ .section .bss
+ .align 2
+fee_restarts:
+ .space 4
+ .previous
/* aargh, a nonrecoverable interrupt, panic */
/* aargh, we don't know which trap this is */
@@ -851,7 +855,11 @@ load_dbcr0:
mtspr SPRN_DBSR,r11 /* clear all pending debug events */
blr
- .comm global_dbcr0,8
+ .section .bss
+ .align 4
+global_dbcr0:
+ .space 8
+ .previous
#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
do_work: /* r10 contains MSR_KERNEL here */
@@ -926,4 +934,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
/* shouldn't return */
b 4b
- .comm ee_restarts,4
+ .section .bss
+ .align 2
+ee_restarts:
+ .space 4
+ .previous
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 4ad499605d0..a4165209ac7 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -40,7 +40,6 @@
#include <asm/time.h>
#include <asm/cputable.h>
#include <asm/btext.h>
-#include <asm/div64.h>
#include <asm/xmon.h>
#include <asm/signal.h>
#include <asm/dcr.h>
@@ -93,7 +92,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(__div64_32);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index e756942e65c..5f364dc5015 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -30,7 +30,11 @@
#include <asm/asm-offsets.h>
#ifdef CONFIG_SMP
- .comm mmu_hash_lock,4
+ .section .bss
+ .align 2
+ .globl mmu_hash_lock
+mmu_hash_lock:
+ .space 4
#endif /* CONFIG_SMP */
/*
@@ -461,9 +465,17 @@ found_slot:
sync /* make sure pte updates get to memory */
blr
- .comm next_slot,4
- .comm primary_pteg_full,4
- .comm htab_hash_searches,4
+ .section .bss
+ .align 2
+next_slot:
+ .space 4
+ .globl primary_pteg_full
+primary_pteg_full:
+ .space 4
+ .globl htab_hash_searches
+htab_hash_searches:
+ .space 4
+ .previous
/*
* Flush the entry for a particular page from the hash table.
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index c023b729880..35ebb6395ae 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -92,7 +92,7 @@ void pgd_free(pgd_t *pgd)
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
pte_t *pte;
extern int mem_init_done;
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 2782cf9da5b..b9a1ce1f28e 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -481,9 +481,17 @@ out:
/* Diagnose 224 functions */
-static void diag224(void *ptr)
+static int diag224(void *ptr)
{
- asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
+ int rc = -ENOTSUPP;
+
+ asm volatile(
+ " diag %1,%2,0x224\n"
+ "0: lhi %0,0x0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "+d" (rc) :"d" (0), "d" (ptr) : "memory");
+ return rc;
}
static int diag224_get_name_table(void)
@@ -492,7 +500,10 @@ static int diag224_get_name_table(void)
diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
if (!diag224_cpu_names)
return -ENOMEM;
- diag224(diag224_cpu_names);
+ if (diag224(diag224_cpu_names)) {
+ kfree(diag224_cpu_names);
+ return -ENOTSUPP;
+ }
EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
return 0;
}
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index dca6eaf82c8..1b2f5ce4532 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -163,7 +163,7 @@ unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
static debug_info_t *debug_area_first = NULL;
static debug_info_t *debug_area_last = NULL;
-static DECLARE_MUTEX(debug_lock);
+static DEFINE_MUTEX(debug_mutex);
static int initialized;
@@ -576,7 +576,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
int rc = 0;
file_private_info_t *p_info;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
p_info = ((file_private_info_t *) file->private_data);
if (p_info->view->input_proc)
rc = p_info->view->input_proc(p_info->debug_info_org,
@@ -584,7 +584,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
length, offset);
else
rc = -EPERM;
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc; /* number of input characters */
}
@@ -602,7 +602,7 @@ debug_open(struct inode *inode, struct file *file)
file_private_info_t *p_info;
debug_info_t *debug_info, *debug_info_snapshot;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_info = file->f_path.dentry->d_inode->i_private;
/* find debug view */
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
@@ -653,7 +653,7 @@ found:
file->private_data = p_info;
debug_info_get(debug_info);
out:
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
@@ -688,7 +688,7 @@ debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
if (!initialized)
BUG();
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
/* create new debug_info */
@@ -702,7 +702,7 @@ out:
if (!rc){
printk(KERN_ERR "debug: debug_register failed for %s\n",name);
}
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
@@ -716,9 +716,9 @@ debug_unregister(debug_info_t * id)
{
if (!id)
goto out;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_info_put(id);
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
out:
return;
@@ -1054,11 +1054,11 @@ __init debug_init(void)
int rc = 0;
s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
printk(KERN_INFO "debug: Initialization complete\n");
initialized = 1;
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 6bfb0889eb1..51d6309e7f3 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -102,7 +102,7 @@ static struct resource data_resource = {
/*
* cpu_init() initializes state that is per-CPU.
*/
-void __devinit cpu_init (void)
+void __cpuinit cpu_init(void)
{
int addr = hard_smp_processor_id();
@@ -915,7 +915,7 @@ setup_arch(char **cmdline_p)
setup_zfcpdump(console_devno);
}
-void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
{
printk("cpu %d "
#ifdef CONFIG_SMP
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 09f028a3266..8ff2feaf9b0 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -492,7 +492,7 @@ static unsigned int __init smp_count_cpus(void)
/*
* Activate a secondary processor.
*/
-int __devinit start_secondary(void *cpuvoid)
+int __cpuinit start_secondary(void *cpuvoid)
{
/* Setup the cpu */
cpu_init();
@@ -741,7 +741,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_create_idle(cpu);
}
-void __devinit smp_prepare_boot_cpu(void)
+void __init smp_prepare_boot_cpu(void)
{
BUG_ON(smp_processor_id() != 0);
@@ -750,7 +750,7 @@ void __devinit smp_prepare_boot_cpu(void)
current_set[0] = current;
}
-void smp_cpus_done(unsigned int max_cpus)
+void __init smp_cpus_done(unsigned int max_cpus)
{
cpu_present_map = cpu_possible_map;
}
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 7b112241705..883b03b040c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -39,7 +39,7 @@ cflags-$(CONFIG_CPU_SH2A) := -m2a $(call cc-option,-m2a-nofpu,)
cflags-$(CONFIG_CPU_SH3) := -m3
cflags-$(CONFIG_CPU_SH4) := -m4 \
$(call cc-option,-mno-implicit-fp,-m4-nofpu)
-cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,)
+cflags-$(CONFIG_CPU_SH4A) := $(call cc-option,-m4a,) $(call cc-option,-m4a-nofpu,)
cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index 8057a27a1bc..cf8e1199433 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <asm/dma.h>
DEFINE_SPINLOCK(dma_spin_lock);
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index 849a9e19139..ebc73b85094 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -149,6 +150,11 @@ static int __init cf_init_se(void)
ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
return 0;
}
+#else
+static int __init cf_init_se(void)
+{
+ return -1;
+}
#endif
int __init cf_init(void)
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 832c0b4a1e6..659cc081e5e 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -320,6 +320,7 @@ skip_restore:
.align 2
5: .long 0x00001000 ! DSP
+6: .long in_nmi
7: .long 0x30000000
! common exception handler
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 8cd04904c77..fab2eb07196 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -12,6 +12,7 @@
*/
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/cache.h>
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index dbebaddcfe3..283e1425ced 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -10,6 +10,8 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+
+#include <linux/err.h>
#include <linux/cache.h>
#include <linux/cpumask.h>
#include <linux/delay.h>
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
index a6bcc913d25..4e7e747d1b6 100644
--- a/arch/sh/kernel/timers/timer.c
+++ b/arch/sh/kernel/timers/timer.c
@@ -13,7 +13,7 @@
#include <linux/string.h>
#include <asm/timer.h>
-static struct sys_timer *sys_timers[] __initdata = {
+static struct sys_timer *sys_timers[] = {
#ifdef CONFIG_SH_TMU
&tmu_timer,
#endif
@@ -26,7 +26,7 @@ static struct sys_timer *sys_timers[] __initdata = {
NULL,
};
-static char timer_override[10] __initdata;
+static char timer_override[10];
static int __init timer_setup(char *str)
{
if (str)
@@ -53,4 +53,3 @@ struct sys_timer *get_sys_timer(void)
return NULL;
}
-
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index e146bafcd14..2aa9438361b 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -17,6 +17,7 @@
#include <linux/gfp.h>
#include <linux/module.h>
#include <linux/elf.h>
+#include <linux/sched.h>
/*
* Should the kernel map a VDSO page into processes and pass its
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index bd992c0048f..fbcc00c6c06 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -178,6 +178,13 @@ config ARCH_HAS_ILOG2_U64
bool
default n
+config EMULATED_CMPXCHG
+ bool
+ default y
+ help
+ Sparc32 does not have a CAS instruction like sparc64. cmpxchg()
+ is emulated, and therefore it is not completely atomic.
+
config SUN_PM
bool
default y
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index f1401b57ccc..7b4612da74a 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -148,7 +148,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
}
/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
-static void __init kick_start_clock(void)
+static void __devinit kick_start_clock(void)
{
struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
unsigned char sec;
@@ -223,7 +223,7 @@ static __inline__ int has_low_battery(void)
return (data1 == data2); /* Was the write blocked? */
}
-static void __init mostek_set_system_time(void)
+static void __devinit mostek_set_system_time(void)
{
unsigned int year, mon, day, hour, min, sec;
struct mostek48t02 *mregs;
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index 559335f4917..cbddeb38ffd 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -2,6 +2,7 @@
* atomic32.c: 32-bit atomic_t implementation
*
* Copyright (C) 2004 Keith M Wesolowski
+ * Copyright (C) 2007 Kyle McMartin
*
* Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
*/
@@ -117,3 +118,17 @@ unsigned long ___change_bit(unsigned long *addr, unsigned long mask)
return old & mask;
}
EXPORT_SYMBOL(___change_bit);
+
+unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new)
+{
+ unsigned long flags;
+ u32 prev;
+
+ spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+ if ((prev = *ptr) == old)
+ *ptr = new;
+ spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+
+ return (unsigned long)prev;
+}
+EXPORT_SYMBOL(__cmpxchg_u32);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 831781cab27..bd00f89eed1 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -147,10 +147,10 @@ config SMP
If you don't know what to do here, say N.
config NR_CPUS
- int "Maximum number of CPUs (2-64)"
- range 2 64
+ int "Maximum number of CPUs (2-1024)"
+ range 2 1024
depends on SMP
- default "32"
+ default "64"
source "drivers/cpufreq/Kconfig"
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index c749dccacc3..d8d19093d12 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -8,11 +8,11 @@ EXTRA_CFLAGS := -Werror
extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o setup.o cpu.o idprom.o \
- traps.o devices.o auxio.o una_asm.o \
+ traps.o auxio.o una_asm.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o central.o pci.o starfire.o semaphore.o \
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
- visemul.o prom.o of_device.o hvapi.o
+ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
deleted file mode 100644
index 0e03c8e218c..00000000000
--- a/arch/sparc64/kernel/devices.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* devices.c: Initial scan of the prom device tree for important
- * Sparc device nodes which we need to find.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/threads.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/bootmem.h>
-
-#include <asm/page.h>
-#include <asm/oplib.h>
-#include <asm/system.h>
-#include <asm/smp.h>
-#include <asm/spitfire.h>
-#include <asm/timer.h>
-#include <asm/cpudata.h>
-
-/* Used to synchronize accesses to NatSemi SUPER I/O chip configure
- * operations in asm/ns87303.h
- */
-DEFINE_SPINLOCK(ns87303_lock);
-
-extern void cpu_probe(void);
-extern void central_probe(void);
-
-static const char *cpu_mid_prop(void)
-{
- if (tlb_type == spitfire)
- return "upa-portid";
- return "portid";
-}
-
-static int get_cpu_mid(struct device_node *dp)
-{
- struct property *prop;
-
- if (tlb_type == hypervisor) {
- struct linux_prom64_registers *reg;
- int len;
-
- prop = of_find_property(dp, "cpuid", &len);
- if (prop && len == 4)
- return *(int *) prop->value;
-
- prop = of_find_property(dp, "reg", NULL);
- reg = prop->value;
- return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
- } else {
- const char *prop_name = cpu_mid_prop();
-
- prop = of_find_property(dp, prop_name, NULL);
- if (prop)
- return *(int *) prop->value;
- return 0;
- }
-}
-
-static int check_cpu_node(struct device_node *dp, int *cur_inst,
- int (*compare)(struct device_node *, int, void *),
- void *compare_arg,
- struct device_node **dev_node, int *mid)
-{
- if (!compare(dp, *cur_inst, compare_arg)) {
- if (dev_node)
- *dev_node = dp;
- if (mid)
- *mid = get_cpu_mid(dp);
- return 0;
- }
-
- (*cur_inst)++;
-
- return -ENODEV;
-}
-
-static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
- void *compare_arg,
- struct device_node **dev_node, int *mid)
-{
- struct device_node *dp;
- int cur_inst;
-
- cur_inst = 0;
- for_each_node_by_type(dp, "cpu") {
- int err = check_cpu_node(dp, &cur_inst,
- compare, compare_arg,
- dev_node, mid);
- if (err == 0)
- return 0;
- }
-
- return -ENODEV;
-}
-
-static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
-{
- int desired_instance = (int) (long) _arg;
-
- if (instance == desired_instance)
- return 0;
- return -ENODEV;
-}
-
-int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
-{
- return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
- dev_node, mid);
-}
-
-static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
-{
- int desired_mid = (int) (long) _arg;
- int this_mid;
-
- this_mid = get_cpu_mid(dp);
- if (this_mid == desired_mid)
- return 0;
- return -ENODEV;
-}
-
-int cpu_find_by_mid(int mid, struct device_node **dev_node)
-{
- return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
- dev_node, NULL);
-}
-
-void __init device_scan(void)
-{
- /* FIX ME FAST... -DaveM */
- ioport_resource.end = 0xffffffffffffffffUL;
-
- prom_printf("Booting Linux...\n");
-
-#ifndef CONFIG_SMP
- {
- struct device_node *dp;
- int err, def;
-
- err = cpu_find_by_instance(0, &dp, NULL);
- if (err) {
- prom_printf("No cpu nodes, cannot continue\n");
- prom_halt();
- }
- cpu_data(0).clock_tick =
- of_getintprop_default(dp, "clock-frequency", 0);
-
- def = ((tlb_type == hypervisor) ?
- (8 * 1024) :
- (16 * 1024));
- cpu_data(0).dcache_size = of_getintprop_default(dp,
- "dcache-size",
- def);
-
- def = 32;
- cpu_data(0).dcache_line_size =
- of_getintprop_default(dp, "dcache-line-size", def);
-
- def = 16 * 1024;
- cpu_data(0).icache_size = of_getintprop_default(dp,
- "icache-size",
- def);
-
- def = 32;
- cpu_data(0).icache_line_size =
- of_getintprop_default(dp, "icache-line-size", def);
-
- def = ((tlb_type == hypervisor) ?
- (3 * 1024 * 1024) :
- (4 * 1024 * 1024));
- cpu_data(0).ecache_size = of_getintprop_default(dp,
- "ecache-size",
- def);
-
- def = 64;
- cpu_data(0).ecache_line_size =
- of_getintprop_default(dp, "ecache-line-size", def);
- printk("CPU[0]: Caches "
- "D[sz(%d):line_sz(%d)] "
- "I[sz(%d):line_sz(%d)] "
- "E[sz(%d):line_sz(%d)]\n",
- cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
- cpu_data(0).icache_size, cpu_data(0).icache_line_size,
- cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
- }
-#endif
-
- central_probe();
-
- cpu_probe();
-}
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 732b77cb71f..ed712e0b337 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1725,96 +1725,142 @@ real_hard_smp_processor_id:
* returns %o0: sysino
*/
.globl sun4v_devino_to_sysino
+ .type sun4v_devino_to_sysino,#function
sun4v_devino_to_sysino:
mov HV_FAST_INTR_DEVINO2SYSINO, %o5
ta HV_FAST_TRAP
retl
mov %o1, %o0
+ .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino
/* %o0: sysino
*
* returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED})
*/
.globl sun4v_intr_getenabled
+ .type sun4v_intr_getenabled,#function
sun4v_intr_getenabled:
mov HV_FAST_INTR_GETENABLED, %o5
ta HV_FAST_TRAP
retl
mov %o1, %o0
+ .size sun4v_intr_getenabled, .-sun4v_intr_getenabled
/* %o0: sysino
* %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
*/
.globl sun4v_intr_setenabled
+ .type sun4v_intr_setenabled,#function
sun4v_intr_setenabled:
mov HV_FAST_INTR_SETENABLED, %o5
ta HV_FAST_TRAP
retl
nop
+ .size sun4v_intr_setenabled, .-sun4v_intr_setenabled
/* %o0: sysino
*
* returns %o0: intr_state (HV_INTR_STATE_*)
*/
.globl sun4v_intr_getstate
+ .type sun4v_intr_getstate,#function
sun4v_intr_getstate:
mov HV_FAST_INTR_GETSTATE, %o5
ta HV_FAST_TRAP
retl
mov %o1, %o0
+ .size sun4v_intr_getstate, .-sun4v_intr_getstate
/* %o0: sysino
* %o1: intr_state (HV_INTR_STATE_*)
*/
.globl sun4v_intr_setstate
+ .type sun4v_intr_setstate,#function
sun4v_intr_setstate:
mov HV_FAST_INTR_SETSTATE, %o5
ta HV_FAST_TRAP
retl
nop
+ .size sun4v_intr_setstate, .-sun4v_intr_setstate
/* %o0: sysino
*
* returns %o0: cpuid
*/
.globl sun4v_intr_gettarget
+ .type sun4v_intr_gettarget,#function
sun4v_intr_gettarget:
mov HV_FAST_INTR_GETTARGET, %o5
ta HV_FAST_TRAP
retl
mov %o1, %o0
+ .size sun4v_intr_gettarget, .-sun4v_intr_gettarget
/* %o0: sysino
* %o1: cpuid
*/
.globl sun4v_intr_settarget
+ .type sun4v_intr_settarget,#function
sun4v_intr_settarget:
mov HV_FAST_INTR_SETTARGET, %o5
ta HV_FAST_TRAP
retl
nop
+ .size sun4v_intr_settarget, .-sun4v_intr_settarget
- /* %o0: type
- * %o1: queue paddr
- * %o2: num queue entries
+ /* %o0: cpuid
+ * %o1: pc
+ * %o2: rtba
+ * %o3: arg0
*
* returns %o0: status
*/
- .globl sun4v_cpu_qconf
-sun4v_cpu_qconf:
- mov HV_FAST_CPU_QCONF, %o5
+ .globl sun4v_cpu_start
+ .type sun4v_cpu_start,#function
+sun4v_cpu_start:
+ mov HV_FAST_CPU_START, %o5
ta HV_FAST_TRAP
retl
nop
+ .size sun4v_cpu_start, .-sun4v_cpu_start
- /* returns %o0: status
+ /* %o0: cpuid
+ *
+ * returns %o0: status
*/
+ .globl sun4v_cpu_stop
+ .type sun4v_cpu_stop,#function
+sun4v_cpu_stop:
+ mov HV_FAST_CPU_STOP, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_cpu_stop, .-sun4v_cpu_stop
+
+ /* returns %o0: status */
.globl sun4v_cpu_yield
+ .type sun4v_cpu_yield, #function
sun4v_cpu_yield:
mov HV_FAST_CPU_YIELD, %o5
ta HV_FAST_TRAP
retl
nop
+ .size sun4v_cpu_yield, .-sun4v_cpu_yield
+
+ /* %o0: type
+ * %o1: queue paddr
+ * %o2: num queue entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_cpu_qconf
+ .type sun4v_cpu_qconf,#function
+sun4v_cpu_qconf:
+ mov HV_FAST_CPU_QCONF, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_cpu_qconf, .-sun4v_cpu_qconf
/* %o0: num cpus in cpu list
* %o1: cpu list paddr
@@ -1823,11 +1869,13 @@ sun4v_cpu_yield:
* returns %o0: status
*/
.globl sun4v_cpu_mondo_send
+ .type sun4v_cpu_mondo_send,#function
sun4v_cpu_mondo_send:
mov HV_FAST_CPU_MONDO_SEND, %o5
ta HV_FAST_TRAP
retl
nop
+ .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send
/* %o0: CPU ID
*
@@ -1835,6 +1883,7 @@ sun4v_cpu_mondo_send:
* %o0: cpu state as HV_CPU_STATE_*
*/
.globl sun4v_cpu_state
+ .type sun4v_cpu_state,#function
sun4v_cpu_state:
mov HV_FAST_CPU_STATE, %o5
ta HV_FAST_TRAP
@@ -1843,6 +1892,37 @@ sun4v_cpu_state:
mov %o1, %o0
1: retl
nop
+ .size sun4v_cpu_state, .-sun4v_cpu_state
+
+ /* %o0: virtual address
+ * %o1: must be zero
+ * %o2: TTE
+ * %o3: HV_MMU_* flags
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_mmu_map_perm_addr
+ .type sun4v_mmu_map_perm_addr,#function
+sun4v_mmu_map_perm_addr:
+ mov HV_FAST_MMU_MAP_PERM_ADDR, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr
+
+ /* %o0: number of TSB descriptions
+ * %o1: TSB descriptions real address
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_mmu_tsb_ctx0
+ .type sun4v_mmu_tsb_ctx0,#function
+sun4v_mmu_tsb_ctx0:
+ mov HV_FAST_MMU_TSB_CTX0, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0
/* %o0: API group number
* %o1: pointer to unsigned long major number storage
@@ -1851,6 +1931,7 @@ sun4v_cpu_state:
* returns %o0: status
*/
.globl sun4v_get_version
+ .type sun4v_get_version,#function
sun4v_get_version:
mov HV_CORE_GET_VER, %o5
mov %o1, %o3
@@ -1859,6 +1940,7 @@ sun4v_get_version:
stx %o1, [%o3]
retl
stx %o2, [%o4]
+ .size sun4v_get_version, .-sun4v_get_version
/* %o0: API group number
* %o1: desired major number
@@ -1868,18 +1950,49 @@ sun4v_get_version:
* returns %o0: status
*/
.globl sun4v_set_version
+ .type sun4v_set_version,#function
sun4v_set_version:
mov HV_CORE_SET_VER, %o5
mov %o3, %o4
ta HV_CORE_TRAP
retl
stx %o1, [%o4]
+ .size sun4v_set_version, .-sun4v_set_version
+
+ /* %o0: pointer to unsigned long time
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_tod_get
+ .type sun4v_tod_get,#function
+sun4v_tod_get:
+ mov %o0, %o4
+ mov HV_FAST_TOD_GET, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_tod_get, .-sun4v_tod_get
+
+ /* %o0: time
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_tod_set
+ .type sun4v_tod_set,#function
+sun4v_tod_set:
+ mov HV_FAST_TOD_SET, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_tod_set, .-sun4v_tod_set
/* %o0: pointer to unsigned long status
*
* returns %o0: signed character
*/
.globl sun4v_con_getchar
+ .type sun4v_con_getchar,#function
sun4v_con_getchar:
mov %o0, %o4
mov HV_FAST_CONS_GETCHAR, %o5
@@ -1889,17 +2002,20 @@ sun4v_con_getchar:
stx %o0, [%o4]
retl
sra %o1, 0, %o0
+ .size sun4v_con_getchar, .-sun4v_con_getchar
/* %o0: signed long character
*
* returns %o0: status
*/
.globl sun4v_con_putchar
+ .type sun4v_con_putchar,#function
sun4v_con_putchar:
mov HV_FAST_CONS_PUTCHAR, %o5
ta HV_FAST_TRAP
retl
sra %o0, 0, %o0
+ .size sun4v_con_putchar, .-sun4v_con_putchar
/* %o0: buffer real address
* %o1: buffer size
@@ -1908,6 +2024,7 @@ sun4v_con_putchar:
* returns %o0: status
*/
.globl sun4v_con_read
+ .type sun4v_con_read,#function
sun4v_con_read:
mov %o2, %o4
mov HV_FAST_CONS_READ, %o5
@@ -1922,6 +2039,7 @@ sun4v_con_read:
stx %o1, [%o4]
1: retl
nop
+ .size sun4v_con_read, .-sun4v_con_read
/* %o0: buffer real address
* %o1: buffer size
@@ -1930,6 +2048,7 @@ sun4v_con_read:
* returns %o0: status
*/
.globl sun4v_con_write
+ .type sun4v_con_write,#function
sun4v_con_write:
mov %o2, %o4
mov HV_FAST_CONS_WRITE, %o5
@@ -1937,3 +2056,517 @@ sun4v_con_write:
stx %o1, [%o4]
retl
nop
+ .size sun4v_con_write, .-sun4v_con_write
+
+ /* %o0: soft state
+ * %o1: address of description string
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_mach_set_soft_state
+ .type sun4v_mach_set_soft_state,#function
+sun4v_mach_set_soft_state:
+ mov HV_FAST_MACH_SET_SOFT_STATE, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state
+
+ /* %o0: exit code
+ *
+ * Does not return.
+ */
+ .globl sun4v_mach_exit
+ .type sun4v_mach_exit,#function
+sun4v_mach_exit:
+ mov HV_FAST_MACH_EXIT, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_mach_exit, .-sun4v_mach_exit
+
+ /* %o0: buffer real address
+ * %o1: buffer length
+ * %o2: pointer to unsigned long real_buf_len
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_mach_desc
+ .type sun4v_mach_desc,#function
+sun4v_mach_desc:
+ mov %o2, %o4
+ mov HV_FAST_MACH_DESC, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_mach_desc, .-sun4v_mach_desc
+
+ /* %o0: new timeout in milliseconds
+ * %o1: pointer to unsigned long orig_timeout
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_mach_set_watchdog
+ .type sun4v_mach_set_watchdog,#function
+sun4v_mach_set_watchdog:
+ mov %o1, %o4
+ mov HV_FAST_MACH_SET_WATCHDOG, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog
+
+ /* No inputs and does not return. */
+ .globl sun4v_mach_sir
+ .type sun4v_mach_sir,#function
+sun4v_mach_sir:
+ mov %o1, %o4
+ mov HV_FAST_MACH_SIR, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_mach_sir, .-sun4v_mach_sir
+
+ /* %o0: channel
+ * %o1: ra
+ * %o2: num_entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_tx_qconf
+ .type sun4v_ldc_tx_qconf,#function
+sun4v_ldc_tx_qconf:
+ mov HV_FAST_LDC_TX_QCONF, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf
+
+ /* %o0: channel
+ * %o1: pointer to unsigned long ra
+ * %o2: pointer to unsigned long num_entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_tx_qinfo
+ .type sun4v_ldc_tx_qinfo,#function
+sun4v_ldc_tx_qinfo:
+ mov %o1, %g1
+ mov %o2, %g2
+ mov HV_FAST_LDC_TX_QINFO, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ stx %o2, [%g2]
+ retl
+ nop
+ .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo
+
+ /* %o0: channel
+ * %o1: pointer to unsigned long head_off
+ * %o2: pointer to unsigned long tail_off
+ * %o2: pointer to unsigned long chan_state
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_tx_get_state
+ .type sun4v_ldc_tx_get_state,#function
+sun4v_ldc_tx_get_state:
+ mov %o1, %g1
+ mov %o2, %g2
+ mov %o3, %g3
+ mov HV_FAST_LDC_TX_GET_STATE, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ stx %o2, [%g2]
+ stx %o3, [%g3]
+ retl
+ nop
+ .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state
+
+ /* %o0: channel
+ * %o1: tail_off
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_tx_set_qtail
+ .type sun4v_ldc_tx_set_qtail,#function
+sun4v_ldc_tx_set_qtail:
+ mov HV_FAST_LDC_TX_SET_QTAIL, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail
+
+ /* %o0: channel
+ * %o1: ra
+ * %o2: num_entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_rx_qconf
+ .type sun4v_ldc_rx_qconf,#function
+sun4v_ldc_rx_qconf:
+ mov HV_FAST_LDC_RX_QCONF, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf
+
+ /* %o0: channel
+ * %o1: pointer to unsigned long ra
+ * %o2: pointer to unsigned long num_entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_rx_qinfo
+ .type sun4v_ldc_rx_qinfo,#function
+sun4v_ldc_rx_qinfo:
+ mov %o1, %g1
+ mov %o2, %g2
+ mov HV_FAST_LDC_RX_QINFO, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ stx %o2, [%g2]
+ retl
+ nop
+ .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo
+
+ /* %o0: channel
+ * %o1: pointer to unsigned long head_off
+ * %o2: pointer to unsigned long tail_off
+ * %o2: pointer to unsigned long chan_state
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_rx_get_state
+ .type sun4v_ldc_rx_get_state,#function
+sun4v_ldc_rx_get_state:
+ mov %o1, %g1
+ mov %o2, %g2
+ mov %o3, %g3
+ mov HV_FAST_LDC_RX_GET_STATE, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ stx %o2, [%g2]
+ stx %o3, [%g3]
+ retl
+ nop
+ .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state
+
+ /* %o0: channel
+ * %o1: head_off
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_rx_set_qhead
+ .type sun4v_ldc_rx_set_qhead,#function
+sun4v_ldc_rx_set_qhead:
+ mov HV_FAST_LDC_RX_SET_QHEAD, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead
+
+ /* %o0: channel
+ * %o1: ra
+ * %o2: num_entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_set_map_table
+ .type sun4v_ldc_set_map_table,#function
+sun4v_ldc_set_map_table:
+ mov HV_FAST_LDC_SET_MAP_TABLE, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table
+
+ /* %o0: channel
+ * %o1: pointer to unsigned long ra
+ * %o2: pointer to unsigned long num_entries
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_get_map_table
+ .type sun4v_ldc_get_map_table,#function
+sun4v_ldc_get_map_table:
+ mov %o1, %g1
+ mov %o2, %g2
+ mov HV_FAST_LDC_GET_MAP_TABLE, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ stx %o2, [%g2]
+ retl
+ nop
+ .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table
+
+ /* %o0: channel
+ * %o1: dir_code
+ * %o2: tgt_raddr
+ * %o3: lcl_raddr
+ * %o4: len
+ * %o5: pointer to unsigned long actual_len
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_copy
+ .type sun4v_ldc_copy,#function
+sun4v_ldc_copy:
+ mov %o5, %g1
+ mov HV_FAST_LDC_COPY, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ nop
+ .size sun4v_ldc_copy, .-sun4v_ldc_copy
+
+ /* %o0: channel
+ * %o1: cookie
+ * %o2: pointer to unsigned long ra
+ * %o3: pointer to unsigned long perm
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_mapin
+ .type sun4v_ldc_mapin,#function
+sun4v_ldc_mapin:
+ mov %o2, %g1
+ mov %o3, %g2
+ mov HV_FAST_LDC_MAPIN, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ stx %o2, [%g2]
+ retl
+ nop
+ .size sun4v_ldc_mapin, .-sun4v_ldc_mapin
+
+ /* %o0: ra
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_unmap
+ .type sun4v_ldc_unmap,#function
+sun4v_ldc_unmap:
+ mov HV_FAST_LDC_UNMAP, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_unmap, .-sun4v_ldc_unmap
+
+ /* %o0: cookie
+ * %o1: mte_cookie
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ldc_revoke
+ .type sun4v_ldc_revoke,#function
+sun4v_ldc_revoke:
+ mov HV_FAST_LDC_REVOKE, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ldc_revoke, .-sun4v_ldc_revoke
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: pointer to unsigned long cookie
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_get_cookie
+ .type sun4v_vintr_get_cookie,#function
+sun4v_vintr_get_cookie:
+ mov %o2, %g1
+ mov HV_FAST_VINTR_GET_COOKIE, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ nop
+ .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: cookie
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_set_cookie
+ .type sun4v_vintr_set_cookie,#function
+sun4v_vintr_set_cookie:
+ mov HV_FAST_VINTR_SET_COOKIE, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: pointer to unsigned long valid_state
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_get_valid
+ .type sun4v_vintr_get_valid,#function
+sun4v_vintr_get_valid:
+ mov %o2, %g1
+ mov HV_FAST_VINTR_GET_VALID, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ nop
+ .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: valid_state
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_set_valid
+ .type sun4v_vintr_set_valid,#function
+sun4v_vintr_set_valid:
+ mov HV_FAST_VINTR_SET_VALID, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: pointer to unsigned long state
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_get_state
+ .type sun4v_vintr_get_state,#function
+sun4v_vintr_get_state:
+ mov %o2, %g1
+ mov HV_FAST_VINTR_GET_STATE, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ nop
+ .size sun4v_vintr_get_state, .-sun4v_vintr_get_state
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: state
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_set_state
+ .type sun4v_vintr_set_state,#function
+sun4v_vintr_set_state:
+ mov HV_FAST_VINTR_SET_STATE, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_vintr_set_state, .-sun4v_vintr_set_state
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: pointer to unsigned long cpuid
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_get_target
+ .type sun4v_vintr_get_target,#function
+sun4v_vintr_get_target:
+ mov %o2, %g1
+ mov HV_FAST_VINTR_GET_TARGET, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%g1]
+ retl
+ nop
+ .size sun4v_vintr_get_target, .-sun4v_vintr_get_target
+
+ /* %o0: device handle
+ * %o1: device INO
+ * %o2: cpuid
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_vintr_set_target
+ .type sun4v_vintr_set_target,#function
+sun4v_vintr_set_target:
+ mov HV_FAST_VINTR_SET_TARGET, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_vintr_set_target, .-sun4v_vintr_set_target
+
+ /* %o0: NCS sub-function
+ * %o1: sub-function arg real-address
+ * %o2: sub-function arg size
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ncs_request
+ .type sun4v_ncs_request,#function
+sun4v_ncs_request:
+ mov HV_FAST_NCS_REQUEST, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ncs_request, .-sun4v_ncs_request
+
+ .globl sun4v_scv_send
+ .type sun4v_scv_send,#function
+sun4v_scv_send:
+ save %sp, -192, %sp
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ mov HV_FAST_SVC_SEND, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%i3]
+ ret
+ restore
+ .size sun4v_scv_send, .-sun4v_scv_send
+
+ .globl sun4v_scv_recv
+ .type sun4v_scv_recv,#function
+sun4v_scv_recv:
+ save %sp, -192, %sp
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ mov HV_FAST_SVC_RECV, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%i3]
+ ret
+ restore
+ .size sun4v_scv_recv, .-sun4v_scv_recv
+
+ .globl sun4v_scv_getstatus
+ .type sun4v_scv_getstatus,#function
+sun4v_scv_getstatus:
+ mov HV_FAST_SVC_GETSTATUS, %o5
+ mov %o1, %o4
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_scv_getstatus, .-sun4v_scv_getstatus
+
+ .globl sun4v_scv_setstatus
+ .type sun4v_scv_setstatus,#function
+sun4v_scv_setstatus:
+ mov HV_FAST_SVC_SETSTATUS, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_scv_setstatus, .-sun4v_scv_setstatus
+
+ .globl sun4v_scv_clrstatus
+ .type sun4v_scv_clrstatus,#function
+sun4v_scv_clrstatus:
+ mov HV_FAST_SVC_CLRSTATUS, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_scv_clrstatus, .-sun4v_scv_clrstatus
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index baea10a9819..77259526cb1 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -523,7 +523,7 @@ tlb_fixup_done:
#else
mov 0, %o0
#endif
- stb %o0, [%g6 + TI_CPU]
+ sth %o0, [%g6 + TI_CPU]
/* Off we go.... */
call start_kernel
@@ -653,33 +653,54 @@ setup_tba:
restore
sparc64_boot_end:
-#include "ktlb.S"
-#include "tsb.S"
#include "etrap.S"
#include "rtrap.S"
#include "winfixup.S"
#include "entry.S"
#include "sun4v_tlb_miss.S"
#include "sun4v_ivec.S"
+#include "ktlb.S"
+#include "tsb.S"
/*
* The following skip makes sure the trap table in ttable.S is aligned
* on a 32K boundary as required by the v9 specs for TBA register.
*
* We align to a 32K boundary, then we have the 32K kernel TSB,
- * then the 32K aligned trap table.
+ * the 64K kernel 4MB TSB, and then the 32K aligned trap table.
*/
1:
.skip 0x4000 + _start - 1b
+! 0x0000000000408000
+
.globl swapper_tsb
swapper_tsb:
.skip (32 * 1024)
-! 0x0000000000408000
+ .globl swapper_4m_tsb
+swapper_4m_tsb:
+ .skip (64 * 1024)
+
+! 0x0000000000420000
+ /* Some care needs to be exercised if you try to move the
+ * location of the trap table relative to other things. For
+ * one thing there are br* instructions in some of the
+ * trap table entires which branch back to code in ktlb.S
+ * Those instructions can only handle a signed 16-bit
+ * displacement.
+ *
+ * There is a binutils bug (bugzilla #4558) which causes
+ * the relocation overflow checks for such instructions to
+ * not be done correctly. So bintuils will not notice the
+ * error and will instead write junk into the relocation and
+ * you'll have an unbootable kernel.
+ */
#include "ttable.S"
+! 0x0000000000428000
+
#include "systbls.S"
.data
diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c
index f03ffc829c7..f34f5d6181e 100644
--- a/arch/sparc64/kernel/hvapi.c
+++ b/arch/sparc64/kernel/hvapi.c
@@ -9,6 +9,7 @@
#include <asm/hypervisor.h>
#include <asm/oplib.h>
+#include <asm/sstate.h>
/* If the hypervisor indicates that the API setting
* calls are unsupported, by returning HV_EBADTRAP or
@@ -107,7 +108,7 @@ int sun4v_hvapi_register(unsigned long group, unsigned long major,
p->minor = actual_minor;
ret = 0;
} else if (hv_ret == HV_EBADTRAP ||
- HV_ENOTSUPPORTED) {
+ hv_ret == HV_ENOTSUPPORTED) {
if (p->flags & FLAG_PRE_API) {
if (major == 1) {
p->major = 1;
@@ -179,6 +180,8 @@ void __init sun4v_hvapi_init(void)
if (sun4v_hvapi_register(group, major, &minor))
goto bad;
+ sun4v_sstate_init();
+
return;
bad:
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 3edc18e1b81..a36f8dd0c02 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -171,8 +171,6 @@ skip:
return 0;
}
-extern unsigned long real_hard_smp_processor_id(void);
-
static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid)
{
unsigned int tid;
@@ -694,9 +692,20 @@ void init_irqwork_curcpu(void)
trap_block[cpu].irq_worklist = 0;
}
-static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type)
+/* Please be very careful with register_one_mondo() and
+ * sun4v_register_mondo_queues().
+ *
+ * On SMP this gets invoked from the CPU trampoline before
+ * the cpu has fully taken over the trap table from OBP,
+ * and it's kernel stack + %g6 thread register state is
+ * not fully cooked yet.
+ *
+ * Therefore you cannot make any OBP calls, not even prom_printf,
+ * from these two routines.
+ */
+static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
{
- unsigned long num_entries = 128;
+ unsigned long num_entries = (qmask + 1) / 64;
unsigned long status;
status = sun4v_cpu_qconf(type, paddr, num_entries);
@@ -711,44 +720,58 @@ static void __cpuinit sun4v_register_mondo_queues(int this_cpu)
{
struct trap_per_cpu *tb = &trap_block[this_cpu];
- register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO);
- register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO);
- register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR);
- register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR);
+ register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO,
+ tb->cpu_mondo_qmask);
+ register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO,
+ tb->dev_mondo_qmask);
+ register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR,
+ tb->resum_qmask);
+ register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR,
+ tb->nonresum_qmask);
}
-static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, int use_bootmem)
+static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem)
{
- void *page;
+ unsigned long size = PAGE_ALIGN(qmask + 1);
+ unsigned long order = get_order(size);
+ void *p = NULL;
- if (use_bootmem)
- page = alloc_bootmem_low_pages(PAGE_SIZE);
- else
- page = (void *) get_zeroed_page(GFP_ATOMIC);
+ if (use_bootmem) {
+ p = __alloc_bootmem_low(size, size, 0);
+ } else {
+ struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
+ if (page)
+ p = page_address(page);
+ }
- if (!page) {
+ if (!p) {
prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
prom_halt();
}
- *pa_ptr = __pa(page);
+ *pa_ptr = __pa(p);
}
-static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, int use_bootmem)
+static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem)
{
- void *page;
+ unsigned long size = PAGE_ALIGN(qmask + 1);
+ unsigned long order = get_order(size);
+ void *p = NULL;
- if (use_bootmem)
- page = alloc_bootmem_low_pages(PAGE_SIZE);
- else
- page = (void *) get_zeroed_page(GFP_ATOMIC);
+ if (use_bootmem) {
+ p = __alloc_bootmem_low(size, size, 0);
+ } else {
+ struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order);
+ if (page)
+ p = page_address(page);
+ }
- if (!page) {
+ if (!p) {
prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
prom_halt();
}
- *pa_ptr = __pa(page);
+ *pa_ptr = __pa(p);
}
static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem)
@@ -779,12 +802,12 @@ void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int
struct trap_per_cpu *tb = &trap_block[cpu];
if (alloc) {
- alloc_one_mondo(&tb->cpu_mondo_pa, use_bootmem);
- alloc_one_mondo(&tb->dev_mondo_pa, use_bootmem);
- alloc_one_mondo(&tb->resum_mondo_pa, use_bootmem);
- alloc_one_kbuf(&tb->resum_kernel_buf_pa, use_bootmem);
- alloc_one_mondo(&tb->nonresum_mondo_pa, use_bootmem);
- alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, use_bootmem);
+ alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask, use_bootmem);
+ alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask, use_bootmem);
+ alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask, use_bootmem);
+ alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask, use_bootmem);
+ alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask, use_bootmem);
+ alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, tb->nonresum_qmask, use_bootmem);
init_cpu_send_mondo_info(tb, use_bootmem);
}
diff --git a/arch/sparc64/kernel/itlb_miss.S b/arch/sparc64/kernel/itlb_miss.S
index ad46e2024f4..5a8377b5495 100644
--- a/arch/sparc64/kernel/itlb_miss.S
+++ b/arch/sparc64/kernel/itlb_miss.S
@@ -11,12 +11,12 @@
/* ITLB ** ICACHE line 2: TSB compare and TLB load */
bne,pn %xcc, tsb_miss_itlb ! Miss
mov FAULT_CODE_ITLB, %g3
- andcc %g5, _PAGE_EXEC_4U, %g0 ! Executable?
+ sethi %hi(_PAGE_EXEC_4U), %g4
+ andcc %g5, %g4, %g0 ! Executable?
be,pn %xcc, tsb_do_fault
nop ! Delay slot, fill me
stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load TLB
retry ! Trap done
- nop
/* ITLB ** ICACHE line 3: */
nop
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
new file mode 100644
index 00000000000..9246c2cf957
--- /dev/null
+++ b/arch/sparc64/kernel/mdesc.c
@@ -0,0 +1,619 @@
+/* mdesc.c: Sun4V machine description handling.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/log2.h>
+
+#include <asm/hypervisor.h>
+#include <asm/mdesc.h>
+#include <asm/prom.h>
+#include <asm/oplib.h>
+#include <asm/smp.h>
+
+/* Unlike the OBP device tree, the machine description is a full-on
+ * DAG. An arbitrary number of ARCs are possible from one
+ * node to other nodes and thus we can't use the OBP device_node
+ * data structure to represent these nodes inside of the kernel.
+ *
+ * Actually, it isn't even a DAG, because there are back pointers
+ * which create cycles in the graph.
+ *
+ * mdesc_hdr and mdesc_elem describe the layout of the data structure
+ * we get from the Hypervisor.
+ */
+struct mdesc_hdr {
+ u32 version; /* Transport version */
+ u32 node_sz; /* node block size */
+ u32 name_sz; /* name block size */
+ u32 data_sz; /* data block size */
+};
+
+struct mdesc_elem {
+ u8 tag;
+#define MD_LIST_END 0x00
+#define MD_NODE 0x4e
+#define MD_NODE_END 0x45
+#define MD_NOOP 0x20
+#define MD_PROP_ARC 0x61
+#define MD_PROP_VAL 0x76
+#define MD_PROP_STR 0x73
+#define MD_PROP_DATA 0x64
+ u8 name_len;
+ u16 resv;
+ u32 name_offset;
+ union {
+ struct {
+ u32 data_len;
+ u32 data_offset;
+ } data;
+ u64 val;
+ } d;
+};
+
+static struct mdesc_hdr *main_mdesc;
+static struct mdesc_node *allnodes;
+
+static struct mdesc_node *allnodes_tail;
+static unsigned int unique_id;
+
+static struct mdesc_node **mdesc_hash;
+static unsigned int mdesc_hash_size;
+
+static inline unsigned int node_hashfn(u64 node)
+{
+ return ((unsigned int) (node ^ (node >> 8) ^ (node >> 16)))
+ & (mdesc_hash_size - 1);
+}
+
+static inline void hash_node(struct mdesc_node *mp)
+{
+ struct mdesc_node **head = &mdesc_hash[node_hashfn(mp->node)];
+
+ mp->hash_next = *head;
+ *head = mp;
+
+ if (allnodes_tail) {
+ allnodes_tail->allnodes_next = mp;
+ allnodes_tail = mp;
+ } else {
+ allnodes = allnodes_tail = mp;
+ }
+}
+
+static struct mdesc_node *find_node(u64 node)
+{
+ struct mdesc_node *mp = mdesc_hash[node_hashfn(node)];
+
+ while (mp) {
+ if (mp->node == node)
+ return mp;
+
+ mp = mp->hash_next;
+ }
+ return NULL;
+}
+
+struct property *md_find_property(const struct mdesc_node *mp,
+ const char *name,
+ int *lenp)
+{
+ struct property *pp;
+
+ for (pp = mp->properties; pp != 0; pp = pp->next) {
+ if (strcasecmp(pp->name, name) == 0) {
+ if (lenp)
+ *lenp = pp->length;
+ break;
+ }
+ }
+ return pp;
+}
+EXPORT_SYMBOL(md_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+const void *md_get_property(const struct mdesc_node *mp, const char *name,
+ int *lenp)
+{
+ struct property *pp = md_find_property(mp, name, lenp);
+ return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(md_get_property);
+
+struct mdesc_node *md_find_node_by_name(struct mdesc_node *from,
+ const char *name)
+{
+ struct mdesc_node *mp;
+
+ mp = from ? from->allnodes_next : allnodes;
+ for (; mp != NULL; mp = mp->allnodes_next) {
+ if (strcmp(mp->name, name) == 0)
+ break;
+ }
+ return mp;
+}
+EXPORT_SYMBOL(md_find_node_by_name);
+
+static unsigned int mdesc_early_allocated;
+
+static void * __init mdesc_early_alloc(unsigned long size)
+{
+ void *ret;
+
+ ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+ if (ret == NULL) {
+ prom_printf("MDESC: alloc of %lu bytes failed.\n", size);
+ prom_halt();
+ }
+
+ memset(ret, 0, size);
+
+ mdesc_early_allocated += size;
+
+ return ret;
+}
+
+static unsigned int __init count_arcs(struct mdesc_elem *ep)
+{
+ unsigned int ret = 0;
+
+ ep++;
+ while (ep->tag != MD_NODE_END) {
+ if (ep->tag == MD_PROP_ARC)
+ ret++;
+ ep++;
+ }
+ return ret;
+}
+
+static void __init mdesc_node_alloc(u64 node, struct mdesc_elem *ep, const char *names)
+{
+ unsigned int num_arcs = count_arcs(ep);
+ struct mdesc_node *mp;
+
+ mp = mdesc_early_alloc(sizeof(*mp) +
+ (num_arcs * sizeof(struct mdesc_arc)));
+ mp->name = names + ep->name_offset;
+ mp->node = node;
+ mp->unique_id = unique_id++;
+ mp->num_arcs = num_arcs;
+
+ hash_node(mp);
+}
+
+static inline struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
+{
+ return (struct mdesc_elem *) (mdesc + 1);
+}
+
+static inline void *name_block(struct mdesc_hdr *mdesc)
+{
+ return ((void *) node_block(mdesc)) + mdesc->node_sz;
+}
+
+static inline void *data_block(struct mdesc_hdr *mdesc)
+{
+ return ((void *) name_block(mdesc)) + mdesc->name_sz;
+}
+
+/* In order to avoid recursion (the graph can be very deep) we use a
+ * two pass algorithm. First we allocate all the nodes and hash them.
+ * Then we iterate over each node, filling in the arcs and properties.
+ */
+static void __init build_all_nodes(struct mdesc_hdr *mdesc)
+{
+ struct mdesc_elem *start, *ep;
+ struct mdesc_node *mp;
+ const char *names;
+ void *data;
+ u64 last_node;
+
+ start = ep = node_block(mdesc);
+ last_node = mdesc->node_sz / 16;
+
+ names = name_block(mdesc);
+
+ while (1) {
+ u64 node = ep - start;
+
+ if (ep->tag == MD_LIST_END)
+ break;
+
+ if (ep->tag != MD_NODE) {
+ prom_printf("MDESC: Inconsistent element list.\n");
+ prom_halt();
+ }
+
+ mdesc_node_alloc(node, ep, names);
+
+ if (ep->d.val >= last_node) {
+ printk("MDESC: Warning, early break out of node scan.\n");
+ printk("MDESC: Next node [%lu] last_node [%lu].\n",
+ node, last_node);
+ break;
+ }
+
+ ep = start + ep->d.val;
+ }
+
+ data = data_block(mdesc);
+ for (mp = allnodes; mp; mp = mp->allnodes_next) {
+ struct mdesc_elem *ep = start + mp->node;
+ struct property **link = &mp->properties;
+ unsigned int this_arc = 0;
+
+ ep++;
+ while (ep->tag != MD_NODE_END) {
+ switch (ep->tag) {
+ case MD_PROP_ARC: {
+ struct mdesc_node *target;
+
+ if (this_arc >= mp->num_arcs) {
+ prom_printf("MDESC: ARC overrun [%u:%u]\n",
+ this_arc, mp->num_arcs);
+ prom_halt();
+ }
+ target = find_node(ep->d.val);
+ if (!target) {
+ printk("MDESC: Warning, arc points to "
+ "missing node, ignoring.\n");
+ break;
+ }
+ mp->arcs[this_arc].name =
+ (names + ep->name_offset);
+ mp->arcs[this_arc].arc = target;
+ this_arc++;
+ break;
+ }
+
+ case MD_PROP_VAL:
+ case MD_PROP_STR:
+ case MD_PROP_DATA: {
+ struct property *p = mdesc_early_alloc(sizeof(*p));
+
+ p->unique_id = unique_id++;
+ p->name = (char *) names + ep->name_offset;
+ if (ep->tag == MD_PROP_VAL) {
+ p->value = &ep->d.val;
+ p->length = 8;
+ } else {
+ p->value = data + ep->d.data.data_offset;
+ p->length = ep->d.data.data_len;
+ }
+ *link = p;
+ link = &p->next;
+ break;
+ }
+
+ case MD_NOOP:
+ break;
+
+ default:
+ printk("MDESC: Warning, ignoring unknown tag type %02x\n",
+ ep->tag);
+ }
+ ep++;
+ }
+ }
+}
+
+static unsigned int __init count_nodes(struct mdesc_hdr *mdesc)
+{
+ struct mdesc_elem *ep = node_block(mdesc);
+ struct mdesc_elem *end;
+ unsigned int cnt = 0;
+
+ end = ((void *)ep) + mdesc->node_sz;
+ while (ep < end) {
+ if (ep->tag == MD_NODE)
+ cnt++;
+ ep++;
+ }
+ return cnt;
+}
+
+static void __init report_platform_properties(void)
+{
+ struct mdesc_node *pn = md_find_node_by_name(NULL, "platform");
+ const char *s;
+ const u64 *v;
+
+ if (!pn) {
+ prom_printf("No platform node in machine-description.\n");
+ prom_halt();
+ }
+
+ s = md_get_property(pn, "banner-name", NULL);
+ printk("PLATFORM: banner-name [%s]\n", s);
+ s = md_get_property(pn, "name", NULL);
+ printk("PLATFORM: name [%s]\n", s);
+
+ v = md_get_property(pn, "hostid", NULL);
+ if (v)
+ printk("PLATFORM: hostid [%08lx]\n", *v);
+ v = md_get_property(pn, "serial#", NULL);
+ if (v)
+ printk("PLATFORM: serial# [%08lx]\n", *v);
+ v = md_get_property(pn, "stick-frequency", NULL);
+ printk("PLATFORM: stick-frequency [%08lx]\n", *v);
+ v = md_get_property(pn, "mac-address", NULL);
+ if (v)
+ printk("PLATFORM: mac-address [%lx]\n", *v);
+ v = md_get_property(pn, "watchdog-resolution", NULL);
+ if (v)
+ printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
+ v = md_get_property(pn, "watchdog-max-timeout", NULL);
+ if (v)
+ printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
+ v = md_get_property(pn, "max-cpus", NULL);
+ if (v)
+ printk("PLATFORM: max-cpus [%lu]\n", *v);
+}
+
+static int inline find_in_proplist(const char *list, const char *match, int len)
+{
+ while (len > 0) {
+ int l;
+
+ if (!strcmp(list, match))
+ return 1;
+ l = strlen(list) + 1;
+ list += l;
+ len -= l;
+ }
+ return 0;
+}
+
+static void __init fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_node *mp)
+{
+ const u64 *level = md_get_property(mp, "level", NULL);
+ const u64 *size = md_get_property(mp, "size", NULL);
+ const u64 *line_size = md_get_property(mp, "line-size", NULL);
+ const char *type;
+ int type_len;
+
+ type = md_get_property(mp, "type", &type_len);
+
+ switch (*level) {
+ case 1:
+ if (find_in_proplist(type, "instn", type_len)) {
+ c->icache_size = *size;
+ c->icache_line_size = *line_size;
+ } else if (find_in_proplist(type, "data", type_len)) {
+ c->dcache_size = *size;
+ c->dcache_line_size = *line_size;
+ }
+ break;
+
+ case 2:
+ c->ecache_size = *size;
+ c->ecache_line_size = *line_size;
+ break;
+
+ default:
+ break;
+ }
+
+ if (*level == 1) {
+ unsigned int i;
+
+ for (i = 0; i < mp->num_arcs; i++) {
+ struct mdesc_node *t = mp->arcs[i].arc;
+
+ if (strcmp(mp->arcs[i].name, "fwd"))
+ continue;
+
+ if (!strcmp(t->name, "cache"))
+ fill_in_one_cache(c, t);
+ }
+ }
+}
+
+static void __init mark_core_ids(struct mdesc_node *mp, int core_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < mp->num_arcs; i++) {
+ struct mdesc_node *t = mp->arcs[i].arc;
+ const u64 *id;
+
+ if (strcmp(mp->arcs[i].name, "back"))
+ continue;
+
+ if (!strcmp(t->name, "cpu")) {
+ id = md_get_property(t, "id", NULL);
+ if (*id < NR_CPUS)
+ cpu_data(*id).core_id = core_id;
+ } else {
+ unsigned int j;
+
+ for (j = 0; j < t->num_arcs; j++) {
+ struct mdesc_node *n = t->arcs[j].arc;
+
+ if (strcmp(t->arcs[j].name, "back"))
+ continue;
+
+ if (strcmp(n->name, "cpu"))
+ continue;
+
+ id = md_get_property(n, "id", NULL);
+ if (*id < NR_CPUS)
+ cpu_data(*id).core_id = core_id;
+ }
+ }
+ }
+}
+
+static void __init set_core_ids(void)
+{
+ struct mdesc_node *mp;
+ int idx;
+
+ idx = 1;
+ md_for_each_node_by_name(mp, "cache") {
+ const u64 *level = md_get_property(mp, "level", NULL);
+ const char *type;
+ int len;
+
+ if (*level != 1)
+ continue;
+
+ type = md_get_property(mp, "type", &len);
+ if (!find_in_proplist(type, "instn", len))
+ continue;
+
+ mark_core_ids(mp, idx);
+
+ idx++;
+ }
+}
+
+static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def)
+{
+ u64 val;
+
+ if (!p)
+ goto use_default;
+ val = *p;
+
+ if (!val || val >= 64)
+ goto use_default;
+
+ *mask = ((1U << val) * 64U) - 1U;
+ return;
+
+use_default:
+ *mask = ((1U << def) * 64U) - 1U;
+}
+
+static void __init get_mondo_data(struct mdesc_node *mp, struct trap_per_cpu *tb)
+{
+ const u64 *val;
+
+ val = md_get_property(mp, "q-cpu-mondo-#bits", NULL);
+ get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
+
+ val = md_get_property(mp, "q-dev-mondo-#bits", NULL);
+ get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
+
+ val = md_get_property(mp, "q-resumable-#bits", NULL);
+ get_one_mondo_bits(val, &tb->resum_qmask, 6);
+
+ val = md_get_property(mp, "q-nonresumable-#bits", NULL);
+ get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
+}
+
+static void __init mdesc_fill_in_cpu_data(void)
+{
+ struct mdesc_node *mp;
+
+ ncpus_probed = 0;
+ md_for_each_node_by_name(mp, "cpu") {
+ const u64 *id = md_get_property(mp, "id", NULL);
+ const u64 *cfreq = md_get_property(mp, "clock-frequency", NULL);
+ struct trap_per_cpu *tb;
+ cpuinfo_sparc *c;
+ unsigned int i;
+ int cpuid;
+
+ ncpus_probed++;
+
+ cpuid = *id;
+
+#ifdef CONFIG_SMP
+ if (cpuid >= NR_CPUS)
+ continue;
+#else
+ /* On uniprocessor we only want the values for the
+ * real physical cpu the kernel booted onto, however
+ * cpu_data() only has one entry at index 0.
+ */
+ if (cpuid != real_hard_smp_processor_id())
+ continue;
+ cpuid = 0;
+#endif
+
+ c = &cpu_data(cpuid);
+ c->clock_tick = *cfreq;
+
+ tb = &trap_block[cpuid];
+ get_mondo_data(mp, tb);
+
+ for (i = 0; i < mp->num_arcs; i++) {
+ struct mdesc_node *t = mp->arcs[i].arc;
+ unsigned int j;
+
+ if (strcmp(mp->arcs[i].name, "fwd"))
+ continue;
+
+ if (!strcmp(t->name, "cache")) {
+ fill_in_one_cache(c, t);
+ continue;
+ }
+
+ for (j = 0; j < t->num_arcs; j++) {
+ struct mdesc_node *n;
+
+ n = t->arcs[j].arc;
+ if (strcmp(t->arcs[j].name, "fwd"))
+ continue;
+
+ if (!strcmp(n->name, "cache"))
+ fill_in_one_cache(c, n);
+ }
+ }
+
+#ifdef CONFIG_SMP
+ cpu_set(cpuid, cpu_present_map);
+ cpu_set(cpuid, phys_cpu_present_map);
+#endif
+
+ c->core_id = 0;
+ }
+
+ set_core_ids();
+
+ smp_fill_in_sib_core_maps();
+}
+
+void __init sun4v_mdesc_init(void)
+{
+ unsigned long len, real_len, status;
+
+ (void) sun4v_mach_desc(0UL, 0UL, &len);
+
+ printk("MDESC: Size is %lu bytes.\n", len);
+
+ main_mdesc = mdesc_early_alloc(len);
+
+ status = sun4v_mach_desc(__pa(main_mdesc), len, &real_len);
+ if (status != HV_EOK || real_len > len) {
+ prom_printf("sun4v_mach_desc fails, err(%lu), "
+ "len(%lu), real_len(%lu)\n",
+ status, len, real_len);
+ prom_halt();
+ }
+
+ len = count_nodes(main_mdesc);
+ printk("MDESC: %lu nodes.\n", len);
+
+ len = roundup_pow_of_two(len);
+
+ mdesc_hash = mdesc_early_alloc(len * sizeof(struct mdesc_node *));
+ mdesc_hash_size = len;
+
+ printk("MDESC: Hash size %lu entries.\n", len);
+
+ build_all_nodes(main_mdesc);
+
+ printk("MDESC: Built graph with %u bytes of memory.\n",
+ mdesc_early_allocated);
+
+ report_platform_properties();
+ mdesc_fill_in_cpu_data();
+}
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index d4c077dc5e8..38a32bc95d2 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -306,6 +306,20 @@ static void __init pci_controller_probe(void)
pci_controller_scan(pci_controller_init);
}
+static int ofpci_verbose;
+
+static int __init ofpci_debug(char *str)
+{
+ int val = 0;
+
+ get_option(&str, &val);
+ if (val)
+ ofpci_verbose = 1;
+ return 1;
+}
+
+__setup("ofpci_debug=", ofpci_debug);
+
static unsigned long pci_parse_of_flags(u32 addr0)
{
unsigned long flags = 0;
@@ -337,7 +351,9 @@ static void pci_parse_of_addrs(struct of_device *op,
addrs = of_get_property(node, "assigned-addresses", &proplen);
if (!addrs)
return;
- printk(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
+ if (ofpci_verbose)
+ printk(" parse addresses (%d bytes) @ %p\n",
+ proplen, addrs);
op_res = &op->resource[0];
for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) {
struct resource *res;
@@ -348,8 +364,9 @@ static void pci_parse_of_addrs(struct of_device *op,
if (!flags)
continue;
i = addrs[0] & 0xff;
- printk(" start: %lx, end: %lx, i: %x\n",
- op_res->start, op_res->end, i);
+ if (ofpci_verbose)
+ printk(" start: %lx, end: %lx, i: %x\n",
+ op_res->start, op_res->end, i);
if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
@@ -393,8 +410,9 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
if (type == NULL)
type = "";
- printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n",
- devfn, type, host_controller);
+ if (ofpci_verbose)
+ printk(" create device, devfn: %x, type: %s\n",
+ devfn, type);
dev->bus = bus;
dev->sysdata = node;
@@ -434,8 +452,9 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
}
- printk(" class: 0x%x device name: %s\n",
- dev->class, pci_name(dev));
+ if (ofpci_verbose)
+ printk(" class: 0x%x device name: %s\n",
+ dev->class, pci_name(dev));
/* I have seen IDE devices which will not respond to
* the bmdma simplex check reads if bus mastering is
@@ -469,7 +488,8 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
}
pci_parse_of_addrs(sd->op, node, dev);
- printk(" adding to system ...\n");
+ if (ofpci_verbose)
+ printk(" adding to system ...\n");
pci_device_add(dev, bus);
@@ -547,7 +567,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
unsigned int flags;
u64 size;
- printk("of_scan_pci_bridge(%s)\n", node->full_name);
+ if (ofpci_verbose)
+ printk("of_scan_pci_bridge(%s)\n", node->full_name);
/* parse bus-range property */
busrange = of_get_property(node, "bus-range", &len);
@@ -632,7 +653,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
simba_cont:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
- printk(" bus name: %s\n", bus->name);
+ if (ofpci_verbose)
+ printk(" bus name: %s\n", bus->name);
pci_of_scan_bus(pbm, node, bus);
}
@@ -646,12 +668,14 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
int reglen, devfn;
struct pci_dev *dev;
- printk("PCI: scan_bus[%s] bus no %d\n",
- node->full_name, bus->number);
+ if (ofpci_verbose)
+ printk("PCI: scan_bus[%s] bus no %d\n",
+ node->full_name, bus->number);
child = NULL;
while ((child = of_get_next_child(node, child)) != NULL) {
- printk(" * %s\n", child->full_name);
+ if (ofpci_verbose)
+ printk(" * %s\n", child->full_name);
reg = of_get_property(child, "reg", &reglen);
if (reg == NULL || reglen < 20)
continue;
@@ -661,7 +685,9 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
if (!dev)
continue;
- printk("PCI: dev header type: %x\n", dev->hdr_type);
+ if (ofpci_verbose)
+ printk("PCI: dev header type: %x\n",
+ dev->hdr_type);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index e2377796de8..323d6c27851 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -762,9 +762,10 @@ void sabre_init(struct device_node *dp, char *model_name)
/* Of course, Sun has to encode things a thousand
* different ways, inconsistently.
*/
- cpu_find_by_instance(0, &dp, NULL);
- if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
- hummingbird_p = 1;
+ for_each_node_by_type(dp, "cpu") {
+ if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
+ hummingbird_p = 1;
+ }
}
}
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 044e8ec4c0f..6b3fe2c1d65 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -12,6 +12,7 @@
#include <linux/percpu.h>
#include <linux/irq.h>
#include <linux/msi.h>
+#include <linux/log2.h>
#include <asm/iommu.h>
#include <asm/irq.h>
@@ -26,6 +27,9 @@
#include "pci_sun4v.h"
+static unsigned long vpci_major = 1;
+static unsigned long vpci_minor = 1;
+
#define PGLIST_NENTS (PAGE_SIZE / sizeof(u64))
struct iommu_batch {
@@ -638,9 +642,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct iommu *iommu = pbm->iommu;
struct property *prop;
- unsigned long num_tsb_entries, sz;
+ unsigned long num_tsb_entries, sz, tsbsize;
u32 vdma[2], dma_mask, dma_offset;
- int tsbsize;
prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
if (prop) {
@@ -654,31 +657,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
vdma[1] = 0x80000000;
}
- dma_mask = vdma[0];
- switch (vdma[1]) {
- case 0x20000000:
- dma_mask |= 0x1fffffff;
- tsbsize = 64;
- break;
-
- case 0x40000000:
- dma_mask |= 0x3fffffff;
- tsbsize = 128;
- break;
-
- case 0x80000000:
- dma_mask |= 0x7fffffff;
- tsbsize = 256;
- break;
-
- default:
- prom_printf("PCI-SUN4V: strange virtual-dma size.\n");
- prom_halt();
+ if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) {
+ prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n",
+ vdma[0], vdma[1]);
+ prom_halt();
};
- tsbsize *= (8 * 1024);
-
- num_tsb_entries = tsbsize / sizeof(iopte_t);
+ dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
+ num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
+ tsbsize = num_tsb_entries * sizeof(iopte_t);
dma_offset = vdma[0];
@@ -689,7 +676,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
iommu->dma_addr_mask = dma_mask;
/* Allocate and initialize the free area map. */
- sz = num_tsb_entries / 8;
+ sz = (num_tsb_entries + 7) / 8;
sz = (sz + 7UL) & ~7UL;
iommu->arena.map = kzalloc(sz, GFP_KERNEL);
if (!iommu->arena.map) {
@@ -1178,6 +1165,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
void sun4v_pci_init(struct device_node *dp, char *model_name)
{
+ static int hvapi_negotiated = 0;
struct pci_controller_info *p;
struct pci_pbm_info *pbm;
struct iommu *iommu;
@@ -1186,6 +1174,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
u32 devhandle;
int i;
+ if (!hvapi_negotiated++) {
+ int err = sun4v_hvapi_register(HV_GRP_PCI,
+ vpci_major,
+ &vpci_minor);
+
+ if (err) {
+ prom_printf("SUN4V_PCI: Could not register hvapi, "
+ "err=%d\n", err);
+ prom_halt();
+ }
+ printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n",
+ vpci_major, vpci_minor);
+ }
+
prop = of_find_property(dp, "reg", NULL);
regs = prop->value;
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 699b24b890d..5d6adea3967 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -19,6 +19,7 @@
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/io.h>
+#include <asm/sstate.h>
#include <linux/unistd.h>
@@ -53,6 +54,7 @@ static void (*poweroff_method)(void) = machine_alt_power_off;
void machine_power_off(void)
{
+ sstate_poweroff();
if (!serial_console || scons_pwroff) {
#ifdef CONFIG_PCI
if (power_reg) {
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 952762bfb4c..f5f97e2c669 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -45,6 +45,7 @@
#include <asm/mmu_context.h>
#include <asm/unistd.h>
#include <asm/hypervisor.h>
+#include <asm/sstate.h>
/* #define VERBOSE_SHOWREGS */
@@ -106,6 +107,7 @@ extern void (*prom_keyboard)(void);
void machine_halt(void)
{
+ sstate_halt();
if (!serial_console && prom_palette)
prom_palette (1);
if (prom_keyboard)
@@ -116,6 +118,7 @@ void machine_halt(void)
void machine_alt_power_off(void)
{
+ sstate_poweroff();
if (!serial_console && prom_palette)
prom_palette(1);
if (prom_keyboard)
@@ -128,6 +131,7 @@ void machine_restart(char * cmd)
{
char *p;
+ sstate_reboot();
p = strchr (reboot_command, '\n');
if (p) *p = 0;
if (!serial_console && prom_palette)
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 02830e4671f..dad4b3ba705 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -28,6 +28,7 @@
#include <asm/irq.h>
#include <asm/asi.h>
#include <asm/upa.h>
+#include <asm/smp.h>
static struct device_node *allnodes;
@@ -1665,6 +1666,150 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl
return ret;
}
+static const char *get_mid_prop(void)
+{
+ return (tlb_type == spitfire ? "upa-portid" : "portid");
+}
+
+struct device_node *of_find_node_by_cpuid(int cpuid)
+{
+ struct device_node *dp;
+ const char *mid_prop = get_mid_prop();
+
+ for_each_node_by_type(dp, "cpu") {
+ int id = of_getintprop_default(dp, mid_prop, -1);
+ const char *this_mid_prop = mid_prop;
+
+ if (id < 0) {
+ this_mid_prop = "cpuid";
+ id = of_getintprop_default(dp, this_mid_prop, -1);
+ }
+
+ if (id < 0) {
+ prom_printf("OF: Serious problem, cpu lacks "
+ "%s property", this_mid_prop);
+ prom_halt();
+ }
+ if (cpuid == id)
+ return dp;
+ }
+ return NULL;
+}
+
+static void __init of_fill_in_cpu_data(void)
+{
+ struct device_node *dp;
+ const char *mid_prop = get_mid_prop();
+
+ ncpus_probed = 0;
+ for_each_node_by_type(dp, "cpu") {
+ int cpuid = of_getintprop_default(dp, mid_prop, -1);
+ const char *this_mid_prop = mid_prop;
+ struct device_node *portid_parent;
+ int portid = -1;
+
+ portid_parent = NULL;
+ if (cpuid < 0) {
+ this_mid_prop = "cpuid";
+ cpuid = of_getintprop_default(dp, this_mid_prop, -1);
+ if (cpuid >= 0) {
+ int limit = 2;
+
+ portid_parent = dp;
+ while (limit--) {
+ portid_parent = portid_parent->parent;
+ if (!portid_parent)
+ break;
+ portid = of_getintprop_default(portid_parent,
+ "portid", -1);
+ if (portid >= 0)
+ break;
+ }
+ }
+ }
+
+ if (cpuid < 0) {
+ prom_printf("OF: Serious problem, cpu lacks "
+ "%s property", this_mid_prop);
+ prom_halt();
+ }
+
+ ncpus_probed++;
+
+#ifdef CONFIG_SMP
+ if (cpuid >= NR_CPUS)
+ continue;
+#else
+ /* On uniprocessor we only want the values for the
+ * real physical cpu the kernel booted onto, however
+ * cpu_data() only has one entry at index 0.
+ */
+ if (cpuid != real_hard_smp_processor_id())
+ continue;
+ cpuid = 0;
+#endif
+
+ cpu_data(cpuid).clock_tick =
+ of_getintprop_default(dp, "clock-frequency", 0);
+
+ if (portid_parent) {
+ cpu_data(cpuid).dcache_size =
+ of_getintprop_default(dp, "l1-dcache-size",
+ 16 * 1024);
+ cpu_data(cpuid).dcache_line_size =
+ of_getintprop_default(dp, "l1-dcache-line-size",
+ 32);
+ cpu_data(cpuid).icache_size =
+ of_getintprop_default(dp, "l1-icache-size",
+ 8 * 1024);
+ cpu_data(cpuid).icache_line_size =
+ of_getintprop_default(dp, "l1-icache-line-size",
+ 32);
+ cpu_data(cpuid).ecache_size =
+ of_getintprop_default(dp, "l2-cache-size", 0);
+ cpu_data(cpuid).ecache_line_size =
+ of_getintprop_default(dp, "l2-cache-line-size", 0);
+ if (!cpu_data(cpuid).ecache_size ||
+ !cpu_data(cpuid).ecache_line_size) {
+ cpu_data(cpuid).ecache_size =
+ of_getintprop_default(portid_parent,
+ "l2-cache-size",
+ (4 * 1024 * 1024));
+ cpu_data(cpuid).ecache_line_size =
+ of_getintprop_default(portid_parent,
+ "l2-cache-line-size", 64);
+ }
+
+ cpu_data(cpuid).core_id = portid + 1;
+ } else {
+ cpu_data(cpuid).dcache_size =
+ of_getintprop_default(dp, "dcache-size", 16 * 1024);
+ cpu_data(cpuid).dcache_line_size =
+ of_getintprop_default(dp, "dcache-line-size", 32);
+
+ cpu_data(cpuid).icache_size =
+ of_getintprop_default(dp, "icache-size", 16 * 1024);
+ cpu_data(cpuid).icache_line_size =
+ of_getintprop_default(dp, "icache-line-size", 32);
+
+ cpu_data(cpuid).ecache_size =
+ of_getintprop_default(dp, "ecache-size",
+ (4 * 1024 * 1024));
+ cpu_data(cpuid).ecache_line_size =
+ of_getintprop_default(dp, "ecache-line-size", 64);
+
+ cpu_data(cpuid).core_id = 0;
+ }
+
+#ifdef CONFIG_SMP
+ cpu_set(cpuid, cpu_present_map);
+ cpu_set(cpuid, phys_cpu_present_map);
+#endif
+ }
+
+ smp_fill_in_sib_core_maps();
+}
+
void __init prom_build_devicetree(void)
{
struct device_node **nextp;
@@ -1679,4 +1824,7 @@ void __init prom_build_devicetree(void)
&nextp);
printk("PROM: Built device tree with %u bytes of memory.\n",
prom_early_allocated);
+
+ if (tlb_type != hypervisor)
+ of_fill_in_cpu_data();
}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index dea9c3c9ec5..de9b4c13f1c 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -46,11 +46,17 @@
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/mmu.h>
+#include <asm/ns87303.h>
#ifdef CONFIG_IP_PNP
#include <net/ipconfig.h>
#endif
+/* Used to synchronize accesses to NatSemi SUPER I/O chip configure
+ * operations in asm/ns87303.h
+ */
+DEFINE_SPINLOCK(ns87303_lock);
+
struct screen_info screen_info = {
0, 0, /* orig-x, orig-y */
0, /* unused */
@@ -370,8 +376,6 @@ void __init setup_arch(char **cmdline_p)
init_cur_cpu_trap(current_thread_info());
paging_init();
-
- smp_setup_cpu_possible_map();
}
static int __init set_preferred_console(void)
@@ -424,7 +428,7 @@ extern void mmu_info(struct seq_file *);
unsigned int dcache_parity_tl1_occurred;
unsigned int icache_parity_tl1_occurred;
-static int ncpus_probed;
+int ncpus_probed;
static int show_cpuinfo(struct seq_file *m, void *__unused)
{
@@ -516,14 +520,6 @@ static int __init topology_init(void)
err = -ENOMEM;
- /* Count the number of physically present processors in
- * the machine, even on uniprocessor, so that /proc/cpuinfo
- * output is consistent with 2.4.x
- */
- ncpus_probed = 0;
- while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
- ncpus_probed++;
-
for_each_possible_cpu(i) {
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p) {
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 24fdf1d0adc..c550bba3490 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -40,6 +40,7 @@
#include <asm/tlb.h>
#include <asm/sections.h>
#include <asm/prom.h>
+#include <asm/mdesc.h>
extern void calibrate_delay(void);
@@ -75,53 +76,6 @@ void smp_bogo(struct seq_file *m)
i, cpu_data(i).clock_tick);
}
-void __init smp_store_cpu_info(int id)
-{
- struct device_node *dp;
- int def;
-
- cpu_data(id).udelay_val = loops_per_jiffy;
-
- cpu_find_by_mid(id, &dp);
- cpu_data(id).clock_tick =
- of_getintprop_default(dp, "clock-frequency", 0);
-
- def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024));
- cpu_data(id).dcache_size =
- of_getintprop_default(dp, "dcache-size", def);
-
- def = 32;
- cpu_data(id).dcache_line_size =
- of_getintprop_default(dp, "dcache-line-size", def);
-
- def = 16 * 1024;
- cpu_data(id).icache_size =
- of_getintprop_default(dp, "icache-size", def);
-
- def = 32;
- cpu_data(id).icache_line_size =
- of_getintprop_default(dp, "icache-line-size", def);
-
- def = ((tlb_type == hypervisor) ?
- (3 * 1024 * 1024) :
- (4 * 1024 * 1024));
- cpu_data(id).ecache_size =
- of_getintprop_default(dp, "ecache-size", def);
-
- def = 64;
- cpu_data(id).ecache_line_size =
- of_getintprop_default(dp, "ecache-line-size", def);
-
- printk("CPU[%d]: Caches "
- "D[sz(%d):line_sz(%d)] "
- "I[sz(%d):line_sz(%d)] "
- "E[sz(%d):line_sz(%d)]\n",
- id,
- cpu_data(id).dcache_size, cpu_data(id).dcache_line_size,
- cpu_data(id).icache_size, cpu_data(id).icache_line_size,
- cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
-}
-
extern void setup_sparc64_timer(void);
static volatile unsigned long callin_flag = 0;
@@ -145,7 +99,7 @@ void __init smp_callin(void)
local_irq_enable();
calibrate_delay();
- smp_store_cpu_info(cpuid);
+ cpu_data(cpuid).udelay_val = loops_per_jiffy;
callin_flag = 1;
__asm__ __volatile__("membar #Sync\n\t"
"flush %%g6" : : : "memory");
@@ -340,9 +294,8 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
prom_startcpu_cpuid(cpu, entry, cookie);
} else {
- struct device_node *dp;
+ struct device_node *dp = of_find_node_by_cpuid(cpu);
- cpu_find_by_mid(cpu, &dp);
prom_startcpu(dp->node, entry, cookie);
}
@@ -447,7 +400,7 @@ static __inline__ void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, c
static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
{
u64 pstate, ver;
- int nack_busy_id, is_jbus;
+ int nack_busy_id, is_jbus, need_more;
if (cpus_empty(mask))
return;
@@ -463,6 +416,7 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
retry:
+ need_more = 0;
__asm__ __volatile__("wrpr %0, %1, %%pstate\n\t"
: : "r" (pstate), "i" (PSTATE_IE));
@@ -491,6 +445,10 @@ retry:
: /* no outputs */
: "r" (target), "i" (ASI_INTR_W));
nack_busy_id++;
+ if (nack_busy_id == 32) {
+ need_more = 1;
+ break;
+ }
}
}
@@ -507,6 +465,16 @@ retry:
if (dispatch_stat == 0UL) {
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: : "r" (pstate));
+ if (unlikely(need_more)) {
+ int i, cnt = 0;
+ for_each_cpu_mask(i, mask) {
+ cpu_clear(i, mask);
+ cnt++;
+ if (cnt == 32)
+ break;
+ }
+ goto retry;
+ }
return;
}
if (!--stuck)
@@ -544,6 +512,8 @@ retry:
if ((dispatch_stat & check_mask) == 0)
cpu_clear(i, mask);
this_busy_nack += 2;
+ if (this_busy_nack == 64)
+ break;
}
goto retry;
@@ -1191,23 +1161,14 @@ int setup_profiling_timer(unsigned int multiplier)
static void __init smp_tune_scheduling(void)
{
- struct device_node *dp;
- int instance;
- unsigned int def, smallest = ~0U;
-
- def = ((tlb_type == hypervisor) ?
- (3 * 1024 * 1024) :
- (4 * 1024 * 1024));
+ unsigned int smallest = ~0U;
+ int i;
- instance = 0;
- while (!cpu_find_by_instance(instance, &dp, NULL)) {
- unsigned int val;
+ for (i = 0; i < NR_CPUS; i++) {
+ unsigned int val = cpu_data(i).ecache_size;
- val = of_getintprop_default(dp, "ecache-size", def);
- if (val < smallest)
+ if (val && val < smallest)
smallest = val;
-
- instance++;
}
/* Any value less than 256K is nonsense. */
@@ -1230,58 +1191,42 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
int i;
if (num_possible_cpus() > max_cpus) {
- int instance, mid;
-
- instance = 0;
- while (!cpu_find_by_instance(instance, NULL, &mid)) {
- if (mid != boot_cpu_id) {
- cpu_clear(mid, phys_cpu_present_map);
- cpu_clear(mid, cpu_present_map);
+ for_each_possible_cpu(i) {
+ if (i != boot_cpu_id) {
+ cpu_clear(i, phys_cpu_present_map);
+ cpu_clear(i, cpu_present_map);
if (num_possible_cpus() <= max_cpus)
break;
}
- instance++;
}
}
- for_each_possible_cpu(i) {
- if (tlb_type == hypervisor) {
- int j;
-
- /* XXX get this mapping from machine description */
- for_each_possible_cpu(j) {
- if ((j >> 2) == (i >> 2))
- cpu_set(j, cpu_sibling_map[i]);
- }
- } else {
- cpu_set(i, cpu_sibling_map[i]);
- }
- }
-
- smp_store_cpu_info(boot_cpu_id);
+ cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
smp_tune_scheduling();
}
-/* Set this up early so that things like the scheduler can init
- * properly. We use the same cpu mask for both the present and
- * possible cpu map.
- */
-void __init smp_setup_cpu_possible_map(void)
+void __devinit smp_prepare_boot_cpu(void)
{
- int instance, mid;
-
- instance = 0;
- while (!cpu_find_by_instance(instance, NULL, &mid)) {
- if (mid < NR_CPUS) {
- cpu_set(mid, phys_cpu_present_map);
- cpu_set(mid, cpu_present_map);
- }
- instance++;
- }
}
-void __devinit smp_prepare_boot_cpu(void)
+void __devinit smp_fill_in_sib_core_maps(void)
{
+ unsigned int i;
+
+ for_each_possible_cpu(i) {
+ unsigned int j;
+
+ if (cpu_data(i).core_id == 0) {
+ cpu_set(i, cpu_sibling_map[i]);
+ continue;
+ }
+
+ for_each_possible_cpu(j) {
+ if (cpu_data(i).core_id ==
+ cpu_data(j).core_id)
+ cpu_set(j, cpu_sibling_map[i]);
+ }
+ }
}
int __cpuinit __cpu_up(unsigned int cpu)
@@ -1337,7 +1282,7 @@ unsigned long __per_cpu_shift __read_mostly;
EXPORT_SYMBOL(__per_cpu_base);
EXPORT_SYMBOL(__per_cpu_shift);
-void __init setup_per_cpu_areas(void)
+void __init real_setup_per_cpu_areas(void)
{
unsigned long goal, size, i;
char *ptr;
diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc64/kernel/sstate.c
new file mode 100644
index 00000000000..5b6e75b7f05
--- /dev/null
+++ b/arch/sparc64/kernel/sstate.c
@@ -0,0 +1,104 @@
+/* sstate.c: System soft state support.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/sstate.h>
+#include <asm/oplib.h>
+#include <asm/head.h>
+#include <asm/io.h>
+
+static int hv_supports_soft_state;
+
+static unsigned long kimage_addr_to_ra(const char *p)
+{
+ unsigned long val = (unsigned long) p;
+
+ return kern_base + (val - KERNBASE);
+}
+
+static void do_set_sstate(unsigned long state, const char *msg)
+{
+ unsigned long err;
+
+ if (!hv_supports_soft_state)
+ return;
+
+ err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg));
+ if (err) {
+ printk(KERN_WARNING "SSTATE: Failed to set soft-state to "
+ "state[%lx] msg[%s], err=%lu\n",
+ state, msg, err);
+ }
+}
+
+static const char booting_msg[32] __attribute__((aligned(32))) =
+ "Linux booting";
+static const char running_msg[32] __attribute__((aligned(32))) =
+ "Linux running";
+static const char halting_msg[32] __attribute__((aligned(32))) =
+ "Linux halting";
+static const char poweroff_msg[32] __attribute__((aligned(32))) =
+ "Linux powering off";
+static const char rebooting_msg[32] __attribute__((aligned(32))) =
+ "Linux rebooting";
+static const char panicing_msg[32] __attribute__((aligned(32))) =
+ "Linux panicing";
+
+void sstate_booting(void)
+{
+ do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg);
+}
+
+void sstate_running(void)
+{
+ do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg);
+}
+
+void sstate_halt(void)
+{
+ do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg);
+}
+
+void sstate_poweroff(void)
+{
+ do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg);
+}
+
+void sstate_reboot(void)
+{
+ do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg);
+}
+
+static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
+{
+ do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block sstate_panic_block = {
+ .notifier_call = sstate_panic_event,
+ .priority = INT_MAX,
+};
+
+void __init sun4v_sstate_init(void)
+{
+ unsigned long major, minor;
+
+ major = 1;
+ minor = 0;
+ if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor))
+ return;
+
+ hv_supports_soft_state = 1;
+
+ prom_sun4v_guest_soft_state();
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &sstate_panic_block);
+}
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index 405855dd886..574bc248bca 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -22,12 +22,12 @@ sun4v_cpu_mondo:
be,pn %xcc, sun4v_cpu_mondo_queue_empty
nop
- /* Get &trap_block[smp_processor_id()] into %g3. */
- ldxa [%g0] ASI_SCRATCHPAD, %g3
- sub %g3, TRAP_PER_CPU_FAULT_INFO, %g3
+ /* Get &trap_block[smp_processor_id()] into %g4. */
+ ldxa [%g0] ASI_SCRATCHPAD, %g4
+ sub %g4, TRAP_PER_CPU_FAULT_INFO, %g4
/* Get CPU mondo queue base phys address into %g7. */
- ldx [%g3 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
+ ldx [%g4 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
/* Now get the cross-call arguments and handler PC, same
* layout as sun4u:
@@ -47,8 +47,7 @@ sun4v_cpu_mondo:
add %g2, 0x40 - 0x8 - 0x8, %g2
/* Update queue head pointer. */
- sethi %hi(8192 - 1), %g4
- or %g4, %lo(8192 - 1), %g4
+ lduw [%g4 + TRAP_PER_CPU_CPU_MONDO_QMASK], %g4
and %g2, %g4, %g2
mov INTRQ_CPU_MONDO_HEAD, %g4
@@ -71,12 +70,12 @@ sun4v_dev_mondo:
be,pn %xcc, sun4v_dev_mondo_queue_empty
nop
- /* Get &trap_block[smp_processor_id()] into %g3. */
- ldxa [%g0] ASI_SCRATCHPAD, %g3
- sub %g3, TRAP_PER_CPU_FAULT_INFO, %g3
+ /* Get &trap_block[smp_processor_id()] into %g4. */
+ ldxa [%g0] ASI_SCRATCHPAD, %g4
+ sub %g4, TRAP_PER_CPU_FAULT_INFO, %g4
/* Get DEV mondo queue base phys address into %g5. */
- ldx [%g3 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
+ ldx [%g4 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
/* Load IVEC into %g3. */
ldxa [%g5 + %g2] ASI_PHYS_USE_EC, %g3
@@ -90,8 +89,7 @@ sun4v_dev_mondo:
*/
/* Update queue head pointer, this frees up some registers. */
- sethi %hi(8192 - 1), %g4
- or %g4, %lo(8192 - 1), %g4
+ lduw [%g4 + TRAP_PER_CPU_DEV_MONDO_QMASK], %g4
and %g2, %g4, %g2
mov INTRQ_DEVICE_MONDO_HEAD, %g4
@@ -143,6 +141,8 @@ sun4v_res_mondo:
brnz,pn %g1, sun4v_res_mondo_queue_full
nop
+ lduw [%g3 + TRAP_PER_CPU_RESUM_QMASK], %g4
+
/* Remember this entry's offset in %g1. */
mov %g2, %g1
@@ -173,8 +173,6 @@ sun4v_res_mondo:
add %g2, 0x08, %g2
/* Update queue head pointer. */
- sethi %hi(8192 - 1), %g4
- or %g4, %lo(8192 - 1), %g4
and %g2, %g4, %g2
mov INTRQ_RESUM_MONDO_HEAD, %g4
@@ -254,6 +252,8 @@ sun4v_nonres_mondo:
brnz,pn %g1, sun4v_nonres_mondo_queue_full
nop
+ lduw [%g3 + TRAP_PER_CPU_NONRESUM_QMASK], %g4
+
/* Remember this entry's offset in %g1. */
mov %g2, %g1
@@ -284,8 +284,6 @@ sun4v_nonres_mondo:
add %g2, 0x08, %g2
/* Update queue head pointer. */
- sethi %hi(8192 - 1), %g4
- or %g4, %lo(8192 - 1), %g4
and %g2, %g4, %g2
mov INTRQ_NONRESUM_MONDO_HEAD, %g4
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 2d63d768996..a31a0439244 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -680,22 +680,14 @@ static int starfire_set_time(u32 val)
static u32 hypervisor_get_time(void)
{
- register unsigned long func asm("%o5");
- register unsigned long arg0 asm("%o0");
- register unsigned long arg1 asm("%o1");
+ unsigned long ret, time;
int retries = 10000;
retry:
- func = HV_FAST_TOD_GET;
- arg0 = 0;
- arg1 = 0;
- __asm__ __volatile__("ta %6"
- : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
- : "0" (func), "1" (arg0), "2" (arg1),
- "i" (HV_FAST_TRAP));
- if (arg0 == HV_EOK)
- return arg1;
- if (arg0 == HV_EWOULDBLOCK) {
+ ret = sun4v_tod_get(&time);
+ if (ret == HV_EOK)
+ return time;
+ if (ret == HV_EWOULDBLOCK) {
if (--retries > 0) {
udelay(100);
goto retry;
@@ -709,20 +701,14 @@ retry:
static int hypervisor_set_time(u32 secs)
{
- register unsigned long func asm("%o5");
- register unsigned long arg0 asm("%o0");
+ unsigned long ret;
int retries = 10000;
retry:
- func = HV_FAST_TOD_SET;
- arg0 = secs;
- __asm__ __volatile__("ta %4"
- : "=&r" (func), "=&r" (arg0)
- : "0" (func), "1" (arg0),
- "i" (HV_FAST_TRAP));
- if (arg0 == HV_EOK)
+ ret = sun4v_tod_set(secs);
+ if (ret == HV_EOK)
return 0;
- if (arg0 == HV_EWOULDBLOCK) {
+ if (ret == HV_EWOULDBLOCK) {
if (--retries > 0) {
udelay(100);
goto retry;
@@ -862,7 +848,6 @@ fs_initcall(clock_init);
static unsigned long sparc64_init_timers(void)
{
struct device_node *dp;
- struct property *prop;
unsigned long clock;
#ifdef CONFIG_SMP
extern void smp_tick_init(void);
@@ -879,17 +864,15 @@ static unsigned long sparc64_init_timers(void)
if (manuf == 0x17 && impl == 0x13) {
/* Hummingbird, aka Ultra-IIe */
tick_ops = &hbtick_operations;
- prop = of_find_property(dp, "stick-frequency", NULL);
+ clock = of_getintprop_default(dp, "stick-frequency", 0);
} else {
tick_ops = &tick_operations;
- cpu_find_by_instance(0, &dp, NULL);
- prop = of_find_property(dp, "clock-frequency", NULL);
+ clock = local_cpu_data().clock_tick;
}
} else {
tick_ops = &stick_operations;
- prop = of_find_property(dp, "stick-frequency", NULL);
+ clock = of_getintprop_default(dp, "stick-frequency", 0);
}
- clock = *(unsigned int *) prop->value;
#ifdef CONFIG_SMP
smp_tick_init();
@@ -1365,6 +1348,7 @@ static int hypervisor_set_rtc_time(struct rtc_time *time)
return hypervisor_set_time(seconds);
}
+#ifdef CONFIG_PCI
static void bq4802_get_rtc_time(struct rtc_time *time)
{
unsigned char val = readb(bq4802_regs + 0x0e);
@@ -1436,6 +1420,7 @@ static int bq4802_set_rtc_time(struct rtc_time *time)
return 0;
}
+#endif /* CONFIG_PCI */
struct mini_rtc_ops {
void (*get_rtc_time)(struct rtc_time *);
@@ -1452,10 +1437,12 @@ static struct mini_rtc_ops hypervisor_rtc_ops = {
.set_rtc_time = hypervisor_set_rtc_time,
};
+#ifdef CONFIG_PCI
static struct mini_rtc_ops bq4802_rtc_ops = {
.get_rtc_time = bq4802_get_rtc_time,
.set_rtc_time = bq4802_set_rtc_time,
};
+#endif /* CONFIG_PCI */
static struct mini_rtc_ops *mini_rtc_ops;
@@ -1579,8 +1566,10 @@ static int __init rtc_mini_init(void)
mini_rtc_ops = &hypervisor_rtc_ops;
else if (this_is_starfire)
mini_rtc_ops = &starfire_rtc_ops;
+#ifdef CONFIG_PCI
else if (bq4802_regs)
mini_rtc_ops = &bq4802_rtc_ops;
+#endif /* CONFIG_PCI */
else
return -ENODEV;
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index d0fde36395b..00a9e3286c8 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -795,8 +795,7 @@ extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector
void __init cheetah_ecache_flush_init(void)
{
unsigned long largest_size, smallest_linesize, order, ver;
- struct device_node *dp;
- int i, instance, sz;
+ int i, sz;
/* Scan all cpu device tree nodes, note two values:
* 1) largest E-cache size
@@ -805,18 +804,20 @@ void __init cheetah_ecache_flush_init(void)
largest_size = 0UL;
smallest_linesize = ~0UL;
- instance = 0;
- while (!cpu_find_by_instance(instance, &dp, NULL)) {
+ for (i = 0; i < NR_CPUS; i++) {
unsigned long val;
- val = of_getintprop_default(dp, "ecache-size",
- (2 * 1024 * 1024));
+ val = cpu_data(i).ecache_size;
+ if (!val)
+ continue;
+
if (val > largest_size)
largest_size = val;
- val = of_getintprop_default(dp, "ecache-line-size", 64);
+
+ val = cpu_data(i).ecache_line_size;
if (val < smallest_linesize)
smallest_linesize = val;
- instance++;
+
}
if (largest_size == 0UL || smallest_linesize == ~0UL) {
@@ -2564,7 +2565,15 @@ void __init trap_init(void)
(TRAP_PER_CPU_TSB_HUGE_TEMP !=
offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
(TRAP_PER_CPU_IRQ_WORKLIST !=
- offsetof(struct trap_per_cpu, irq_worklist)))
+ offsetof(struct trap_per_cpu, irq_worklist)) ||
+ (TRAP_PER_CPU_CPU_MONDO_QMASK !=
+ offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
+ (TRAP_PER_CPU_DEV_MONDO_QMASK !=
+ offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
+ (TRAP_PER_CPU_RESUM_QMASK !=
+ offsetof(struct trap_per_cpu, resum_qmask)) ||
+ (TRAP_PER_CPU_NONRESUM_QMASK !=
+ offsetof(struct trap_per_cpu, nonresum_qmask)))
trap_per_cpu_offsets_are_bolixed_dave();
if ((TSB_CONFIG_TSB !=
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 6e5b01d779d..3010227fe24 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -23,6 +23,7 @@
#include <linux/kprobes.h>
#include <linux/cache.h>
#include <linux/sort.h>
+#include <linux/percpu.h>
#include <asm/head.h>
#include <asm/system.h>
@@ -43,8 +44,8 @@
#include <asm/tsb.h>
#include <asm/hypervisor.h>
#include <asm/prom.h>
-
-extern void device_scan(void);
+#include <asm/sstate.h>
+#include <asm/mdesc.h>
#define MAX_PHYS_ADDRESS (1UL << 42UL)
#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL)
@@ -60,8 +61,11 @@ unsigned long kern_linear_pte_xor[2] __read_mostly;
unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
#ifndef CONFIG_DEBUG_PAGEALLOC
-/* A special kernel TSB for 4MB and 256MB linear mappings. */
-struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
+/* A special kernel TSB for 4MB and 256MB linear mappings.
+ * Space is allocated for this right after the trap table
+ * in arch/sparc64/kernel/head.S
+ */
+extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
#endif
#define MAX_BANKS 32
@@ -190,12 +194,9 @@ inline void flush_dcache_page_impl(struct page *page)
}
#define PG_dcache_dirty PG_arch_1
-#define PG_dcache_cpu_shift 24UL
-#define PG_dcache_cpu_mask (256UL - 1UL)
-
-#if NR_CPUS > 256
-#error D-cache dirty tracking and thread_info->cpu need fixing for > 256 cpus
-#endif
+#define PG_dcache_cpu_shift 32UL
+#define PG_dcache_cpu_mask \
+ ((1UL<<ilog2(roundup_pow_of_two(NR_CPUS)))-1UL)
#define dcache_dirty_cpu(page) \
(((page)->flags >> PG_dcache_cpu_shift) & PG_dcache_cpu_mask)
@@ -557,26 +558,11 @@ static void __init hypervisor_tlb_lock(unsigned long vaddr,
unsigned long pte,
unsigned long mmu)
{
- register unsigned long func asm("%o5");
- register unsigned long arg0 asm("%o0");
- register unsigned long arg1 asm("%o1");
- register unsigned long arg2 asm("%o2");
- register unsigned long arg3 asm("%o3");
-
- func = HV_FAST_MMU_MAP_PERM_ADDR;
- arg0 = vaddr;
- arg1 = 0;
- arg2 = pte;
- arg3 = mmu;
- __asm__ __volatile__("ta 0x80"
- : "=&r" (func), "=&r" (arg0),
- "=&r" (arg1), "=&r" (arg2),
- "=&r" (arg3)
- : "0" (func), "1" (arg0), "2" (arg1),
- "3" (arg2), "4" (arg3));
- if (arg0 != 0) {
+ unsigned long ret = sun4v_mmu_map_perm_addr(vaddr, 0, pte, mmu);
+
+ if (ret != 0) {
prom_printf("hypervisor_tlb_lock[%lx:%lx:%lx:%lx]: "
- "errors with %lx\n", vaddr, 0, pte, mmu, arg0);
+ "errors with %lx\n", vaddr, 0, pte, mmu, ret);
prom_halt();
}
}
@@ -1313,20 +1299,16 @@ static void __init sun4v_ktsb_init(void)
void __cpuinit sun4v_ktsb_register(void)
{
- register unsigned long func asm("%o5");
- register unsigned long arg0 asm("%o0");
- register unsigned long arg1 asm("%o1");
- unsigned long pa;
+ unsigned long pa, ret;
pa = kern_base + ((unsigned long)&ktsb_descr[0] - KERNBASE);
- func = HV_FAST_MMU_TSB_CTX0;
- arg0 = NUM_KTSB_DESCR;
- arg1 = pa;
- __asm__ __volatile__("ta %6"
- : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
- : "0" (func), "1" (arg0), "2" (arg1),
- "i" (HV_FAST_TRAP));
+ ret = sun4v_mmu_tsb_ctx0(NUM_KTSB_DESCR, pa);
+ if (ret != 0) {
+ prom_printf("hypervisor_mmu_tsb_ctx0[%lx]: "
+ "errors with %lx\n", pa, ret);
+ prom_halt();
+ }
}
/* paging_init() sets up the page tables */
@@ -1334,6 +1316,9 @@ void __cpuinit sun4v_ktsb_register(void)
extern void cheetah_ecache_flush_init(void);
extern void sun4v_patch_tlb_handlers(void);
+extern void cpu_probe(void);
+extern void central_probe(void);
+
static unsigned long last_valid_pfn;
pgd_t swapper_pg_dir[2048];
@@ -1345,9 +1330,24 @@ void __init paging_init(void)
unsigned long end_pfn, pages_avail, shift, phys_base;
unsigned long real_end, i;
+ /* These build time checkes make sure that the dcache_dirty_cpu()
+ * page->flags usage will work.
+ *
+ * When a page gets marked as dcache-dirty, we store the
+ * cpu number starting at bit 32 in the page->flags. Also,
+ * functions like clear_dcache_dirty_cpu use the cpu mask
+ * in 13-bit signed-immediate instruction fields.
+ */
+ BUILD_BUG_ON(FLAGS_RESERVED != 32);
+ BUILD_BUG_ON(SECTIONS_WIDTH + NODES_WIDTH + ZONES_WIDTH +
+ ilog2(roundup_pow_of_two(NR_CPUS)) > FLAGS_RESERVED);
+ BUILD_BUG_ON(NR_CPUS > 4096);
+
kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
+ sstate_booting();
+
/* Invalidate both kernel TSBs. */
memset(swapper_tsb, 0x40, sizeof(swapper_tsb));
#ifndef CONFIG_DEBUG_PAGEALLOC
@@ -1416,8 +1416,13 @@ void __init paging_init(void)
kernel_physical_mapping_init();
+ real_setup_per_cpu_areas();
+
prom_build_devicetree();
+ if (tlb_type == hypervisor)
+ sun4v_mdesc_init();
+
{
unsigned long zones_size[MAX_NR_ZONES];
unsigned long zholes_size[MAX_NR_ZONES];
@@ -1434,7 +1439,10 @@ void __init paging_init(void)
zholes_size);
}
- device_scan();
+ prom_printf("Booting Linux...\n");
+
+ central_probe();
+ cpu_probe();
}
static void __init taint_real_pages(void)
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index 0b4213720d4..f3e0c14e9ee 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -15,6 +15,25 @@
#include <asm/oplib.h>
#include <asm/system.h>
+int prom_service_exists(const char *service_name)
+{
+ int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_INOUT(1, 1), service_name);
+
+ if (err)
+ return 0;
+ return 1;
+}
+
+void prom_sun4v_guest_soft_state(void)
+{
+ const char *svc = "SUNW,soft-state-supported";
+
+ if (!prom_service_exists(svc))
+ return;
+ p1275_cmd(svc, P1275_INOUT(0, 0));
+}
+
/* Reset and reboot the machine with the command 'bcommand'. */
void prom_reboot(const char *bcommand)
{