diff options
Diffstat (limited to 'arch/ia64/sn')
-rw-r--r-- | arch/ia64/sn/kernel/huberror.c | 14 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_acpi_init.c | 17 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_common.c | 2 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 20 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/irq.c | 27 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 26 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_hwperf.c | 6 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/timer.c | 26 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/tiocx.c | 2 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_provider.c | 3 | ||||
-rw-r--r-- | arch/ia64/sn/pci/tioca_provider.c | 2 | ||||
-rw-r--r-- | arch/ia64/sn/pci/tioce_provider.c | 1 |
13 files changed, 116 insertions, 31 deletions
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/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index c6216f454ffb..3c7178f5dce8 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -418,7 +418,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev) void __iomem *addr; struct pcidev_info *pcidev_info = NULL; struct sn_irq_info *sn_irq_info = NULL; - size_t size; + size_t image_size, size; if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { panic("%s: Failure obtaining pcidev_info for %s\n", @@ -428,17 +428,16 @@ sn_acpi_slot_fixup(struct pci_dev *dev) if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) { /* * A valid ROM image exists and has been shadowed by the - * PROM. Setup the pci_dev ROM resource to point to - * the shadowed copy. + * PROM. Setup the pci_dev ROM resource with the address + * of the shadowed copy, and the actual length of the ROM image. */ - size = dev->resource[PCI_ROM_RESOURCE].end - - dev->resource[PCI_ROM_RESOURCE].start; - addr = - ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], - size); + size = pci_resource_len(dev, PCI_ROM_RESOURCE); + addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], + size); + image_size = pci_get_rom_size(addr, size); dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; dev->resource[PCI_ROM_RESOURCE].end = - (unsigned long) addr + size; + (unsigned long) addr + image_size - 1; dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; } sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index 787ed642dd49..4594770e685a 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -391,7 +391,7 @@ void sn_bus_free_sysdata(void) * hubdev_init_node() - Creates the HUB data structure and link them to it's * own NODE specific data area. */ -void hubdev_init_node(nodepda_t * npda, cnodeid_t node) +void __init hubdev_init_node(nodepda_t * npda, cnodeid_t node) { struct hubdev_info *hubdev_info; int size; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 6b10e5d28488..906b93674b76 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -259,9 +259,23 @@ sn_io_slot_fixup(struct pci_dev *dev) insert_resource(&ioport_resource, &dev->resource[idx]); else insert_resource(&iomem_resource, &dev->resource[idx]); - /* If ROM, mark as shadowed in PROM */ - if (idx == PCI_ROM_RESOURCE) - dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY; + /* + * If ROM, set the actual ROM image size, and mark as + * shadowed in PROM. + */ + if (idx == PCI_ROM_RESOURCE) { + size_t image_size; + void __iomem *rom; + + rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE), + size + 1); + image_size = pci_get_rom_size(rom, size + 1); + dev->resource[PCI_ROM_RESOURCE].end = + dev->resource[PCI_ROM_RESOURCE].start + + image_size - 1; + dev->resource[PCI_ROM_RESOURCE].flags |= + IORESOURCE_ROM_BIOS_COPY; + } } /* Create a pci_window in the pci_controller struct for * each device resource. 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/setup.c b/arch/ia64/sn/kernel/setup.c index 684b1c984a44..1f38a3a68390 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -25,7 +25,6 @@ #include <linux/interrupt.h> #include <linux/acpi.h> #include <linux/compiler.h> -#include <linux/sched.h> #include <linux/root_dev.h> #include <linux/nodemask.h> #include <linux/pm.h> 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 6da9854751cd..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; @@ -750,9 +751,10 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) goto error; } else if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { + int cpuobj_index = 0; + memset(p, 0, a.sz); for (i = 0; i < nobj; i++) { - int cpuobj_index = 0; if (!SN_HWPERF_IS_NODE(objs + i)) continue; node = sn_hwperf_obj_to_cnode(objs + i); diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index 56a88b6df4b4..cf67fc562054 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c @@ -11,6 +11,7 @@ #include <linux/sched.h> #include <linux/time.h> #include <linux/interrupt.h> +#include <linux/clocksource.h> #include <asm/hw_irq.h> #include <asm/system.h> @@ -22,11 +23,19 @@ extern unsigned long sn_rtc_cycles_per_second; -static struct time_interpolator sn2_interpolator = { - .drift = -1, - .shift = 10, - .mask = (1LL << 55) - 1, - .source = TIME_SOURCE_MMIO64 +static cycle_t read_sn2(void) +{ + return (cycle_t)readq(RTC_COUNTER_ADDR); +} + +static struct clocksource clocksource_sn2 = { + .name = "sn2_rtc", + .rating = 450, + .read = read_sn2, + .mask = (1LL << 55) - 1, + .mult = 0, + .shift = 10, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; /* @@ -47,9 +56,10 @@ ia64_sn_udelay (unsigned long usecs) void __init sn_timer_init(void) { - sn2_interpolator.frequency = sn_rtc_cycles_per_second; - sn2_interpolator.addr = RTC_COUNTER_ADDR; - register_time_interpolator(&sn2_interpolator); + clocksource_sn2.fsys_mmio = RTC_COUNTER_ADDR; + clocksource_sn2.mult = clocksource_hz2mult(sn_rtc_cycles_per_second, + clocksource_sn2.shift); + clocksource_register(&clocksource_sn2); ia64_udelay = &ia64_sn_udelay; } diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 493380b2c05f..5a289e4de838 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -369,7 +369,7 @@ static void tio_corelet_reset(nasid_t nasid, int corelet) static int is_fpga_tio(int nasid, int *bt) { - u16 ioboard_type; + u16 uninitialized_var(ioboard_type); /* GCC be quiet */ s64 rc; rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index b42bfcae6f91..ab3eaf85fe4d 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -80,7 +80,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft) u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus) { s64 rc; - u16 ioboard; + u16 uninitialized_var(ioboard); /* GCC be quiet */ nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base); rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard); @@ -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; } |