Michal Suchanek 9c0489
From fa2a5dfe2ddd0e7c77e5f608e1fa374192e5be97 Mon Sep 17 00:00:00 2001
Michal Suchanek 9c0489
From: Nathan Lynch <nathanl@linux.ibm.com>
Michal Suchanek 9c0489
Date: Mon, 27 Sep 2021 15:19:32 -0500
Michal Suchanek 9c0489
Subject: [PATCH] powerpc/pseries/cpuhp: delete add/remove_by_count code
Michal Suchanek 9c0489
Michal Suchanek 9c0489
References: bsc#1065729
Michal Suchanek 9c0489
Patch-mainline: v5.16-rc1
Michal Suchanek 9c0489
Git-commit: fa2a5dfe2ddd0e7c77e5f608e1fa374192e5be97
Michal Suchanek 9c0489
Michal Suchanek 9c0489
The core DLPAR code supports two actions (add and remove) and three
Michal Suchanek 9c0489
subtypes of action:
Michal Suchanek 9c0489
Michal Suchanek 9c0489
* By DRC index: the action is attempted on a single specified resource.
Michal Suchanek 9c0489
  This is the usual case for processors.
Michal Suchanek 9c0489
* By indexed count: the action is attempted on a range of resources
Michal Suchanek 9c0489
  beginning at the specified index. This is implemented only by the memory
Michal Suchanek 9c0489
  DLPAR code.
Michal Suchanek 9c0489
* By count: the lower layer (CPU or memory) is responsible for locating the
Michal Suchanek 9c0489
  specified number of resources to which the action can be applied.
Michal Suchanek 9c0489
Michal Suchanek 9c0489
I cannot find any evidence of the "by count" subtype being used by drmgr or
Michal Suchanek 9c0489
qemu for processors. And when I try to exercise this code, the add case
Michal Suchanek 9c0489
does not work:
Michal Suchanek 9c0489
Michal Suchanek 9c0489
  $ ppc64_cpu --smt ; nproc
Michal Suchanek 9c0489
  SMT=8
Michal Suchanek 9c0489
  24
Michal Suchanek 9c0489
  $ printf "cpu remove count 2" > /sys/kernel/dlpar
Michal Suchanek 9c0489
  $ nproc
Michal Suchanek 9c0489
  8
Michal Suchanek 9c0489
  $ printf "cpu add count 2" > /sys/kernel/dlpar
Michal Suchanek 9c0489
  -bash: printf: write error: Invalid argument
Michal Suchanek 9c0489
  $ dmesg | tail -2
Michal Suchanek 9c0489
  pseries-hotplug-cpu: Failed to find enough CPUs (1 of 2) to add
Michal Suchanek 9c0489
  dlpar: Could not handle DLPAR request "cpu add count 2"
Michal Suchanek 9c0489
  $ nproc
Michal Suchanek 9c0489
  8
Michal Suchanek 9c0489
  $ drmgr -c cpu -a -q 2         # this uses the by-index method
Michal Suchanek 9c0489
  Validating CPU DLPAR capability...yes.
Michal Suchanek 9c0489
  CPU 1
Michal Suchanek 9c0489
  CPU 17
Michal Suchanek 9c0489
  $ nproc
Michal Suchanek 9c0489
  24
Michal Suchanek 9c0489
Michal Suchanek 9c0489
This is because find_drc_info_cpus_to_add() does not increment drc_index
Michal Suchanek 9c0489
appropriately during its search.
Michal Suchanek 9c0489
Michal Suchanek 9c0489
This is not hard to fix. But the _by_count() functions also have the
Michal Suchanek 9c0489
property that they attempt to roll back all prior operations if the entire
Michal Suchanek 9c0489
request cannot be satisfied, even though the rollback itself can encounter
Michal Suchanek 9c0489
errors. It's not possible to provide transaction-like behavior at this
Michal Suchanek 9c0489
level, and it's undesirable to have code that can only pretend to do that.
Michal Suchanek 9c0489
Any users of these functions cannot know what the state of the system is in
Michal Suchanek 9c0489
the error case. And the error paths are, to my knowledge, impossible to
Michal Suchanek 9c0489
test without adding custom error injection code.
Michal Suchanek 9c0489
Michal Suchanek 9c0489
Summary:
Michal Suchanek 9c0489
Michal Suchanek 9c0489
* This code has not worked reliably since its introduction.
Michal Suchanek 9c0489
* There is no evidence that it is used.
Michal Suchanek 9c0489
* It contains questionable rollback behaviors in error paths which are
Michal Suchanek 9c0489
  difficult to test.
Michal Suchanek 9c0489
Michal Suchanek 9c0489
So let's remove it.
Michal Suchanek 9c0489
Michal Suchanek 9c0489
Fixes: ac71380071d1 ("powerpc/pseries: Add CPU dlpar remove functionality")
Michal Suchanek 9c0489
Fixes: 90edf184b9b7 ("powerpc/pseries: Add CPU dlpar add functionality")
Michal Suchanek 9c0489
Fixes: b015f6bc9547 ("powerpc/pseries: Add cpu DLPAR support for drc-info property")
Michal Suchanek 9c0489
Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Michal Suchanek 9c0489
Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Michal Suchanek 9c0489
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Michal Suchanek 9c0489
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek 9c0489
Link: https://lore.kernel.org/r/20210927201933.76786-4-nathanl@linux.ibm.com
Michal Suchanek 9c0489
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 9c0489
---
Michal Suchanek 9c0489
 arch/powerpc/platforms/pseries/hotplug-cpu.c | 218 +------------------
Michal Suchanek 9c0489
 1 file changed, 2 insertions(+), 216 deletions(-)
Michal Suchanek 9c0489
Michal Suchanek 9c0489
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
Michal Suchanek 9c0489
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
Michal Suchanek 9c0489
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
Michal Suchanek 9c0489
@@ -741,216 +741,6 @@ static int dlpar_cpu_remove_by_index(u32 drc_index)
Michal Suchanek 9c0489
 	return rc;
Michal Suchanek 9c0489
 }
Michal Suchanek 9c0489
 
Michal Suchanek 9c0489
-static int find_dlpar_cpus_to_remove(u32 *cpu_drcs, int cpus_to_remove)
Michal Suchanek 9c0489
-{
Michal Suchanek 9c0489
-	struct device_node *dn;
Michal Suchanek 9c0489
-	int cpus_found = 0;
Michal Suchanek 9c0489
-	int rc;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	/* We want to find cpus_to_remove + 1 CPUs to ensure we do not
Michal Suchanek 9c0489
-	 * remove the last CPU.
Michal Suchanek 9c0489
-	 */
Michal Suchanek 9c0489
-	for_each_node_by_type(dn, "cpu") {
Michal Suchanek 9c0489
-		cpus_found++;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		if (cpus_found > cpus_to_remove) {
Michal Suchanek 9c0489
-			of_node_put(dn);
Michal Suchanek 9c0489
-			break;
Michal Suchanek 9c0489
-		}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		/* Note that cpus_found is always 1 ahead of the index
Michal Suchanek 9c0489
-		 * into the cpu_drcs array, so we use cpus_found - 1
Michal Suchanek 9c0489
-		 */
Michal Suchanek 9c0489
-		rc = of_property_read_u32(dn, "ibm,my-drc-index",
Michal Suchanek 9c0489
-					  &cpu_drcs[cpus_found - 1]);
Michal Suchanek 9c0489
-		if (rc) {
Michal Suchanek 9c0489
-			pr_warn("Error occurred getting drc-index for %pOFn\n",
Michal Suchanek 9c0489
-				dn);
Michal Suchanek 9c0489
-			of_node_put(dn);
Michal Suchanek 9c0489
-			return -1;
Michal Suchanek 9c0489
-		}
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	if (cpus_found < cpus_to_remove) {
Michal Suchanek 9c0489
-		pr_warn("Failed to find enough CPUs (%d of %d) to remove\n",
Michal Suchanek 9c0489
-			cpus_found, cpus_to_remove);
Michal Suchanek 9c0489
-	} else if (cpus_found == cpus_to_remove) {
Michal Suchanek 9c0489
-		pr_warn("Cannot remove all CPUs\n");
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	return cpus_found;
Michal Suchanek 9c0489
-}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-static int dlpar_cpu_remove_by_count(u32 cpus_to_remove)
Michal Suchanek 9c0489
-{
Michal Suchanek 9c0489
-	u32 *cpu_drcs;
Michal Suchanek 9c0489
-	int cpus_found;
Michal Suchanek 9c0489
-	int cpus_removed = 0;
Michal Suchanek 9c0489
-	int i, rc;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	pr_debug("Attempting to hot-remove %d CPUs\n", cpus_to_remove);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	cpu_drcs = kcalloc(cpus_to_remove, sizeof(*cpu_drcs), GFP_KERNEL);
Michal Suchanek 9c0489
-	if (!cpu_drcs)
Michal Suchanek 9c0489
-		return -EINVAL;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	cpus_found = find_dlpar_cpus_to_remove(cpu_drcs, cpus_to_remove);
Michal Suchanek 9c0489
-	if (cpus_found <= cpus_to_remove) {
Michal Suchanek 9c0489
-		kfree(cpu_drcs);
Michal Suchanek 9c0489
-		return -EINVAL;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	for (i = 0; i < cpus_to_remove; i++) {
Michal Suchanek 9c0489
-		rc = dlpar_cpu_remove_by_index(cpu_drcs[i]);
Michal Suchanek 9c0489
-		if (rc)
Michal Suchanek 9c0489
-			break;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		cpus_removed++;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	if (cpus_removed != cpus_to_remove) {
Michal Suchanek 9c0489
-		pr_warn("CPU hot-remove failed, adding back removed CPUs\n");
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		for (i = 0; i < cpus_removed; i++)
Michal Suchanek 9c0489
-			dlpar_cpu_add(cpu_drcs[i]);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		rc = -EINVAL;
Michal Suchanek 9c0489
-	} else {
Michal Suchanek 9c0489
-		rc = 0;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	kfree(cpu_drcs);
Michal Suchanek 9c0489
-	return rc;
Michal Suchanek 9c0489
-}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-static int find_drc_info_cpus_to_add(struct device_node *cpus,
Michal Suchanek 9c0489
-				     struct property *info,
Michal Suchanek 9c0489
-				     u32 *cpu_drcs, u32 cpus_to_add)
Michal Suchanek 9c0489
-{
Michal Suchanek 9c0489
-	struct of_drc_info drc;
Michal Suchanek 9c0489
-	const __be32 *value;
Michal Suchanek 9c0489
-	u32 count, drc_index;
Michal Suchanek 9c0489
-	int cpus_found = 0;
Michal Suchanek 9c0489
-	int i, j;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	if (!info)
Michal Suchanek 9c0489
-		return -1;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	value = of_prop_next_u32(info, NULL, &count);
Michal Suchanek 9c0489
-	if (value)
Michal Suchanek 9c0489
-		value++;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	for (i = 0; i < count; i++) {
Michal Suchanek 9c0489
-		of_read_drc_info_cell(&info, &value, &drc);
Michal Suchanek 9c0489
-		if (strncmp(drc.drc_type, "CPU", 3))
Michal Suchanek 9c0489
-			break;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		drc_index = drc.drc_index_start;
Michal Suchanek 9c0489
-		for (j = 0; j < drc.num_sequential_elems; j++) {
Michal Suchanek 9c0489
-			if (dlpar_cpu_exists(cpus, drc_index))
Michal Suchanek 9c0489
-				continue;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-			cpu_drcs[cpus_found++] = drc_index;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-			if (cpus_found == cpus_to_add)
Michal Suchanek 9c0489
-				return cpus_found;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-			drc_index += drc.sequential_inc;
Michal Suchanek 9c0489
-		}
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	return cpus_found;
Michal Suchanek 9c0489
-}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-static int find_drc_index_cpus_to_add(struct device_node *cpus,
Michal Suchanek 9c0489
-				      u32 *cpu_drcs, u32 cpus_to_add)
Michal Suchanek 9c0489
-{
Michal Suchanek 9c0489
-	int cpus_found = 0;
Michal Suchanek 9c0489
-	int index, rc;
Michal Suchanek 9c0489
-	u32 drc_index;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	/* Search the ibm,drc-indexes array for possible CPU drcs to
Michal Suchanek 9c0489
-	 * add. Note that the format of the ibm,drc-indexes array is
Michal Suchanek 9c0489
-	 * the number of entries in the array followed by the array
Michal Suchanek 9c0489
-	 * of drc values so we start looking at index = 1.
Michal Suchanek 9c0489
-	 */
Michal Suchanek 9c0489
-	index = 1;
Michal Suchanek 9c0489
-	while (cpus_found < cpus_to_add) {
Michal Suchanek 9c0489
-		rc = of_property_read_u32_index(cpus, "ibm,drc-indexes",
Michal Suchanek 9c0489
-						index++, &drc_index);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		if (rc)
Michal Suchanek 9c0489
-			break;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		if (dlpar_cpu_exists(cpus, drc_index))
Michal Suchanek 9c0489
-			continue;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		cpu_drcs[cpus_found++] = drc_index;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	return cpus_found;
Michal Suchanek 9c0489
-}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-static int dlpar_cpu_add_by_count(u32 cpus_to_add)
Michal Suchanek 9c0489
-{
Michal Suchanek 9c0489
-	struct device_node *parent;
Michal Suchanek 9c0489
-	struct property *info;
Michal Suchanek 9c0489
-	u32 *cpu_drcs;
Michal Suchanek 9c0489
-	int cpus_added = 0;
Michal Suchanek 9c0489
-	int cpus_found;
Michal Suchanek 9c0489
-	int i, rc;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	pr_debug("Attempting to hot-add %d CPUs\n", cpus_to_add);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	cpu_drcs = kcalloc(cpus_to_add, sizeof(*cpu_drcs), GFP_KERNEL);
Michal Suchanek 9c0489
-	if (!cpu_drcs)
Michal Suchanek 9c0489
-		return -EINVAL;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	parent = of_find_node_by_path("/cpus");
Michal Suchanek 9c0489
-	if (!parent) {
Michal Suchanek 9c0489
-		pr_warn("Could not find CPU root node in device tree\n");
Michal Suchanek 9c0489
-		kfree(cpu_drcs);
Michal Suchanek 9c0489
-		return -1;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	info = of_find_property(parent, "ibm,drc-info", NULL);
Michal Suchanek 9c0489
-	if (info)
Michal Suchanek 9c0489
-		cpus_found = find_drc_info_cpus_to_add(parent, info, cpu_drcs, cpus_to_add);
Michal Suchanek 9c0489
-	else
Michal Suchanek 9c0489
-		cpus_found = find_drc_index_cpus_to_add(parent, cpu_drcs, cpus_to_add);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	of_node_put(parent);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	if (cpus_found < cpus_to_add) {
Michal Suchanek 9c0489
-		pr_warn("Failed to find enough CPUs (%d of %d) to add\n",
Michal Suchanek 9c0489
-			cpus_found, cpus_to_add);
Michal Suchanek 9c0489
-		kfree(cpu_drcs);
Michal Suchanek 9c0489
-		return -EINVAL;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	for (i = 0; i < cpus_to_add; i++) {
Michal Suchanek 9c0489
-		rc = dlpar_cpu_add(cpu_drcs[i]);
Michal Suchanek 9c0489
-		if (rc)
Michal Suchanek 9c0489
-			break;
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		cpus_added++;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	if (cpus_added < cpus_to_add) {
Michal Suchanek 9c0489
-		pr_warn("CPU hot-add failed, removing any added CPUs\n");
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		for (i = 0; i < cpus_added; i++)
Michal Suchanek 9c0489
-			dlpar_cpu_remove_by_index(cpu_drcs[i]);
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-		rc = -EINVAL;
Michal Suchanek 9c0489
-	} else {
Michal Suchanek 9c0489
-		rc = 0;
Michal Suchanek 9c0489
-	}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
-	kfree(cpu_drcs);
Michal Suchanek 9c0489
-	return rc;
Michal Suchanek 9c0489
-}
Michal Suchanek 9c0489
-
Michal Suchanek 9c0489
 int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
Michal Suchanek 9c0489
 {
Michal Suchanek 9c0489
 	u32 drc_index;
Michal Suchanek 9c0489
@@ -962,9 +752,7 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
Michal Suchanek 9c0489
 
Michal Suchanek 9c0489
 	switch (hp_elog->action) {
Michal Suchanek 9c0489
 	case PSERIES_HP_ELOG_ACTION_REMOVE:
Michal Suchanek 9c0489
-		if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
Michal Suchanek 9c0489
-			rc = dlpar_cpu_remove_by_count(count);
Michal Suchanek 9c0489
-		else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
Michal Suchanek 9c0489
+		if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
Michal Suchanek 9c0489
 			rc = dlpar_cpu_remove_by_index(drc_index);
Michal Suchanek 9c0489
 		else
Michal Suchanek 9c0489
 			rc = -EINVAL;
Michal Suchanek 9c0489
@@ -978,9 +766,7 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
Michal Suchanek 9c0489
 			rc = -EINVAL;
Michal Suchanek 9c0489
 		break;
Michal Suchanek 9c0489
 	case PSERIES_HP_ELOG_ACTION_ADD:
Michal Suchanek 9c0489
-		if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT)
Michal Suchanek 9c0489
-			rc = dlpar_cpu_add_by_count(count);
Michal Suchanek 9c0489
-		else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
Michal Suchanek 9c0489
+		if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX)
Michal Suchanek 9c0489
 			rc = dlpar_cpu_add(drc_index);
Michal Suchanek 9c0489
 		else
Michal Suchanek 9c0489
 			rc = -EINVAL;
Michal Suchanek 9c0489
-- 
Michal Suchanek 9c0489
2.31.1
Michal Suchanek 9c0489