aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/xpc_partition.c
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2005-10-25 15:09:51 -0400
committerTony Luck <tony.luck@intel.com>2005-10-25 19:32:39 -0400
commit4b38fcd4858204cb3667eb7b3aca48ffb1002f05 (patch)
tree2125f5d9689e5bdc64ce2e4f35d8a8220c2e0054 /arch/ia64/sn/kernel/xpc_partition.c
parente54af724c1ae3530c95135157776c9be65cdb747 (diff)
[IA64-SGI] XPC changes to support more than 2k nasids
XPC needs to be changed to support up to 16k nasids on an SGI Altix system. Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/sn/kernel/xpc_partition.c')
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c140
1 files changed, 80 insertions, 60 deletions
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 958488f55699..6bb1091f2a4d 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -47,13 +47,16 @@ static u64 xpc_sh2_IPI_access3;
47u64 xpc_prot_vec[MAX_COMPACT_NODES]; 47u64 xpc_prot_vec[MAX_COMPACT_NODES];
48 48
49 49
50/* this partition's reserved page */ 50/* this partition's reserved page pointers */
51struct xpc_rsvd_page *xpc_rsvd_page; 51struct xpc_rsvd_page *xpc_rsvd_page;
52 52static u64 *xpc_part_nasids;
53/* this partition's XPC variables (within the reserved page) */ 53static u64 *xpc_mach_nasids;
54struct xpc_vars *xpc_vars; 54struct xpc_vars *xpc_vars;
55struct xpc_vars_part *xpc_vars_part; 55struct xpc_vars_part *xpc_vars_part;
56 56
57static int xp_nasid_mask_bytes; /* actual size in bytes of nasid mask */
58static int xp_nasid_mask_words; /* actual size in words of nasid mask */
59
57 60
58/* 61/*
59 * For performance reasons, each entry of xpc_partitions[] is cacheline 62 * For performance reasons, each entry of xpc_partitions[] is cacheline
@@ -65,15 +68,16 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
65 68
66 69
67/* 70/*
68 * Generic buffer used to store a local copy of the remote partitions 71 * Generic buffer used to store a local copy of portions of a remote
69 * reserved page or XPC variables. 72 * partition's reserved page (either its header and part_nasids mask,
73 * or its vars).
70 * 74 *
71 * xpc_discovery runs only once and is a seperate thread that is 75 * xpc_discovery runs only once and is a seperate thread that is
72 * very likely going to be processing in parallel with receiving 76 * very likely going to be processing in parallel with receiving
73 * interrupts. 77 * interrupts.
74 */ 78 */
75char ____cacheline_aligned 79char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
76 xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE]; 80 XP_NASID_MASK_BYTES];
77 81
78 82
79/* 83/*
@@ -136,7 +140,7 @@ xpc_rsvd_page_init(void)
136{ 140{
137 struct xpc_rsvd_page *rp; 141 struct xpc_rsvd_page *rp;
138 AMO_t *amos_page; 142 AMO_t *amos_page;
139 u64 rp_pa, next_cl, nasid_array = 0; 143 u64 rp_pa, nasid_array = 0;
140 int i, ret; 144 int i, ret;
141 145
142 146
@@ -144,7 +148,8 @@ xpc_rsvd_page_init(void)
144 148
145 rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0), 149 rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),
146 (u64) xpc_remote_copy_buffer, 150 (u64) xpc_remote_copy_buffer,
147 XPC_RSVD_PAGE_ALIGNED_SIZE); 151 XPC_RP_HEADER_SIZE +
152 L1_CACHE_BYTES);
148 if (rp_pa == 0) { 153 if (rp_pa == 0) {
149 dev_err(xpc_part, "SAL failed to locate the reserved page\n"); 154 dev_err(xpc_part, "SAL failed to locate the reserved page\n");
150 return NULL; 155 return NULL;
@@ -159,12 +164,19 @@ xpc_rsvd_page_init(void)
159 164
160 rp->version = XPC_RP_VERSION; 165 rp->version = XPC_RP_VERSION;
161 166
162 /* 167 /* establish the actual sizes of the nasid masks */
163 * Place the XPC variables on the cache line following the 168 if (rp->SAL_version == 1) {
164 * reserved page structure. 169 /* SAL_version 1 didn't set the nasids_size field */
165 */ 170 rp->nasids_size = 128;
166 next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE; 171 }
167 xpc_vars = (struct xpc_vars *) next_cl; 172 xp_nasid_mask_bytes = rp->nasids_size;
173 xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
174
175 /* setup the pointers to the various items in the reserved page */
176 xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
177 xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
178 xpc_vars = XPC_RP_VARS(rp);
179 xpc_vars_part = XPC_RP_VARS_PART(rp);
168 180
169 /* 181 /*
170 * Before clearing xpc_vars, see if a page of AMOs had been previously 182 * Before clearing xpc_vars, see if a page of AMOs had been previously
@@ -216,26 +228,23 @@ xpc_rsvd_page_init(void)
216 amos_page = (AMO_t *) TO_AMO((u64) amos_page); 228 amos_page = (AMO_t *) TO_AMO((u64) amos_page);
217 } 229 }
218 230
231 /* clear xpc_vars */
219 memset(xpc_vars, 0, sizeof(struct xpc_vars)); 232 memset(xpc_vars, 0, sizeof(struct xpc_vars));
220 233
221 /*
222 * Place the XPC per partition specific variables on the cache line
223 * following the XPC variables structure.
224 */
225 next_cl += XPC_VARS_ALIGNED_SIZE;
226 memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *
227 XP_MAX_PARTITIONS);
228 xpc_vars_part = (struct xpc_vars_part *) next_cl;
229 xpc_vars->vars_part_pa = __pa(next_cl);
230
231 xpc_vars->version = XPC_V_VERSION; 234 xpc_vars->version = XPC_V_VERSION;
232 xpc_vars->act_nasid = cpuid_to_nasid(0); 235 xpc_vars->act_nasid = cpuid_to_nasid(0);
233 xpc_vars->act_phys_cpuid = cpu_physical_id(0); 236 xpc_vars->act_phys_cpuid = cpu_physical_id(0);
237 xpc_vars->vars_part_pa = __pa(xpc_vars_part);
238 xpc_vars->amos_page_pa = ia64_tpa((u64) amos_page);
234 xpc_vars->amos_page = amos_page; /* save for next load of XPC */ 239 xpc_vars->amos_page = amos_page; /* save for next load of XPC */
235 240
236 241
242 /* clear xpc_vars_part */
243 memset((u64 *) xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
244 XP_MAX_PARTITIONS);
245
237 /* initialize the activate IRQ related AMO variables */ 246 /* initialize the activate IRQ related AMO variables */
238 for (i = 0; i < XP_NASID_MASK_WORDS; i++) { 247 for (i = 0; i < xp_nasid_mask_words; i++) {
239 (void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i); 248 (void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
240 } 249 }
241 250
@@ -243,10 +252,7 @@ xpc_rsvd_page_init(void)
243 (void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO); 252 (void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
244 (void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO); 253 (void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
245 254
246 /* export AMO page's physical address to other partitions */ 255 /* timestamp of when reserved page was setup by XPC */
247 xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);
248
249 /* timestamp of when reserved page was initialized */
250 rp->stamp = CURRENT_TIME; 256 rp->stamp = CURRENT_TIME;
251 257
252 /* 258 /*
@@ -406,7 +412,7 @@ xpc_check_remote_hb(void)
406 /* pull the remote_hb cache line */ 412 /* pull the remote_hb cache line */
407 bres = xp_bte_copy(part->remote_vars_pa, 413 bres = xp_bte_copy(part->remote_vars_pa,
408 ia64_tpa((u64) remote_vars), 414 ia64_tpa((u64) remote_vars),
409 XPC_VARS_ALIGNED_SIZE, 415 XPC_RP_VARS_SIZE,
410 (BTE_NOTIFY | BTE_WACQUIRE), NULL); 416 (BTE_NOTIFY | BTE_WACQUIRE), NULL);
411 if (bres != BTE_SUCCESS) { 417 if (bres != BTE_SUCCESS) {
412 XPC_DEACTIVATE_PARTITION(part, 418 XPC_DEACTIVATE_PARTITION(part,
@@ -434,10 +440,11 @@ xpc_check_remote_hb(void)
434 440
435 441
436/* 442/*
437 * Get a copy of the remote partition's rsvd page. 443 * Get a copy of a portion of the remote partition's rsvd page.
438 * 444 *
439 * remote_rp points to a buffer that is cacheline aligned for BTE copies and 445 * remote_rp points to a buffer that is cacheline aligned for BTE copies and
440 * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE. 446 * is large enough to contain a copy of their reserved page header and
447 * part_nasids mask.
441 */ 448 */
442static enum xpc_retval 449static enum xpc_retval
443xpc_get_remote_rp(int nasid, u64 *discovered_nasids, 450xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
@@ -449,16 +456,17 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
449 /* get the reserved page's physical address */ 456 /* get the reserved page's physical address */
450 457
451 *remote_rp_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp, 458 *remote_rp_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,
452 XPC_RSVD_PAGE_ALIGNED_SIZE); 459 XPC_RP_HEADER_SIZE +
460 xp_nasid_mask_bytes);
453 if (*remote_rp_pa == 0) { 461 if (*remote_rp_pa == 0) {
454 return xpcNoRsvdPageAddr; 462 return xpcNoRsvdPageAddr;
455 } 463 }
456 464
457 465
458 /* pull over the reserved page structure */ 466 /* pull over the reserved page header and part_nasids mask */
459 467
460 bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp), 468 bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
461 XPC_RSVD_PAGE_ALIGNED_SIZE, 469 XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
462 (BTE_NOTIFY | BTE_WACQUIRE), NULL); 470 (BTE_NOTIFY | BTE_WACQUIRE), NULL);
463 if (bres != BTE_SUCCESS) { 471 if (bres != BTE_SUCCESS) {
464 return xpc_map_bte_errors(bres); 472 return xpc_map_bte_errors(bres);
@@ -466,8 +474,11 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
466 474
467 475
468 if (discovered_nasids != NULL) { 476 if (discovered_nasids != NULL) {
469 for (i = 0; i < XP_NASID_MASK_WORDS; i++) { 477 u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
470 discovered_nasids[i] |= remote_rp->part_nasids[i]; 478
479
480 for (i = 0; i < xp_nasid_mask_words; i++) {
481 discovered_nasids[i] |= remote_part_nasids[i];
471 } 482 }
472 } 483 }
473 484
@@ -494,10 +505,10 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
494 505
495 506
496/* 507/*
497 * Get a copy of the remote partition's XPC variables. 508 * Get a copy of the remote partition's XPC variables from the reserved page.
498 * 509 *
499 * remote_vars points to a buffer that is cacheline aligned for BTE copies and 510 * remote_vars points to a buffer that is cacheline aligned for BTE copies and
500 * assumed to be of size XPC_VARS_ALIGNED_SIZE. 511 * assumed to be of size XPC_RP_VARS_SIZE.
501 */ 512 */
502static enum xpc_retval 513static enum xpc_retval
503xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars) 514xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
@@ -513,7 +524,7 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
513 /* pull over the cross partition variables */ 524 /* pull over the cross partition variables */
514 525
515 bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars), 526 bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
516 XPC_VARS_ALIGNED_SIZE, 527 XPC_RP_VARS_SIZE,
517 (BTE_NOTIFY | BTE_WACQUIRE), NULL); 528 (BTE_NOTIFY | BTE_WACQUIRE), NULL);
518 if (bres != BTE_SUCCESS) { 529 if (bres != BTE_SUCCESS) {
519 return xpc_map_bte_errors(bres); 530 return xpc_map_bte_errors(bres);
@@ -778,14 +789,13 @@ xpc_identify_act_IRQ_sender(void)
778 u64 nasid; /* remote nasid */ 789 u64 nasid; /* remote nasid */
779 int n_IRQs_detected = 0; 790 int n_IRQs_detected = 0;
780 AMO_t *act_amos; 791 AMO_t *act_amos;
781 struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
782 792
783 793
784 act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS; 794 act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
785 795
786 796
787 /* scan through act AMO variable looking for non-zero entries */ 797 /* scan through act AMO variable looking for non-zero entries */
788 for (word = 0; word < XP_NASID_MASK_WORDS; word++) { 798 for (word = 0; word < xp_nasid_mask_words; word++) {
789 799
790 if (xpc_exiting) { 800 if (xpc_exiting) {
791 break; 801 break;
@@ -807,7 +817,7 @@ xpc_identify_act_IRQ_sender(void)
807 * remote nasid in our reserved pages machine mask. 817 * remote nasid in our reserved pages machine mask.
808 * This is used in the event of module reload. 818 * This is used in the event of module reload.
809 */ 819 */
810 rp->mach_nasids[word] |= nasid_mask; 820 xpc_mach_nasids[word] |= nasid_mask;
811 821
812 822
813 /* locate the nasid(s) which sent interrupts */ 823 /* locate the nasid(s) which sent interrupts */
@@ -992,6 +1002,7 @@ xpc_discovery(void)
992 u64 remote_rp_pa; 1002 u64 remote_rp_pa;
993 u64 remote_vars_pa; 1003 u64 remote_vars_pa;
994 int region; 1004 int region;
1005 int region_size;
995 int max_regions; 1006 int max_regions;
996 int nasid; 1007 int nasid;
997 struct xpc_rsvd_page *rp; 1008 struct xpc_rsvd_page *rp;
@@ -1001,7 +1012,8 @@ xpc_discovery(void)
1001 enum xpc_retval ret; 1012 enum xpc_retval ret;
1002 1013
1003 1014
1004 remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE, 1015 remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
1016 xp_nasid_mask_bytes,
1005 GFP_KERNEL, &remote_rp_base); 1017 GFP_KERNEL, &remote_rp_base);
1006 if (remote_rp == NULL) { 1018 if (remote_rp == NULL) {
1007 return; 1019 return;
@@ -1009,13 +1021,13 @@ xpc_discovery(void)
1009 remote_vars = (struct xpc_vars *) remote_rp; 1021 remote_vars = (struct xpc_vars *) remote_rp;
1010 1022
1011 1023
1012 discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS, 1024 discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words,
1013 GFP_KERNEL); 1025 GFP_KERNEL);
1014 if (discovered_nasids == NULL) { 1026 if (discovered_nasids == NULL) {
1015 kfree(remote_rp_base); 1027 kfree(remote_rp_base);
1016 return; 1028 return;
1017 } 1029 }
1018 memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS); 1030 memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
1019 1031
1020 rp = (struct xpc_rsvd_page *) xpc_rsvd_page; 1032 rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
1021 1033
@@ -1024,11 +1036,19 @@ xpc_discovery(void)
1024 * nodes that can comprise an access protection grouping. The access 1036 * nodes that can comprise an access protection grouping. The access
1025 * protection is in regards to memory, IOI and IPI. 1037 * protection is in regards to memory, IOI and IPI.
1026 */ 1038 */
1027//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or 1039 max_regions = 64;
1028//>>> include/asm-ia64/sn/addrs.h 1040 region_size = sn_region_size;
1029#define SH1_MAX_REGIONS 64 1041
1030#define SH2_MAX_REGIONS 256 1042 switch (region_size) {
1031 max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS; 1043 case 128:
1044 max_regions *= 2;
1045 case 64:
1046 max_regions *= 2;
1047 case 32:
1048 max_regions *= 2;
1049 region_size = 16;
1050 DBUG_ON(!is_shub2());
1051 }
1032 1052
1033 for (region = 0; region < max_regions; region++) { 1053 for (region = 0; region < max_regions; region++) {
1034 1054
@@ -1038,8 +1058,8 @@ xpc_discovery(void)
1038 1058
1039 dev_dbg(xpc_part, "searching region %d\n", region); 1059 dev_dbg(xpc_part, "searching region %d\n", region);
1040 1060
1041 for (nasid = (region * sn_region_size * 2); 1061 for (nasid = (region * region_size * 2);
1042 nasid < ((region + 1) * sn_region_size * 2); 1062 nasid < ((region + 1) * region_size * 2);
1043 nasid += 2) { 1063 nasid += 2) {
1044 1064
1045 if ((volatile int) xpc_exiting) { 1065 if ((volatile int) xpc_exiting) {
@@ -1049,14 +1069,14 @@ xpc_discovery(void)
1049 dev_dbg(xpc_part, "checking nasid %d\n", nasid); 1069 dev_dbg(xpc_part, "checking nasid %d\n", nasid);
1050 1070
1051 1071
1052 if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) { 1072 if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
1053 dev_dbg(xpc_part, "PROM indicates Nasid %d is " 1073 dev_dbg(xpc_part, "PROM indicates Nasid %d is "
1054 "part of the local partition; skipping " 1074 "part of the local partition; skipping "
1055 "region\n", nasid); 1075 "region\n", nasid);
1056 break; 1076 break;
1057 } 1077 }
1058 1078
1059 if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) { 1079 if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
1060 dev_dbg(xpc_part, "PROM indicates Nasid %d was " 1080 dev_dbg(xpc_part, "PROM indicates Nasid %d was "
1061 "not on Numa-Link network at reset\n", 1081 "not on Numa-Link network at reset\n",
1062 nasid); 1082 nasid);
@@ -1178,12 +1198,12 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
1178 return xpcPartitionDown; 1198 return xpcPartitionDown;
1179 } 1199 }
1180 1200
1181 part_nasid_pa = part->remote_rp_pa + 1201 memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
1182 (u64) &((struct xpc_rsvd_page *) 0)->part_nasids; 1202
1203 part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
1183 1204
1184 bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask), 1205 bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
1185 L1_CACHE_ALIGN(XP_NASID_MASK_BYTES), 1206 xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
1186 (BTE_NOTIFY | BTE_WACQUIRE), NULL);
1187 1207
1188 return xpc_map_bte_errors(bte_res); 1208 return xpc_map_bte_errors(bte_res);
1189} 1209}