diff mbox

[v2,3/3] powerpc/pseries: Update affinity for memory and cpus specified in a PRRN event

Message ID f535217c-c8ce-5b7e-a5d4-9f4570ad25a6@linux.vnet.ibm.com (mailing list archive)
State Superseded
Headers show

Commit Message

John Allen Dec. 15, 2016, 10:22 p.m. UTC
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>
---

Comments

Nathan Fontenot Jan. 4, 2017, 7:39 p.m. UTC | #1
On 12/15/2016 04:22 PM, John Allen wrote:
> 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>
> ---
> diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
> index a26a020..8836130 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 <asm/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 a560a98..d62d48a 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,33 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
>  	return rc;
>  }
> 
> +void pseries_prrn_update_node(__be32 phandle)
> +{
> +	struct pseries_hp_errorlog *hp_elog;
> +	struct device_node *dn;
> +
> +	hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
> +	if (!hp_elog)
> +		return;
> +
> +	dn = of_find_node_by_phandle(be32_to_cpu(phandle));

You should check for the presence of the device node prior to doing the
kzalloc, this way you can avoid the alloc/free calls in cases where it
is not needed.

Also, you do need to do a of_node_put() on the device node if it is found.

-Nathan
 
> +
> +	/*
> +	 * If the phandle was not found, assume phandle is the drc index of
> +	 * an LMB.
> +	 */
> +	if (!dn) {
> +		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 +302,10 @@ int pseries_devicetree_update(s32 scope)
>  					break;
>  				case UPDATE_DT_NODE:
>  					update_dt_node(phandle, scope);
> +
> +					if (scope == PRRN_SCOPE)
> +						pseries_prrn_update_node(phandle);
> +
>  					break;
>  				case ADD_DT_NODE:
>  					drc_index = *data++;
>
diff mbox

Patch

diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index a26a020..8836130 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 <asm/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 a560a98..d62d48a 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,33 @@  static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
 	return rc;
 }

+void pseries_prrn_update_node(__be32 phandle)
+{
+	struct pseries_hp_errorlog *hp_elog;
+	struct device_node *dn;
+
+	hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
+	if (!hp_elog)
+		return;
+
+	dn = of_find_node_by_phandle(be32_to_cpu(phandle));
+
+	/*
+	 * If the phandle was not found, assume phandle is the drc index of
+	 * an LMB.
+	 */
+	if (!dn) {
+		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 +302,10 @@  int pseries_devicetree_update(s32 scope)
 					break;
 				case UPDATE_DT_NODE:
 					update_dt_node(phandle, scope);
+
+					if (scope == PRRN_SCOPE)
+						pseries_prrn_update_node(phandle);
+
 					break;
 				case ADD_DT_NODE:
 					drc_index = *data++;