Takashi Iwai ab71a3
From 48d4180939e12c4bd2846f984436d895bb9699ed Mon Sep 17 00:00:00 2001
Takashi Iwai ab71a3
From: Vishal Verma <vishal.l.verma@intel.com>
Takashi Iwai ab71a3
Date: Wed, 16 Nov 2022 16:37:37 -0700
Takashi Iwai ab71a3
Subject: [PATCH] ACPI: HMAT: Fix initiator registration for single-initiator systems
Takashi Iwai ab71a3
Git-commit: 48d4180939e12c4bd2846f984436d895bb9699ed
Takashi Iwai ab71a3
Patch-mainline: v6.1-rc8
Takashi Iwai ab71a3
References: git-fixes
Takashi Iwai ab71a3
Takashi Iwai ab71a3
In a system with a single initiator node, and one or more memory-only
Takashi Iwai ab71a3
'target' nodes, the memory-only node(s) would fail to register their
Takashi Iwai ab71a3
initiator node correctly. i.e. in sysfs:
Takashi Iwai ab71a3
Takashi Iwai ab71a3
  # ls /sys/devices/system/node/node0/access0/targets/
Takashi Iwai ab71a3
  node0
Takashi Iwai ab71a3
Takashi Iwai ab71a3
Where as the correct behavior should be:
Takashi Iwai ab71a3
Takashi Iwai ab71a3
  # ls /sys/devices/system/node/node0/access0/targets/
Takashi Iwai ab71a3
  node0 node1
Takashi Iwai ab71a3
Takashi Iwai ab71a3
This happened because hmat_register_target_initiators() uses list_sort()
Takashi Iwai ab71a3
to sort the initiator list, but the sort comparision function
Takashi Iwai ab71a3
(initiator_cmp()) is overloaded to also set the node mask's bits.
Takashi Iwai ab71a3
Takashi Iwai ab71a3
In a system with a single initiator, the list is singular, and list_sort
Takashi Iwai ab71a3
elides the comparision helper call. Thus the node mask never gets set,
Takashi Iwai ab71a3
and the subsequent search for the best initiator comes up empty.
Takashi Iwai ab71a3
Takashi Iwai ab71a3
Add a new helper to consume the sorted initiator list, and generate the
Takashi Iwai ab71a3
nodemask, decoupling it from the overloaded initiator_cmp() comparision
Takashi Iwai ab71a3
callback. This prevents the singular list corner case naturally, and
Takashi Iwai ab71a3
makes the code easier to follow as well.
Takashi Iwai ab71a3
Takashi Iwai ab71a3
Cc: <stable@vger.kernel.org>
Takashi Iwai ab71a3
Cc: Rafael J. Wysocki <rafael@kernel.org>
Takashi Iwai ab71a3
Cc: Liu Shixin <liushixin2@huawei.com>
Takashi Iwai ab71a3
Cc: Dan Williams <dan.j.williams@intel.com>
Takashi Iwai ab71a3
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Takashi Iwai ab71a3
Reported-by: Chris Piper <chris.d.piper@intel.com>
Takashi Iwai ab71a3
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Takashi Iwai ab71a3
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Takashi Iwai ab71a3
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Takashi Iwai ab71a3
Link: https://lore.kernel.org/r/20221116-acpi_hmat_fix-v2-2-3712569be691@intel.com
Takashi Iwai ab71a3
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Takashi Iwai ab71a3
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai ab71a3
Takashi Iwai ab71a3
---
Takashi Iwai ab71a3
 drivers/acpi/numa/hmat.c | 26 ++++++++++++++++++++------
Takashi Iwai ab71a3
 1 file changed, 20 insertions(+), 6 deletions(-)
Takashi Iwai ab71a3
Takashi Iwai ab71a3
diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
Takashi Iwai ab71a3
index 144a84f429ed..6cceca64a6bc 100644
Takashi Iwai ab71a3
--- a/drivers/acpi/numa/hmat.c
Takashi Iwai ab71a3
+++ b/drivers/acpi/numa/hmat.c
Takashi Iwai ab71a3
@@ -562,17 +562,26 @@ static int initiator_cmp(void *priv, const struct list_head *a,
Takashi Iwai ab71a3
 {
Takashi Iwai ab71a3
 	struct memory_initiator *ia;
Takashi Iwai ab71a3
 	struct memory_initiator *ib;
Takashi Iwai ab71a3
-	unsigned long *p_nodes = priv;
Takashi Iwai ab71a3
 
Takashi Iwai ab71a3
 	ia = list_entry(a, struct memory_initiator, node);
Takashi Iwai ab71a3
 	ib = list_entry(b, struct memory_initiator, node);
Takashi Iwai ab71a3
 
Takashi Iwai ab71a3
-	set_bit(ia->processor_pxm, p_nodes);
Takashi Iwai ab71a3
-	set_bit(ib->processor_pxm, p_nodes);
Takashi Iwai ab71a3
-
Takashi Iwai ab71a3
 	return ia->processor_pxm - ib->processor_pxm;
Takashi Iwai ab71a3
 }
Takashi Iwai ab71a3
 
Takashi Iwai ab71a3
+static int initiators_to_nodemask(unsigned long *p_nodes)
Takashi Iwai ab71a3
+{
Takashi Iwai ab71a3
+	struct memory_initiator *initiator;
Takashi Iwai ab71a3
+
Takashi Iwai ab71a3
+	if (list_empty(&initiators))
Takashi Iwai ab71a3
+		return -ENXIO;
Takashi Iwai ab71a3
+
Takashi Iwai ab71a3
+	list_for_each_entry(initiator, &initiators, node)
Takashi Iwai ab71a3
+		set_bit(initiator->processor_pxm, p_nodes);
Takashi Iwai ab71a3
+
Takashi Iwai ab71a3
+	return 0;
Takashi Iwai ab71a3
+}
Takashi Iwai ab71a3
+
Takashi Iwai ab71a3
 static void hmat_register_target_initiators(struct memory_target *target)
Takashi Iwai ab71a3
 {
Takashi Iwai ab71a3
 	static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
Takashi Iwai ab71a3
@@ -609,7 +618,10 @@ static void hmat_register_target_initiators(struct memory_target *target)
Takashi Iwai ab71a3
 	 * initiators.
Takashi Iwai ab71a3
 	 */
Takashi Iwai ab71a3
 	bitmap_zero(p_nodes, MAX_NUMNODES);
Takashi Iwai ab71a3
-	list_sort(p_nodes, &initiators, initiator_cmp);
Takashi Iwai ab71a3
+	list_sort(NULL, &initiators, initiator_cmp);
Takashi Iwai ab71a3
+	if (initiators_to_nodemask(p_nodes) < 0)
Takashi Iwai ab71a3
+		return;
Takashi Iwai ab71a3
+
Takashi Iwai ab71a3
 	if (!access0done) {
Takashi Iwai ab71a3
 		for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
Takashi Iwai ab71a3
 			loc = localities_types[i];
Takashi Iwai ab71a3
@@ -643,7 +655,9 @@ static void hmat_register_target_initiators(struct memory_target *target)
Takashi Iwai ab71a3
 
Takashi Iwai ab71a3
 	/* Access 1 ignores Generic Initiators */
Takashi Iwai ab71a3
 	bitmap_zero(p_nodes, MAX_NUMNODES);
Takashi Iwai ab71a3
-	list_sort(p_nodes, &initiators, initiator_cmp);
Takashi Iwai ab71a3
+	if (initiators_to_nodemask(p_nodes) < 0)
Takashi Iwai ab71a3
+		return;
Takashi Iwai ab71a3
+
Takashi Iwai ab71a3
 	for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
Takashi Iwai ab71a3
 		loc = localities_types[i];
Takashi Iwai ab71a3
 		if (!loc)
Takashi Iwai ab71a3
-- 
Takashi Iwai ab71a3
2.35.3
Takashi Iwai ab71a3