* [PATCH 1/2] powerpc/hotplug: Ensure enough nodes avail for operations
2017-06-18 18:45 [PATCH V5 0/2] powerpc/dlpar: Correct display of hot-add/hot-remove CPUs and memory Michael Bringmann
@ 2017-06-18 18:46 ` Michael Bringmann
2017-06-18 18:46 ` [PATCH V5 2/2] powerpc/numa: Update CPU topology when VPHN enabled Michael Bringmann
1 sibling, 0 replies; 4+ messages in thread
From: Michael Bringmann @ 2017-06-18 18:46 UTC (permalink / raw)
To: linuxppc-dev, linuxppc-dev
Cc: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Michael Bringmann, David Gibson, Reza Arbab, John Allen,
Thomas Gleixner, Bharata B Rao, Shailendra Singh,
Aneesh Kumar K.V, Sebastian Andrzej Siewior, Rashmica Gupta,
Ingo Molnar
powerpc/hotplug: On systems like PowerPC which allow 'hot-add' of CPU or memory
resources, it may occur that the new resources are to be inserted into nodes
that were not used for these resources at bootup. In the kernel, any node that
is used must be defined and initialized at boot. In order to meet both
needs, this patch adds a new kernel command line option (numnodes=<int>)
for use by the PowerPC architecture-specific code that defines the maximum
number of nodes that the kernel will ever need in its current hardware
environment. The boot code that initializes nodes for PowerPC will read
this value and use it to ensure that all of the desired nodes are setup
in the 'node_possible_map', and elsewhere.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
---
arch/powerpc/mm/numa.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 371792e..11b04a3 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -60,10 +60,27 @@
static int n_mem_addr_cells, n_mem_size_cells;
static int form1_affinity;
+#define TOPOLOGY_DEF_NUM_NODES 0
#define MAX_DISTANCE_REF_POINTS 4
static int distance_ref_points_depth;
static const __be32 *distance_ref_points;
static int distance_lookup_table[MAX_NUMNODES][MAX_DISTANCE_REF_POINTS];
+static int topology_num_nodes = TOPOLOGY_DEF_NUM_NODES;
+
+/*
+ * Topology-related early parameters
+ */
+static int __init early_num_nodes(char *p)
+{
+ if (!p)
+ return 1;
+
+ topology_num_nodes = memparse(p, &p);
+ dbg("topology num nodes = 0x%d\n", topology_num_nodes);
+
+ return 0;
+}
+early_param("numnodes", early_num_nodes);
/*
* Allocate node_to_cpumask_map based on number of available nodes
@@ -892,6 +909,18 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
NODE_DATA(nid)->node_spanned_pages = spanned_pages;
}
+static void __init setup_min_nodes(void)
+{
+ int i, l = topology_num_nodes;
+
+ for (i = 0; i < l; i++) {
+ if (!node_possible(i)) {
+ setup_node_data(i, 0, 0);
+ node_set(i, node_possible_map);
+ }
+ }
+}
+
void __init initmem_init(void)
{
int nid, cpu;
@@ -911,6 +940,8 @@ void __init initmem_init(void)
*/
nodes_and(node_possible_map, node_possible_map, node_online_map);
+ setup_min_nodes();
+
for_each_online_node(nid) {
unsigned long start_pfn, end_pfn;
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH V5 2/2] powerpc/numa: Update CPU topology when VPHN enabled
2017-06-18 18:45 [PATCH V5 0/2] powerpc/dlpar: Correct display of hot-add/hot-remove CPUs and memory Michael Bringmann
2017-06-18 18:46 ` [PATCH 1/2] powerpc/hotplug: Ensure enough nodes avail for operations Michael Bringmann
@ 2017-06-18 18:46 ` Michael Bringmann
2017-06-19 2:46 ` kbuild test robot
1 sibling, 1 reply; 4+ messages in thread
From: Michael Bringmann @ 2017-06-18 18:46 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Reza Arbab, Thomas Gleixner, Bharata B Rao, Balbir Singh,
Michael Bringmann, Shailendra Singh, Aneesh Kumar K.V,
Sebastian Andrzej Siewior, Nathan Fontenot, Andrew Donnellan,
John Allen, Tyrel Datwyler, Sahil Mehta, Rashmica Gupta,
Ingo Molnar
powerpc/numa: Correct the currently broken capability to set the
topology for shared CPUs in LPARs. At boot time for shared CPU
lpars, the topology for each shared CPU is set to node zero, however,
this is now updated correctly using the Virtual Processor Home Node
(VPHN) capabilities information provided by the pHyp.
Also, update initialization checks for device-tree attributes to
independently recognize PRRN or VPHN usage.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
Changes in V5:
-- Independently recognize PRRN or VPHN usage at boot time.
-- Modify interface used to trigger domain updates in shared configs.
---
arch/powerpc/include/asm/topology.h | 11 ++++
arch/powerpc/mm/numa.c | 64 +++++++++++++++++++++++---
arch/powerpc/platforms/pseries/dlpar.c | 2 +
arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +
4 files changed, 72 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 8b3b46b..8b20ac4 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -62,6 +62,7 @@ static inline void sysfs_remove_device_from_node(struct device *dev,
#if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
extern int start_topology_update(void);
extern int stop_topology_update(void);
+extern int timed_topology_update(int nsecs);
extern int prrn_is_enabled(void);
#else
static inline int start_topology_update(void)
@@ -72,12 +73,22 @@ static inline int stop_topology_update(void)
{
return 0;
}
+static int timed_topology_update(int nsecs)
+{
+ return 0;
+}
static inline int prrn_is_enabled(void)
{
return 0;
}
#endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */
+#if defined(CONFIG_PPC_SPLPAR)
+extern void shared_topology_update(void);
+#else
+#define shared_topology_update() 0
+#endif /* CONFIG_PPC_SPLPAR */
+
#include <asm-generic/topology.h>
#ifdef CONFIG_SMP
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 11b04a3..6111448 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -29,6 +29,7 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include <asm/cputhreads.h>
#include <asm/sparsemem.h>
#include <asm/prom.h>
@@ -935,7 +936,7 @@ void __init initmem_init(void)
/*
* Reduce the possible NUMA nodes to the online NUMA nodes,
- * since we do not support node hotplug. This ensures that we
+ * since we do not support node hotplug. This ensures that we
* lower the maximum NUMA node ID to what is actually present.
*/
nodes_and(node_possible_map, node_possible_map, node_online_map);
@@ -1179,11 +1180,16 @@ struct topology_update_data {
int new_nid;
};
+#define TOPOLOGY_DEF_TIMER_SECS 60
+
static u8 vphn_cpu_change_counts[NR_CPUS][MAX_DISTANCE_REF_POINTS];
static cpumask_t cpu_associativity_changes_mask;
static int vphn_enabled;
static int prrn_enabled;
static void reset_topology_timer(void);
+static int topology_timer_secs = TOPOLOGY_DEF_TIMER_SECS;
+static int topology_inited;
+static int topology_update_needed;
/*
* Store the current values of the associativity change counters in the
@@ -1277,6 +1283,12 @@ static long vphn_get_associativity(unsigned long cpu,
"hcall_vphn() experienced a hardware fault "
"preventing VPHN. Disabling polling...\n");
stop_topology_update();
+ break;
+ case H_SUCCESS:
+ printk(KERN_INFO
+ "VPHN hcall succeeded. Reset polling...\n");
+ timed_topology_update(0);
+ break;
}
return rc;
@@ -1352,8 +1364,11 @@ int arch_update_cpu_topology(void)
struct device *dev;
int weight, new_nid, i = 0;
- if (!prrn_enabled && !vphn_enabled)
+ if (!prrn_enabled && !vphn_enabled) {
+ if (!topology_inited)
+ topology_update_needed = 1;
return 0;
+ }
weight = cpumask_weight(&cpu_associativity_changes_mask);
if (!weight)
@@ -1392,6 +1407,8 @@ int arch_update_cpu_topology(void)
cpumask_andnot(&cpu_associativity_changes_mask,
&cpu_associativity_changes_mask,
cpu_sibling_mask(cpu));
+ pr_info("Assoc chg gives same node %d for cpu%d\n",
+ new_nid, cpu);
cpu = cpu_last_thread_sibling(cpu);
continue;
}
@@ -1408,6 +1425,9 @@ int arch_update_cpu_topology(void)
cpu = cpu_last_thread_sibling(cpu);
}
+ if (i)
+ updates[i-1].next = NULL;
+
pr_debug("Topology update for the following CPUs:\n");
if (cpumask_weight(&updated_cpus)) {
for (ud = &updates[0]; ud; ud = ud->next) {
@@ -1454,6 +1474,7 @@ int arch_update_cpu_topology(void)
out:
kfree(updates);
+ topology_update_needed = 0;
return changed;
}
@@ -1468,6 +1489,14 @@ static void topology_schedule_update(void)
schedule_work(&topology_work);
}
+void shared_topology_update(void)
+{
+ if (firmware_has_feature(FW_FEATURE_VPHN) &&
+ lppaca_shared_proc(get_lppaca()))
+ topology_schedule_update();
+}
+EXPORT_SYMBOL(shared_topology_update);
+
static void topology_timer_fn(unsigned long ignored)
{
if (prrn_enabled && cpumask_weight(&cpu_associativity_changes_mask))
@@ -1484,7 +1513,7 @@ static void topology_timer_fn(unsigned long ignored)
static void reset_topology_timer(void)
{
topology_timer.data = 0;
- topology_timer.expires = jiffies + 60 * HZ;
+ topology_timer.expires = jiffies + topology_timer_secs * HZ;
mod_timer(&topology_timer, topology_timer.expires);
}
@@ -1534,15 +1563,14 @@ int start_topology_update(void)
if (firmware_has_feature(FW_FEATURE_PRRN)) {
if (!prrn_enabled) {
prrn_enabled = 1;
- vphn_enabled = 0;
#ifdef CONFIG_SMP
rc = of_reconfig_notifier_register(&dt_update_nb);
#endif
}
- } else if (firmware_has_feature(FW_FEATURE_VPHN) &&
+ }
+ if (firmware_has_feature(FW_FEATURE_VPHN) &&
lppaca_shared_proc(get_lppaca())) {
if (!vphn_enabled) {
- prrn_enabled = 0;
vphn_enabled = 1;
setup_cpu_associativity_change_counters();
init_timer_deferrable(&topology_timer);
@@ -1565,7 +1593,8 @@ int stop_topology_update(void)
#ifdef CONFIG_SMP
rc = of_reconfig_notifier_unregister(&dt_update_nb);
#endif
- } else if (vphn_enabled) {
+ }
+ if (vphn_enabled) {
vphn_enabled = 0;
rc = del_timer_sync(&topology_timer);
}
@@ -1573,6 +1602,22 @@ int stop_topology_update(void)
return rc;
}
+/*
+ * Change polling interval for associativity changes.
+ */
+int timed_topology_update(int nsecs)
+{
+ if (nsecs > 0)
+ topology_timer_secs = nsecs;
+ else
+ topology_timer_secs = TOPOLOGY_DEF_TIMER_SECS;
+
+ if (vphn_enabled)
+ reset_topology_timer();
+
+ return 0;
+}
+
int prrn_is_enabled(void)
{
return prrn_enabled;
@@ -1631,6 +1676,11 @@ static int topology_update_init(void)
if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
return -ENOMEM;
+ topology_inited = 1;
+ if (topology_update_needed)
+ bitmap_fill(cpumask_bits(&cpu_associativity_changes_mask),
+ nr_cpumask_bits);
+
return 0;
}
device_initcall(topology_update_init);
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index bda18d8..0219cd3 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -592,6 +592,8 @@ static ssize_t dlpar_show(struct class *class, struct class_attribute *attr,
static int __init pseries_dlpar_init(void)
{
+ shared_topology_update();
+
pseries_hp_wq = alloc_workqueue("pseries hotplug workqueue",
WQ_UNBOUND, 1);
return sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr);
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 7bc0e91..96c02d0 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -356,6 +356,7 @@ static int dlpar_online_cpu(struct device_node *dn)
BUG_ON(get_cpu_current_state(cpu)
!= CPU_STATE_OFFLINE);
cpu_maps_update_done();
+ timed_topology_update(1);
rc = device_online(get_cpu_device(cpu));
if (rc)
goto out;
@@ -522,6 +523,7 @@ static int dlpar_offline_cpu(struct device_node *dn)
set_preferred_offline_state(cpu,
CPU_STATE_OFFLINE);
cpu_maps_update_done();
+ timed_topology_update(1);
rc = device_offline(get_cpu_device(cpu));
if (rc)
goto out;
^ permalink raw reply related [flat|nested] 4+ messages in thread