diff options
Diffstat (limited to 'arch/ia64/sn')
24 files changed, 343 insertions, 383 deletions
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 00700f7e683..dfb3f290237 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -10,6 +10,7 @@ #include <linux/nodemask.h> #include <asm/sn/types.h> #include <asm/sn/addrs.h> +#include <asm/sn/sn_feature_sets.h> #include <asm/sn/geo.h> #include <asm/sn/io.h> #include <asm/sn/pcibr_provider.h> @@ -22,6 +23,10 @@ #include "xtalk/hubdev.h" #include "xtalk/xwidgetdev.h" + +extern void sn_init_cpei_timer(void); +extern void register_sn_procfs(void); + static struct list_head sn_sysdata_list; /* sysdata list struct */ @@ -39,12 +44,12 @@ struct brick { struct slab_info slab_info[MAX_SLABS + 1]; }; -int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ +int sn_ioif_inited; /* SN I/O infrastructure initialized? */ struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ -static int max_segment_number = 0; /* Default highest segment number */ -static int max_pcibus_number = 255; /* Default highest pci bus number */ +static int max_segment_number; /* Default highest segment number */ +static int max_pcibus_number = 255; /* Default highest pci bus number */ /* * Hooks and struct for unsupported pci providers @@ -83,7 +88,6 @@ static inline u64 sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, u64 address) { - struct ia64_sal_retval ret_stuff; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -93,7 +97,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, (u64) nasid, (u64) widget_num, (u64) device_num, (u64) address, 0, 0, 0); return ret_stuff.status; - } /* @@ -101,7 +104,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, */ static inline u64 sal_get_hubdev_info(u64 handle, u64 address) { - struct ia64_sal_retval ret_stuff; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -117,7 +119,6 @@ static inline u64 sal_get_hubdev_info(u64 handle, u64 address) */ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) { - struct ia64_sal_retval ret_stuff; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -173,8 +174,8 @@ sn_pcidev_info_get(struct pci_dev *dev) */ static u8 war_implemented = 0; -static void sn_device_fixup_war(u64 nasid, u64 widget, int device, - struct sn_flush_device_common *common) +static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, + struct sn_flush_device_common *common) { struct sn_flush_device_war *war_list; struct sn_flush_device_war *dev_entry; @@ -198,22 +199,23 @@ static void sn_device_fixup_war(u64 nasid, u64 widget, int device, dev_entry = war_list + device; memcpy(common,dev_entry, sizeof(*common)); - kfree(war_list); + + return isrv.status; } /* * 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; struct hubdev_info *hubdev; u64 status; u64 nasid; - int i, widget, device; + int i, widget, device, size; /* * Get SGI Specific HUB chipset information. @@ -249,53 +251,40 @@ static void sn_fixup_ionodes(void) if (!hubdev->hdi_flush_nasid_list.widget_p) continue; + size = (HUB_WIDGET_ID_MAX + 1) * + sizeof(struct sn_flush_device_kernel *); hubdev->hdi_flush_nasid_list.widget_p = - kmalloc((HUB_WIDGET_ID_MAX + 1) * - sizeof(struct sn_flush_device_kernel *), - GFP_KERNEL); - memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, - (HUB_WIDGET_ID_MAX + 1) * - sizeof(struct sn_flush_device_kernel *)); + kzalloc(size, GFP_KERNEL); + if (!hubdev->hdi_flush_nasid_list.widget_p) + BUG(); for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { - sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET * - sizeof(struct - sn_flush_device_kernel), - GFP_KERNEL); + size = DEV_PER_WIDGET * + sizeof(struct sn_flush_device_kernel); + sn_flush_device_kernel = kzalloc(size, GFP_KERNEL); if (!sn_flush_device_kernel) BUG(); - memset(sn_flush_device_kernel, 0x0, - DEV_PER_WIDGET * - sizeof(struct sn_flush_device_kernel)); dev_entry = sn_flush_device_kernel; for (device = 0; device < DEV_PER_WIDGET; device++,dev_entry++) { - dev_entry->common = kmalloc(sizeof(struct - sn_flush_device_common), - GFP_KERNEL); + size = sizeof(struct sn_flush_device_common); + dev_entry->common = kzalloc(size, GFP_KERNEL); if (!dev_entry->common) BUG(); - memset(dev_entry->common, 0x0, sizeof(struct - sn_flush_device_common)); - - status = sal_get_device_dmaflush_list(nasid, - widget, - device, - (u64)(dev_entry->common)); - if (status) { - if (sn_sal_rev() < 0x0450) { - /* shortlived WAR for older - * PROM images - */ - sn_device_fixup_war(nasid, - widget, - device, - dev_entry->common); - } - else - BUG(); - } + + if (sn_prom_feature_available( + PRF_DEVICE_FLUSH_LIST)) + status = sal_get_device_dmaflush_list( + nasid, widget, device, + (u64)(dev_entry->common)); + else + status = sn_device_fixup_war(nasid, + widget, device, + dev_entry->common); + if (status != SALRET_OK) + panic("SAL call failed: %s\n", + ia64_sal_strerror(status)); spin_lock_init(&dev_entry->sfdl_flush_lock); } @@ -383,13 +372,12 @@ void sn_pci_fixup_slot(struct pci_dev *dev) pci_dev_get(dev); /* for the sysdata pointer */ pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); - if (pcidev_info <= 0) + if (!pcidev_info) BUG(); /* Cannot afford to run out of memory */ - sn_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_KERNEL); - if (sn_irq_info <= 0) + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); + if (!sn_irq_info) BUG(); /* Cannot afford to run out of memory */ - memset(sn_irq_info, 0, sizeof(struct sn_irq_info)); /* Call to retrieve pci device information needed by kernel. */ status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, @@ -467,6 +455,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; } /* @@ -475,13 +470,13 @@ void sn_pci_fixup_slot(struct pci_dev *dev) */ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) { - int status = 0; + int status; int nasid, cnode; struct pci_controller *controller; struct sn_pci_controller *sn_controller; struct pcibus_bussoft *prom_bussoft_ptr; struct hubdev_info *hubdev_info; - void *provider_soft = NULL; + void *provider_soft; struct sn_pcibus_provider *provider; status = sal_get_pcibus_info((u64) segment, (u64) busnum, @@ -528,6 +523,8 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) bus->sysdata = controller; if (provider->bus_fixup) provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); + else + provider_soft = NULL; if (provider_soft == NULL) { /* fixup failed or not applicable */ @@ -610,15 +607,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; } @@ -631,13 +628,8 @@ sn_sysdata_free_start: static int __init sn_pci_init(void) { - int i = 0; - int j = 0; + int i, j; struct pci_dev *pci_dev = NULL; - extern void sn_init_cpei_timer(void); -#ifdef CONFIG_PROC_FS - extern void register_sn_procfs(void); -#endif if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) return 0; @@ -693,32 +685,29 @@ static int __init sn_pci_init(void) */ void hubdev_init_node(nodepda_t * npda, cnodeid_t node) { - struct hubdev_info *hubdev_info; + int size; + pg_data_t *pg; + + size = sizeof(struct hubdev_info); if (node >= num_online_nodes()) /* Headless/memless IO nodes */ - hubdev_info = - (struct hubdev_info *)alloc_bootmem_node(NODE_DATA(0), - sizeof(struct - hubdev_info)); + pg = NODE_DATA(0); else - hubdev_info = - (struct hubdev_info *)alloc_bootmem_node(NODE_DATA(node), - sizeof(struct - hubdev_info)); - npda->pdinfo = (void *)hubdev_info; + pg = NODE_DATA(node); + + hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size); + npda->pdinfo = (void *)hubdev_info; } geoid_t cnodeid_get_geoid(cnodeid_t cnode) { - struct hubdev_info *hubdev; hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); return hubdev->hdi_geoid; - } subsys_initcall(sn_pci_init); 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..5b84836c217 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); @@ -74,7 +75,7 @@ EXPORT_SYMBOL(sn_rtc_cycles_per_second); DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); EXPORT_PER_CPU_SYMBOL(__sn_hub_info); -DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]); +DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]); EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid); DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); @@ -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 @@ -330,6 +317,7 @@ struct pcdp_vga_device { #define PCDP_PCI_TRANS_IOPORT 0x02 #define PCDP_PCI_TRANS_MMIO 0x01 +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) static void sn_scan_pcdp(void) { @@ -371,6 +359,17 @@ sn_scan_pcdp(void) break; /* once we find the primary, we're done */ } } +#endif + +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 @@ -386,6 +385,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 +437,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 +450,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 +580,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 +722,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 +741,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/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c index 81c63b2f8ae..6ae276d5d50 100644 --- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c +++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1999,2001-2004, 2006 Silicon Graphics, Inc. All Rights Reserved. * * Module to export the system's Firmware Interface Tables, including * PROM revision numbers and banners, in /proc @@ -190,7 +190,7 @@ static int read_version_entry(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = 0; + int len; /* data holds the NASID of the node */ len = dump_version(page, (unsigned long)data); @@ -202,7 +202,7 @@ static int read_fit_entry(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = 0; + int len; /* data holds the NASID of the node */ len = dump_fit(page, (unsigned long)data); @@ -229,13 +229,16 @@ int __init prominfo_init(void) struct proc_dir_entry *p; cnodeid_t cnodeid; unsigned long nasid; + int size; char name[NODE_NAME_LEN]; if (!ia64_platform_is("sn2")) return 0; - proc_entries = kmalloc(num_online_nodes() * sizeof(struct proc_dir_entry *), - GFP_KERNEL); + size = num_online_nodes() * sizeof(struct proc_dir_entry *); + proc_entries = kzalloc(size, GFP_KERNEL); + if (!proc_entries) + return -ENOMEM; sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL); @@ -244,14 +247,12 @@ int __init prominfo_init(void) sprintf(name, "node%d", cnodeid); *entp = proc_mkdir(name, sgi_prominfo_entry); nasid = cnodeid_to_nasid(cnodeid); - p = create_proc_read_entry( - "fit", 0, *entp, read_fit_entry, - (void *)nasid); + p = create_proc_read_entry("fit", 0, *entp, read_fit_entry, + (void *)nasid); if (p) p->owner = THIS_MODULE; - p = create_proc_read_entry( - "version", 0, *entp, read_version_entry, - (void *)nasid); + p = create_proc_read_entry("version", 0, *entp, + read_version_entry, (void *)nasid); if (p) p->owner = THIS_MODULE; entp++; @@ -263,7 +264,7 @@ int __init prominfo_init(void) void __exit prominfo_exit(void) { struct proc_dir_entry **entp; - unsigned cnodeid; + unsigned int cnodeid; char name[NODE_NAME_LEN]; entp = proc_entries; diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 471bbaa65d1..b2e1e746b47 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,24 @@ 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); +extern unsigned long +sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, + volatile unsigned long *, unsigned long, + volatile unsigned long *, unsigned long); +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 - -static inline int ptc_lock(unsigned long *flagp) -{ - spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); - return 0; -} - -static inline void ptc_unlock(unsigned long flags, int opt) -{ - spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); -} -#endif +#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) struct ptc_stats { unsigned long ptc_l; @@ -151,27 +71,32 @@ 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; }; +#define sn2_ptctest 0 + 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 +126,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 +194,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); + spin_lock_irqsave(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 +251,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(); + } + + spin_unlock_irqrestore(PTC_LOCK(shub1), flags); preempt_enable(); } @@ -321,27 +268,31 @@ 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, - volatile unsigned long *ptc1, unsigned long data1) + +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, - 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 +403,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 +429,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); } @@ -493,7 +446,7 @@ static struct proc_dir_entry *proc_sn2_ptc; static int __init sn2_ptc_init(void) { if (!ia64_platform_is("sn2")) - return -ENOSYS; + return 0; if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); 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/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index a06719d752a..c686d9c12f7 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c @@ -6,11 +6,11 @@ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #include <linux/config.h> -#include <asm/uaccess.h> #ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <asm/uaccess.h> #include <asm/sn/sn_sal.h> static int partition_id_show(struct seq_file *s, void *p) @@ -90,10 +90,10 @@ static int coherence_id_open(struct inode *inode, struct file *file) return single_open(file, coherence_id_show, NULL); } -static struct proc_dir_entry *sn_procfs_create_entry( - const char *name, struct proc_dir_entry *parent, - int (*openfunc)(struct inode *, struct file *), - int (*releasefunc)(struct inode *, struct file *)) +static struct proc_dir_entry +*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent, + int (*openfunc)(struct inode *, struct file *), + int (*releasefunc)(struct inode *, struct file *)) { struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); @@ -126,24 +126,24 @@ void register_sn_procfs(void) return; sn_procfs_create_entry("partition_id", sgi_proc_dir, - partition_id_open, single_release); + partition_id_open, single_release); sn_procfs_create_entry("system_serial_number", sgi_proc_dir, - system_serial_number_open, single_release); + system_serial_number_open, single_release); sn_procfs_create_entry("licenseID", sgi_proc_dir, - licenseID_open, single_release); + licenseID_open, single_release); e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, - sn_force_interrupt_open, single_release); + sn_force_interrupt_open, single_release); if (e) e->proc_fops->write = sn_force_interrupt_write_proc; sn_procfs_create_entry("coherence_id", sgi_proc_dir, - coherence_id_open, single_release); + coherence_id_open, single_release); sn_procfs_create_entry("sn_topology", sgi_proc_dir, - sn_topology_open, sn_topology_release); + sn_topology_open, sn_topology_release); } #endif /* CONFIG_PROC_FS */ diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index deb9baf4d47..56a88b6df4b 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c @@ -14,6 +14,7 @@ #include <asm/hw_irq.h> #include <asm/system.h> +#include <asm/timex.h> #include <asm/sn/leds.h> #include <asm/sn/shub_mmr.h> @@ -28,9 +29,27 @@ static struct time_interpolator sn2_interpolator = { .source = TIME_SOURCE_MMIO64 }; +/* + * sn udelay uses the RTC instead of the ITC because the ITC is not + * synchronized across all CPUs, and the thread may migrate to another CPU + * if preemption is enabled. + */ +static void +ia64_sn_udelay (unsigned long usecs) +{ + unsigned long start = rtc_time(); + unsigned long end = start + + usecs * sn_rtc_cycles_per_second / 1000000; + + while (time_before((unsigned long)rtc_time(), end)) + cpu_relax(); +} + 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); + + ia64_udelay = &ia64_sn_udelay; } diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c index adf5db2e2af..fa7f6994591 100644 --- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c +++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c @@ -1,7 +1,7 @@ /* * * - * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2005, 2006 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -22,11 +22,6 @@ * License along with this program; if not, write the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index d263d3e8fbb..99cb28e7429 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -284,12 +284,10 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq, if ((nasid & 1) == 0) return NULL; - sn_irq_info = kmalloc(sn_irq_size, GFP_KERNEL); + sn_irq_info = kzalloc(sn_irq_size, GFP_KERNEL); if (sn_irq_info == NULL) return NULL; - memset(sn_irq_info, 0x0, sn_irq_size); - status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq, req_nasid, slice); if (status) { @@ -486,7 +484,7 @@ static int __init tiocx_init(void) int found_tiocx_device = 0; if (!ia64_platform_is("sn2")) - return -ENODEV; + return 0; bus_register(&tiocx_bus_type); diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 8d950c778bb..cdf6856ce08 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -447,7 +447,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) nbytes = nentries * ch->msg_size; ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, - (GFP_KERNEL | GFP_DMA), + GFP_KERNEL, &ch->local_msgqueue_base); if (ch->local_msgqueue == NULL) { continue; @@ -455,7 +455,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) memset(ch->local_msgqueue, 0, nbytes); nbytes = nentries * sizeof(struct xpc_notify); - ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA)); + ch->notify_queue = kmalloc(nbytes, GFP_KERNEL); if (ch->notify_queue == NULL) { kfree(ch->local_msgqueue_base); ch->local_msgqueue = NULL; @@ -502,7 +502,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) nbytes = nentries * ch->msg_size; ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, - (GFP_KERNEL | GFP_DMA), + GFP_KERNEL, &ch->remote_msgqueue_base); if (ch->remote_msgqueue == NULL) { continue; @@ -738,7 +738,9 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) /* make sure all activity has settled down first */ - if (atomic_read(&ch->references) > 0) { + if (atomic_read(&ch->references) > 0 || + ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) { return; } DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); @@ -775,7 +777,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) /* both sides are disconnected now */ - if (ch->flags & XPC_C_CONNECTCALLOUT) { + if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) { spin_unlock_irqrestore(&ch->lock, *irq_flags); xpc_disconnect_callout(ch, xpcDisconnected); spin_lock_irqsave(&ch->lock, *irq_flags); @@ -1300,7 +1302,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number) "delivered=%d, partid=%d, channel=%d\n", nmsgs_sent, ch->partid, ch->number); - if (ch->flags & XPC_C_CONNECTCALLOUT) { + if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) { xpc_activate_kthreads(ch, nmsgs_sent); } } diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index c75f8aeefc2..8cbf1643257 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); + } } @@ -747,12 +750,16 @@ xpc_daemonize_kthread(void *args) /* let registerer know that connection has been established */ spin_lock_irqsave(&ch->lock, irq_flags); - if (!(ch->flags & XPC_C_CONNECTCALLOUT)) { - ch->flags |= XPC_C_CONNECTCALLOUT; + if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { + ch->flags |= XPC_C_CONNECTEDCALLOUT; spin_unlock_irqrestore(&ch->lock, irq_flags); xpc_connected_callout(ch); + spin_lock_irqsave(&ch->lock, irq_flags); + ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE; + spin_unlock_irqrestore(&ch->lock, irq_flags); + /* * It is possible that while the callout was being * made that the remote partition sent some messages. @@ -774,15 +781,17 @@ xpc_daemonize_kthread(void *args) if (atomic_dec_return(&ch->kthreads_assigned) == 0) { spin_lock_irqsave(&ch->lock, irq_flags); - if ((ch->flags & XPC_C_CONNECTCALLOUT) && - !(ch->flags & XPC_C_DISCONNECTCALLOUT)) { - ch->flags |= XPC_C_DISCONNECTCALLOUT; + if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { + ch->flags |= XPC_C_DISCONNECTINGCALLOUT; spin_unlock_irqrestore(&ch->lock, irq_flags); xpc_disconnect_callout(ch, xpcDisconnecting); - } else { - spin_unlock_irqrestore(&ch->lock, irq_flags); + + spin_lock_irqsave(&ch->lock, irq_flags); + ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; } + spin_unlock_irqrestore(&ch->lock, irq_flags); if (atomic_dec_return(&part->nchannels_engaged) == 0) { xpc_mark_partition_disengaged(part); xpc_IPI_send_disengage(part); 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/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 9bf9f23b9a1..b4b84c26921 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -90,14 +90,14 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, */ node = pcibus_to_node(pdev->bus); if (likely(node >=0)) { - struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size)); + struct page *p = alloc_pages_node(node, flags, get_order(size)); if (likely(p)) cpuaddr = page_address(p); else return NULL; } else - cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + cpuaddr = (void *)__get_free_pages(flags, get_order(size)); if (unlikely(!cpuaddr)) return NULL; @@ -335,10 +335,10 @@ int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) */ SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, - pci_domain_nr(bus), bus->number, - 0, /* io */ - 0, /* read */ - port, size, __pa(val)); + pci_domain_nr(bus), bus->number, + 0, /* io */ + 0, /* read */ + port, size, __pa(val)); if (isrv.status == 0) return size; @@ -381,10 +381,10 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) */ SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE, - pci_domain_nr(bus), bus->number, - 0, /* io */ - 1, /* write */ - port, size, __pa(&val)); + pci_domain_nr(bus), bus->number, + 0, /* io */ + 1, /* write */ + port, size, __pa(&val)); if (isrv.status == 0) return size; 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 diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index aa3fa5152a3..1f0253bfe0a 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved. */ #include <linux/types.h> @@ -12,7 +12,7 @@ #include <asm/sn/pcibus_provider_defs.h> #include <asm/sn/pcidev.h> -int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ +int pcibr_invalidate_ate; /* by default don't invalidate ATE on free */ /* * mark_ate: Mark the ate as either free or inuse. @@ -20,14 +20,12 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ static void mark_ate(struct ate_resource *ate_resource, int start, int number, u64 value) { - u64 *ate = ate_resource->ate; int index; int length = 0; for (index = start; length < number; index++, length++) ate[index] = value; - } /* @@ -37,7 +35,6 @@ static void mark_ate(struct ate_resource *ate_resource, int start, int number, static int find_free_ate(struct ate_resource *ate_resource, int start, int count) { - u64 *ate = ate_resource->ate; int index; int start_free; @@ -70,12 +67,10 @@ static int find_free_ate(struct ate_resource *ate_resource, int start, static inline void free_ate_resource(struct ate_resource *ate_resource, int start) { - mark_ate(ate_resource, start, ate_resource->ate[start], 0); if ((ate_resource->lowest_free_index > start) || (ate_resource->lowest_free_index < 0)) ate_resource->lowest_free_index = start; - } /* @@ -84,7 +79,6 @@ static inline void free_ate_resource(struct ate_resource *ate_resource, static inline int alloc_ate_resource(struct ate_resource *ate_resource, int ate_needed) { - int start_index; /* @@ -118,19 +112,12 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, */ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) { - int status = 0; - u64 flag; + int status; + unsigned long flags; - flag = pcibr_lock(pcibus_info); + spin_lock_irqsave(&pcibus_info->pbi_lock, flags); status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); - - if (status < 0) { - /* Failed to allocate */ - pcibr_unlock(pcibus_info, flag); - return -1; - } - - pcibr_unlock(pcibus_info, flag); + spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags); return status; } @@ -182,7 +169,7 @@ void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) ate_write(pcibus_info, index, count, (ate & ~PCI32_ATE_V)); } - flags = pcibr_lock(pcibus_info); + spin_lock_irqsave(&pcibus_info->pbi_lock, flags); free_ate_resource(&pcibus_info->pbi_int_ate_resource, index); - pcibr_unlock(pcibus_info, flags); + spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags); } diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 54ce5b7ceed..9f86bb6519a 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -137,14 +137,12 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, pci_addr |= PCI64_ATTR_VIRTUAL; return pci_addr; - } static dma_addr_t pcibr_dmatrans_direct32(struct pcidev_info * info, u64 paddr, size_t req_size, u64 flags) { - struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; @@ -171,7 +169,6 @@ pcibr_dmatrans_direct32(struct pcidev_info * info, } return PCI32_DIRECT_BASE | offset; - } /* @@ -218,9 +215,8 @@ void sn_dma_flush(u64 addr) u64 flags; u64 itte; struct hubdev_info *hubinfo; - volatile struct sn_flush_device_kernel *p; - volatile struct sn_flush_device_common *common; - + struct sn_flush_device_kernel *p; + struct sn_flush_device_common *common; struct sn_flush_nasid_entry *flush_nasid_list; if (!sn_ioif_inited) @@ -310,8 +306,7 @@ void sn_dma_flush(u64 addr) (common->sfdl_slot - 1)); } } else { - spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock, - flags); + spin_lock_irqsave(&p->sfdl_flush_lock, flags); *common->sfdl_flush_addr = 0; /* force an interrupt. */ @@ -322,8 +317,7 @@ void sn_dma_flush(u64 addr) cpu_relax(); /* okay, everything is synched up. */ - spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, - flags); + spin_unlock_irqrestore(&p->sfdl_flush_lock, flags); } return; } diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 2fac27049bf..98f716bd92f 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -163,9 +163,12 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = - kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); - memset(soft->pbi_int_ate_resource.ate, 0, - (soft->pbi_int_ate_size * sizeof(u64))); + kzalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); + + if (!soft->pbi_int_ate_resource.ate) { + kfree(soft); + return NULL; + } if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { /* TIO PCI Bridge: find nearest node with CPUs */ |