Skip to content

Commit 2e454fb

Browse files
committed
cxl, acpi/hmat: Update CXL access coordinates directly instead of through HMAT
The current implementation of CXL memory hotplug notifier gets called before the HMAT memory hotplug notifier. The CXL driver calculates the access coordinates (bandwidth and latency values) for the CXL end to end path (i.e. CPU to endpoint). When the CXL region is onlined, the CXL memory hotplug notifier writes the access coordinates to the HMAT target structs. Then the HMAT memory hotplug notifier is called and it creates the access coordinates for the node sysfs attributes. During testing on an Intel platform, it was found that although the newly calculated coordinates were pushed to sysfs, the sysfs attributes for the access coordinates showed up with the wrong initiator. The system has 4 nodes (0, 1, 2, 3) where node 0 and 1 are CPU nodes and node 2 and 3 are CXL nodes. The expectation is that node 2 would show up as a target to node 0: /sys/devices/system/node/node2/access0/initiators/node0 However it was observed that node 2 showed up as a target under node 1: /sys/devices/system/node/node2/access0/initiators/node1 The original intent of the 'ext_updated' flag in HMAT handling code was to stop HMAT memory hotplug callback from clobbering the access coordinates after CXL has injected its calculated coordinates and replaced the generic target access coordinates provided by the HMAT table in the HMAT target structs. However the flag is hacky at best and blocks the updates from other CXL regions that are onlined in the same node later on. Remove the 'ext_updated' flag usage and just update the access coordinates for the nodes directly without touching HMAT target data. The hotplug memory callback ordering is changed. Instead of changing CXL, move HMAT back so there's room for the levels rather than have CXL share the same level as SLAB_CALLBACK_PRI. The change will resulting in the CXL callback to be executed after the HMAT callback. With the change, the CXL hotplug memory notifier runs after the HMAT callback. The HMAT callback will create the node sysfs attributes for access coordinates. The CXL callback will write the access coordinates to the now created node sysfs attributes directly and will not pollute the HMAT target values. A nodemask is introduced to keep track if a node has been updated and prevents further updates. Fixes: 067353a ("cxl/region: Add memory hotplug notifier for cxl region") Cc: stable@vger.kernel.org Tested-by: Marc Herbert <marc.herbert@linux.intel.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20250829222907.1290912-4-dave.jiang@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
1 parent b57fc65 commit 2e454fb

5 files changed

Lines changed: 13 additions & 21 deletions

File tree

drivers/acpi/numa/hmat.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ struct memory_target {
7474
struct node_cache_attrs cache_attrs;
7575
u8 gen_port_device_handle[ACPI_SRAT_DEVICE_HANDLE_SIZE];
7676
bool registered;
77-
bool ext_updated; /* externally updated */
7877
};
7978

8079
struct memory_initiator {
@@ -391,7 +390,6 @@ int hmat_update_target_coordinates(int nid, struct access_coordinate *coord,
391390
coord->read_bandwidth, access);
392391
hmat_update_target_access(target, ACPI_HMAT_WRITE_BANDWIDTH,
393392
coord->write_bandwidth, access);
394-
target->ext_updated = true;
395393

396394
return 0;
397395
}
@@ -773,10 +771,6 @@ static void hmat_update_target_attrs(struct memory_target *target,
773771
u32 best = 0;
774772
int i;
775773

776-
/* Don't update if an external agent has changed the data. */
777-
if (target->ext_updated)
778-
return;
779-
780774
/* Don't update for generic port if there's no device handle */
781775
if ((access == NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL ||
782776
access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&

drivers/cxl/core/cdat.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,8 +1081,3 @@ int cxl_update_hmat_access_coordinates(int nid, struct cxl_region *cxlr,
10811081
{
10821082
return hmat_update_target_coordinates(nid, &cxlr->coord[access], access);
10831083
}
1084-
1085-
bool cxl_need_node_perf_attrs_update(int nid)
1086-
{
1087-
return !acpi_node_backed_by_real_pxm(nid);
1088-
}

drivers/cxl/core/core.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ long cxl_pci_get_latency(struct pci_dev *pdev);
139139
int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c);
140140
int cxl_update_hmat_access_coordinates(int nid, struct cxl_region *cxlr,
141141
enum access_coordinate_class access);
142-
bool cxl_need_node_perf_attrs_update(int nid);
143142
int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
144143
struct access_coordinate *c);
145144

drivers/cxl/core/region.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
* 3. Decoder targets
3131
*/
3232

33+
/*
34+
* nodemask that sets per node when the access_coordinates for the node has
35+
* been updated by the CXL memory hotplug notifier.
36+
*/
37+
static nodemask_t nodemask_region_seen = NODE_MASK_NONE;
38+
3339
static struct cxl_region *to_cxl_region(struct device *dev);
3440

3541
#define __ACCESS_ATTR_RO(_level, _name) { \
@@ -2442,14 +2448,8 @@ static bool cxl_region_update_coordinates(struct cxl_region *cxlr, int nid)
24422448

24432449
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
24442450
if (cxlr->coord[i].read_bandwidth) {
2445-
rc = 0;
2446-
if (cxl_need_node_perf_attrs_update(nid))
2447-
node_set_perf_attrs(nid, &cxlr->coord[i], i);
2448-
else
2449-
rc = cxl_update_hmat_access_coordinates(nid, cxlr, i);
2450-
2451-
if (rc == 0)
2452-
cset++;
2451+
node_update_perf_attrs(nid, &cxlr->coord[i], i);
2452+
cset++;
24532453
}
24542454
}
24552455

@@ -2487,6 +2487,10 @@ static int cxl_region_perf_attrs_callback(struct notifier_block *nb,
24872487
if (nid != region_nid)
24882488
return NOTIFY_DONE;
24892489

2490+
/* No action needed if node bit already set */
2491+
if (node_test_and_set(nid, nodemask_region_seen))
2492+
return NOTIFY_DONE;
2493+
24902494
if (!cxl_region_update_coordinates(cxlr, nid))
24912495
return NOTIFY_DONE;
24922496

include/linux/memory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ struct mem_section;
120120
*/
121121
#define DEFAULT_CALLBACK_PRI 0
122122
#define SLAB_CALLBACK_PRI 1
123-
#define HMAT_CALLBACK_PRI 2
124123
#define CXL_CALLBACK_PRI 5
124+
#define HMAT_CALLBACK_PRI 6
125125
#define MM_COMPUTE_BATCH_PRI 10
126126
#define CPUSET_CALLBACK_PRI 10
127127
#define MEMTIER_HOTPLUG_PRI 100

0 commit comments

Comments
 (0)