summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Allen <jallen@linux.vnet.ibm.com>2017-01-06 13:28:54 -0600
committerMichael Ellerman <mpe@ellerman.id.au>2017-02-02 20:36:38 +1100
commit675d8ee685195249d1b35e12a29f614a9888b16d (patch)
treef5404f665d36b50a575768813b5a0df551f2bf3e
parente70d59700fc32c9249b26acd4120303c497e84f1 (diff)
downloadlinux-675d8ee685195249d1b35e12a29f614a9888b16d.tar.gz
linux-675d8ee685195249d1b35e12a29f614a9888b16d.tar.bz2
linux-675d8ee685195249d1b35e12a29f614a9888b16d.zip
powerpc/pseries: Update affinity for memory and cpus specified in a PRRN event
Extend the existing PRRN infrastructure to perform the actual affinity updating for cpus and memory in addition to the device tree updating. For cpus, dynamic affinity updating already appears to exist in the kernel in the form of arch_update_cpu_topology(). For memory, we must place a READD operation on the hotplug queue for any phandle included in the PRRN event that is determined to be an LMB. Signed-off-by: John Allen <jallen@linux.vnet.ibm.com> Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/rtasd.c7
-rw-r--r--arch/powerpc/platforms/pseries/mobility.c34
2 files changed, 40 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 2bf1f9b5b34b..3650732639ed 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -21,6 +21,7 @@
#include <linux/cpu.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
+#include <linux/topology.h>
#include <linux/uaccess.h>
#include <asm/io.h>
@@ -282,6 +283,7 @@ static void prrn_work_fn(struct work_struct *work)
* the RTAS event.
*/
pseries_devicetree_update(-prrn_update_scope);
+ arch_update_cpu_topology();
}
static DECLARE_WORK(prrn_work, prrn_work_fn);
@@ -434,7 +436,10 @@ static void do_event_scan(void)
}
if (error == 0) {
- pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);
+ if (rtas_error_type((struct rtas_error_log *)logdata) !=
+ RTAS_TYPE_PRRN)
+ pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG,
+ 0);
handle_rtas_event((struct rtas_error_log *)logdata);
}
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index a560a98bcf3b..5a0c7ba429ce 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -39,6 +39,7 @@ struct update_props_workarea {
#define ADD_DT_NODE 0x03000000
#define MIGRATION_SCOPE (1)
+#define PRRN_SCOPE -2
static int mobility_rtas_call(int token, char *buf, s32 scope)
{
@@ -236,6 +237,35 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
return rc;
}
+static void prrn_update_node(__be32 phandle)
+{
+ struct pseries_hp_errorlog *hp_elog;
+ struct device_node *dn;
+
+ /*
+ * If a node is found from a the given phandle, the phandle does not
+ * represent the drc index of an LMB and we can ignore.
+ */
+ dn = of_find_node_by_phandle(be32_to_cpu(phandle));
+ if (dn) {
+ of_node_put(dn);
+ return;
+ }
+
+ hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
+ if(!hp_elog)
+ return;
+
+ hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM;
+ hp_elog->action = PSERIES_HP_ELOG_ACTION_READD;
+ hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
+ hp_elog->_drc_u.drc_index = phandle;
+
+ queue_hotplug_event(hp_elog, NULL, NULL);
+
+ kfree(hp_elog);
+}
+
int pseries_devicetree_update(s32 scope)
{
char *rtas_buf;
@@ -274,6 +304,10 @@ int pseries_devicetree_update(s32 scope)
break;
case UPDATE_DT_NODE:
update_dt_node(phandle, scope);
+
+ if (scope == PRRN_SCOPE)
+ prrn_update_node(phandle);
+
break;
case ADD_DT_NODE:
drc_index = *data++;