aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-07-30 01:34:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-30 12:41:49 -0400
commit94bd2708d4a95d7da5a1c7c28a063eccd127fb69 (patch)
treebcc65d3966e240017f8fb355114ec07c906b0b63
parent908787db9b95f548270af18d83d62b9d2020ca10 (diff)
sgi-xp: prepare xpc_rsvd_page to work on either sn2 or uv hardware
Prepare XPC's reserved page header to work for either sn2 or uv. Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/misc/sgi-xp/Makefile3
-rw-r--r--drivers/misc/sgi-xp/xp.h5
-rw-r--r--drivers/misc/sgi-xp/xpc.h57
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c27
-rw-r--r--drivers/misc/sgi-xp/xpc_partition.c149
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c111
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c48
7 files changed, 267 insertions, 133 deletions
diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile
index b50f2921781..b3eeff31ebf 100644
--- a/drivers/misc/sgi-xp/Makefile
+++ b/drivers/misc/sgi-xp/Makefile
@@ -7,6 +7,7 @@ xp-y := xp_main.o xp_uv.o
7xp-$(CONFIG_IA64) += xp_sn2.o xp_nofault.o 7xp-$(CONFIG_IA64) += xp_sn2.o xp_nofault.o
8 8
9obj-$(CONFIG_SGI_XP) += xpc.o 9obj-$(CONFIG_SGI_XP) += xpc.o
10xpc-y := xpc_main.o xpc_channel.o xpc_partition.o 10xpc-y := xpc_main.o xpc_uv.o xpc_channel.o xpc_partition.o
11xpc-$(CONFIG_IA64) += xpc_sn2.o
11 12
12obj-$(CONFIG_SGI_XP) += xpnet.o 13obj-$(CONFIG_SGI_XP) += xpnet.o
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
index c42196a1a6b..0f75592896d 100644
--- a/drivers/misc/sgi-xp/xp.h
+++ b/drivers/misc/sgi-xp/xp.h
@@ -220,9 +220,10 @@ enum xp_retval {
220 220
221 xpBteCopyError, /* 52: bte_copy() returned error */ 221 xpBteCopyError, /* 52: bte_copy() returned error */
222 xpSalError, /* 53: sn SAL error */ 222 xpSalError, /* 53: sn SAL error */
223 xpRsvdPageNotSet, /* 54: the reserved page is not set up */
223 224
224 xpUnsupported, /* 54: unsupported functionality or resource */ 225 xpUnsupported, /* 55: unsupported functionality or resource */
225 xpUnknownReason /* 55: unknown reason - must be last in enum */ 226 xpUnknownReason /* 56: unknown reason - must be last in enum */
226}; 227};
227 228
228/* 229/*
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
index 60388bed770..94b52bb8151 100644
--- a/drivers/misc/sgi-xp/xpc.h
+++ b/drivers/misc/sgi-xp/xpc.h
@@ -71,11 +71,11 @@
71 * 71 *
72 * reserved page header 72 * reserved page header
73 * 73 *
74 * The first cacheline of the reserved page contains the header 74 * The first two 64-byte cachelines of the reserved page contain the
75 * (struct xpc_rsvd_page). Before SAL initialization has completed, 75 * header (struct xpc_rsvd_page). Before SAL initialization has completed,
76 * SAL has set up the following fields of the reserved page header: 76 * SAL has set up the following fields of the reserved page header:
77 * SAL_signature, SAL_version, partid, and nasids_size. The other 77 * SAL_signature, SAL_version, SAL_partid, and SAL_nasids_size. The
78 * fields are set up by XPC. (xpc_rsvd_page points to the local 78 * other fields are set up by XPC. (xpc_rsvd_page points to the local
79 * partition's reserved page.) 79 * partition's reserved page.)
80 * 80 *
81 * part_nasids mask 81 * part_nasids mask
@@ -89,11 +89,11 @@
89 * nasids. The part_nasids mask is located starting at the first cacheline 89 * nasids. The part_nasids mask is located starting at the first cacheline
90 * following the reserved page header. The mach_nasids mask follows right 90 * following the reserved page header. The mach_nasids mask follows right
91 * after the part_nasids mask. The size in bytes of each mask is reflected 91 * after the part_nasids mask. The size in bytes of each mask is reflected
92 * by the reserved page header field 'nasids_size'. (Local partition's 92 * by the reserved page header field 'SAL_nasids_size'. (Local partition's
93 * mask pointers are xpc_part_nasids and xpc_mach_nasids.) 93 * mask pointers are xpc_part_nasids and xpc_mach_nasids.)
94 * 94 *
95 * vars 95 * vars (ia64-sn2 only)
96 * vars part 96 * vars part (ia64-sn2 only)
97 * 97 *
98 * Immediately following the mach_nasids mask are the XPC variables 98 * Immediately following the mach_nasids mask are the XPC variables
99 * required by other partitions. First are those that are generic to all 99 * required by other partitions. First are those that are generic to all
@@ -101,25 +101,31 @@
101 * which are partition specific (vars part). These are setup by XPC. 101 * which are partition specific (vars part). These are setup by XPC.
102 * (Local partition's vars pointers are xpc_vars and xpc_vars_part.) 102 * (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
103 * 103 *
104 * Note: Until vars_pa is set, the partition XPC code has not been initialized. 104 * Note: Until 'stamp' is set non-zero, the partition XPC code has not been
105 * initialized.
105 */ 106 */
106struct xpc_rsvd_page { 107struct xpc_rsvd_page {
107 u64 SAL_signature; /* SAL: unique signature */ 108 u64 SAL_signature; /* SAL: unique signature */
108 u64 SAL_version; /* SAL: version */ 109 u64 SAL_version; /* SAL: version */
109 u8 partid; /* SAL: partition ID */ 110 short SAL_partid; /* SAL: partition ID */
111 short max_npartitions; /* value of XPC_MAX_PARTITIONS */
110 u8 version; 112 u8 version;
111 u8 pad1[6]; /* align to next u64 in cacheline */ 113 u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */
112 u64 vars_pa; /* physical address of struct xpc_vars */ 114 union {
115 u64 vars_pa; /* physical address of struct xpc_vars */
116 u64 activate_mq_gpa; /* global phys address of activate_mq */
117 } sn;
113 struct timespec stamp; /* time when reserved page was setup by XPC */ 118 struct timespec stamp; /* time when reserved page was setup by XPC */
114 u64 pad2[9]; /* align to last u64 in cacheline */ 119 u64 pad2[9]; /* align to last u64 in 2nd 64-byte cacheline */
115 u64 nasids_size; /* SAL: size of each nasid mask in bytes */ 120 u64 SAL_nasids_size; /* SAL: size of each nasid mask in bytes */
116}; 121};
117 122
118#define XPC_RP_VERSION _XPC_VERSION(1, 1) /* version 1.1 of the reserved page */ 123#define XPC_RP_VERSION _XPC_VERSION(2, 0) /* version 2.0 of the reserved page */
119 124
120#define XPC_SUPPORTS_RP_STAMP(_version) \ 125#define XPC_SUPPORTS_RP_STAMP(_version) \
121 (_version >= _XPC_VERSION(1, 1)) 126 (_version >= _XPC_VERSION(1, 1))
122 127
128#define ZERO_STAMP ((struct timespec){0, 0})
123/* 129/*
124 * compare stamps - the return value is: 130 * compare stamps - the return value is:
125 * 131 *
@@ -218,10 +224,10 @@ xpc_disallow_hb(short partid, struct xpc_vars *vars)
218 * 224 *
219 * An array of these structures, one per partition, will be defined. As a 225 * An array of these structures, one per partition, will be defined. As a
220 * partition becomes active XPC will copy the array entry corresponding to 226 * partition becomes active XPC will copy the array entry corresponding to
221 * itself from that partition. It is desirable that the size of this 227 * itself from that partition. It is desirable that the size of this structure
222 * structure evenly divide into a cacheline, such that none of the entries 228 * evenly divides into a 128-byte cacheline, such that none of the entries in
223 * in this array crosses a cacheline boundary. As it is now, each entry 229 * this array crosses a 128-byte cacheline boundary. As it is now, each entry
224 * occupies half a cacheline. 230 * occupies a 64-byte cacheline.
225 */ 231 */
226struct xpc_vars_part { 232struct xpc_vars_part {
227 u64 magic; 233 u64 magic;
@@ -632,16 +638,25 @@ extern void xpc_activate_kthreads(struct xpc_channel *, int);
632extern void xpc_create_kthreads(struct xpc_channel *, int, int); 638extern void xpc_create_kthreads(struct xpc_channel *, int, int);
633extern void xpc_disconnect_wait(int); 639extern void xpc_disconnect_wait(int);
634 640
641extern enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *);
642
643/* found in xpc_sn2.c */
644extern void xpc_init_sn2(void);
645extern struct xpc_vars *xpc_vars; /*>>> eliminate from here */
646extern struct xpc_vars_part *xpc_vars_part; /*>>> eliminate from here */
647
648/* found in xpc_uv.c */
649extern void xpc_init_uv(void);
650
635/* found in xpc_partition.c */ 651/* found in xpc_partition.c */
636extern int xpc_exiting; 652extern int xpc_exiting;
637extern struct xpc_vars *xpc_vars; 653extern int xp_nasid_mask_words;
638extern struct xpc_rsvd_page *xpc_rsvd_page; 654extern struct xpc_rsvd_page *xpc_rsvd_page;
639extern struct xpc_vars_part *xpc_vars_part;
640extern struct xpc_partition *xpc_partitions; 655extern struct xpc_partition *xpc_partitions;
641extern char *xpc_remote_copy_buffer; 656extern char *xpc_remote_copy_buffer;
642extern void *xpc_remote_copy_buffer_base; 657extern void *xpc_remote_copy_buffer_base;
643extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **); 658extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
644extern struct xpc_rsvd_page *xpc_rsvd_page_init(void); 659extern struct xpc_rsvd_page *xpc_setup_rsvd_page(void);
645extern void xpc_allow_IPI_ops(void); 660extern void xpc_allow_IPI_ops(void);
646extern void xpc_restrict_IPI_ops(void); 661extern void xpc_restrict_IPI_ops(void);
647extern int xpc_identify_act_IRQ_sender(void); 662extern int xpc_identify_act_IRQ_sender(void);
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index a05c7c7da22..2180f1f7e08 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -175,6 +175,8 @@ static struct notifier_block xpc_die_notifier = {
175 .notifier_call = xpc_system_die, 175 .notifier_call = xpc_system_die,
176}; 176};
177 177
178enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *rp);
179
178/* 180/*
179 * Timer function to enforce the timelimit on the partition disengage request. 181 * Timer function to enforce the timelimit on the partition disengage request.
180 */ 182 */
@@ -949,7 +951,7 @@ xpc_do_exit(enum xp_retval reason)
949 DBUG_ON(xpc_partition_engaged(-1UL)); 951 DBUG_ON(xpc_partition_engaged(-1UL));
950 952
951 /* indicate to others that our reserved page is uninitialized */ 953 /* indicate to others that our reserved page is uninitialized */
952 xpc_rsvd_page->vars_pa = 0; 954 xpc_rsvd_page->stamp = ZERO_STAMP;
953 955
954 /* now it's time to eliminate our heartbeat */ 956 /* now it's time to eliminate our heartbeat */
955 del_timer_sync(&xpc_hb_timer); 957 del_timer_sync(&xpc_hb_timer);
@@ -1128,8 +1130,24 @@ xpc_init(void)
1128 struct task_struct *kthread; 1130 struct task_struct *kthread;
1129 size_t buf_size; 1131 size_t buf_size;
1130 1132
1131 if (!ia64_platform_is("sn2")) 1133 if (is_shub()) {
1134 /*
1135 * The ia64-sn2 architecture supports at most 64 partitions.
1136 * And the inability to unregister remote AMOs restricts us
1137 * further to only support exactly 64 partitions on this
1138 * architecture, no less.
1139 */
1140 if (xp_max_npartitions != 64)
1141 return -EINVAL;
1142
1143 xpc_init_sn2();
1144
1145 } else if (is_uv()) {
1146 xpc_init_uv();
1147
1148 } else {
1132 return -ENODEV; 1149 return -ENODEV;
1150 }
1133 1151
1134 snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); 1152 snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
1135 snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); 1153 snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
@@ -1214,7 +1232,7 @@ xpc_init(void)
1214 * other partitions to discover we are alive and establish initial 1232 * other partitions to discover we are alive and establish initial
1215 * communications. 1233 * communications.
1216 */ 1234 */
1217 xpc_rsvd_page = xpc_rsvd_page_init(); 1235 xpc_rsvd_page = xpc_setup_rsvd_page();
1218 if (xpc_rsvd_page == NULL) { 1236 if (xpc_rsvd_page == NULL) {
1219 dev_err(xpc_part, "can't setup our reserved page\n"); 1237 dev_err(xpc_part, "can't setup our reserved page\n");
1220 ret = -EBUSY; 1238 ret = -EBUSY;
@@ -1273,7 +1291,8 @@ xpc_init(void)
1273 /* initialization was not successful */ 1291 /* initialization was not successful */
1274out_4: 1292out_4:
1275 /* indicate to others that our reserved page is uninitialized */ 1293 /* indicate to others that our reserved page is uninitialized */
1276 xpc_rsvd_page->vars_pa = 0; 1294 xpc_rsvd_page->stamp = ZERO_STAMP;
1295
1277 del_timer_sync(&xpc_hb_timer); 1296 del_timer_sync(&xpc_hb_timer);
1278 (void)unregister_die_notifier(&xpc_die_notifier); 1297 (void)unregister_die_notifier(&xpc_die_notifier);
1279 (void)unregister_reboot_notifier(&xpc_reboot_notifier); 1298 (void)unregister_reboot_notifier(&xpc_reboot_notifier);
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
index 6c82f205097..1db84cb4914 100644
--- a/drivers/misc/sgi-xp/xpc_partition.c
+++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -20,7 +20,6 @@
20#include <linux/cache.h> 20#include <linux/cache.h>
21#include <linux/mmzone.h> 21#include <linux/mmzone.h>
22#include <linux/nodemask.h> 22#include <linux/nodemask.h>
23#include <asm/uncached.h>
24#include <asm/sn/intr.h> 23#include <asm/sn/intr.h>
25#include <asm/sn/sn_sal.h> 24#include <asm/sn/sn_sal.h>
26#include <asm/sn/nodepda.h> 25#include <asm/sn/nodepda.h>
@@ -44,11 +43,10 @@ u64 xpc_prot_vec[MAX_NUMNODES];
44struct xpc_rsvd_page *xpc_rsvd_page; 43struct xpc_rsvd_page *xpc_rsvd_page;
45static u64 *xpc_part_nasids; 44static u64 *xpc_part_nasids;
46static u64 *xpc_mach_nasids; 45static u64 *xpc_mach_nasids;
47struct xpc_vars *xpc_vars;
48struct xpc_vars_part *xpc_vars_part;
49 46
50static int xp_nasid_mask_bytes; /* actual size in bytes of nasid mask */ 47/* >>> next two variables should be 'xpc_' if they remain here */
51static int xp_nasid_mask_words; /* actual size in words of nasid mask */ 48static int xp_sizeof_nasid_mask; /* actual size in bytes of nasid mask */
49int xp_nasid_mask_words; /* actual size in words of nasid mask */
52 50
53struct xpc_partition *xpc_partitions; 51struct xpc_partition *xpc_partitions;
54 52
@@ -150,12 +148,10 @@ xpc_get_rsvd_page_pa(int nasid)
150 * communications. 148 * communications.
151 */ 149 */
152struct xpc_rsvd_page * 150struct xpc_rsvd_page *
153xpc_rsvd_page_init(void) 151xpc_setup_rsvd_page(void)
154{ 152{
155 struct xpc_rsvd_page *rp; 153 struct xpc_rsvd_page *rp;
156 AMO_t *amos_page; 154 u64 rp_pa;
157 u64 rp_pa, nasid_array = 0;
158 int i, ret;
159 155
160 /* get the local reserved page's address */ 156 /* get the local reserved page's address */
161 157
@@ -168,110 +164,44 @@ xpc_rsvd_page_init(void)
168 } 164 }
169 rp = (struct xpc_rsvd_page *)__va(rp_pa); 165 rp = (struct xpc_rsvd_page *)__va(rp_pa);
170 166
171 if (rp->partid != sn_partition_id) { 167 if (rp->SAL_version < 3) {
172 dev_err(xpc_part, "the reserved page's partid of %d should be " 168 /* SAL_versions < 3 had a SAL_partid defined as a u8 */
173 "%d\n", rp->partid, sn_partition_id); 169 rp->SAL_partid &= 0xff;
170 }
171 BUG_ON(rp->SAL_partid != sn_partition_id);
172
173 if (rp->SAL_partid < 0 || rp->SAL_partid >= xp_max_npartitions) {
174 dev_err(xpc_part, "the reserved page's partid of %d is outside "
175 "supported range (< 0 || >= %d)\n", rp->SAL_partid,
176 xp_max_npartitions);
174 return NULL; 177 return NULL;
175 } 178 }
176 179
177 rp->version = XPC_RP_VERSION; 180 rp->version = XPC_RP_VERSION;
181 rp->max_npartitions = xp_max_npartitions;
178 182
179 /* establish the actual sizes of the nasid masks */ 183 /* establish the actual sizes of the nasid masks */
180 if (rp->SAL_version == 1) { 184 if (rp->SAL_version == 1) {
181 /* SAL_version 1 didn't set the nasids_size field */ 185 /* SAL_version 1 didn't set the nasids_size field */
182 rp->nasids_size = 128; 186 rp->SAL_nasids_size = 128;
183 } 187 }
184 xp_nasid_mask_bytes = rp->nasids_size; 188 xp_sizeof_nasid_mask = rp->SAL_nasids_size;
185 xp_nasid_mask_words = xp_nasid_mask_bytes / 8; 189 xp_nasid_mask_words = DIV_ROUND_UP(xp_sizeof_nasid_mask,
190 BYTES_PER_WORD);
186 191
187 /* setup the pointers to the various items in the reserved page */ 192 /* setup the pointers to the various items in the reserved page */
188 xpc_part_nasids = XPC_RP_PART_NASIDS(rp); 193 xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
189 xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp); 194 xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
190 xpc_vars = XPC_RP_VARS(rp);
191 xpc_vars_part = XPC_RP_VARS_PART(rp);
192 195
193 /* 196 if (xpc_rsvd_page_init(rp) != xpSuccess)
194 * Before clearing xpc_vars, see if a page of AMOs had been previously 197 return NULL;
195 * allocated. If not we'll need to allocate one and set permissions
196 * so that cross-partition AMOs are allowed.
197 *
198 * The allocated AMO page needs MCA reporting to remain disabled after
199 * XPC has unloaded. To make this work, we keep a copy of the pointer
200 * to this page (i.e., amos_page) in the struct xpc_vars structure,
201 * which is pointed to by the reserved page, and re-use that saved copy
202 * on subsequent loads of XPC. This AMO page is never freed, and its
203 * memory protections are never restricted.
204 */
205 amos_page = xpc_vars->amos_page;
206 if (amos_page == NULL) {
207 amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0, 1));
208 if (amos_page == NULL) {
209 dev_err(xpc_part, "can't allocate page of AMOs\n");
210 return NULL;
211 }
212
213 /*
214 * Open up AMO-R/W to cpu. This is done for Shub 1.1 systems
215 * when xpc_allow_IPI_ops() is called via xpc_hb_init().
216 */
217 if (!enable_shub_wars_1_1()) {
218 ret = sn_change_memprotect(ia64_tpa((u64)amos_page),
219 PAGE_SIZE,
220 SN_MEMPROT_ACCESS_CLASS_1,
221 &nasid_array);
222 if (ret != 0) {
223 dev_err(xpc_part, "can't change memory "
224 "protections\n");
225 uncached_free_page(__IA64_UNCACHED_OFFSET |
226 TO_PHYS((u64)amos_page), 1);
227 return NULL;
228 }
229 }
230 } else if (!IS_AMO_ADDRESS((u64)amos_page)) {
231 /*
232 * EFI's XPBOOT can also set amos_page in the reserved page,
233 * but it happens to leave it as an uncached physical address
234 * and we need it to be an uncached virtual, so we'll have to
235 * convert it.
236 */
237 if (!IS_AMO_PHYS_ADDRESS((u64)amos_page)) {
238 dev_err(xpc_part, "previously used amos_page address "
239 "is bad = 0x%p\n", (void *)amos_page);
240 return NULL;
241 }
242 amos_page = (AMO_t *)TO_AMO((u64)amos_page);
243 }
244
245 /* clear xpc_vars */
246 memset(xpc_vars, 0, sizeof(struct xpc_vars));
247
248 xpc_vars->version = XPC_V_VERSION;
249 xpc_vars->act_nasid = cpuid_to_nasid(0);
250 xpc_vars->act_phys_cpuid = cpu_physical_id(0);
251 xpc_vars->vars_part_pa = __pa(xpc_vars_part);
252 xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page);
253 xpc_vars->amos_page = amos_page; /* save for next load of XPC */
254
255 /* clear xpc_vars_part */
256 memset((u64 *)xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
257 xp_max_npartitions);
258
259 /* initialize the activate IRQ related AMO variables */
260 for (i = 0; i < xp_nasid_mask_words; i++)
261 (void)xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
262
263 /* initialize the engaged remote partitions related AMO variables */
264 (void)xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
265 (void)xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
266
267 /* timestamp of when reserved page was setup by XPC */
268 rp->stamp = CURRENT_TIME;
269 198
270 /* 199 /*
200 * Set timestamp of when reserved page was setup by XPC.
271 * This signifies to the remote partition that our reserved 201 * This signifies to the remote partition that our reserved
272 * page is initialized. 202 * page is initialized.
273 */ 203 */
274 rp->vars_pa = __pa(xpc_vars); 204 rp->stamp = CURRENT_TIME;
275 205
276 return rp; 206 return rp;
277} 207}
@@ -465,7 +395,7 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
465 395
466 /* pull over the reserved page header and part_nasids mask */ 396 /* pull over the reserved page header and part_nasids mask */
467 ret = xp_remote_memcpy(remote_rp, (void *)*remote_rp_pa, 397 ret = xp_remote_memcpy(remote_rp, (void *)*remote_rp_pa,
468 XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes); 398 XPC_RP_HEADER_SIZE + xp_sizeof_nasid_mask);
469 if (ret != xpSuccess) 399 if (ret != xpSuccess)
470 return ret; 400 return ret;
471 401
@@ -476,19 +406,28 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
476 discovered_nasids[i] |= remote_part_nasids[i]; 406 discovered_nasids[i] |= remote_part_nasids[i];
477 } 407 }
478 408
479 /* check that the partid is for another partition */ 409 /* check that the partid is valid and is for another partition */
480 410
481 if (remote_rp->partid < 0 || remote_rp->partid >= xp_max_npartitions) 411 if (remote_rp->SAL_partid < 0 ||
412 remote_rp->SAL_partid >= xp_max_npartitions) {
482 return xpInvalidPartid; 413 return xpInvalidPartid;
414 }
483 415
484 if (remote_rp->partid == sn_partition_id) 416 if (remote_rp->SAL_partid == sn_partition_id)
485 return xpLocalPartid; 417 return xpLocalPartid;
486 418
419 /* see if the rest of the reserved page has been set up by XPC */
420 if (timespec_equal(&remote_rp->stamp, &ZERO_STAMP))
421 return xpRsvdPageNotSet;
422
487 if (XPC_VERSION_MAJOR(remote_rp->version) != 423 if (XPC_VERSION_MAJOR(remote_rp->version) !=
488 XPC_VERSION_MAJOR(XPC_RP_VERSION)) { 424 XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
489 return xpBadVersion; 425 return xpBadVersion;
490 } 426 }
491 427
428 if (remote_rp->max_npartitions <= sn_partition_id)
429 return xpInvalidPartid;
430
492 return xpSuccess; 431 return xpSuccess;
493} 432}
494 433
@@ -592,7 +531,7 @@ xpc_identify_act_IRQ_req(int nasid)
592 int remote_rp_version; 531 int remote_rp_version;
593 int reactivate = 0; 532 int reactivate = 0;
594 int stamp_diff; 533 int stamp_diff;
595 struct timespec remote_rp_stamp = { 0, 0 }; 534 struct timespec remote_rp_stamp = { 0, 0 }; /*>>> ZERO_STAMP */
596 short partid; 535 short partid;
597 struct xpc_partition *part; 536 struct xpc_partition *part;
598 enum xp_retval ret; 537 enum xp_retval ret;
@@ -608,12 +547,12 @@ xpc_identify_act_IRQ_req(int nasid)
608 return; 547 return;
609 } 548 }
610 549
611 remote_vars_pa = remote_rp->vars_pa; 550 remote_vars_pa = remote_rp->sn.vars_pa;
612 remote_rp_version = remote_rp->version; 551 remote_rp_version = remote_rp->version;
613 if (XPC_SUPPORTS_RP_STAMP(remote_rp_version)) 552 if (XPC_SUPPORTS_RP_STAMP(remote_rp_version))
614 remote_rp_stamp = remote_rp->stamp; 553 remote_rp_stamp = remote_rp->stamp;
615 554
616 partid = remote_rp->partid; 555 partid = remote_rp->SAL_partid;
617 part = &xpc_partitions[partid]; 556 part = &xpc_partitions[partid];
618 557
619 /* pull over the cross partition variables */ 558 /* pull over the cross partition variables */
@@ -977,7 +916,7 @@ xpc_discovery(void)
977 enum xp_retval ret; 916 enum xp_retval ret;
978 917
979 remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE + 918 remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
980 xp_nasid_mask_bytes, 919 xp_sizeof_nasid_mask,
981 GFP_KERNEL, &remote_rp_base); 920 GFP_KERNEL, &remote_rp_base);
982 if (remote_rp == NULL) 921 if (remote_rp == NULL)
983 return; 922 return;
@@ -1063,9 +1002,9 @@ xpc_discovery(void)
1063 continue; 1002 continue;
1064 } 1003 }
1065 1004
1066 remote_vars_pa = remote_rp->vars_pa; 1005 remote_vars_pa = remote_rp->sn.vars_pa;
1067 1006
1068 partid = remote_rp->partid; 1007 partid = remote_rp->SAL_partid;
1069 part = &xpc_partitions[partid]; 1008 part = &xpc_partitions[partid];
1070 1009
1071 /* pull over the cross partition variables */ 1010 /* pull over the cross partition variables */
@@ -1155,5 +1094,5 @@ xpc_initiate_partid_to_nasids(short partid, void *nasid_mask)
1155 part_nasid_pa = (u64)XPC_RP_PART_NASIDS(part->remote_rp_pa); 1094 part_nasid_pa = (u64)XPC_RP_PART_NASIDS(part->remote_rp_pa);
1156 1095
1157 return xp_remote_memcpy(nasid_mask, (void *)part_nasid_pa, 1096 return xp_remote_memcpy(nasid_mask, (void *)part_nasid_pa,
1158 xp_nasid_mask_bytes); 1097 xp_sizeof_nasid_mask);
1159} 1098}
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
new file mode 100644
index 00000000000..5a37348715c
--- /dev/null
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -0,0 +1,111 @@
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) 2008 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9/*
10 * Cross Partition Communication (XPC) sn2-based functions.
11 *
12 * Architecture specific implementation of common functions.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <asm/uncached.h>
18#include <asm/sn/sn_sal.h>
19#include "xpc.h"
20
21struct xpc_vars *xpc_vars;
22struct xpc_vars_part *xpc_vars_part;
23
24static enum xp_retval
25xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
26{
27 AMO_t *amos_page;
28 u64 nasid_array = 0;
29 int i;
30 int ret;
31
32 xpc_vars = XPC_RP_VARS(rp);
33
34 rp->sn.vars_pa = __pa(xpc_vars);
35
36 xpc_vars_part = XPC_RP_VARS_PART(rp);
37
38 /*
39 * Before clearing xpc_vars, see if a page of AMOs had been previously
40 * allocated. If not we'll need to allocate one and set permissions
41 * so that cross-partition AMOs are allowed.
42 *
43 * The allocated AMO page needs MCA reporting to remain disabled after
44 * XPC has unloaded. To make this work, we keep a copy of the pointer
45 * to this page (i.e., amos_page) in the struct xpc_vars structure,
46 * which is pointed to by the reserved page, and re-use that saved copy
47 * on subsequent loads of XPC. This AMO page is never freed, and its
48 * memory protections are never restricted.
49 */
50 amos_page = xpc_vars->amos_page;
51 if (amos_page == NULL) {
52 amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0, 1));
53 if (amos_page == NULL) {
54 dev_err(xpc_part, "can't allocate page of AMOs\n");
55 return xpNoMemory;
56 }
57
58 /*
59 * Open up AMO-R/W to cpu. This is done for Shub 1.1 systems
60 * when xpc_allow_IPI_ops() is called via xpc_hb_init().
61 */
62 if (!enable_shub_wars_1_1()) {
63 ret = sn_change_memprotect(ia64_tpa((u64)amos_page),
64 PAGE_SIZE,
65 SN_MEMPROT_ACCESS_CLASS_1,
66 &nasid_array);
67 if (ret != 0) {
68 dev_err(xpc_part, "can't change memory "
69 "protections\n");
70 uncached_free_page(__IA64_UNCACHED_OFFSET |
71 TO_PHYS((u64)amos_page), 1);
72 return xpSalError;
73 }
74 }
75 }
76
77 /* clear xpc_vars */
78 memset(xpc_vars, 0, sizeof(struct xpc_vars));
79
80 xpc_vars->version = XPC_V_VERSION;
81 xpc_vars->act_nasid = cpuid_to_nasid(0);
82 xpc_vars->act_phys_cpuid = cpu_physical_id(0);
83 xpc_vars->vars_part_pa = __pa(xpc_vars_part);
84 xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page);
85 xpc_vars->amos_page = amos_page; /* save for next load of XPC */
86
87 /* clear xpc_vars_part */
88 memset((u64 *)xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
89 xp_max_npartitions);
90
91 /* initialize the activate IRQ related AMO variables */
92 for (i = 0; i < xp_nasid_mask_words; i++)
93 (void)xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
94
95 /* initialize the engaged remote partitions related AMO variables */
96 (void)xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
97 (void)xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
98
99 return xpSuccess;
100}
101
102void
103xpc_init_sn2(void)
104{
105 xpc_rsvd_page_init = xpc_rsvd_page_init_sn2;
106}
107
108void
109xpc_exit_sn2(void)
110{
111}
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
new file mode 100644
index 00000000000..8327cd4017e
--- /dev/null
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -0,0 +1,48 @@
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) 2008 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9/*
10 * Cross Partition Communication (XPC) uv-based functions.
11 *
12 * Architecture specific implementation of common functions.
13 *
14 */
15
16#include <linux/kernel.h>
17
18/* >>> #include <gru/grukservices.h> */
19/* >>> uv_gpa() is defined in <gru/grukservices.h> */
20#define uv_gpa(_a) ((unsigned long)_a)
21
22/* >>> temporarily define next three items for xpc.h */
23#define SGI_XPC_ACTIVATE 23
24#define SGI_XPC_NOTIFY 24
25#define sn_send_IPI_phys(_a, _b, _c, _d)
26
27#include "xpc.h"
28
29static void *xpc_activate_mq;
30
31static enum xp_retval
32xpc_rsvd_page_init_uv(struct xpc_rsvd_page *rp)
33{
34 /* >>> need to have established xpc_activate_mq earlier */
35 rp->sn.activate_mq_gpa = uv_gpa(xpc_activate_mq);
36 return xpSuccess;
37}
38
39void
40xpc_init_uv(void)
41{
42 xpc_rsvd_page_init = xpc_rsvd_page_init_uv;
43}
44
45void
46xpc_exit_uv(void)
47{
48}