aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/Kconfig12
-rw-r--r--arch/ia64/configs/bigsur_defconfig2
-rw-r--r--arch/ia64/configs/gensparse_defconfig2
-rw-r--r--arch/ia64/configs/sim_defconfig2
-rw-r--r--arch/ia64/configs/sn2_defconfig2
-rw-r--r--arch/ia64/configs/tiger_defconfig2
-rw-r--r--arch/ia64/configs/zx1_defconfig2
-rw-r--r--arch/ia64/defconfig3
-rw-r--r--arch/ia64/hp/sim/boot/boot_head.S1
-rw-r--r--arch/ia64/hp/sim/hpsim_console.c16
-rw-r--r--arch/ia64/hp/sim/hpsim_setup.c9
-rw-r--r--arch/ia64/hp/sim/simeth.c15
-rw-r--r--arch/ia64/hp/sim/simscsi.c3
-rw-r--r--arch/ia64/ia32/audit.c2
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c8
-rw-r--r--arch/ia64/kernel/irq.c5
-rw-r--r--arch/ia64/kernel/irq_ia64.c28
-rw-r--r--arch/ia64/kernel/mca.c34
-rw-r--r--arch/ia64/kernel/process.c10
-rw-r--r--arch/ia64/kernel/ptrace.c11
-rw-r--r--arch/ia64/kernel/setup.c8
-rw-r--r--arch/ia64/kernel/smpboot.c6
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S12
-rw-r--r--arch/ia64/mm/contig.c3
-rw-r--r--arch/ia64/mm/discontig.c3
-rw-r--r--arch/ia64/mm/fault.c14
-rw-r--r--arch/ia64/mm/hugetlbpage.c6
-rw-r--r--arch/ia64/sn/kernel/huberror.c14
-rw-r--r--arch/ia64/sn/kernel/irq.c27
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c26
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c3
-rw-r--r--arch/ia64/sn/kernel/tiocx.c3
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c1
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c2
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c1
35 files changed, 204 insertions, 94 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 21aa4fc5f8ef..8c39913d1729 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -327,17 +327,7 @@ config FORCE_CPEI_RETARGET
This option it useful to enable this feature on older BIOS's as well.
You can also enable this by using boot command line option force_cpei=1.
-config PREEMPT
- bool "Preemptible Kernel"
- help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
+source "kernel/Kconfig.preempt"
source "mm/Kconfig"
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
index 9eb48c0927b0..6dd8655664f3 100644
--- a/arch/ia64/configs/bigsur_defconfig
+++ b/arch/ia64/configs/bigsur_defconfig
@@ -42,7 +42,7 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_SLAB=y
+CONFIG_SLUB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 3a9ed951db08..e86fbd39c795 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -43,7 +43,7 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_SLAB=y
+CONFIG_SLUB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
diff --git a/arch/ia64/configs/sim_defconfig b/arch/ia64/configs/sim_defconfig
index c420d9f3df98..546a772f438e 100644
--- a/arch/ia64/configs/sim_defconfig
+++ b/arch/ia64/configs/sim_defconfig
@@ -43,7 +43,7 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_SLAB=y
+CONFIG_SLUB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 4c9ffc47bc7a..9aecfceeb38c 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -46,7 +46,7 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
+CONFIG_SLUB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 3dbb3987df27..797acf9066c1 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -53,7 +53,7 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
+CONFIG_SLUB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 4a060fc39934..0a06b1333c95 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -48,7 +48,7 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
+CONFIG_SLUB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 03172dc8c403..0210545e7f61 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -53,8 +53,7 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
diff --git a/arch/ia64/hp/sim/boot/boot_head.S b/arch/ia64/hp/sim/boot/boot_head.S
index a9bd71ac78e2..8808565491fb 100644
--- a/arch/ia64/hp/sim/boot/boot_head.S
+++ b/arch/ia64/hp/sim/boot/boot_head.S
@@ -26,6 +26,7 @@ GLOBAL_ENTRY(_start)
movl sp = stack_mem+16384-16
bsw.1
br.call.sptk.many rp=start_bootloader
+0: nop 0 /* dummy nop to make unwinding work */
END(_start)
/*
diff --git a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c
index 6e149c8ab835..01663bc42b1a 100644
--- a/arch/ia64/hp/sim/hpsim_console.c
+++ b/arch/ia64/hp/sim/hpsim_console.c
@@ -21,6 +21,7 @@
#include <asm/machvec.h>
#include <asm/pgtable.h>
#include <asm/sal.h>
+#include <asm/hpsim.h>
#include "hpsim_ssc.h"
@@ -28,7 +29,7 @@ static int simcons_init (struct console *, char *);
static void simcons_write (struct console *, const char *, unsigned);
static struct tty_driver *simcons_console_device (struct console *, int *);
-struct console hpsim_cons = {
+static struct console hpsim_cons = {
.name = "simcons",
.write = simcons_write,
.device = simcons_console_device,
@@ -58,7 +59,18 @@ simcons_write (struct console *cons, const char *buf, unsigned count)
static struct tty_driver *simcons_console_device (struct console *c, int *index)
{
- extern struct tty_driver *hp_simserial_driver;
*index = c->index;
return hp_simserial_driver;
}
+
+int simcons_register(void)
+{
+ if (!ia64_platform_is("hpsim"))
+ return 1;
+
+ if (hpsim_cons.flags & CON_ENABLED)
+ return 1;
+
+ register_console(&hpsim_cons);
+ return 0;
+}
diff --git a/arch/ia64/hp/sim/hpsim_setup.c b/arch/ia64/hp/sim/hpsim_setup.c
index f2297192a582..f629e903ebc7 100644
--- a/arch/ia64/hp/sim/hpsim_setup.c
+++ b/arch/ia64/hp/sim/hpsim_setup.c
@@ -21,6 +21,7 @@
#include <asm/machvec.h>
#include <asm/pgtable.h>
#include <asm/sal.h>
+#include <asm/hpsim.h>
#include "hpsim_ssc.h"
@@ -41,11 +42,5 @@ hpsim_setup (char **cmdline_p)
{
ROOT_DEV = Root_SDA1; /* default to first SCSI drive */
-#ifdef CONFIG_HP_SIMSERIAL_CONSOLE
- {
- extern struct console hpsim_cons;
- if (ia64_platform_is("hpsim"))
- register_console(&hpsim_cons);
- }
-#endif
+ simcons_register();
}
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index f26077a773d5..08b117e2c54b 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -22,6 +22,9 @@
#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/irq.h>
+#include <asm/hpsim.h>
+
+#include "hpsim_ssc.h"
#define SIMETH_RECV_MAX 10
@@ -35,12 +38,6 @@
#define SIMETH_FRAME_SIZE ETH_FRAME_LEN
-#define SSC_NETDEV_PROBE 100
-#define SSC_NETDEV_SEND 101
-#define SSC_NETDEV_RECV 102
-#define SSC_NETDEV_ATTACH 103
-#define SSC_NETDEV_DETACH 104
-
#define NETWORK_INTR 8
struct simeth_local {
@@ -124,9 +121,6 @@ simeth_probe (void)
return r;
}
-extern long ia64_ssc (long, long, long, long, int);
-extern void ia64_ssc_connect_irq (long intr, long irq);
-
static inline int
netdev_probe(char *name, unsigned char *ether)
{
@@ -300,6 +294,9 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
return NOTIFY_DONE;
}
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
/*
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index a43e1e1822ad..d62fa76e5a7d 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/timer.h>
#include <asm/irq.h>
+#include "hpsim_ssc.h"
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -59,8 +60,6 @@ struct disk_stat {
unsigned count;
};
-extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
-
static int desc[16] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
index 8850fe40ea34..5e901c75df1b 100644
--- a/arch/ia64/ia32/audit.c
+++ b/arch/ia64/ia32/audit.c
@@ -1,4 +1,4 @@
-#include <asm-i386/unistd.h>
+#include <asm-x86/unistd_32.h>
unsigned ia32_dir_class[] = {
#include <asm-generic/audit_dir_write.h>
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index 15c08d52f09f..b8498ea62068 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -113,10 +113,8 @@ processor_get_freq (
saved_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu) {
- ret = -EAGAIN;
+ if (smp_processor_id() != cpu)
goto migrate_end;
- }
/* processor_get_pstate gets the instantaneous frequency */
ret = processor_get_pstate(&value);
@@ -125,7 +123,7 @@ processor_get_freq (
set_cpus_allowed(current, saved_mask);
printk(KERN_WARNING "get performance failed with error %d\n",
ret);
- ret = -EAGAIN;
+ ret = 0;
goto migrate_end;
}
clock_freq = extract_clock(data, value, cpu);
@@ -323,8 +321,6 @@ acpi_cpufreq_cpu_init (
data->acpi_data.states[i].transition_latency * 1000;
}
}
- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
policy->cur = processor_get_freq(data, policy->cpu);
/* table init */
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index cc3ee4ef37af..44be1c952b7c 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -33,6 +33,11 @@ void ack_bad_irq(unsigned int irq)
}
#ifdef CONFIG_IA64_GENERIC
+ia64_vector __ia64_irq_to_vector(int irq)
+{
+ return irq_cfg[irq].vector;
+}
+
unsigned int __ia64_local_vector_to_irq (ia64_vector vec)
{
return __get_cpu_var(vector_irq)[vec];
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index c47c8acc96e3..00a4599e5f47 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -82,7 +82,7 @@ struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
};
DEFINE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq) = {
- [0 ... IA64_NUM_VECTORS - 1] = IA64_SPURIOUS_INT_VECTOR
+ [0 ... IA64_NUM_VECTORS - 1] = -1
};
static cpumask_t vector_table[IA64_NUM_VECTORS] = {
@@ -179,7 +179,7 @@ static void __clear_irq_vector(int irq)
domain = cfg->domain;
cpus_and(mask, cfg->domain, cpu_online_map);
for_each_cpu_mask(cpu, mask)
- per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR;
+ per_cpu(vector_irq, cpu)[vector] = -1;
cfg->vector = IRQ_VECTOR_UNASSIGNED;
cfg->domain = CPU_MASK_NONE;
irq_status[irq] = IRQ_UNUSED;
@@ -249,7 +249,7 @@ void __setup_vector_irq(int cpu)
/* Clear vector_irq */
for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
- per_cpu(vector_irq, cpu)[vector] = IA64_SPURIOUS_INT_VECTOR;
+ per_cpu(vector_irq, cpu)[vector] = -1;
/* Mark the inuse vectors */
for (irq = 0; irq < NR_IRQS; ++irq) {
if (!cpu_isset(cpu, irq_cfg[irq].domain))
@@ -432,10 +432,18 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
} else if (unlikely(IS_RESCHEDULE(vector)))
kstat_this_cpu.irqs[vector]++;
else {
+ int irq = local_vector_to_irq(vector);
+
ia64_setreg(_IA64_REG_CR_TPR, vector);
ia64_srlz_d();
- generic_handle_irq(local_vector_to_irq(vector));
+ if (unlikely(irq < 0)) {
+ printk(KERN_ERR "%s: Unexpected interrupt "
+ "vector %d on CPU %d is not mapped "
+ "to any IRQ!\n", __FUNCTION__, vector,
+ smp_processor_id());
+ } else
+ generic_handle_irq(irq);
/*
* Disable interrupts and send EOI:
@@ -483,6 +491,7 @@ void ia64_process_pending_intr(void)
kstat_this_cpu.irqs[vector]++;
else {
struct pt_regs *old_regs = set_irq_regs(NULL);
+ int irq = local_vector_to_irq(vector);
ia64_setreg(_IA64_REG_CR_TPR, vector);
ia64_srlz_d();
@@ -493,8 +502,15 @@ void ia64_process_pending_intr(void)
* it will work. I hope it works!.
* Probably could shared code.
*/
- vectors_in_migration[local_vector_to_irq(vector)]=0;
- generic_handle_irq(local_vector_to_irq(vector));
+ if (unlikely(irq < 0)) {
+ printk(KERN_ERR "%s: Unexpected interrupt "
+ "vector %d on CPU %d not being mapped "
+ "to any IRQ!!\n", __FUNCTION__, vector,
+ smp_processor_id());
+ } else {
+ vectors_in_migration[irq]=0;
+ generic_handle_irq(irq);
+ }
set_irq_regs(old_regs);
/*
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index ff28620cb992..63b73f3d4c9f 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2018,22 +2018,26 @@ ia64_mca_late_init(void)
if (cpe_vector >= 0) {
/* If platform supports CPEI, enable the irq. */
- cpe_poll_enabled = 0;
- for (irq = 0; irq < NR_IRQS; ++irq)
- if (irq_to_vector(irq) == cpe_vector) {
- desc = irq_desc + irq;
- desc->status |= IRQ_PER_CPU;
- setup_irq(irq, &mca_cpe_irqaction);
- ia64_cpe_irq = irq;
- }
- ia64_mca_register_cpev(cpe_vector);
- IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n", __FUNCTION__);
- } else {
- /* If platform doesn't support CPEI, get the timer going. */
- if (cpe_poll_enabled) {
- ia64_mca_cpe_poll(0UL);
- IA64_MCA_DEBUG("%s: CPEP setup and enabled.\n", __FUNCTION__);
+ irq = local_vector_to_irq(cpe_vector);
+ if (irq > 0) {
+ cpe_poll_enabled = 0;
+ desc = irq_desc + irq;
+ desc->status |= IRQ_PER_CPU;
+ setup_irq(irq, &mca_cpe_irqaction);
+ ia64_cpe_irq = irq;
+ ia64_mca_register_cpev(cpe_vector);
+ IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n",
+ __FUNCTION__);
+ return 0;
}
+ printk(KERN_ERR "%s: Failed to find irq for CPE "
+ "interrupt handler, vector %d\n",
+ __FUNCTION__, cpe_vector);
+ }
+ /* If platform doesn't support CPEI, get the timer going. */
+ if (cpe_poll_enabled) {
+ ia64_mca_cpe_poll(0UL);
+ IA64_MCA_DEBUG("%s: CPEP setup and enabled.\n", __FUNCTION__);
}
}
#endif
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 4158906c45aa..c613fc0e91cc 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -198,9 +198,13 @@ default_idle (void)
{
local_irq_enable();
while (!need_resched()) {
- if (can_do_pal_halt)
- safe_halt();
- else
+ if (can_do_pal_halt) {
+ local_irq_disable();
+ if (!need_resched()) {
+ safe_halt();
+ }
+ local_irq_enable();
+ } else
cpu_relax();
}
}
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 00f803246948..2e96f17b2f3b 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -951,10 +951,14 @@ access_uarea (struct task_struct *child, unsigned long addr,
return 0;
case PT_CR_IPSR:
- if (write_access)
- pt->cr_ipsr = ((*data & IPSR_MASK)
+ if (write_access) {
+ unsigned long tmp = *data;
+ /* psr.ri==3 is a reserved value: SDM 2:25 */
+ if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
+ tmp &= ~IA64_PSR_RI;
+ pt->cr_ipsr = ((tmp & IPSR_MASK)
| (pt->cr_ipsr & ~IPSR_MASK));
- else
+ } else
*data = (pt->cr_ipsr & IPSR_MASK);
return 0;
@@ -1573,7 +1577,6 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
case PTRACE_DETACH:
/* detach a process that was attached. */
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
ret = ptrace_detach(child, data);
goto out_tsk;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index cd9a37a552c3..9e392a30d197 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -60,6 +60,7 @@
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/unistd.h>
+#include <asm/hpsim.h>
#if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
# error "struct cpuinfo_ia64 too big!"
@@ -389,6 +390,8 @@ early_console_setup (char *cmdline)
if (!efi_setup_pcdp_console(cmdline))
earlycons++;
#endif
+ if (!simcons_register())
+ earlycons++;
return (earlycons) ? 0 : -1;
}
@@ -953,6 +956,11 @@ cpu_init (void)
/* clear TPR & XTP to enable all interrupt classes: */
ia64_setreg(_IA64_REG_CR_TPR, 0);
+
+ /* Clear any pending interrupts left by SAL/EFI */
+ while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
+ ia64_eoi();
+
#ifdef CONFIG_SMP
normal_xtp();
#endif
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 62209dcf06d3..308772f7cddc 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -58,6 +58,7 @@
#include <asm/system.h>
#include <asm/tlbflush.h>
#include <asm/unistd.h>
+#include <asm/sn/arch.h>
#define SMP_DEBUG 0
@@ -730,6 +731,11 @@ int __cpu_disable(void)
return (-EBUSY);
}
+ if (ia64_platform_is("sn2")) {
+ if (!sn_cpu_disable_allowed(cpu))
+ return -EBUSY;
+ }
+
cpu_clear(cpu, cpu_online_map);
if (migrate_platform_irqs(cpu)) {
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 83e80677de70..00232b4357ba 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -20,6 +20,8 @@ PHDRS {
code PT_LOAD;
percpu PT_LOAD;
data PT_LOAD;
+ note PT_NOTE;
+ unwind 0x70000001; /* PT_IA_64_UNWIND, but ld doesn't match the name */
}
SECTIONS
{
@@ -62,6 +64,9 @@ SECTIONS
/* Read-only data */
+ NOTES :code :note /* put .notes in text and mark in PT_NOTE */
+ code_continues : {} :code /* switch back to regular program... */
+
/* Exception table */
. = ALIGN(16);
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET)
@@ -99,7 +104,8 @@ SECTIONS
__start_unwind = .;
*(.IA_64.unwind*)
__end_unwind = .;
- }
+ } :code :unwind
+ code_continues2 : {} : code
RODATA
@@ -276,10 +282,6 @@ SECTIONS
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
- /* Discard them for now since Intel SoftSDV cannot handle them.
- .comment 0 : { *(.comment) }
- .note 0 : { *(.note) }
- */
/DISCARD/ : { *(.comment) }
/DISCARD/ : { *(.note) }
}
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 7ac8592a35b6..d3c538be466c 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -17,6 +17,7 @@
#include <linux/bootmem.h>
#include <linux/efi.h>
#include <linux/mm.h>
+#include <linux/nmi.h>
#include <linux/swap.h>
#include <asm/meminit.h>
@@ -56,6 +57,8 @@ void show_mem(void)
present = pgdat->node_present_pages;
for(i = 0; i < pgdat->node_spanned_pages; i++) {
struct page *page;
+ if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
+ touch_nmi_watchdog();
if (pfn_valid(pgdat->node_start_pfn + i))
page = pfn_to_page(pgdat->node_start_pfn + i);
else {
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 0dbf0e81f8c0..0d34585058c8 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/nmi.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
#include <linux/acpi.h>
@@ -533,6 +534,8 @@ void show_mem(void)
present = pgdat->node_present_pages;
for(i = 0; i < pgdat->node_spanned_pages; i++) {
struct page *page;
+ if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
+ touch_nmi_watchdog();
if (pfn_valid(pgdat->node_start_pfn + i))
page = pfn_to_page(pgdat->node_start_pfn + i);
else {
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 73ccb6010c05..9150ffaff9e8 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -112,11 +112,17 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
down_read(&mm->mmap_sem);
vma = find_vma_prev(mm, address, &prev_vma);
- if (!vma)
+ if (!vma && !prev_vma )
goto bad_area;
- /* find_vma_prev() returns vma such that address < vma->vm_end or NULL */
- if (address < vma->vm_start)
+ /*
+ * find_vma_prev() returns vma such that address < vma->vm_end or NULL
+ *
+ * May find no vma, but could be that the last vm area is the
+ * register backing store that needs to expand upwards, in
+ * this case vma will be null, but prev_vma will ne non-null
+ */
+ if (( !vma && prev_vma ) || (address < vma->vm_start) )
goto check_expansion;
good_area:
@@ -172,6 +178,8 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
check_expansion:
if (!(prev_vma && (prev_vma->vm_flags & VM_GROWSUP) && (address == prev_vma->vm_end))) {
+ if (!vma)
+ goto bad_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
if (REGION_NUMBER(address) != REGION_NUMBER(vma->vm_start)
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index d22861c5b04c..a9ff685aea25 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -75,10 +75,8 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
* Don't actually need to do any preparation, but need to make sure
* the address is in the right region.
*/
-int prepare_hugepage_range(unsigned long addr, unsigned long len, pgoff_t pgoff)
+int prepare_hugepage_range(unsigned long addr, unsigned long len)
{
- if (pgoff & (~HPAGE_MASK >> PAGE_SHIFT))
- return -EINVAL;
if (len & ~HPAGE_MASK)
return -EINVAL;
if (addr & ~HPAGE_MASK)
@@ -151,7 +149,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
/* Handle MAP_FIXED */
if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(addr, len, pgoff))
+ if (prepare_hugepage_range(addr, len))
return -EINVAL;
return addr;
}
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 2c3f9dfca78b..b663168da55c 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -185,11 +185,14 @@ void hubiio_crb_error_handler(struct hubdev_info *hubdev_info)
*/
void hub_error_init(struct hubdev_info *hubdev_info)
{
+
if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
- "SN_hub_error", (void *)hubdev_info))
+ "SN_hub_error", (void *)hubdev_info)) {
printk("hub_error_init: Failed to request_irq for 0x%p\n",
hubdev_info);
- return;
+ return;
+ }
+ sn_set_err_irq_affinity(SGI_II_ERROR);
}
@@ -202,11 +205,14 @@ void hub_error_init(struct hubdev_info *hubdev_info)
*/
void ice_error_init(struct hubdev_info *hubdev_info)
{
+
if (request_irq
(SGI_TIO_ERROR, (void *)hub_eint_handler, IRQF_SHARED, "SN_TIO_error",
- (void *)hubdev_info))
+ (void *)hubdev_info)) {
printk("ice_error_init: request_irq() error hubdev_info 0x%p\n",
hubdev_info);
- return;
+ return;
+ }
+ sn_set_err_irq_affinity(SGI_TIO_ERROR);
}
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 7f6d2360a262..0f9b12683bf3 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -19,6 +19,7 @@
#include <asm/sn/pcidev.h>
#include <asm/sn/shub_mmr.h>
#include <asm/sn/sn_sal.h>
+#include <asm/sn/sn_feature_sets.h>
static void force_interrupt(int irq);
static void register_intr_pda(struct sn_irq_info *sn_irq_info);
@@ -233,6 +234,20 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
(void)sn_retarget_vector(sn_irq_info, nasid, slice);
}
+#ifdef CONFIG_SMP
+void sn_set_err_irq_affinity(unsigned int irq)
+{
+ /*
+ * On systems which support CPU disabling (SHub2), all error interrupts
+ * are targetted at the boot CPU.
+ */
+ if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT))
+ set_irq_affinity_info(irq, cpu_physical_id(0), 0);
+}
+#else
+void sn_set_err_irq_affinity(unsigned int irq) { }
+#endif
+
static void
sn_mask_irq(unsigned int irq)
{
@@ -256,6 +271,13 @@ struct irq_chip irq_type_sn = {
.set_affinity = sn_set_affinity_irq
};
+ia64_vector sn_irq_to_vector(int irq)
+{
+ if (irq >= IA64_NUM_VECTORS)
+ return 0;
+ return (ia64_vector)irq;
+}
+
unsigned int sn_local_vector_to_irq(u8 vector)
{
return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector));
@@ -398,7 +420,10 @@ sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
struct sn_pcibus_provider *pci_provider;
pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
- if (pci_provider && pci_provider->force_interrupt)
+
+ /* Don't force an interrupt if the irq has been disabled */
+ if (!(irq_desc[sn_irq_info->irq_irq].status & IRQ_DISABLED) &&
+ pci_provider && pci_provider->force_interrupt)
(*pci_provider->force_interrupt)(sn_irq_info);
}
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 033c8a9f000e..f3c69329e145 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -40,6 +40,7 @@
#include <asm/sn/shub_mmr.h>
#include <asm/sn/nodepda.h>
#include <asm/sn/rw_mmr.h>
+#include <asm/sn/sn_feature_sets.h>
DEFINE_PER_CPU(struct ptc_stats, ptcstats);
DECLARE_PER_CPU(struct ptc_stats, ptcstats);
@@ -429,6 +430,31 @@ void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
sn_send_IPI_phys(nasid, physid, vector, delivery_mode);
}
+#ifdef CONFIG_HOTPLUG_CPU
+/**
+ * sn_cpu_disable_allowed - Determine if a CPU can be disabled.
+ * @cpu - CPU that is requested to be disabled.
+ *
+ * CPU disable is only allowed on SHub2 systems running with a PROM
+ * that supports CPU disable. It is not permitted to disable the boot processor.
+ */
+bool sn_cpu_disable_allowed(int cpu)
+{
+ if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) {
+ if (cpu != 0)
+ return true;
+ else
+ printk(KERN_WARNING
+ "Disabling the boot processor is not allowed.\n");
+
+ } else
+ printk(KERN_WARNING
+ "CPU disable is not supported on this system.\n");
+
+ return false;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
#ifdef CONFIG_PROC_FS
#define PTC_BASENAME "sgi_sn/ptc_statistics"
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index df8d5bed6119..1a8e49607f11 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -66,7 +66,8 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
}
sz = sn_hwperf_obj_cnt * sizeof(struct sn_hwperf_object_info);
- if ((objbuf = (struct sn_hwperf_object_info *) vmalloc(sz)) == NULL) {
+ objbuf = vmalloc(sz);
+ if (objbuf == NULL) {
printk("sn_hwperf_enum_objects: vmalloc(%d) failed\n", (int)sz);
e = -ENOMEM;
goto out;
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 5a289e4de838..a88eba3314d7 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
}
-static int tiocx_uevent(struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
{
return -ENODEV;
}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 42485ad50ceb..ab3eaf85fe4d 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -145,6 +145,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
printk(KERN_WARNING
"pcibr cannot allocate interrupt for error handler\n");
}
+ sn_set_err_irq_affinity(SGI_PCIASIC_ERROR);
/*
* Update the Bridge with the "kernel" pagesize
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index d798dd4d0dc4..ef048a674772 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -654,6 +654,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
__FUNCTION__, SGI_TIOCA_ERROR,
(int)tioca_common->ca_common.bs_persist_busnum);
+ sn_set_err_irq_affinity(SGI_TIOCA_ERROR);
+
/* Setup locality information */
controller->node = tioca_kern->ca_closest_node;
return tioca_common;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 84b72b27e27f..cee9379d44e0 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -1034,6 +1034,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
tioce_common->ce_pcibus.bs_persist_segment,
tioce_common->ce_pcibus.bs_persist_busnum);
+ sn_set_err_irq_affinity(SGI_PCIASIC_ERROR);
return tioce_common;
}