Skip to contentSkip to conversation

Subject: x86, UV: fixes to tlb shootdown

PATCH In review [email protected] 1 participant 17 messages Jun 21, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v5 cover Subject: x86, UV: fixes to tlb shootdown

Version 1 was a series of 6 patches, submitted Jun14 2011.

Version 2 of this series: 8 patches
- Adds more explanation to "UV: smp_processor_id in a preemptable region"
- Splits "UV: correct reset_with_ipi()" into its 3 logical changes
- Adds statement of importance to "UV: correct UV2 BAU destination timeout"

Version 3 of this series:
- Uses get_cpu()/put_cpu() to bound the region in which cpu number is used in "UV: smp_processor_id in a preemptable region"

Version 4 of this series:
- cc's [email protected]
- Moves non-change notes out of the changelog text

Version 5 of this series:
- removes the Diffed against tags

[PATCH 1/8 v5] x86, UV: smp_processor_id in a preemptable region [PATCH 2/8 v5] x86, UV: inline header file functions [PATCH 3/8 v5] x86, UV: allow for non-consecutive sockets [PATCH 4/8 v5] x86, UV: correct reset_with_ipi() [PATCH 5/8 v5] x86, UV: rename hubmask to pnmask [PATCH 6/8 v5] x86, UV: remove cpumask_t from the stack [PATCH 7/8 v5] x86, UV: correct failed topology memory leak [PATCH 8/8 v5] x86, UV: correct UV2 BAU destination timeout

Signature · 4 lines
Cliff Wickman
SGI
[email protected]
(651) 683-3824
#1 lore raw

PATCH v5 1/8 x86, UV: smp_processor_id in a preemptable region

Fix a call by tunables_write() to smp_processor_id() within a preemptable region.
Call get_cpu()/put_cpu() around the region where the returned cpu number is actually used, which makes it non-preemptable.

---

A DEBUG_PREEMPT warning is prevented.
UV does not support cpu hotplug yet, but this is a step toward that ability.

 arch/x86/platform/uv/tlb_uv.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/platform/uv/tlb_uv.c +3 -2
Index: linux/arch/x86/platform/uv/tlb_uv.c
===================================================================
@@ -1334,9 +1334,10 @@ static ssize_t tunables_write(struct fil
 
 	instr[count] = '\0';
 
-	bcp = &per_cpu(bau_control, smp_processor_id());
-
+	cpu = get_cpu();
+	bcp = &per_cpu(bau_control, cpu);
 	ret = parse_tunables_write(bcp, instr, count);
+	put_cpu();
 	if (ret)
 		return ret;
 
#2 lore raw

[tip:x86/uv] x86, UV: Fix smp_processor_id() use in a preemptable region

Commit-ID:  00b30cf04a775b5292ab704f782394e36e25617d
Gitweb:     http://git.kernel.org/tip/00b30cf04a775b5292ab704f782394e36e25617d
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:26 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:31 +0200

x86, UV: Fix smp_processor_id() use in a preemptable region

Fix a call by tunables_write() to smp_processor_id() within a preemptable region.

Call get_cpu()/put_cpu() around the region where the returned cpu number is actually used, which makes it non-preemptable.

A DEBUG_PREEMPT warning is prevented.

UV does not support cpu hotplug yet, but this is a step toward that ability as well.

---
 arch/x86/platform/uv/tlb_uv.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/platform/uv/tlb_uv.c +3 -2
index 68e467f..34be650 100644
@@ -1334,9 +1334,10 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
 
 	instr[count] = '\0';
 
-	bcp = &per_cpu(bau_control, smp_processor_id());
-
+	cpu = get_cpu();
+	bcp = &per_cpu(bau_control, cpu);
 	ret = parse_tunables_write(bcp, instr, count);
+	put_cpu();
 	if (ret)
 		return ret;
 
#3 lore raw

PATCH v5 2/8 x86, UV: inline header file functions

In reply to [email protected]

Make all the functions in uv_bau.h inline so that it can be included in the fake prom (used in simulations).

---

If not inlined the unused functions will generate compiler warnings.

 arch/x86/include/asm/uv/uv_bau.h |   28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +14 -14
Index: linux/arch/x86/include/asm/uv/uv_bau.h
===================================================================
@@ -526,72 +526,72 @@ struct bau_control {
 	struct hub_and_pnode	*thp;
 };
 
-static unsigned long read_mmr_uv2_status(void)
+static inline unsigned long read_mmr_uv2_status(void)
 {
 	return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
 }
 
-static void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
+static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
 }
 
-static void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
+static inline void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, mmr_image);
 }
 
-static void write_mmr_activation(unsigned long index)
+static inline void write_mmr_activation(unsigned long index)
 {
 	write_lmmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
 }
 
-static void write_gmmr_activation(int pnode, unsigned long mmr_image)
+static inline void write_gmmr_activation(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image);
 }
 
-static void write_mmr_payload_first(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image);
 }
 
-static void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, mmr_image);
 }
 
-static void write_mmr_payload_last(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_last(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST, mmr_image);
 }
 
-static void write_mmr_misc_control(int pnode, unsigned long mmr_image)
+static inline void write_mmr_misc_control(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
 }
 
-static unsigned long read_mmr_misc_control(int pnode)
+static inline unsigned long read_mmr_misc_control(int pnode)
 {
 	return read_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL);
 }
 
-static void write_mmr_sw_ack(unsigned long mr)
+static inline void write_mmr_sw_ack(unsigned long mr)
 {
 	uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
 }
 
-static unsigned long read_mmr_sw_ack(void)
+static inline unsigned long read_mmr_sw_ack(void)
 {
 	return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
 }
 
-static unsigned long read_gmmr_sw_ack(int pnode)
+static inline unsigned long read_gmmr_sw_ack(int pnode)
 {
 	return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
 }
 
-static void write_mmr_data_config(int pnode, unsigned long mr)
+static inline void write_mmr_data_config(int pnode, unsigned long mr)
 {
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
 }
#4 lore raw

[tip:x86/uv] x86, UV: Inline header file functions

Commit-ID:  b18fb2c04ac46885f5b0226cd945e763eae51567
Gitweb:     http://git.kernel.org/tip/b18fb2c04ac46885f5b0226cd945e763eae51567
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:27 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:31 +0200

x86, UV: Inline header file functions

Make all the functions in uv_bau.h inline so that it can be included in the fake prom (used in simulations).

If not inlined the unused functions will generate compiler warnings.

---
 arch/x86/include/asm/uv/uv_bau.h |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +14 -14
index a291c40..605e613 100644
@@ -526,72 +526,72 @@ struct bau_control {
 	struct hub_and_pnode	*thp;
 };
 
-static unsigned long read_mmr_uv2_status(void)
+static inline unsigned long read_mmr_uv2_status(void)
 {
 	return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
 }
 
-static void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
+static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
 }
 
-static void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
+static inline void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, mmr_image);
 }
 
-static void write_mmr_activation(unsigned long index)
+static inline void write_mmr_activation(unsigned long index)
 {
 	write_lmmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
 }
 
-static void write_gmmr_activation(int pnode, unsigned long mmr_image)
+static inline void write_gmmr_activation(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image);
 }
 
-static void write_mmr_payload_first(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image);
 }
 
-static void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, mmr_image);
 }
 
-static void write_mmr_payload_last(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_last(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST, mmr_image);
 }
 
-static void write_mmr_misc_control(int pnode, unsigned long mmr_image)
+static inline void write_mmr_misc_control(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
 }
 
-static unsigned long read_mmr_misc_control(int pnode)
+static inline unsigned long read_mmr_misc_control(int pnode)
 {
 	return read_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL);
 }
 
-static void write_mmr_sw_ack(unsigned long mr)
+static inline void write_mmr_sw_ack(unsigned long mr)
 {
 	uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
 }
 
-static unsigned long read_mmr_sw_ack(void)
+static inline unsigned long read_mmr_sw_ack(void)
 {
 	return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
 }
 
-static unsigned long read_gmmr_sw_ack(int pnode)
+static inline unsigned long read_gmmr_sw_ack(int pnode)
 {
 	return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
 }
 
-static void write_mmr_data_config(int pnode, unsigned long mr)
+static inline void write_mmr_data_config(int pnode, unsigned long mr)
 {
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
 }
#5 lore raw

PATCH v5 3/8 x86, UV: allow for non-consecutive sockets

In reply to [email protected]

Fix for the topology in which there is a socket 1 on a blade with no socket 0.

---

Only call make_per_cpu_thp() for present sockets. We have only seen this fail for internal configurations.

 arch/x86/platform/uv/tlb_uv.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/platform/uv/tlb_uv.c +1 -1
Index: linux/arch/x86/platform/uv/tlb_uv.c
===================================================================
@@ -1752,10 +1752,10 @@ static int __init summarize_uvhub_socket
 				sdp = &bdp->socket[socket];
 				if (scan_sock(sdp, bdp, &smaster, &hmaster))
 					return 1;
+				make_per_cpu_thp(smaster);
 			}
 			socket++;
 			socket_mask = (socket_mask >> 1);
-			make_per_cpu_thp(smaster);
 		}
 	}
 	return 0;
#6 lore raw

[tip:x86/uv] x86, UV: Allow for non-consecutive sockets

Commit-ID:  9c9153db22870c3f37add83bea30500fcc268a73
Gitweb:     http://git.kernel.org/tip/9c9153db22870c3f37add83bea30500fcc268a73
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:28 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:32 +0200

x86, UV: Allow for non-consecutive sockets

Fix for the topology in which there is a socket 1 on a blade with no socket 0.

Only call make_per_cpu_thp() for present sockets. We have only seen this fail for internal configurations.

---
 arch/x86/platform/uv/tlb_uv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/platform/uv/tlb_uv.c +1 -1
index 34be650..7623b08 100644
@@ -1752,10 +1752,10 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
 				sdp = &bdp->socket[socket];
 				if (scan_sock(sdp, bdp, &smaster, &hmaster))
 					return 1;
+				make_per_cpu_thp(smaster);
 			}
 			socket++;
 			socket_mask = (socket_mask >> 1);
-			make_per_cpu_thp(smaster);
 		}
 	}
 	return 0;
#7 lore raw

PATCH v5 4/8 x86, UV: correct reset_with_ipi()

In reply to [email protected]

Fix reset_with_ipi() to look up a cpu for a blade based on the distribution map being indexed by the potentially sparsely numbered pnode.

This patch is critical to tlb shootdown on a partitioned UV system, or one with nonconsecutive blade numbers.

---

The distribution map bits represent pnodes relative to the partition base pnode. Previous to this patch it had been assuming bits based on 0-based, consecutive blade ids.

 arch/x86/platform/uv/tlb_uv.c |   33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)
arch/x86/platform/uv/tlb_uv.c +21 -12
Index: linux/arch/x86/platform/uv/tlb_uv.c
===================================================================
@@ -296,14 +296,18 @@ static void bau_process_message(struct m
 }
 
 /*
- * Determine the first cpu on a uvhub.
+ * Determine the first cpu on a pnode.
  */
-static int uvhub_to_first_cpu(int uvhub)
+static int pnode_to_first_cpu(int pnode, struct bau_control *smaster)
 {
 	int cpu;
-	for_each_present_cpu(cpu)
-		if (uvhub == uv_cpu_to_blade_id(cpu))
+	struct hub_and_pnode *hpp;
+
+	for_each_present_cpu(cpu) {
+		hpp = &smaster->thp[cpu];
+		if (pnode == hpp->pnode)
 			return cpu;
+	}
 	return -1;
 }
 
@@ -366,23 +370,28 @@ static void do_reset(void *ptr)
  * Use IPI to get all target uvhubs to release resources held by
  * a given sending cpu number.
  */
-static void reset_with_ipi(struct bau_targ_hubmask *distribution, int sender)
+static void reset_with_ipi(struct bau_targ_hubmask *distribution,
+						struct bau_control *bcp)
 {
-	int uvhub;
+	int pnode;
+	int apnode;
 	int maskbits;
 	cpumask_t mask;
+	int sender = bcp->cpu;
+	struct bau_control *smaster = bcp->socket_master;
 	struct reset_args reset_args;
 
 	reset_args.sender = sender;
 	cpus_clear(mask);
 	/* find a single cpu for each uvhub in this distribution mask */
 	maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE;
-	for (uvhub = 0; uvhub < maskbits; uvhub++) {
+	/* each bit is a pnode relative to the partition base pnode */
+	for (pnode = 0; pnode < maskbits; pnode++) {
 		int cpu;
-		if (!bau_uvhub_isset(uvhub, distribution))
+		if (!bau_uvhub_isset(pnode, distribution))
 			continue;
-		/* find a cpu for this uvhub */
-		cpu = uvhub_to_first_cpu(uvhub);
+		apnode = pnode + bcp->partition_base_pnode;
+		cpu = pnode_to_first_cpu(apnode, smaster);
 		cpu_set(cpu, mask);
 	}
 
@@ -604,7 +613,7 @@ static void destination_plugged(struct b
 		quiesce_local_uvhub(hmaster);
 
 		spin_lock(&hmaster->queue_lock);
-		reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+		reset_with_ipi(&bau_desc->distribution, bcp);
 		spin_unlock(&hmaster->queue_lock);
 
 		end_uvhub_quiesce(hmaster);
@@ -626,7 +635,7 @@ static void destination_timeout(struct b
 		quiesce_local_uvhub(hmaster);
 
 		spin_lock(&hmaster->queue_lock);
-		reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+		reset_with_ipi(&bau_desc->distribution, bcp);
 		spin_unlock(&hmaster->queue_lock);
 
 		end_uvhub_quiesce(hmaster);
#8 lore raw

[tip:x86/uv] x86, UV: Correct reset_with_ipi()

Commit-ID:  485f07d349a3e5059413b886a3bc1996c4b3d14d
Gitweb:     http://git.kernel.org/tip/485f07d349a3e5059413b886a3bc1996c4b3d14d
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:29 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:32 +0200

x86, UV: Correct reset_with_ipi()

Fix reset_with_ipi() to look up a cpu for a blade based on the distribution map being indexed by the potentially sparsely numbered pnode.

This patch is critical to tlb shootdown on a partitioned UV system, or one with nonconsecutive blade numbers.

The distribution map bits represent pnodes relative to the partition base pnode. Previous to this patch it had been assuming bits based on 0-based, consecutive blade ids.

---
 arch/x86/platform/uv/tlb_uv.c |   33 +++++++++++++++++++++------------
 1 files changed, 21 insertions(+), 12 deletions(-)
arch/x86/platform/uv/tlb_uv.c +21 -12
index 7623b08..4b28e09 100644
@@ -296,14 +296,18 @@ static void bau_process_message(struct msg_desc *mdp,
 }
 
 /*
- * Determine the first cpu on a uvhub.
+ * Determine the first cpu on a pnode.
  */
-static int uvhub_to_first_cpu(int uvhub)
+static int pnode_to_first_cpu(int pnode, struct bau_control *smaster)
 {
 	int cpu;
-	for_each_present_cpu(cpu)
-		if (uvhub == uv_cpu_to_blade_id(cpu))
+	struct hub_and_pnode *hpp;
+
+	for_each_present_cpu(cpu) {
+		hpp = &smaster->thp[cpu];
+		if (pnode == hpp->pnode)
 			return cpu;
+	}
 	return -1;
 }
 
@@ -366,23 +370,28 @@ static void do_reset(void *ptr)
  * Use IPI to get all target uvhubs to release resources held by
  * a given sending cpu number.
  */
-static void reset_with_ipi(struct bau_targ_hubmask *distribution, int sender)
+static void reset_with_ipi(struct bau_targ_hubmask *distribution,
+						struct bau_control *bcp)
 {
-	int uvhub;
+	int pnode;
+	int apnode;
 	int maskbits;
 	cpumask_t mask;
+	int sender = bcp->cpu;
+	struct bau_control *smaster = bcp->socket_master;
 	struct reset_args reset_args;
 
 	reset_args.sender = sender;
 	cpus_clear(mask);
 	/* find a single cpu for each uvhub in this distribution mask */
 	maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE;
-	for (uvhub = 0; uvhub < maskbits; uvhub++) {
+	/* each bit is a pnode relative to the partition base pnode */
+	for (pnode = 0; pnode < maskbits; pnode++) {
 		int cpu;
-		if (!bau_uvhub_isset(uvhub, distribution))
+		if (!bau_uvhub_isset(pnode, distribution))
 			continue;
-		/* find a cpu for this uvhub */
-		cpu = uvhub_to_first_cpu(uvhub);
+		apnode = pnode + bcp->partition_base_pnode;
+		cpu = pnode_to_first_cpu(apnode, smaster);
 		cpu_set(cpu, mask);
 	}
 
@@ -604,7 +613,7 @@ static void destination_plugged(struct bau_desc *bau_desc,
 		quiesce_local_uvhub(hmaster);
 
 		spin_lock(&hmaster->queue_lock);
-		reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+		reset_with_ipi(&bau_desc->distribution, bcp);
 		spin_unlock(&hmaster->queue_lock);
 
 		end_uvhub_quiesce(hmaster);
@@ -626,7 +635,7 @@ static void destination_timeout(struct bau_desc *bau_desc,
 		quiesce_local_uvhub(hmaster);
 
 		spin_lock(&hmaster->queue_lock);
-		reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+		reset_with_ipi(&bau_desc->distribution, bcp);
 		spin_unlock(&hmaster->queue_lock);
 
 		end_uvhub_quiesce(hmaster);
#9 lore raw

PATCH v5 5/8 x86, UV: rename hubmask to pnmask

In reply to [email protected]

Rename 'bau_targ_hubmask' to 'pnmask' for clarity.

---

The BAU distribution bit mask is indexed by pnode number, not hub or blade number. This important fact is not clear while the mask is called a 'hubmask'.

 arch/x86/include/asm/uv/uv_bau.h |   12 ++++++------
 arch/x86/platform/uv/tlb_uv.c    |    5 ++---
 2 files changed, 8 insertions(+), 9 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +6 -6
Index: linux/arch/x86/include/asm/uv/uv_bau.h
===================================================================
@@ -183,7 +183,7 @@
  * 'base_dest_nasid' field of the header corresponds to the
  * destination nodeID associated with that specified bit.
  */
-struct bau_targ_hubmask {
+struct pnmask {
 	unsigned long		bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)];
 };
 
@@ -314,7 +314,7 @@ struct bau_msg_header {
  * Should be 64 bytes
  */
 struct bau_desc {
-	struct bau_targ_hubmask	distribution;
+	struct pnmask			distribution;
 	/*
 	 * message template, consisting of header and payload:
 	 */
@@ -596,20 +596,20 @@ static inline void write_mmr_data_config
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
 }
 
-static inline int bau_uvhub_isset(int uvhub, struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_isset(int uvhub, struct pnmask *dstp)
 {
 	return constant_test_bit(uvhub, &dstp->bits[0]);
 }
-static inline void bau_uvhub_set(int pnode, struct bau_targ_hubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct pnmask *dstp)
 {
 	__set_bit(pnode, &dstp->bits[0]);
 }
-static inline void bau_uvhubs_clear(struct bau_targ_hubmask *dstp,
+static inline void bau_uvhubs_clear(struct pnmask *dstp,
 				    int nbits)
 {
 	bitmap_zero(&dstp->bits[0], nbits);
 }
-static inline int bau_uvhub_weight(struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_weight(struct pnmask *dstp)
 {
 	return bitmap_weight((unsigned long *)&dstp->bits[0],
 				UV_DISTRIBUTION_SIZE);
arch/x86/platform/uv/tlb_uv.c +2 -3
Index: linux/arch/x86/platform/uv/tlb_uv.c
===================================================================
@@ -370,8 +370,7 @@ static void do_reset(void *ptr)
  * Use IPI to get all target uvhubs to release resources held by
  * a given sending cpu number.
  */
-static void reset_with_ipi(struct bau_targ_hubmask *distribution,
-						struct bau_control *bcp)
+static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
 {
 	int pnode;
 	int apnode;
@@ -384,7 +383,7 @@ static void reset_with_ipi(struct bau_ta
 	reset_args.sender = sender;
 	cpus_clear(mask);
 	/* find a single cpu for each uvhub in this distribution mask */
-	maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE;
+	maskbits = sizeof(struct pnmask) * BITSPERBYTE;
 	/* each bit is a pnode relative to the partition base pnode */
 	for (pnode = 0; pnode < maskbits; pnode++) {
 		int cpu;
#10 lore raw

[tip:x86/uv] x86, UV: Rename hubmask to pnmask

Commit-ID:  a456eaab87461e33d94e748565eabd474283a475
Gitweb:     http://git.kernel.org/tip/a456eaab87461e33d94e748565eabd474283a475
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:30 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:32 +0200

x86, UV: Rename hubmask to pnmask

Rename 'bau_targ_hubmask' to 'pnmask' for clarity.

The BAU distribution bit mask is indexed by pnode number, not hub or blade number. This important fact is not clear while the mask is called a 'hubmask'.

---
 arch/x86/include/asm/uv/uv_bau.h |   12 ++++++------
 arch/x86/platform/uv/tlb_uv.c    |    5 ++---
 2 files changed, 8 insertions(+), 9 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +6 -6
index 605e613..fa6a48e 100644
@@ -183,7 +183,7 @@
  * 'base_dest_nasid' field of the header corresponds to the
  * destination nodeID associated with that specified bit.
  */
-struct bau_targ_hubmask {
+struct pnmask {
 	unsigned long		bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)];
 };
 
@@ -314,7 +314,7 @@ struct bau_msg_header {
  * Should be 64 bytes
  */
 struct bau_desc {
-	struct bau_targ_hubmask	distribution;
+	struct pnmask			distribution;
 	/*
 	 * message template, consisting of header and payload:
 	 */
@@ -596,20 +596,20 @@ static inline void write_mmr_data_config(int pnode, unsigned long mr)
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
 }
 
-static inline int bau_uvhub_isset(int uvhub, struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_isset(int uvhub, struct pnmask *dstp)
 {
 	return constant_test_bit(uvhub, &dstp->bits[0]);
 }
-static inline void bau_uvhub_set(int pnode, struct bau_targ_hubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct pnmask *dstp)
 {
 	__set_bit(pnode, &dstp->bits[0]);
 }
-static inline void bau_uvhubs_clear(struct bau_targ_hubmask *dstp,
+static inline void bau_uvhubs_clear(struct pnmask *dstp,
 				    int nbits)
 {
 	bitmap_zero(&dstp->bits[0], nbits);
 }
-static inline int bau_uvhub_weight(struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_weight(struct pnmask *dstp)
 {
 	return bitmap_weight((unsigned long *)&dstp->bits[0],
 				UV_DISTRIBUTION_SIZE);
arch/x86/platform/uv/tlb_uv.c +2 -3
index 4b28e09..191ef28 100644
@@ -370,8 +370,7 @@ static void do_reset(void *ptr)
  * Use IPI to get all target uvhubs to release resources held by
  * a given sending cpu number.
  */
-static void reset_with_ipi(struct bau_targ_hubmask *distribution,
-						struct bau_control *bcp)
+static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
 {
 	int pnode;
 	int apnode;
@@ -384,7 +383,7 @@ static void reset_with_ipi(struct bau_targ_hubmask *distribution,
 	reset_args.sender = sender;
 	cpus_clear(mask);
 	/* find a single cpu for each uvhub in this distribution mask */
-	maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE;
+	maskbits = sizeof(struct pnmask) * BITSPERBYTE;
 	/* each bit is a pnode relative to the partition base pnode */
 	for (pnode = 0; pnode < maskbits; pnode++) {
 		int cpu;
#11 lore raw

PATCH v5 6/8 x86, UV: remove cpumask_t from the stack

In reply to [email protected]

Remove the large stack-resident cpumask_t from reset_with_ipi()'s stack by allocating one per uvhub.

---

Due to the limited size of the stack the potentially huge cpumask_t may cause stack overrun. We haven't seen it happen yet, but we need to make it a practice not to push such structures onto the stack.

 arch/x86/include/asm/uv/uv_bau.h |    1 +
 arch/x86/platform/uv/tlb_uv.c    |   19 +++++++++++++++----
 2 files changed, 16 insertions(+), 4 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +1 -0
Index: linux/arch/x86/include/asm/uv/uv_bau.h
===================================================================
@@ -488,6 +488,7 @@ struct bau_control {
 	struct bau_control	*uvhub_master;
 	struct bau_control	*socket_master;
 	struct ptc_stats	*statp;
+	cpumask_t		*cpumask;
 	unsigned long		timeout_interval;
 	unsigned long		set_bau_on_time;
 	atomic_t		active_descriptor_count;
arch/x86/platform/uv/tlb_uv.c +15 -4
Index: linux/arch/x86/platform/uv/tlb_uv.c
===================================================================
@@ -375,13 +375,13 @@ static void reset_with_ipi(struct pnmask
 	int pnode;
 	int apnode;
 	int maskbits;
-	cpumask_t mask;
 	int sender = bcp->cpu;
+	cpumask_t *mask = bcp->uvhub_master->cpumask;
 	struct bau_control *smaster = bcp->socket_master;
 	struct reset_args reset_args;
 
 	reset_args.sender = sender;
-	cpus_clear(mask);
+	cpus_clear(*mask);
 	/* find a single cpu for each uvhub in this distribution mask */
 	maskbits = sizeof(struct pnmask) * BITSPERBYTE;
 	/* each bit is a pnode relative to the partition base pnode */
@@ -391,11 +391,11 @@ static void reset_with_ipi(struct pnmask
 			continue;
 		apnode = pnode + bcp->partition_base_pnode;
 		cpu = pnode_to_first_cpu(apnode, smaster);
-		cpu_set(cpu, mask);
+		cpu_set(cpu, *mask);
 	}
 
 	/* IPI all cpus; preemption is already disabled */
-	smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1);
+	smp_call_function_many(mask, do_reset, (void *)&reset_args, 1);
 	return;
 }
 
@@ -1696,6 +1696,16 @@ static void make_per_cpu_thp(struct bau_
 }
 
 /*
+ * Each uvhub is to get a local cpumask.
+ */
+static void make_per_hub_cpumask(struct bau_control *hmaster)
+{
+	int sz = sizeof(cpumask_t);
+
+	hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode);
+}
+
+/*
  * Initialize all the per_cpu information for the cpu's on a given socket,
  * given what has been gathered into the socket_desc struct.
  * And reports the chosen hub and socket masters back to the caller.
@@ -1765,6 +1775,7 @@ static int __init summarize_uvhub_socket
 			socket++;
 			socket_mask = (socket_mask >> 1);
 		}
+		make_per_hub_cpumask(hmaster);
 	}
 	return 0;
 }
#12 lore raw

[tip:x86/uv] x86, UV: Remove cpumask_t from the stack

Commit-ID:  442d3924926c62741912d8a930220af253922007
Gitweb:     http://git.kernel.org/tip/442d3924926c62741912d8a930220af253922007
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:31 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:33 +0200

x86, UV: Remove cpumask_t from the stack

Remove the large stack-resident cpumask_t from reset_with_ipi()'s stack by allocating one per uvhub.

Due to the limited size of the stack the potentially huge cpumask_t may cause stack overrun. We haven't seen it happen yet, but we need to make it a practice not to push such structures onto the stack.

---
 arch/x86/include/asm/uv/uv_bau.h |    1 +
 arch/x86/platform/uv/tlb_uv.c    |   19 +++++++++++++++----
 2 files changed, 16 insertions(+), 4 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +1 -0
index fa6a48e..16ce58c 100644
@@ -488,6 +488,7 @@ struct bau_control {
 	struct bau_control	*uvhub_master;
 	struct bau_control	*socket_master;
 	struct ptc_stats	*statp;
+	cpumask_t		*cpumask;
 	unsigned long		timeout_interval;
 	unsigned long		set_bau_on_time;
 	atomic_t		active_descriptor_count;
arch/x86/platform/uv/tlb_uv.c +15 -4
index 191ef28..5265842 100644
@@ -375,13 +375,13 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
 	int pnode;
 	int apnode;
 	int maskbits;
-	cpumask_t mask;
 	int sender = bcp->cpu;
+	cpumask_t *mask = bcp->uvhub_master->cpumask;
 	struct bau_control *smaster = bcp->socket_master;
 	struct reset_args reset_args;
 
 	reset_args.sender = sender;
-	cpus_clear(mask);
+	cpus_clear(*mask);
 	/* find a single cpu for each uvhub in this distribution mask */
 	maskbits = sizeof(struct pnmask) * BITSPERBYTE;
 	/* each bit is a pnode relative to the partition base pnode */
@@ -391,11 +391,11 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
 			continue;
 		apnode = pnode + bcp->partition_base_pnode;
 		cpu = pnode_to_first_cpu(apnode, smaster);
-		cpu_set(cpu, mask);
+		cpu_set(cpu, *mask);
 	}
 
 	/* IPI all cpus; preemption is already disabled */
-	smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1);
+	smp_call_function_many(mask, do_reset, (void *)&reset_args, 1);
 	return;
 }
 
@@ -1696,6 +1696,16 @@ static void make_per_cpu_thp(struct bau_control *smaster)
 }
 
 /*
+ * Each uvhub is to get a local cpumask.
+ */
+static void make_per_hub_cpumask(struct bau_control *hmaster)
+{
+	int sz = sizeof(cpumask_t);
+
+	hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode);
+}
+
+/*
  * Initialize all the per_cpu information for the cpu's on a given socket,
  * given what has been gathered into the socket_desc struct.
  * And reports the chosen hub and socket masters back to the caller.
@@ -1765,6 +1775,7 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
 			socket++;
 			socket_mask = (socket_mask >> 1);
 		}
+		make_per_hub_cpumask(hmaster);
 	}
 	return 0;
 }
#13 lore raw

PATCH v5 7/8 x86, UV: correct failed topology memory leak

In reply to [email protected]

Fix a memory leak in init_per_cpu() when the topology check fails.

---

The leak should never occur after development. It would only occur in an unexpected topology that would make the BAU unuseable as a result.

 arch/x86/platform/uv/tlb_uv.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/platform/uv/tlb_uv.c +7 -2
Index: linux/arch/x86/platform/uv/tlb_uv.c
===================================================================
@@ -1797,15 +1797,20 @@ static int __init init_per_cpu(int nuvhu
 	uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
 
 	if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask))
-		return 1;
+		goto fail;
 
 	if (summarize_uvhub_sockets(nuvhubs, uvhub_descs, uvhub_mask))
-		return 1;
+		goto fail;
 
 	kfree(uvhub_descs);
 	kfree(uvhub_mask);
 	init_per_cpu_tunables();
 	return 0;
+
+fail:
+	kfree(uvhub_descs);
+	kfree(uvhub_mask);
+	return 1;
 }
 
 /*
#14 lore raw

[tip:x86/uv] x86, UV: Correct failed topology memory leak

Commit-ID:  bbd270e6f45a5ca30e1d3b6133c516a9dc9dd6c0
Gitweb:     http://git.kernel.org/tip/bbd270e6f45a5ca30e1d3b6133c516a9dc9dd6c0
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:32 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:33 +0200

x86, UV: Correct failed topology memory leak

Fix a memory leak in init_per_cpu() when the topology check fails.

The leak should never occur on deployed systems. It would only occur in an unexpected topology that would make the BAU unuseable as a result.

---
 arch/x86/platform/uv/tlb_uv.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
arch/x86/platform/uv/tlb_uv.c +7 -2
index 5265842..db8b915 100644
@@ -1797,15 +1797,20 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
 	uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
 
 	if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask))
-		return 1;
+		goto fail;
 
 	if (summarize_uvhub_sockets(nuvhubs, uvhub_descs, uvhub_mask))
-		return 1;
+		goto fail;
 
 	kfree(uvhub_descs);
 	kfree(uvhub_mask);
 	init_per_cpu_tunables();
 	return 0;
+
+fail:
+	kfree(uvhub_descs);
+	kfree(uvhub_mask);
+	return 1;
 }
 
 /*
#15 lore raw

PATCH v5 8/8 x86, UV: correct UV2 BAU destination timeout

In reply to [email protected]

Correct the UV2 broacast assist unit's destination timeout period. And the activation status register in UV2 should be tested for a destination timeout with a 4, not a 2. The values for Active versus Timeout were reversed.

This patch is critical for TLB shootdown on an Altix UV2 system (i.e. the follow-on to the current Altix UV).

---

Destination timeout period:
The period is set in 4 bits of memory-mapped register MISC_CONTROL. The left bit toggles base period between 10us and 80us. The other 3 bits are the multiplier.
Decimal 15, hex f, gives the maximum: 7 * 80us

 arch/x86/include/asm/uv/uv_bau.h |   18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +13 -5
Index: linux/arch/x86/include/asm/uv/uv_bau.h
===================================================================
@@ -67,7 +67,7 @@
  *  we're using 655us, similar to UV1: 65 units of 10us
  */
 #define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL)
-#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (65*10UL)
+#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)
 
 #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD	(is_uv1_hub() ?			\
 		UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD :			\
@@ -106,12 +106,20 @@
 #define DS_SOURCE_TIMEOUT		3
 /*
  * bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2
- * values 1 and 5 will not occur
+ * values 1 and 3 will not occur
+ *        Decoded meaning              ERROR  BUSY    AUX ERR
+ * -------------------------------     ----   -----   -------
+ * IDLE                                 0       0        0
+ * BUSY (active)                        0       1        0
+ * SW Ack Timeout (destination)         1       0        0
+ * SW Ack INTD rejected (strong NACK)   1       0        1
+ * Source Side Time Out Detected        1       1        0
+ * Destination Side PUT Failed          1       1        1
  */
 #define UV2H_DESC_IDLE			0
-#define UV2H_DESC_DEST_TIMEOUT		2
-#define UV2H_DESC_DEST_STRONG_NACK	3
-#define UV2H_DESC_BUSY			4
+#define UV2H_DESC_BUSY			2
+#define UV2H_DESC_DEST_TIMEOUT		4
+#define UV2H_DESC_DEST_STRONG_NACK	5
 #define UV2H_DESC_SOURCE_TIMEOUT	6
 #define UV2H_DESC_DEST_PUT_ERR		7
 
#16 lore raw

[tip:x86/uv] x86, UV: Correct UV2 BAU destination timeout

Commit-ID:  ae90c232be376bd8a283f3b6fb37cb5bd2635d67
Gitweb:     http://git.kernel.org/tip/ae90c232be376bd8a283f3b6fb37cb5bd2635d67
Author:     [email protected] <[email protected]>
AuthorDate: Tue, 21 Jun 2011 07:21:33 -0500
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 21 Jun 2011 14:50:34 +0200

x86, UV: Correct UV2 BAU destination timeout

Correct the UV2 broacast assist unit's destination timeout period. And the activation status register in UV2 should be tested for a destination timeout with a 4, not a 2. The values for Active versus Timeout were reversed.

This patch is critical for TLB shootdown on an Altix UV2 system (i.e. the follow-on to the current Altix UV).

Destination timeout period:
The period is set in 4 bits of memory-mapped register MISC_CONTROL. The left bit toggles base period between 10us and 80us. The other 3 bits are the multiplier.
Decimal 15, hex f, gives the maximum: 7 * 80us

---
 arch/x86/include/asm/uv/uv_bau.h |   18 +++++++++++++-----
 1 files changed, 13 insertions(+), 5 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +13 -5
index 16ce58c..37d3698 100644
@@ -67,7 +67,7 @@
  *  we're using 655us, similar to UV1: 65 units of 10us
  */
 #define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL)
-#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (65*10UL)
+#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)
 
 #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD	(is_uv1_hub() ?			\
 		UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD :			\
@@ -106,12 +106,20 @@
 #define DS_SOURCE_TIMEOUT		3
 /*
  * bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2
- * values 1 and 5 will not occur
+ * values 1 and 3 will not occur
+ *        Decoded meaning              ERROR  BUSY    AUX ERR
+ * -------------------------------     ----   -----   -------
+ * IDLE                                 0       0        0
+ * BUSY (active)                        0       1        0
+ * SW Ack Timeout (destination)         1       0        0
+ * SW Ack INTD rejected (strong NACK)   1       0        1
+ * Source Side Time Out Detected        1       1        0
+ * Destination Side PUT Failed          1       1        1
  */
 #define UV2H_DESC_IDLE			0
-#define UV2H_DESC_DEST_TIMEOUT		2
-#define UV2H_DESC_DEST_STRONG_NACK	3
-#define UV2H_DESC_BUSY			4
+#define UV2H_DESC_BUSY			2
+#define UV2H_DESC_DEST_TIMEOUT		4
+#define UV2H_DESC_DEST_STRONG_NACK	5
 #define UV2H_DESC_SOURCE_TIMEOUT	6
 #define UV2H_DESC_DEST_PUT_ERR		7