From 17764d2437b0c4440e0718205f2c26dbaa72bc27 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 28 Aug 2007 16:01:21 -0700 Subject: [IA64] Fix unexpected interrupt vector handling Fix handling for spurious interrupts not being mapped to any IRQs. Currently, spurious interrupts that are not mapped to any IRQs are handled as IRQ 15 (== IA64_SPURIOUS_VECTOR). But it is not proper because vector != irq. We need special handlings for such spurious interrupts not being mapped to any IRQs. Signed-off-by: Kenji Kaneshige Signed-off-by: Tony Luck --- arch/ia64/kernel/irq_ia64.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index c47c8acc96e..00a4599e5f4 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); /* -- cgit v1.2.3 From f740e6c9c55cac6ab0a7d44a464b54467cca4f4f Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 22 Aug 2007 19:53:30 +0900 Subject: [IA64] Clear pending interrupts at CPU boot up time The pending interrupts can be remaining at boot up time on some platform. This will cause spurious interrupts when interrupt is enabled for the first time. This patch clears IVR at the CPU initialization to eliminate such spurious interrupts. Signed-off-by: Kenji Kaneshige Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/ia64') diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 407efea04bf..1f9b1d818dc 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -960,6 +960,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 -- cgit v1.2.3 From 1aac0b5739ae192ee812eee09625ebfc08c2d760 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 24 Aug 2007 01:40:26 +0200 Subject: [IA64] Remove unnecessary cast of allocation return value in sn_hwperf_enum_objects() vmalloc() returns a void pointer - no need to cast it. Signed-off-by: Jesper Juhl Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/sn2/sn_hwperf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/ia64') diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index df8d5bed611..1a8e49607f1 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; -- cgit v1.2.3 From 6e9de18120988388cdae5097c09e774416d58745 Mon Sep 17 00:00:00 2001 From: John Keller Date: Wed, 22 Aug 2007 19:32:06 -0500 Subject: [IA64] SN: Add support for CPU disable Add additional support for CPU disable on SN platforms. Correctly setup the smp_affinity mask for I/O error IRQs. Restrict the use of the feature to Altix 4000 and 450 systems running with a CPU disable capable PROM, and do not allow disabling of CPU 0. Signed-off-by: John Keller Signed-off-by: Tony Luck --- arch/ia64/kernel/smpboot.c | 6 ++++++ arch/ia64/sn/kernel/huberror.c | 14 ++++++++++---- arch/ia64/sn/kernel/irq.c | 15 +++++++++++++++ arch/ia64/sn/kernel/sn2/sn2_smp.c | 26 ++++++++++++++++++++++++++ arch/ia64/sn/pci/pcibr/pcibr_provider.c | 1 + arch/ia64/sn/pci/tioca_provider.c | 2 ++ arch/ia64/sn/pci/tioce_provider.c | 1 + 7 files changed, 61 insertions(+), 4 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 62209dcf06d..308772f7cdd 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -58,6 +58,7 @@ #include #include #include +#include #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/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 2c3f9dfca78..b663168da55 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 36004738944..0f9b12683bf 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -19,6 +19,7 @@ #include #include #include +#include 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) { diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 033c8a9f000..f3c69329e14 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -40,6 +40,7 @@ #include #include #include +#include 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/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 42485ad50ce..ab3eaf85fe4 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 d798dd4d0dc..ef048a67477 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 84b72b27e27..cee9379d44e 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; } -- cgit v1.2.3 From 99a19cf1c0eb22bad83fff060f08330ee9e029e2 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 22 Aug 2007 14:34:38 -0400 Subject: [IA64] Stop bogus NMI & softlockup warnings in ia64 show_mem When dumping memory via sysrq-m it is possible to take a bogus NMI watchdog or softlockup watchdog because the dump can take a long time on big memory systems. Occasionally tickle the watchdog when doing the dump. Signed-off-by: Prarit Bhargava Signed-off-by: Tony Luck --- arch/ia64/mm/contig.c | 3 +++ arch/ia64/mm/discontig.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'arch/ia64') diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 7ac8592a35b..d3c538be466 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -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 0dbf0e81f8c..0d34585058c 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -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 { -- cgit v1.2.3 From 8b713c67bccef7cabb0ee915f47eb33d82636af9 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 21 Aug 2007 13:51:45 +1000 Subject: [IA64] Enable early console for Ski simulator This patch cleans up the `enable early console for SKI' patch (471e7a44848f467c9b83adc3463d019d2fa8817f), and 1. potentially allows the gensparse_defconfig to work again. (there are other problems running a generic kernel on Ski) 2. fixes the `console registered twice' problem. 3. Cleans up the code by moving the `extern hpsim_cons' declaration to a new asm/hpsim.h file. Thanks to Jes for comments. Signed-off-by: Peter Chubb Signed-off-by: Tony Luck --- arch/ia64/hp/sim/hpsim_console.c | 15 ++++++++++++++- arch/ia64/hp/sim/hpsim_setup.c | 9 ++------- arch/ia64/kernel/setup.c | 8 ++------ 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c index 6e149c8ab83..0475a545240 100644 --- a/arch/ia64/hp/sim/hpsim_console.c +++ b/arch/ia64/hp/sim/hpsim_console.c @@ -21,6 +21,7 @@ #include #include #include +#include #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, @@ -62,3 +63,15 @@ static struct tty_driver *simcons_console_device (struct console *c, int *index) *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 f2297192a58..f629e903ebc 100644 --- a/arch/ia64/hp/sim/hpsim_setup.c +++ b/arch/ia64/hp/sim/hpsim_setup.c @@ -21,6 +21,7 @@ #include #include #include +#include #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/kernel/setup.c b/arch/ia64/kernel/setup.c index 1f9b1d818dc..9e392a30d19 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -60,6 +60,7 @@ #include #include #include +#include #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE) # error "struct cpuinfo_ia64 too big!" @@ -389,13 +390,8 @@ early_console_setup (char *cmdline) if (!efi_setup_pcdp_console(cmdline)) earlycons++; #endif -#ifdef CONFIG_HP_SIMSERIAL_CONSOLE - { - extern struct console hpsim_cons; - register_console(&hpsim_cons); + if (!simcons_register()) earlycons++; - } -#endif return (earlycons) ? 0 : -1; } -- cgit v1.2.3 From 7b3166dbc3df5b72f2ba4ea130f4461e318a3838 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 21 Aug 2007 13:57:01 +1000 Subject: [IA64] Cleanup HPSIM code (was: Re: Enable early console for Ski simulator) After my last patch we have a new header file for HP simulator use. Here's code to use it for stuff that used to have `extern' statements inline in the code. Functionality should not change with this patch. Signed-off-by: Peter Chubb Signed-off-by: Tony Luck --- arch/ia64/hp/sim/hpsim_console.c | 1 - arch/ia64/hp/sim/simeth.c | 12 +++--------- arch/ia64/hp/sim/simscsi.c | 3 +-- 3 files changed, 4 insertions(+), 12 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c index 0475a545240..01663bc42b1 100644 --- a/arch/ia64/hp/sim/hpsim_console.c +++ b/arch/ia64/hp/sim/hpsim_console.c @@ -59,7 +59,6 @@ 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; } diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index f26077a773d..4017696ada6 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -22,6 +22,9 @@ #include #include #include +#include + +#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) { diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index e62694f8ef7..4552a1cf5b3 100644 --- a/arch/ia64/hp/sim/simscsi.c +++ b/arch/ia64/hp/sim/simscsi.c @@ -14,6 +14,7 @@ #include #include #include +#include "hpsim_ssc.h" #include #include @@ -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 }; -- cgit v1.2.3