aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/kernel')
-rw-r--r--arch/ia64/sn/kernel/Makefile3
-rw-r--r--arch/ia64/sn/kernel/bte.c2
-rw-r--r--arch/ia64/sn/kernel/io_init.c29
-rw-r--r--arch/ia64/sn/kernel/irq.c21
-rw-r--r--arch/ia64/sn/kernel/pio_phys.S71
-rw-r--r--arch/ia64/sn/kernel/setup.c11
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c21
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c8
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c39
-rw-r--r--arch/ia64/sn/kernel/tiocx.c10
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c102
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c1
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c28
13 files changed, 251 insertions, 95 deletions
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 3e9b4eea7418..ab9c48c88012 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -10,7 +10,8 @@
10CPPFLAGS += -I$(srctree)/arch/ia64/sn/include 10CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
11 11
12obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ 12obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
13 huberror.o io_init.o iomv.o klconflib.o sn2/ 13 huberror.o io_init.o iomv.o klconflib.o pio_phys.o \
14 sn2/
14obj-$(CONFIG_IA64_GENERIC) += machvec.o 15obj-$(CONFIG_IA64_GENERIC) += machvec.o
15obj-$(CONFIG_SGI_TIOCX) += tiocx.o 16obj-$(CONFIG_SGI_TIOCX) += tiocx.o
16obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o 17obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 1f11db470d90..e952ef4f6d91 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -36,7 +36,7 @@ static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface)
36 nodepda_t *tmp_nodepda; 36 nodepda_t *tmp_nodepda;
37 37
38 if (nasid_to_cnodeid(nasid) == -1) 38 if (nasid_to_cnodeid(nasid) == -1)
39 return (struct bteinfo_s *)NULL;; 39 return (struct bteinfo_s *)NULL;
40 40
41 tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid)); 41 tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid));
42 return &tmp_nodepda->bte_if[interface]; 42 return &tmp_nodepda->bte_if[interface];
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index dfb3f2902379..5101ac462643 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -13,6 +13,8 @@
13#include <asm/sn/sn_feature_sets.h> 13#include <asm/sn/sn_feature_sets.h>
14#include <asm/sn/geo.h> 14#include <asm/sn/geo.h>
15#include <asm/sn/io.h> 15#include <asm/sn/io.h>
16#include <asm/sn/l1.h>
17#include <asm/sn/module.h>
16#include <asm/sn/pcibr_provider.h> 18#include <asm/sn/pcibr_provider.h>
17#include <asm/sn/pcibus_provider_defs.h> 19#include <asm/sn/pcibus_provider_defs.h>
18#include <asm/sn/pcidev.h> 20#include <asm/sn/pcidev.h>
@@ -710,9 +712,36 @@ cnodeid_get_geoid(cnodeid_t cnode)
710 return hubdev->hdi_geoid; 712 return hubdev->hdi_geoid;
711} 713}
712 714
715void sn_generate_path(struct pci_bus *pci_bus, char *address)
716{
717 nasid_t nasid;
718 cnodeid_t cnode;
719 geoid_t geoid;
720 moduleid_t moduleid;
721 u16 bricktype;
722
723 nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
724 cnode = nasid_to_cnodeid(nasid);
725 geoid = cnodeid_get_geoid(cnode);
726 moduleid = geo_module(geoid);
727
728 sprintf(address, "module_%c%c%c%c%.2d",
729 '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
730 '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
731 '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
732 MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
733
734 /* Tollhouse requires slot id to be displayed */
735 bricktype = MODULE_GET_BTYPE(moduleid);
736 if ((bricktype == L1_BRICKTYPE_191010) ||
737 (bricktype == L1_BRICKTYPE_1932))
738 sprintf(address, "%s^%d", address, geo_slot(geoid));
739}
740
713subsys_initcall(sn_pci_init); 741subsys_initcall(sn_pci_init);
714EXPORT_SYMBOL(sn_pci_fixup_slot); 742EXPORT_SYMBOL(sn_pci_fixup_slot);
715EXPORT_SYMBOL(sn_pci_unfixup_slot); 743EXPORT_SYMBOL(sn_pci_unfixup_slot);
716EXPORT_SYMBOL(sn_pci_controller_fixup); 744EXPORT_SYMBOL(sn_pci_controller_fixup);
717EXPORT_SYMBOL(sn_bus_store_sysdata); 745EXPORT_SYMBOL(sn_bus_store_sysdata);
718EXPORT_SYMBOL(sn_bus_free_sysdata); 746EXPORT_SYMBOL(sn_bus_free_sysdata);
747EXPORT_SYMBOL(sn_generate_path);
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index c373113d073a..c265e02f5036 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -350,9 +350,6 @@ static void force_interrupt(int irq)
350static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) 350static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
351{ 351{
352 u64 regval; 352 u64 regval;
353 int irr_reg_num;
354 int irr_bit;
355 u64 irr_reg;
356 struct pcidev_info *pcidev_info; 353 struct pcidev_info *pcidev_info;
357 struct pcibus_info *pcibus_info; 354 struct pcibus_info *pcibus_info;
358 355
@@ -373,23 +370,7 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
373 pdi_pcibus_info; 370 pdi_pcibus_info;
374 regval = pcireg_intr_status_get(pcibus_info); 371 regval = pcireg_intr_status_get(pcibus_info);
375 372
376 irr_reg_num = irq_to_vector(irq) / 64; 373 if (!ia64_get_irr(irq_to_vector(irq))) {
377 irr_bit = irq_to_vector(irq) % 64;
378 switch (irr_reg_num) {
379 case 0:
380 irr_reg = ia64_getreg(_IA64_REG_CR_IRR0);
381 break;
382 case 1:
383 irr_reg = ia64_getreg(_IA64_REG_CR_IRR1);
384 break;
385 case 2:
386 irr_reg = ia64_getreg(_IA64_REG_CR_IRR2);
387 break;
388 case 3:
389 irr_reg = ia64_getreg(_IA64_REG_CR_IRR3);
390 break;
391 }
392 if (!test_bit(irr_bit, &irr_reg)) {
393 if (!test_bit(irq, pda->sn_in_service_ivecs)) { 374 if (!test_bit(irq, pda->sn_in_service_ivecs)) {
394 regval &= 0xff; 375 regval &= 0xff;
395 if (sn_irq_info->irq_int_bit & regval & 376 if (sn_irq_info->irq_int_bit & regval &
diff --git a/arch/ia64/sn/kernel/pio_phys.S b/arch/ia64/sn/kernel/pio_phys.S
new file mode 100644
index 000000000000..3c7d48d6ecb8
--- /dev/null
+++ b/arch/ia64/sn/kernel/pio_phys.S
@@ -0,0 +1,71 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
7 *
8 * This file contains macros used to access MMR registers via
9 * uncached physical addresses.
10 * pio_phys_read_mmr - read an MMR
11 * pio_phys_write_mmr - write an MMR
12 * pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
13 * Second MMR will be skipped if address is NULL
14 *
15 * Addresses passed to these routines should be uncached physical addresses
16 * ie., 0x80000....
17 */
18
19
20
21#include <asm/asmmacro.h>
22#include <asm/page.h>
23
24GLOBAL_ENTRY(pio_phys_read_mmr)
25 .prologue
26 .regstk 1,0,0,0
27 .body
28 mov r2=psr
29 rsm psr.i | psr.dt
30 ;;
31 srlz.d
32 ld8.acq r8=[r32]
33 ;;
34 mov psr.l=r2;;
35 srlz.d
36 br.ret.sptk.many rp
37END(pio_phys_read_mmr)
38
39GLOBAL_ENTRY(pio_phys_write_mmr)
40 .prologue
41 .regstk 2,0,0,0
42 .body
43 mov r2=psr
44 rsm psr.i | psr.dt
45 ;;
46 srlz.d
47 st8.rel [r32]=r33
48 ;;
49 mov psr.l=r2;;
50 srlz.d
51 br.ret.sptk.many rp
52END(pio_phys_write_mmr)
53
54GLOBAL_ENTRY(pio_atomic_phys_write_mmrs)
55 .prologue
56 .regstk 4,0,0,0
57 .body
58 mov r2=psr
59 cmp.ne p9,p0=r34,r0;
60 rsm psr.i | psr.dt | psr.ic
61 ;;
62 srlz.d
63 st8.rel [r32]=r33
64(p9) st8.rel [r34]=r35
65 ;;
66 mov psr.l=r2;;
67 srlz.d
68 br.ret.sptk.many rp
69END(pio_atomic_phys_write_mmrs)
70
71
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 5b84836c2171..30988dfbddff 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8 8
9#include <linux/config.h> 9#include <linux/config.h>
@@ -327,10 +327,11 @@ sn_scan_pcdp(void)
327 struct pcdp_interface_pci if_pci; 327 struct pcdp_interface_pci if_pci;
328 extern struct efi efi; 328 extern struct efi efi;
329 329
330 pcdp = efi.hcdp; 330 if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
331 if (! pcdp)
332 return; /* no hcdp/pcdp table */ 331 return; /* no hcdp/pcdp table */
333 332
333 pcdp = __va(efi.hcdp);
334
334 if (pcdp->rev < 3) 335 if (pcdp->rev < 3)
335 return; /* only support PCDP (rev >= 3) */ 336 return; /* only support PCDP (rev >= 3) */
336 337
@@ -498,6 +499,7 @@ void __init sn_setup(char **cmdline_p)
498 * for sn. 499 * for sn.
499 */ 500 */
500 pm_power_off = ia64_sn_power_down; 501 pm_power_off = ia64_sn_power_down;
502 current->thread.flags |= IA64_THREAD_MIGRATION;
501} 503}
502 504
503/** 505/**
@@ -660,7 +662,8 @@ void __init sn_cpu_init(void)
660 SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; 662 SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
661 u64 *pio; 663 u64 *pio;
662 pio = is_shub1() ? pio1 : pio2; 664 pio = is_shub1() ? pio1 : pio2;
663 pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); 665 pda->pio_write_status_addr =
666 (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
664 pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; 667 pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
665 } 668 }
666 669
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index b2e1e746b47f..d9d306c79f2d 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -93,6 +93,27 @@ static inline unsigned long wait_piowc(void)
93 return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; 93 return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
94} 94}
95 95
96/**
97 * sn_migrate - SN-specific task migration actions
98 * @task: Task being migrated to new CPU
99 *
100 * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order.
101 * Context switching user threads which have memory-mapped MMIO may cause
102 * PIOs to issue from seperate CPUs, thus the PIO writes must be drained
103 * from the previous CPU's Shub before execution resumes on the new CPU.
104 */
105void sn_migrate(struct task_struct *task)
106{
107 pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu);
108 volatile unsigned long *adr = last_pda->pio_write_status_addr;
109 unsigned long val = last_pda->pio_write_status_val;
110
111 /* Drain PIO writes from old CPU's Shub */
112 while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK)
113 != val))
114 cpu_relax();
115}
116
96void sn_tlb_migrate_finish(struct mm_struct *mm) 117void sn_tlb_migrate_finish(struct mm_struct *mm)
97{ 118{
98 /* flush_tlb_mm is inefficient if more than 1 users of mm */ 119 /* flush_tlb_mm is inefficient if more than 1 users of mm */
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 70db21f3df21..d917afa30b27 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -110,7 +110,11 @@ static int sn_hwperf_geoid_to_cnode(char *location)
110 if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) 110 if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
111 return -1; 111 return -1;
112 112
113 for_each_node(cnode) { 113 /*
114 * FIXME: replace with cleaner for_each_XXX macro which addresses
115 * both compute and IO nodes once ACPI3.0 is available.
116 */
117 for (cnode = 0; cnode < num_cnodes; cnode++) {
114 geoid = cnodeid_get_geoid(cnode); 118 geoid = cnodeid_get_geoid(cnode);
115 module_id = geo_module(geoid); 119 module_id = geo_module(geoid);
116 this_rack = MODULE_GET_RACK(module_id); 120 this_rack = MODULE_GET_RACK(module_id);
@@ -605,7 +609,7 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
605 op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK; 609 op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK;
606 610
607 if (cpu != SN_HWPERF_ARG_ANY_CPU) { 611 if (cpu != SN_HWPERF_ARG_ANY_CPU) {
608 if (cpu >= num_online_cpus() || !cpu_online(cpu)) { 612 if (cpu >= NR_CPUS || !cpu_online(cpu)) {
609 r = -EINVAL; 613 r = -EINVAL;
610 goto out; 614 goto out;
611 } 615 }
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index c686d9c12f7b..5100261310f7 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -93,19 +93,22 @@ static int coherence_id_open(struct inode *inode, struct file *file)
93static struct proc_dir_entry 93static struct proc_dir_entry
94*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent, 94*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent,
95 int (*openfunc)(struct inode *, struct file *), 95 int (*openfunc)(struct inode *, struct file *),
96 int (*releasefunc)(struct inode *, struct file *)) 96 int (*releasefunc)(struct inode *, struct file *),
97 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *))
97{ 98{
98 struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); 99 struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
99 100
100 if (e) { 101 if (e) {
101 e->proc_fops = (struct file_operations *)kmalloc( 102 struct file_operations *f;
102 sizeof(struct file_operations), GFP_KERNEL); 103
103 if (e->proc_fops) { 104 f = kzalloc(sizeof(*f), GFP_KERNEL);
104 memset(e->proc_fops, 0, sizeof(struct file_operations)); 105 if (f) {
105 e->proc_fops->open = openfunc; 106 f->open = openfunc;
106 e->proc_fops->read = seq_read; 107 f->read = seq_read;
107 e->proc_fops->llseek = seq_lseek; 108 f->llseek = seq_lseek;
108 e->proc_fops->release = releasefunc; 109 f->release = releasefunc;
110 f->write = write;
111 e->proc_fops = f;
109 } 112 }
110 } 113 }
111 114
@@ -119,31 +122,29 @@ extern int sn_topology_release(struct inode *, struct file *);
119void register_sn_procfs(void) 122void register_sn_procfs(void)
120{ 123{
121 static struct proc_dir_entry *sgi_proc_dir = NULL; 124 static struct proc_dir_entry *sgi_proc_dir = NULL;
122 struct proc_dir_entry *e;
123 125
124 BUG_ON(sgi_proc_dir != NULL); 126 BUG_ON(sgi_proc_dir != NULL);
125 if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL))) 127 if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
126 return; 128 return;
127 129
128 sn_procfs_create_entry("partition_id", sgi_proc_dir, 130 sn_procfs_create_entry("partition_id", sgi_proc_dir,
129 partition_id_open, single_release); 131 partition_id_open, single_release, NULL);
130 132
131 sn_procfs_create_entry("system_serial_number", sgi_proc_dir, 133 sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
132 system_serial_number_open, single_release); 134 system_serial_number_open, single_release, NULL);
133 135
134 sn_procfs_create_entry("licenseID", sgi_proc_dir, 136 sn_procfs_create_entry("licenseID", sgi_proc_dir,
135 licenseID_open, single_release); 137 licenseID_open, single_release, NULL);
136 138
137 e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, 139 sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir,
138 sn_force_interrupt_open, single_release); 140 sn_force_interrupt_open, single_release,
139 if (e) 141 sn_force_interrupt_write_proc);
140 e->proc_fops->write = sn_force_interrupt_write_proc;
141 142
142 sn_procfs_create_entry("coherence_id", sgi_proc_dir, 143 sn_procfs_create_entry("coherence_id", sgi_proc_dir,
143 coherence_id_open, single_release); 144 coherence_id_open, single_release, NULL);
144 145
145 sn_procfs_create_entry("sn_topology", sgi_proc_dir, 146 sn_procfs_create_entry("sn_topology", sgi_proc_dir,
146 sn_topology_open, sn_topology_release); 147 sn_topology_open, sn_topology_release, NULL);
147} 148}
148 149
149#endif /* CONFIG_PROC_FS */ 150#endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 99cb28e74295..feaf1a6e8101 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -369,9 +369,15 @@ static void tio_corelet_reset(nasid_t nasid, int corelet)
369 369
370static int is_fpga_tio(int nasid, int *bt) 370static int is_fpga_tio(int nasid, int *bt)
371{ 371{
372 int ioboard_type; 372 u16 ioboard_type;
373 s64 rc;
373 374
374 ioboard_type = ia64_sn_sysctl_ioboard_get(nasid); 375 rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
376 if (rc) {
377 printk(KERN_WARNING "ia64_sn_sysctl_ioboard_get failed: %ld\n",
378 rc);
379 return 0;
380 }
375 381
376 switch (ioboard_type) { 382 switch (ioboard_type) {
377 case L1_BRICKTYPE_SA: 383 case L1_BRICKTYPE_SA:
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index cdf6856ce089..d0abddd9ffe6 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -21,7 +21,6 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/cache.h> 22#include <linux/cache.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/slab.h>
25#include <linux/mutex.h> 24#include <linux/mutex.h>
26#include <linux/completion.h> 25#include <linux/completion.h>
27#include <asm/sn/bte.h> 26#include <asm/sn/bte.h>
@@ -30,6 +29,31 @@
30 29
31 30
32/* 31/*
32 * Guarantee that the kzalloc'd memory is cacheline aligned.
33 */
34static void *
35xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
36{
37 /* see if kzalloc will give us cachline aligned memory by default */
38 *base = kzalloc(size, flags);
39 if (*base == NULL) {
40 return NULL;
41 }
42 if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
43 return *base;
44 }
45 kfree(*base);
46
47 /* nope, we'll have to do it ourselves */
48 *base = kzalloc(size + L1_CACHE_BYTES, flags);
49 if (*base == NULL) {
50 return NULL;
51 }
52 return (void *) L1_CACHE_ALIGN((u64) *base);
53}
54
55
56/*
33 * Set up the initial values for the XPartition Communication channels. 57 * Set up the initial values for the XPartition Communication channels.
34 */ 58 */
35static void 59static void
@@ -93,20 +117,19 @@ xpc_setup_infrastructure(struct xpc_partition *part)
93 * Allocate all of the channel structures as a contiguous chunk of 117 * Allocate all of the channel structures as a contiguous chunk of
94 * memory. 118 * memory.
95 */ 119 */
96 part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS, 120 part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
97 GFP_KERNEL); 121 GFP_KERNEL);
98 if (part->channels == NULL) { 122 if (part->channels == NULL) {
99 dev_err(xpc_chan, "can't get memory for channels\n"); 123 dev_err(xpc_chan, "can't get memory for channels\n");
100 return xpcNoMemory; 124 return xpcNoMemory;
101 } 125 }
102 memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS);
103 126
104 part->nchannels = XPC_NCHANNELS; 127 part->nchannels = XPC_NCHANNELS;
105 128
106 129
107 /* allocate all the required GET/PUT values */ 130 /* allocate all the required GET/PUT values */
108 131
109 part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE, 132 part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
110 GFP_KERNEL, &part->local_GPs_base); 133 GFP_KERNEL, &part->local_GPs_base);
111 if (part->local_GPs == NULL) { 134 if (part->local_GPs == NULL) {
112 kfree(part->channels); 135 kfree(part->channels);
@@ -115,55 +138,51 @@ xpc_setup_infrastructure(struct xpc_partition *part)
115 "values\n"); 138 "values\n");
116 return xpcNoMemory; 139 return xpcNoMemory;
117 } 140 }
118 memset(part->local_GPs, 0, XPC_GP_SIZE);
119 141
120 part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE, 142 part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
121 GFP_KERNEL, &part->remote_GPs_base); 143 GFP_KERNEL, &part->remote_GPs_base);
122 if (part->remote_GPs == NULL) { 144 if (part->remote_GPs == NULL) {
123 kfree(part->channels);
124 part->channels = NULL;
125 kfree(part->local_GPs_base);
126 part->local_GPs = NULL;
127 dev_err(xpc_chan, "can't get memory for remote get/put " 145 dev_err(xpc_chan, "can't get memory for remote get/put "
128 "values\n"); 146 "values\n");
147 kfree(part->local_GPs_base);
148 part->local_GPs = NULL;
149 kfree(part->channels);
150 part->channels = NULL;
129 return xpcNoMemory; 151 return xpcNoMemory;
130 } 152 }
131 memset(part->remote_GPs, 0, XPC_GP_SIZE);
132 153
133 154
134 /* allocate all the required open and close args */ 155 /* allocate all the required open and close args */
135 156
136 part->local_openclose_args = xpc_kmalloc_cacheline_aligned( 157 part->local_openclose_args = xpc_kzalloc_cacheline_aligned(
137 XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, 158 XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
138 &part->local_openclose_args_base); 159 &part->local_openclose_args_base);
139 if (part->local_openclose_args == NULL) { 160 if (part->local_openclose_args == NULL) {
140 kfree(part->channels); 161 dev_err(xpc_chan, "can't get memory for local connect args\n");
141 part->channels = NULL;
142 kfree(part->local_GPs_base);
143 part->local_GPs = NULL;
144 kfree(part->remote_GPs_base); 162 kfree(part->remote_GPs_base);
145 part->remote_GPs = NULL; 163 part->remote_GPs = NULL;
146 dev_err(xpc_chan, "can't get memory for local connect args\n"); 164 kfree(part->local_GPs_base);
165 part->local_GPs = NULL;
166 kfree(part->channels);
167 part->channels = NULL;
147 return xpcNoMemory; 168 return xpcNoMemory;
148 } 169 }
149 memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
150 170
151 part->remote_openclose_args = xpc_kmalloc_cacheline_aligned( 171 part->remote_openclose_args = xpc_kzalloc_cacheline_aligned(
152 XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, 172 XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
153 &part->remote_openclose_args_base); 173 &part->remote_openclose_args_base);
154 if (part->remote_openclose_args == NULL) { 174 if (part->remote_openclose_args == NULL) {
155 kfree(part->channels); 175 dev_err(xpc_chan, "can't get memory for remote connect args\n");
156 part->channels = NULL;
157 kfree(part->local_GPs_base);
158 part->local_GPs = NULL;
159 kfree(part->remote_GPs_base);
160 part->remote_GPs = NULL;
161 kfree(part->local_openclose_args_base); 176 kfree(part->local_openclose_args_base);
162 part->local_openclose_args = NULL; 177 part->local_openclose_args = NULL;
163 dev_err(xpc_chan, "can't get memory for remote connect args\n"); 178 kfree(part->remote_GPs_base);
179 part->remote_GPs = NULL;
180 kfree(part->local_GPs_base);
181 part->local_GPs = NULL;
182 kfree(part->channels);
183 part->channels = NULL;
164 return xpcNoMemory; 184 return xpcNoMemory;
165 } 185 }
166 memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
167 186
168 187
169 xpc_initialize_channels(part, partid); 188 xpc_initialize_channels(part, partid);
@@ -186,18 +205,18 @@ xpc_setup_infrastructure(struct xpc_partition *part)
186 ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ, 205 ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ,
187 part->IPI_owner, (void *) (u64) partid); 206 part->IPI_owner, (void *) (u64) partid);
188 if (ret != 0) { 207 if (ret != 0) {
189 kfree(part->channels);
190 part->channels = NULL;
191 kfree(part->local_GPs_base);
192 part->local_GPs = NULL;
193 kfree(part->remote_GPs_base);
194 part->remote_GPs = NULL;
195 kfree(part->local_openclose_args_base);
196 part->local_openclose_args = NULL;
197 kfree(part->remote_openclose_args_base);
198 part->remote_openclose_args = NULL;
199 dev_err(xpc_chan, "can't register NOTIFY IRQ handler, " 208 dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
200 "errno=%d\n", -ret); 209 "errno=%d\n", -ret);
210 kfree(part->remote_openclose_args_base);
211 part->remote_openclose_args = NULL;
212 kfree(part->local_openclose_args_base);
213 part->local_openclose_args = NULL;
214 kfree(part->remote_GPs_base);
215 part->remote_GPs = NULL;
216 kfree(part->local_GPs_base);
217 part->local_GPs = NULL;
218 kfree(part->channels);
219 part->channels = NULL;
201 return xpcLackOfResources; 220 return xpcLackOfResources;
202 } 221 }
203 222
@@ -446,22 +465,20 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
446 for (nentries = ch->local_nentries; nentries > 0; nentries--) { 465 for (nentries = ch->local_nentries; nentries > 0; nentries--) {
447 466
448 nbytes = nentries * ch->msg_size; 467 nbytes = nentries * ch->msg_size;
449 ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, 468 ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
450 GFP_KERNEL, 469 GFP_KERNEL,
451 &ch->local_msgqueue_base); 470 &ch->local_msgqueue_base);
452 if (ch->local_msgqueue == NULL) { 471 if (ch->local_msgqueue == NULL) {
453 continue; 472 continue;
454 } 473 }
455 memset(ch->local_msgqueue, 0, nbytes);
456 474
457 nbytes = nentries * sizeof(struct xpc_notify); 475 nbytes = nentries * sizeof(struct xpc_notify);
458 ch->notify_queue = kmalloc(nbytes, GFP_KERNEL); 476 ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
459 if (ch->notify_queue == NULL) { 477 if (ch->notify_queue == NULL) {
460 kfree(ch->local_msgqueue_base); 478 kfree(ch->local_msgqueue_base);
461 ch->local_msgqueue = NULL; 479 ch->local_msgqueue = NULL;
462 continue; 480 continue;
463 } 481 }
464 memset(ch->notify_queue, 0, nbytes);
465 482
466 spin_lock_irqsave(&ch->lock, irq_flags); 483 spin_lock_irqsave(&ch->lock, irq_flags);
467 if (nentries < ch->local_nentries) { 484 if (nentries < ch->local_nentries) {
@@ -501,13 +518,12 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
501 for (nentries = ch->remote_nentries; nentries > 0; nentries--) { 518 for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
502 519
503 nbytes = nentries * ch->msg_size; 520 nbytes = nentries * ch->msg_size;
504 ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, 521 ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
505 GFP_KERNEL, 522 GFP_KERNEL,
506 &ch->remote_msgqueue_base); 523 &ch->remote_msgqueue_base);
507 if (ch->remote_msgqueue == NULL) { 524 if (ch->remote_msgqueue == NULL) {
508 continue; 525 continue;
509 } 526 }
510 memset(ch->remote_msgqueue, 0, nbytes);
511 527
512 spin_lock_irqsave(&ch->lock, irq_flags); 528 spin_lock_irqsave(&ch->lock, irq_flags);
513 if (nentries < ch->remote_nentries) { 529 if (nentries < ch->remote_nentries) {
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 8cbf16432570..99b123a6421a 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -52,7 +52,6 @@
52#include <linux/syscalls.h> 52#include <linux/syscalls.h>
53#include <linux/cache.h> 53#include <linux/cache.h>
54#include <linux/interrupt.h> 54#include <linux/interrupt.h>
55#include <linux/slab.h>
56#include <linux/delay.h> 55#include <linux/delay.h>
57#include <linux/reboot.h> 56#include <linux/reboot.h>
58#include <linux/completion.h> 57#include <linux/completion.h>
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 88a730e6cfdb..94211429fd0c 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -81,6 +81,31 @@ char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
81 81
82 82
83/* 83/*
84 * Guarantee that the kmalloc'd memory is cacheline aligned.
85 */
86static void *
87xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
88{
89 /* see if kmalloc will give us cachline aligned memory by default */
90 *base = kmalloc(size, flags);
91 if (*base == NULL) {
92 return NULL;
93 }
94 if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
95 return *base;
96 }
97 kfree(*base);
98
99 /* nope, we'll have to do it ourselves */
100 *base = kmalloc(size + L1_CACHE_BYTES, flags);
101 if (*base == NULL) {
102 return NULL;
103 }
104 return (void *) L1_CACHE_ALIGN((u64) *base);
105}
106
107
108/*
84 * Given a nasid, get the physical address of the partition's reserved page 109 * Given a nasid, get the physical address of the partition's reserved page
85 * for that nasid. This function returns 0 on any error. 110 * for that nasid. This function returns 0 on any error.
86 */ 111 */
@@ -1038,13 +1063,12 @@ xpc_discovery(void)
1038 remote_vars = (struct xpc_vars *) remote_rp; 1063 remote_vars = (struct xpc_vars *) remote_rp;
1039 1064
1040 1065
1041 discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words, 1066 discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
1042 GFP_KERNEL); 1067 GFP_KERNEL);
1043 if (discovered_nasids == NULL) { 1068 if (discovered_nasids == NULL) {
1044 kfree(remote_rp_base); 1069 kfree(remote_rp_base);
1045 return; 1070 return;
1046 } 1071 }
1047 memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
1048 1072
1049 rp = (struct xpc_rsvd_page *) xpc_rsvd_page; 1073 rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
1050 1074