|
@@ -47,13 +47,16 @@ static u64 xpc_sh2_IPI_access3;
|
|
|
u64 xpc_prot_vec[MAX_COMPACT_NODES];
|
|
|
|
|
|
|
|
|
-/* this partition's reserved page */
|
|
|
+/* this partition's reserved page pointers */
|
|
|
struct xpc_rsvd_page *xpc_rsvd_page;
|
|
|
-
|
|
|
-/* this partition's XPC variables (within the reserved page) */
|
|
|
+static u64 *xpc_part_nasids;
|
|
|
+static u64 *xpc_mach_nasids;
|
|
|
struct xpc_vars *xpc_vars;
|
|
|
struct xpc_vars_part *xpc_vars_part;
|
|
|
|
|
|
+static int xp_nasid_mask_bytes; /* actual size in bytes of nasid mask */
|
|
|
+static int xp_nasid_mask_words; /* actual size in words of nasid mask */
|
|
|
+
|
|
|
|
|
|
/*
|
|
|
* For performance reasons, each entry of xpc_partitions[] is cacheline
|
|
@@ -65,15 +68,16 @@ struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
|
|
|
|
|
|
|
|
|
/*
|
|
|
- * Generic buffer used to store a local copy of the remote partitions
|
|
|
- * reserved page or XPC variables.
|
|
|
+ * Generic buffer used to store a local copy of portions of a remote
|
|
|
+ * partition's reserved page (either its header and part_nasids mask,
|
|
|
+ * or its vars).
|
|
|
*
|
|
|
* xpc_discovery runs only once and is a seperate thread that is
|
|
|
* very likely going to be processing in parallel with receiving
|
|
|
* interrupts.
|
|
|
*/
|
|
|
-char ____cacheline_aligned
|
|
|
- xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE];
|
|
|
+char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
|
|
|
+ XP_NASID_MASK_BYTES];
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -136,7 +140,7 @@ xpc_rsvd_page_init(void)
|
|
|
{
|
|
|
struct xpc_rsvd_page *rp;
|
|
|
AMO_t *amos_page;
|
|
|
- u64 rp_pa, next_cl, nasid_array = 0;
|
|
|
+ u64 rp_pa, nasid_array = 0;
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
@@ -144,7 +148,8 @@ xpc_rsvd_page_init(void)
|
|
|
|
|
|
rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),
|
|
|
(u64) xpc_remote_copy_buffer,
|
|
|
- XPC_RSVD_PAGE_ALIGNED_SIZE);
|
|
|
+ XPC_RP_HEADER_SIZE +
|
|
|
+ L1_CACHE_BYTES);
|
|
|
if (rp_pa == 0) {
|
|
|
dev_err(xpc_part, "SAL failed to locate the reserved page\n");
|
|
|
return NULL;
|
|
@@ -159,12 +164,19 @@ xpc_rsvd_page_init(void)
|
|
|
|
|
|
rp->version = XPC_RP_VERSION;
|
|
|
|
|
|
- /*
|
|
|
- * Place the XPC variables on the cache line following the
|
|
|
- * reserved page structure.
|
|
|
- */
|
|
|
- next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE;
|
|
|
- xpc_vars = (struct xpc_vars *) next_cl;
|
|
|
+ /* establish the actual sizes of the nasid masks */
|
|
|
+ if (rp->SAL_version == 1) {
|
|
|
+ /* SAL_version 1 didn't set the nasids_size field */
|
|
|
+ rp->nasids_size = 128;
|
|
|
+ }
|
|
|
+ xp_nasid_mask_bytes = rp->nasids_size;
|
|
|
+ xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
|
|
|
+
|
|
|
+ /* setup the pointers to the various items in the reserved page */
|
|
|
+ xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
|
|
|
+ xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
|
|
|
+ xpc_vars = XPC_RP_VARS(rp);
|
|
|
+ xpc_vars_part = XPC_RP_VARS_PART(rp);
|
|
|
|
|
|
/*
|
|
|
* Before clearing xpc_vars, see if a page of AMOs had been previously
|
|
@@ -216,26 +228,23 @@ xpc_rsvd_page_init(void)
|
|
|
amos_page = (AMO_t *) TO_AMO((u64) amos_page);
|
|
|
}
|
|
|
|
|
|
+ /* clear xpc_vars */
|
|
|
memset(xpc_vars, 0, sizeof(struct xpc_vars));
|
|
|
|
|
|
- /*
|
|
|
- * Place the XPC per partition specific variables on the cache line
|
|
|
- * following the XPC variables structure.
|
|
|
- */
|
|
|
- next_cl += XPC_VARS_ALIGNED_SIZE;
|
|
|
- memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *
|
|
|
- XP_MAX_PARTITIONS);
|
|
|
- xpc_vars_part = (struct xpc_vars_part *) next_cl;
|
|
|
- xpc_vars->vars_part_pa = __pa(next_cl);
|
|
|
-
|
|
|
xpc_vars->version = XPC_V_VERSION;
|
|
|
xpc_vars->act_nasid = cpuid_to_nasid(0);
|
|
|
xpc_vars->act_phys_cpuid = cpu_physical_id(0);
|
|
|
+ xpc_vars->vars_part_pa = __pa(xpc_vars_part);
|
|
|
+ xpc_vars->amos_page_pa = ia64_tpa((u64) amos_page);
|
|
|
xpc_vars->amos_page = amos_page; /* save for next load of XPC */
|
|
|
|
|
|
|
|
|
+ /* clear xpc_vars_part */
|
|
|
+ memset((u64 *) xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
|
|
|
+ XP_MAX_PARTITIONS);
|
|
|
+
|
|
|
/* initialize the activate IRQ related AMO variables */
|
|
|
- for (i = 0; i < XP_NASID_MASK_WORDS; i++) {
|
|
|
+ for (i = 0; i < xp_nasid_mask_words; i++) {
|
|
|
(void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
|
|
|
}
|
|
|
|
|
@@ -243,10 +252,7 @@ xpc_rsvd_page_init(void)
|
|
|
(void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
|
|
|
(void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
|
|
|
|
|
|
- /* export AMO page's physical address to other partitions */
|
|
|
- xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);
|
|
|
-
|
|
|
- /* timestamp of when reserved page was initialized */
|
|
|
+ /* timestamp of when reserved page was setup by XPC */
|
|
|
rp->stamp = CURRENT_TIME;
|
|
|
|
|
|
/*
|
|
@@ -406,7 +412,7 @@ xpc_check_remote_hb(void)
|
|
|
/* pull the remote_hb cache line */
|
|
|
bres = xp_bte_copy(part->remote_vars_pa,
|
|
|
ia64_tpa((u64) remote_vars),
|
|
|
- XPC_VARS_ALIGNED_SIZE,
|
|
|
+ XPC_RP_VARS_SIZE,
|
|
|
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
|
|
if (bres != BTE_SUCCESS) {
|
|
|
XPC_DEACTIVATE_PARTITION(part,
|
|
@@ -434,10 +440,11 @@ xpc_check_remote_hb(void)
|
|
|
|
|
|
|
|
|
/*
|
|
|
- * Get a copy of the remote partition's rsvd page.
|
|
|
+ * Get a copy of a portion of the remote partition's rsvd page.
|
|
|
*
|
|
|
* remote_rp points to a buffer that is cacheline aligned for BTE copies and
|
|
|
- * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE.
|
|
|
+ * is large enough to contain a copy of their reserved page header and
|
|
|
+ * part_nasids mask.
|
|
|
*/
|
|
|
static enum xpc_retval
|
|
|
xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
|
|
@@ -449,16 +456,17 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
|
|
|
/* get the reserved page's physical address */
|
|
|
|
|
|
*remote_rp_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,
|
|
|
- XPC_RSVD_PAGE_ALIGNED_SIZE);
|
|
|
+ XPC_RP_HEADER_SIZE +
|
|
|
+ xp_nasid_mask_bytes);
|
|
|
if (*remote_rp_pa == 0) {
|
|
|
return xpcNoRsvdPageAddr;
|
|
|
}
|
|
|
|
|
|
|
|
|
- /* pull over the reserved page structure */
|
|
|
+ /* pull over the reserved page header and part_nasids mask */
|
|
|
|
|
|
bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
|
|
|
- XPC_RSVD_PAGE_ALIGNED_SIZE,
|
|
|
+ XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
|
|
|
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
|
|
if (bres != BTE_SUCCESS) {
|
|
|
return xpc_map_bte_errors(bres);
|
|
@@ -466,8 +474,11 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
|
|
|
|
|
|
|
|
|
if (discovered_nasids != NULL) {
|
|
|
- for (i = 0; i < XP_NASID_MASK_WORDS; i++) {
|
|
|
- discovered_nasids[i] |= remote_rp->part_nasids[i];
|
|
|
+ u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
|
|
|
+
|
|
|
+
|
|
|
+ for (i = 0; i < xp_nasid_mask_words; i++) {
|
|
|
+ discovered_nasids[i] |= remote_part_nasids[i];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -494,10 +505,10 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
|
|
|
|
|
|
|
|
|
/*
|
|
|
- * Get a copy of the remote partition's XPC variables.
|
|
|
+ * Get a copy of the remote partition's XPC variables from the reserved page.
|
|
|
*
|
|
|
* remote_vars points to a buffer that is cacheline aligned for BTE copies and
|
|
|
- * assumed to be of size XPC_VARS_ALIGNED_SIZE.
|
|
|
+ * assumed to be of size XPC_RP_VARS_SIZE.
|
|
|
*/
|
|
|
static enum xpc_retval
|
|
|
xpc_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)
|
|
|
/* pull over the cross partition variables */
|
|
|
|
|
|
bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
|
|
|
- XPC_VARS_ALIGNED_SIZE,
|
|
|
+ XPC_RP_VARS_SIZE,
|
|
|
(BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
|
|
if (bres != BTE_SUCCESS) {
|
|
|
return xpc_map_bte_errors(bres);
|
|
@@ -778,14 +789,13 @@ xpc_identify_act_IRQ_sender(void)
|
|
|
u64 nasid; /* remote nasid */
|
|
|
int n_IRQs_detected = 0;
|
|
|
AMO_t *act_amos;
|
|
|
- struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
|
|
|
|
|
|
|
|
|
act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
|
|
|
|
|
|
|
|
|
/* scan through act AMO variable looking for non-zero entries */
|
|
|
- for (word = 0; word < XP_NASID_MASK_WORDS; word++) {
|
|
|
+ for (word = 0; word < xp_nasid_mask_words; word++) {
|
|
|
|
|
|
if (xpc_exiting) {
|
|
|
break;
|
|
@@ -807,7 +817,7 @@ xpc_identify_act_IRQ_sender(void)
|
|
|
* remote nasid in our reserved pages machine mask.
|
|
|
* This is used in the event of module reload.
|
|
|
*/
|
|
|
- rp->mach_nasids[word] |= nasid_mask;
|
|
|
+ xpc_mach_nasids[word] |= nasid_mask;
|
|
|
|
|
|
|
|
|
/* locate the nasid(s) which sent interrupts */
|
|
@@ -992,6 +1002,7 @@ xpc_discovery(void)
|
|
|
u64 remote_rp_pa;
|
|
|
u64 remote_vars_pa;
|
|
|
int region;
|
|
|
+ int region_size;
|
|
|
int max_regions;
|
|
|
int nasid;
|
|
|
struct xpc_rsvd_page *rp;
|
|
@@ -1001,7 +1012,8 @@ xpc_discovery(void)
|
|
|
enum xpc_retval ret;
|
|
|
|
|
|
|
|
|
- remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE,
|
|
|
+ remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
|
|
|
+ xp_nasid_mask_bytes,
|
|
|
GFP_KERNEL, &remote_rp_base);
|
|
|
if (remote_rp == NULL) {
|
|
|
return;
|
|
@@ -1009,13 +1021,13 @@ xpc_discovery(void)
|
|
|
remote_vars = (struct xpc_vars *) remote_rp;
|
|
|
|
|
|
|
|
|
- discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS,
|
|
|
+ discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words,
|
|
|
GFP_KERNEL);
|
|
|
if (discovered_nasids == NULL) {
|
|
|
kfree(remote_rp_base);
|
|
|
return;
|
|
|
}
|
|
|
- memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS);
|
|
|
+ memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
|
|
|
|
|
|
rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
|
|
|
|
|
@@ -1024,11 +1036,19 @@ xpc_discovery(void)
|
|
|
* nodes that can comprise an access protection grouping. The access
|
|
|
* protection is in regards to memory, IOI and IPI.
|
|
|
*/
|
|
|
-//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or
|
|
|
-//>>> include/asm-ia64/sn/addrs.h
|
|
|
-#define SH1_MAX_REGIONS 64
|
|
|
-#define SH2_MAX_REGIONS 256
|
|
|
- max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS;
|
|
|
+ max_regions = 64;
|
|
|
+ region_size = sn_region_size;
|
|
|
+
|
|
|
+ switch (region_size) {
|
|
|
+ case 128:
|
|
|
+ max_regions *= 2;
|
|
|
+ case 64:
|
|
|
+ max_regions *= 2;
|
|
|
+ case 32:
|
|
|
+ max_regions *= 2;
|
|
|
+ region_size = 16;
|
|
|
+ DBUG_ON(!is_shub2());
|
|
|
+ }
|
|
|
|
|
|
for (region = 0; region < max_regions; region++) {
|
|
|
|
|
@@ -1038,8 +1058,8 @@ xpc_discovery(void)
|
|
|
|
|
|
dev_dbg(xpc_part, "searching region %d\n", region);
|
|
|
|
|
|
- for (nasid = (region * sn_region_size * 2);
|
|
|
- nasid < ((region + 1) * sn_region_size * 2);
|
|
|
+ for (nasid = (region * region_size * 2);
|
|
|
+ nasid < ((region + 1) * region_size * 2);
|
|
|
nasid += 2) {
|
|
|
|
|
|
if ((volatile int) xpc_exiting) {
|
|
@@ -1049,14 +1069,14 @@ xpc_discovery(void)
|
|
|
dev_dbg(xpc_part, "checking nasid %d\n", nasid);
|
|
|
|
|
|
|
|
|
- if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) {
|
|
|
+ if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
|
|
|
dev_dbg(xpc_part, "PROM indicates Nasid %d is "
|
|
|
"part of the local partition; skipping "
|
|
|
"region\n", nasid);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) {
|
|
|
+ if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
|
|
|
dev_dbg(xpc_part, "PROM indicates Nasid %d was "
|
|
|
"not on Numa-Link network at reset\n",
|
|
|
nasid);
|
|
@@ -1178,12 +1198,12 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
|
|
|
return xpcPartitionDown;
|
|
|
}
|
|
|
|
|
|
- part_nasid_pa = part->remote_rp_pa +
|
|
|
- (u64) &((struct xpc_rsvd_page *) 0)->part_nasids;
|
|
|
+ memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
|
|
|
+
|
|
|
+ part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
|
|
|
|
|
|
bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
|
|
|
- L1_CACHE_ALIGN(XP_NASID_MASK_BYTES),
|
|
|
- (BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
|
|
+ xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
|
|
|
|
|
|
return xpc_map_bte_errors(bte_res);
|
|
|
}
|