diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/Kconfig | 4 | ||||
-rw-r--r-- | arch/ia64/dig/setup.c | 10 | ||||
-rw-r--r-- | arch/ia64/ia32/ia32_signal.c | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/efi.c | 16 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 16 | ||||
-rw-r--r-- | arch/ia64/kernel/fsys.S | 29 | ||||
-rw-r--r-- | arch/ia64/kernel/head.S | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/mca_drv.c | 3 | ||||
-rw-r--r-- | arch/ia64/kernel/sal.c | 75 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/time.c | 27 | ||||
-rw-r--r-- | arch/ia64/sn/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/bte.c | 17 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 17 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/irq.c | 25 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/klconflib.c | 29 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/mca.c | 5 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 73 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 196 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_hwperf.c | 5 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/xpc_main.c | 19 | ||||
-rw-r--r-- | arch/ia64/sn/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/Makefile | 2 |
25 files changed, 321 insertions, 261 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 199eeaf0f4e..845cd0902a5 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -194,7 +194,6 @@ config IA64_L1_CACHE_SHIFT default "7" if MCKINLEY default "6" if ITANIUM -# align cache-sensitive data to 64 bytes config IA64_CYCLONE bool "Cyclone (EXA) Time Source support" help @@ -374,6 +373,9 @@ config IA64_PALINFO To use this option, you have to ensure that the "/proc file system support" (CONFIG_PROC_FS) is enabled, too. +config SGI_SN + def_bool y if (IA64_SGI_SN2 || IA64_GENERIC) + source "drivers/firmware/Kconfig" source "fs/Kconfig.binfmt" diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c index d58003f1ad0..c9104bfff66 100644 --- a/arch/ia64/dig/setup.c +++ b/arch/ia64/dig/setup.c @@ -25,16 +25,6 @@ #include <asm/machvec.h> #include <asm/system.h> -/* - * This is here so we can use the CMOS detection in ide-probe.c to - * determine what drives are present. In theory, we don't need this - * as the auto-detection could be done via ide-probe.c:do_probe() but - * in practice that would be much slower, which is painful when - * running in the simulator. Note that passing zeroes in DRIVE_INFO - * is sufficient (the IDE driver will autodetect the drive geometry). - */ -char drive_info[4*16]; - void __init dig_setup (char **cmdline_p) { diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index 5856510210f..b3355a9ca2c 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -515,6 +515,7 @@ sys32_signal (int sig, unsigned int handler) sigact_set_handler(&new_sa, handler, 0); new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; + sigemptyset(&new_sa.sa.sa_mask); ret = do_sigaction(sig, &new_sa, &old_sa); diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index c485a3b32ba..9990320b6f9 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -410,24 +410,16 @@ efi_init (void) efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; - char *cp, *end, vendor[100] = "unknown"; + char *cp, vendor[100] = "unknown"; extern char saved_command_line[]; int i; /* it's too early to be able to use the standard kernel command line support... */ for (cp = saved_command_line; *cp; ) { if (memcmp(cp, "mem=", 4) == 0) { - cp += 4; - mem_limit = memparse(cp, &end); - if (end != cp) - break; - cp = end; + mem_limit = memparse(cp + 4, &cp); } else if (memcmp(cp, "max_addr=", 9) == 0) { - cp += 9; - max_addr = GRANULEROUNDDOWN(memparse(cp, &end)); - if (end != cp) - break; - cp = end; + max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); } else { while (*cp != ' ' && *cp) ++cp; @@ -458,7 +450,7 @@ efi_init (void) /* Show what we know for posterity */ c16 = __va(efi.systab->fw_vendor); if (c16) { - for (i = 0;i < (int) sizeof(vendor) && *c16; ++i) + for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i) vendor[i] = *c16++; vendor[i] = '\0'; } diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 7a6ffd61378..27b222c277e 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1601,5 +1601,21 @@ sys_call_table: data8 sys_inotify_add_watch data8 sys_inotify_rm_watch data8 sys_migrate_pages // 1280 + data8 sys_openat + data8 sys_mkdirat + data8 sys_mknodat + data8 sys_fchownat + data8 sys_futimesat // 1285 + data8 sys_newfstatat + data8 sys_unlinkat + data8 sys_renameat + data8 sys_linkat + data8 sys_symlinkat // 1290 + data8 sys_readlinkat + data8 sys_fchmodat + data8 sys_faccessat + data8 sys_ni_syscall // reserved for pselect + data8 sys_ni_syscall // 1295 reserved for ppoll + data8 sys_unshare .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index ce423910ca9..ac6055c8311 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -878,31 +878,8 @@ fsyscall_table: data8 0 // timer_delete data8 0 // clock_settime data8 fsys_clock_gettime // clock_gettime - data8 0 // clock_getres // 1255 - data8 0 // clock_nanosleep - data8 0 // fstatfs64 - data8 0 // statfs64 - data8 0 - data8 0 // 1260 - data8 0 - data8 0 // mq_open - data8 0 // mq_unlink - data8 0 // mq_timedsend - data8 0 // mq_timedreceive // 1265 - data8 0 // mq_notify - data8 0 // mq_getsetattr - data8 0 // kexec_load - data8 0 - data8 0 // 1270 - data8 0 - data8 0 - data8 0 - data8 0 - data8 0 // 1275 - data8 0 - data8 0 - data8 0 - data8 0 - data8 0 // 1280 + #define __NR_syscall_last 1255 + + .space 8*(NR_syscalls + 1024 - __NR_syscall_last), 0 .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index fbc7ea35dd5..f1778a84ea6 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -352,6 +352,7 @@ start_ap: mov ar.rsc=0 // place RSE in enforced lazy mode ;; loadrs // clear the dirty partition + mov IA64_KR(PER_CPU_DATA)=r0 // clear physical per-CPU base ;; mov ar.bspstore=r2 // establish the new RSE stack ;; diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 3492e3211a4..8fd93afa75a 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -437,6 +437,9 @@ recover_from_read_error(slidx_table_t *slidx, * the process not have any locks of kernel. */ + /* Is minstate valid? */ + if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate)) + return 0; psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr); /* diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index acc0f132f86..056f7a6eedc 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -14,6 +14,7 @@ #include <linux/spinlock.h> #include <linux/string.h> +#include <asm/delay.h> #include <asm/page.h> #include <asm/sal.h> #include <asm/pal.h> @@ -214,6 +215,78 @@ chk_nointroute_opt(void) static void __init sal_desc_ap_wakeup(void *p) { } #endif +/* + * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading + * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as + * "in-service" and masks other interrupts of equal or lower priority. + * + * HP internal defect reports: F1859, F2775, F3031. + */ +static int sal_cache_flush_drops_interrupts; + +static void __init +check_sal_cache_flush (void) +{ + unsigned long flags, itv; + int cpu; + u64 vector; + + cpu = get_cpu(); + local_irq_save(flags); + + /* + * Schedule a timer interrupt, wait until it's reported, and see if + * SAL_CACHE_FLUSH drops it. + */ + itv = ia64_get_itv(); + BUG_ON((itv & (1 << 16)) == 0); + + ia64_set_itv(IA64_TIMER_VECTOR); + ia64_set_itm(ia64_get_itc() + 1000); + + while (!ia64_get_irr(IA64_TIMER_VECTOR)) + cpu_relax(); + + ia64_sal_cache_flush(3); + + if (ia64_get_irr(IA64_TIMER_VECTOR)) { + vector = ia64_get_ivr(); + ia64_eoi(); + WARN_ON(vector != IA64_TIMER_VECTOR); + } else { + sal_cache_flush_drops_interrupts = 1; + printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; " + "PAL_CACHE_FLUSH will be used instead\n"); + ia64_eoi(); + } + + ia64_set_itv(itv); + local_irq_restore(flags); + put_cpu(); +} + +s64 +ia64_sal_cache_flush (u64 cache_type) +{ + struct ia64_sal_retval isrv; + + if (sal_cache_flush_drops_interrupts) { + unsigned long flags; + u64 progress; + s64 rc; + + progress = 0; + local_irq_save(flags); + rc = ia64_pal_cache_flush(cache_type, + PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL); + local_irq_restore(flags); + return rc; + } + + SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); + return isrv.status; +} + void __init ia64_sal_init (struct ia64_sal_systab *systab) { @@ -262,6 +335,8 @@ ia64_sal_init (struct ia64_sal_systab *systab) } p += SAL_DESC_SIZE(*p); } + + check_sal_cache_flush(); } int diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c0766575a3a..35f7835294a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -71,6 +71,8 @@ unsigned long __per_cpu_offset[NR_CPUS]; EXPORT_SYMBOL(__per_cpu_offset); #endif +extern void ia64_setup_printk_clock(void); + DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info); DEFINE_PER_CPU(unsigned long, local_per_cpu_offset); DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8); @@ -445,6 +447,8 @@ setup_arch (char **cmdline_p) /* process SAL system table: */ ia64_sal_init(efi.sal_systab); + ia64_setup_printk_clock(); + #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 028a2b95936..a094ec49ccf 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -278,3 +278,30 @@ udelay (unsigned long usecs) } } EXPORT_SYMBOL(udelay); + +static unsigned long long ia64_itc_printk_clock(void) +{ + if (ia64_get_kr(IA64_KR_PER_CPU_DATA)) + return sched_clock(); + return 0; +} + +static unsigned long long ia64_default_printk_clock(void) +{ + return (unsigned long long)(jiffies_64 - INITIAL_JIFFIES) * + (1000000000/HZ); +} + +unsigned long long (*ia64_printk_clock)(void) = &ia64_default_printk_clock; + +unsigned long long printk_clock(void) +{ + return ia64_printk_clock(); +} + +void __init +ia64_setup_printk_clock(void) +{ + if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) + ia64_printk_clock = ia64_itc_printk_clock; +} diff --git a/arch/ia64/sn/Makefile b/arch/ia64/sn/Makefile index a269f6d84c2..79a7df02e81 100644 --- a/arch/ia64/sn/Makefile +++ b/arch/ia64/sn/Makefile @@ -9,6 +9,4 @@ # Makefile for the sn ia64 subplatform # -CPPFLAGS += -I$(srctree)/arch/ia64/sn/include - obj-y += kernel/ pci/ diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 4351c4ff984..3e9b4eea741 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -7,6 +7,8 @@ # Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All Rights Reserved. # +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ huberror.o io_init.o iomv.o klconflib.o sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index dd73c0cb754..1f11db470d9 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/config.h> @@ -186,18 +186,13 @@ retry_bteop: /* Initialize the notification to a known value. */ *bte->most_rcnt_na = BTE_WORD_BUSY; - notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)); + notif_phys_addr = (u64)bte->most_rcnt_na; - if (is_shub2()) { - src = SH2_TIO_PHYS_TO_DMA(src); - dest = SH2_TIO_PHYS_TO_DMA(dest); - notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr); - } /* Set the source and destination registers */ - BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); - BTE_SRC_STORE(bte, TO_PHYS(src)); - BTE_PRINTKV(("IBDA = 0x%lx)\n", (TO_PHYS(dest)))); - BTE_DEST_STORE(bte, TO_PHYS(dest)); + BTE_PRINTKV(("IBSA = 0x%lx)\n", src)); + BTE_SRC_STORE(bte, src); + BTE_PRINTKV(("IBDA = 0x%lx)\n", dest)); + BTE_DEST_STORE(bte, dest); /* Set the notification register */ BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr)); diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index a4c78152b33..3437c239042 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -208,7 +208,7 @@ static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for * each node in the system. */ -static void sn_fixup_ionodes(void) +static void __init sn_fixup_ionodes(void) { struct sn_flush_device_kernel *sn_flush_device_kernel; struct sn_flush_device_kernel *dev_entry; @@ -467,6 +467,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev) pcidev_info->pdi_sn_irq_info = NULL; kfree(sn_irq_info); } + + /* + * MSI currently not supported on altix. Remove this when + * the MSI abstraction patches are integrated into the kernel + * (sometime after 2.6.16 releases) + */ + dev->no_msi = 1; } /* @@ -610,15 +617,15 @@ void sn_bus_store_sysdata(struct pci_dev *dev) void sn_bus_free_sysdata(void) { struct sysdata_el *element; - struct list_head *list; + struct list_head *list, *safe; -sn_sysdata_free_start: - list_for_each(list, &sn_sysdata_list) { + list_for_each_safe(list, safe, &sn_sysdata_list) { element = list_entry(list, struct sysdata_el, entry); list_del(&element->entry); + list_del(&(((struct pcidev_info *) + (element->sysdata))->pdi_list)); kfree(element->sysdata); kfree(element); - goto sn_sysdata_free_start; } return; } diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index ec37084bdc1..c373113d073 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -5,11 +5,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/irq.h> #include <linux/spinlock.h> +#include <linux/init.h> #include <asm/sn/addrs.h> #include <asm/sn/arch.h> #include <asm/sn/intr.h> @@ -76,17 +77,15 @@ static void sn_enable_irq(unsigned int irq) static void sn_ack_irq(unsigned int irq) { - u64 event_occurred, mask = 0; + u64 event_occurred, mask; irq = irq & 0xff; - event_occurred = - HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); + event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); mask = event_occurred & SH_ALL_INT_MASK; - HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), - mask); + HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); - move_irq(irq); + move_native_irq(irq); } static void sn_end_irq(unsigned int irq) @@ -219,9 +218,8 @@ static void register_intr_pda(struct sn_irq_info *sn_irq_info) pdacpu(cpu)->sn_last_irq = irq; } - if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) { + if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq; - } } static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) @@ -289,7 +287,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); spin_unlock(&sn_irq_info_lock); - (void)register_intr_pda(sn_irq_info); + register_intr_pda(sn_irq_info); } void sn_irq_unfixup(struct pci_dev *pci_dev) @@ -301,7 +299,9 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) return; sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info; - if (!sn_irq_info || !sn_irq_info->irq_irq) { + if (!sn_irq_info) + return; + if (!sn_irq_info->irq_irq) { kfree(sn_irq_info); return; } @@ -419,7 +419,7 @@ void sn_lb_int_war_check(void) rcu_read_unlock(); } -void sn_irq_lh_init(void) +void __init sn_irq_lh_init(void) { int i; @@ -434,5 +434,4 @@ void sn_irq_lh_init(void) INIT_LIST_HEAD(sn_irq_lh[i]); } - } diff --git a/arch/ia64/sn/kernel/klconflib.c b/arch/ia64/sn/kernel/klconflib.c index 0f11a3299cd..87682b48ef8 100644 --- a/arch/ia64/sn/kernel/klconflib.c +++ b/arch/ia64/sn/kernel/klconflib.c @@ -78,31 +78,30 @@ format_module_id(char *buffer, moduleid_t m, int fmt) position = MODULE_GET_BPOS(m); if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { - /* Brief module number format, eg. 002c15 */ + /* Brief module number format, eg. 002c15 */ - /* Decompress the rack number */ - *buffer++ = '0' + RACK_GET_CLASS(rack); - *buffer++ = '0' + RACK_GET_GROUP(rack); - *buffer++ = '0' + RACK_GET_NUM(rack); + /* Decompress the rack number */ + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); - /* Add the brick type */ - *buffer++ = brickchar; + /* Add the brick type */ + *buffer++ = brickchar; } else if (fmt == MODULE_FORMAT_LONG) { - /* Fuller hwgraph format, eg. rack/002/bay/15 */ + /* Fuller hwgraph format, eg. rack/002/bay/15 */ - strcpy(buffer, "rack" "/"); buffer += strlen(buffer); + strcpy(buffer, "rack" "/"); buffer += strlen(buffer); - *buffer++ = '0' + RACK_GET_CLASS(rack); - *buffer++ = '0' + RACK_GET_GROUP(rack); - *buffer++ = '0' + RACK_GET_NUM(rack); + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); - strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); + strcpy(buffer, "/" "bay" "/"); buffer += strlen(buffer); } /* Add the bay position, using at least two digits */ if (position < 10) - *buffer++ = '0'; + *buffer++ = '0'; sprintf(buffer, "%d", position); - } diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 9ab684d1bb5..3db62f24596 100644 --- a/arch/ia64/sn/kernel/mca.c +++ b/arch/ia64/sn/kernel/mca.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/types.h> @@ -137,7 +137,8 @@ int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdat static int __init sn_salinfo_init(void) { - salinfo_platform_oemdata = &sn_salinfo_platform_oemdata; + if (ia64_platform_is("sn2")) + salinfo_platform_oemdata = &sn_salinfo_platform_oemdata; return 0; } diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index e510dce9971..48645ac120f 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -67,6 +67,7 @@ extern unsigned long last_time_offset; extern void (*ia64_mark_idle) (int); extern void snidle(int); extern unsigned char acpi_kbd_controller_present; +extern unsigned long long (*ia64_printk_clock)(void); unsigned long sn_rtc_cycles_per_second; EXPORT_SYMBOL(sn_rtc_cycles_per_second); @@ -125,20 +126,6 @@ struct screen_info sn_screen_info = { }; /* - * This is here so we can use the CMOS detection in ide-probe.c to - * determine what drives are present. In theory, we don't need this - * as the auto-detection could be done via ide-probe.c:do_probe() but - * in practice that would be much slower, which is painful when - * running in the simulator. Note that passing zeroes in DRIVE_INFO - * is sufficient (the IDE driver will autodetect the drive geometry). - */ -#ifdef CONFIG_IA64_GENERIC -extern char drive_info[4 * 16]; -#else -char drive_info[4 * 16]; -#endif - -/* * This routine can only be used during init, since * smp_boot_data is an init data structure. * We have to use smp_boot_data.cpu_phys_id to find @@ -209,7 +196,7 @@ void __init early_sn_setup(void) } extern int platform_intr_list[]; -static int __initdata shub_1_1_found = 0; +static int __initdata shub_1_1_found; /* * sn_check_for_wars @@ -372,6 +359,16 @@ sn_scan_pcdp(void) } } +static unsigned long sn2_rtc_initial; + +static unsigned long long ia64_sn2_printk_clock(void) +{ + unsigned long rtc_now = rtc_time(); + + return (rtc_now - sn2_rtc_initial) * + (1000000000 / sn_rtc_cycles_per_second); +} + /** * sn_setup - SN platform setup routine * @cmdline_p: kernel command line @@ -386,6 +383,7 @@ void __init sn_setup(char **cmdline_p) u32 version = sn_sal_rev(); extern void sn_cpu_init(void); + sn2_rtc_initial = rtc_time(); ia64_sn_plat_set_error_handling_features(); // obsolete ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV); ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES); @@ -437,19 +435,6 @@ void __init sn_setup(char **cmdline_p) */ build_cnode_tables(); - /* - * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard - * support here so we don't have to listen to failed keyboard probe - * messages. - */ - if (version <= 0x0209 && acpi_kbd_controller_present) { - printk(KERN_INFO "Disabling legacy keyboard support as prom " - "is too old and doesn't provide FADT\n"); - acpi_kbd_controller_present = 0; - } - - printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); - status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift); @@ -463,6 +448,21 @@ void __init sn_setup(char **cmdline_p) platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR; + ia64_printk_clock = ia64_sn2_printk_clock; + + /* + * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard + * support here so we don't have to listen to failed keyboard probe + * messages. + */ + if (version <= 0x0209 && acpi_kbd_controller_present) { + printk(KERN_INFO "Disabling legacy keyboard support as prom " + "is too old and doesn't provide FADT\n"); + acpi_kbd_controller_present = 0; + } + + printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF); + /* * we set the default root device to /dev/hda * to make simulation easy @@ -578,13 +578,17 @@ void __init sn_cpu_init(void) sn_prom_type = 2; else sn_prom_type = 1; - printk("Running on medusa with %s PROM\n", (sn_prom_type == 1) ? "real" : "fake"); + printk(KERN_INFO "Running on medusa with %s PROM\n", + (sn_prom_type == 1) ? "real" : "fake"); } memset(pda, 0, sizeof(pda)); - if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift, - &sn_system_size, &sn_sharing_domain_size, &sn_partition_id, - &sn_coherency_id, &sn_region_size)) + if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, + &sn_hub_info->nasid_bitmask, + &sn_hub_info->nasid_shift, + &sn_system_size, &sn_sharing_domain_size, + &sn_partition_id, &sn_coherency_id, + &sn_region_size)) BUG(); sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2; @@ -716,7 +720,8 @@ void __init build_cnode_tables(void) for_each_online_node(node) { kl_config_hdr_t *klgraph_header; nasid = cnodeid_to_nasid(node); - if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL) + klgraph_header = ia64_sn_get_klconfig_addr(nasid); + if (klgraph_header == NULL) BUG(); brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info); while (brd) { @@ -734,7 +739,7 @@ nasid_slice_to_cpuid(int nasid, int slice) { long cpu; - for (cpu=0; cpu < NR_CPUS; cpu++) + for (cpu = 0; cpu < NR_CPUS; cpu++) if (cpuid_to_nasid(cpu) == nasid && cpuid_to_slice(cpu) == slice) return cpu; diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile index 170bde4549d..99e17769323 100644 --- a/arch/ia64/sn/kernel/sn2/Makefile +++ b/arch/ia64/sn/kernel/sn2/Makefile @@ -9,5 +9,7 @@ # sn2 specific kernel files # +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 471bbaa65d1..f153a4c35c7 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved. */ #include <linux/init.h> @@ -46,104 +46,28 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats); static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); -void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0, - volatile unsigned long *, unsigned long data1); +void sn2_ptc_deadlock_recovery(short *, short, short, int, volatile unsigned long *, unsigned long, + volatile unsigned long *, unsigned long); -#ifdef DEBUG_PTC /* - * ptctest: - * - * xyz - 3 digit hex number: - * x - Force PTC purges to use shub: - * 0 - no force - * 1 - force - * y - interupt enable - * 0 - disable interrupts - * 1 - leave interuupts enabled - * z - type of lock: - * 0 - global lock - * 1 - node local lock - * 2 - no lock - * - * Note: on shub1, only ptctest == 0 is supported. Don't try other values! + * Note: some is the following is captured here to make degugging easier + * (the macros make more sense if you see the debug patch - not posted) */ - -static unsigned int sn2_ptctest = 0; - -static int __init ptc_test(char *str) -{ - get_option(&str, &sn2_ptctest); - return 1; -} -__setup("ptctest=", ptc_test); - -static inline int ptc_lock(unsigned long *flagp) -{ - unsigned long opt = sn2_ptctest & 255; - - switch (opt) { - case 0x00: - spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); - break; - case 0x01: - spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp); - break; - case 0x02: - local_irq_save(*flagp); - break; - case 0x10: - spin_lock(&sn2_global_ptc_lock); - break; - case 0x11: - spin_lock(&sn_nodepda->ptc_lock); - break; - case 0x12: - break; - default: - BUG(); - } - return opt; -} - -static inline void ptc_unlock(unsigned long flags, int opt) -{ - switch (opt) { - case 0x00: - spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); - break; - case 0x01: - spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags); - break; - case 0x02: - local_irq_restore(flags); - break; - case 0x10: - spin_unlock(&sn2_global_ptc_lock); - break; - case 0x11: - spin_unlock(&sn_nodepda->ptc_lock); - break; - case 0x12: - break; - default: - BUG(); - } -} -#else - #define sn2_ptctest 0 +#define local_node_uses_ptc_ga(sh1) ((sh1) ? 1 : 0) +#define max_active_pio(sh1) ((sh1) ? 32 : 7) +#define reset_max_active_on_deadlock() 1 +#define PTC_LOCK(sh1) ((sh1) ? &sn2_global_ptc_lock : &sn_nodepda->ptc_lock) -static inline int ptc_lock(unsigned long *flagp) +static inline void ptc_lock(int sh1, unsigned long *flagp) { - spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); - return 0; + spin_lock_irqsave(PTC_LOCK(sh1), *flagp); } -static inline void ptc_unlock(unsigned long flags, int opt) +static inline void ptc_unlock(int sh1, unsigned long flags) { - spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); + spin_unlock_irqrestore(PTC_LOCK(sh1), flags); } -#endif struct ptc_stats { unsigned long ptc_l; @@ -151,27 +75,30 @@ struct ptc_stats { unsigned long shub_ptc_flushes; unsigned long nodes_flushed; unsigned long deadlocks; + unsigned long deadlocks2; unsigned long lock_itc_clocks; unsigned long shub_itc_clocks; unsigned long shub_itc_clocks_max; + unsigned long shub_ptc_flushes_not_my_mm; }; static inline unsigned long wait_piowc(void) { - volatile unsigned long *piows, zeroval; - unsigned long ws; + volatile unsigned long *piows; + unsigned long zeroval, ws; piows = pda->pio_write_status_addr; zeroval = pda->pio_write_status_val; do { cpu_relax(); } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval); - return ws; + return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; } void sn_tlb_migrate_finish(struct mm_struct *mm) { - if (mm == current->mm) + /* flush_tlb_mm is inefficient if more than 1 users of mm */ + if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1) flush_tlb_mm(mm); } @@ -201,12 +128,14 @@ void sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) { - int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; - int mymm = (mm == current->active_mm && current->mm); + int i, ibegin, shub1, cnode, mynasid, cpu, lcpu = 0, nasid; + int mymm = (mm == current->active_mm && mm == current->mm); + int use_cpu_ptcga; volatile unsigned long *ptc0, *ptc1; - unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; + unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; short nasids[MAX_NUMNODES], nix; nodemask_t nodes_flushed; + int active, max_active, deadlock; nodes_clear(nodes_flushed); i = 0; @@ -267,41 +196,56 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, mynasid = get_nasid(); + use_cpu_ptcga = local_node_uses_ptc_ga(shub1); + max_active = max_active_pio(shub1); itc = ia64_get_itc(); - opt = ptc_lock(&flags); + ptc_lock(shub1, &flags); itc2 = ia64_get_itc(); + __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; __get_cpu_var(ptcstats).shub_ptc_flushes++; __get_cpu_var(ptcstats).nodes_flushed += nix; + if (!mymm) + __get_cpu_var(ptcstats).shub_ptc_flushes_not_my_mm++; + if (use_cpu_ptcga && !mymm) { + old_rr = ia64_get_rr(start); + ia64_set_rr(start, (old_rr & 0xff) | (rr_value << 8)); + ia64_srlz_d(); + } + + wait_piowc(); do { if (shub1) data1 = start | (1UL << SH1_PTC_1_START_SHFT); else data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); - for (i = 0; i < nix; i++) { + deadlock = 0; + active = 0; + for (ibegin = 0, i = 0; i < nix; i++) { nasid = nasids[i]; - if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) { + if (use_cpu_ptcga && unlikely(nasid == mynasid)) { ia64_ptcga(start, nbits << 2); ia64_srlz_i(); } else { ptc0 = CHANGE_NASID(nasid, ptc0); if (ptc1) ptc1 = CHANGE_NASID(nasid, ptc1); - pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, - data1); - flushed = 1; + pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1); + active++; + } + if (active >= max_active || i == (nix - 1)) { + if ((deadlock = wait_piowc())) { + sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); + if (reset_max_active_on_deadlock()) + max_active = 1; + } + active = 0; + ibegin = i + 1; } } - if (flushed - && (wait_piowc() & - (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) { - sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1); - } - start += (1UL << nbits); - } while (start < end); itc2 = ia64_get_itc() - itc2; @@ -309,7 +253,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2; - ptc_unlock(flags, opt); + if (old_rr) { + ia64_set_rr(start, old_rr); + ia64_srlz_d(); + } + + ptc_unlock(shub1, flags); preempt_enable(); } @@ -321,27 +270,30 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, * TLB flush transaction. The recovery sequence is somewhat tricky & is * coded in assembly language. */ -void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0, +void sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid, volatile unsigned long *ptc0, unsigned long data0, volatile unsigned long *ptc1, unsigned long data1) { - extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, + extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); short nasid, i; - unsigned long *piows, zeroval; + unsigned long *piows, zeroval, n; __get_cpu_var(ptcstats).deadlocks++; piows = (unsigned long *) pda->pio_write_status_addr; zeroval = pda->pio_write_status_val; - for (i=0; i < nix; i++) { + + for (i=ib; i <= ie; i++) { nasid = nasids[i]; - if (!(sn2_ptctest & 3) && nasid == mynasid) + if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid) continue; ptc0 = CHANGE_NASID(nasid, ptc0); if (ptc1) ptc1 = CHANGE_NASID(nasid, ptc1); - sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); + + n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); + __get_cpu_var(ptcstats).deadlocks2 += n; } } @@ -452,20 +404,22 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) cpu = *(loff_t *) data; if (!cpu) { - seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n"); + seq_printf(file, + "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); seq_printf(file, "# ptctest %d\n", sn2_ptctest); } if (cpu < NR_CPUS && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); - seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, + seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, stat->deadlocks, 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, - 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec); + 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, + stat->shub_ptc_flushes_not_my_mm, + stat->deadlocks2); } - return 0; } @@ -476,7 +430,7 @@ static struct seq_operations sn2_ptc_seq_ops = { .show = sn2_ptc_seq_show }; -int sn2_ptc_proc_open(struct inode *inode, struct file *file) +static int sn2_ptc_proc_open(struct inode *inode, struct file *file) { return seq_open(file, &sn2_ptc_seq_ops); } diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 19b54fbcd7e..70db21f3df2 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved. * * SGI Altix topology and hardware performance monitoring API. * Mark Goodwin <markgw@sgi.com>. @@ -973,6 +973,9 @@ static int __devinit sn_hwperf_misc_register_init(void) { int e; + if (!ia64_platform_is("sn2")) + return 0; + sn_hwperf_init(); /* diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index c75f8aeefc2..9cd460dfe27 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -575,18 +575,21 @@ xpc_activate_partition(struct xpc_partition *part) spin_lock_irqsave(&part->act_lock, irq_flags); - pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0); - DBUG_ON(part->act_state != XPC_P_INACTIVE); - if (pid > 0) { - part->act_state = XPC_P_ACTIVATION_REQ; - XPC_SET_REASON(part, xpcCloneKThread, __LINE__); - } else { - XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); - } + part->act_state = XPC_P_ACTIVATION_REQ; + XPC_SET_REASON(part, xpcCloneKThread, __LINE__); spin_unlock_irqrestore(&part->act_lock, irq_flags); + + pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0); + + if (unlikely(pid <= 0)) { + spin_lock_irqsave(&part->act_lock, irq_flags); + part->act_state = XPC_P_INACTIVE; + XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); + spin_unlock_irqrestore(&part->act_lock, irq_flags); + } } diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile index 321576b1b42..c6946784a6a 100644 --- a/arch/ia64/sn/pci/Makefile +++ b/arch/ia64/sn/pci/Makefile @@ -7,4 +7,6 @@ # # Makefile for the sn pci general routines. +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile index 1850c4a94c4..3b403ea456f 100644 --- a/arch/ia64/sn/pci/pcibr/Makefile +++ b/arch/ia64/sn/pci/pcibr/Makefile @@ -7,5 +7,7 @@ # # Makefile for the sn2 io routines. +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + obj-y += pcibr_dma.o pcibr_reg.o \ pcibr_ate.o pcibr_provider.o |