aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/numa/hmat.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/numa/hmat.c')
-rw-r--r--drivers/acpi/numa/hmat.c83
1 files changed, 64 insertions, 19 deletions
diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
index d6b85f0f6082f..2c8ccc91ebe6d 100644
--- a/drivers/acpi/numa/hmat.c
+++ b/drivers/acpi/numa/hmat.c
@@ -59,9 +59,8 @@ struct target_cache {
};
enum {
- NODE_ACCESS_CLASS_0 = 0,
- NODE_ACCESS_CLASS_1,
- NODE_ACCESS_CLASS_GENPORT_SINK,
+ NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL = ACCESS_COORDINATE_MAX,
+ NODE_ACCESS_CLASS_GENPORT_SINK_CPU,
NODE_ACCESS_CLASS_MAX,
};
@@ -75,6 +74,7 @@ struct memory_target {
struct node_cache_attrs cache_attrs;
u8 gen_port_device_handle[ACPI_SRAT_DEVICE_HANDLE_SIZE];
bool registered;
+ bool ext_updated; /* externally updated */
};
struct memory_initiator {
@@ -127,7 +127,8 @@ static struct memory_target *acpi_find_genport_target(u32 uid)
/**
* acpi_get_genport_coordinates - Retrieve the access coordinates for a generic port
* @uid: ACPI unique id
- * @coord: The access coordinates written back out for the generic port
+ * @coord: The access coordinates written back out for the generic port.
+ * Expect 2 levels array.
*
* Return: 0 on success. Errno on failure.
*
@@ -143,7 +144,10 @@ int acpi_get_genport_coordinates(u32 uid,
if (!target)
return -ENOENT;
- *coord = target->coord[NODE_ACCESS_CLASS_GENPORT_SINK];
+ coord[ACCESS_COORDINATE_LOCAL] =
+ target->coord[NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL];
+ coord[ACCESS_COORDINATE_CPU] =
+ target->coord[NODE_ACCESS_CLASS_GENPORT_SINK_CPU];
return 0;
}
@@ -325,6 +329,35 @@ static void hmat_update_target_access(struct memory_target *target,
}
}
+int hmat_update_target_coordinates(int nid, struct access_coordinate *coord,
+ enum access_coordinate_class access)
+{
+ struct memory_target *target;
+ int pxm;
+
+ if (nid == NUMA_NO_NODE)
+ return -EINVAL;
+
+ pxm = node_to_pxm(nid);
+ guard(mutex)(&target_lock);
+ target = find_mem_target(pxm);
+ if (!target)
+ return -ENODEV;
+
+ hmat_update_target_access(target, ACPI_HMAT_READ_LATENCY,
+ coord->read_latency, access);
+ hmat_update_target_access(target, ACPI_HMAT_WRITE_LATENCY,
+ coord->write_latency, access);
+ hmat_update_target_access(target, ACPI_HMAT_READ_BANDWIDTH,
+ coord->read_bandwidth, access);
+ hmat_update_target_access(target, ACPI_HMAT_WRITE_BANDWIDTH,
+ coord->write_bandwidth, access);
+ target->ext_updated = true;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hmat_update_target_coordinates);
+
static __init void hmat_add_locality(struct acpi_hmat_locality *hmat_loc)
{
struct memory_locality *loc;
@@ -374,11 +407,11 @@ static __init void hmat_update_target(unsigned int tgt_pxm, unsigned int init_px
if (target && target->processor_pxm == init_pxm) {
hmat_update_target_access(target, type, value,
- NODE_ACCESS_CLASS_0);
+ ACCESS_COORDINATE_LOCAL);
/* If the node has a CPU, update access 1 */
if (node_state(pxm_to_node(init_pxm), N_CPU))
hmat_update_target_access(target, type, value,
- NODE_ACCESS_CLASS_1);
+ ACCESS_COORDINATE_CPU);
}
}
@@ -696,8 +729,13 @@ static void hmat_update_target_attrs(struct memory_target *target,
u32 best = 0;
int i;
+ /* Don't update if an external agent has changed the data. */
+ if (target->ext_updated)
+ return;
+
/* Don't update for generic port if there's no device handle */
- if (access == NODE_ACCESS_CLASS_GENPORT_SINK &&
+ if ((access == NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL ||
+ access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&
!(*(u16 *)target->gen_port_device_handle))
return;
@@ -709,7 +747,8 @@ static void hmat_update_target_attrs(struct memory_target *target,
*/
if (target->processor_pxm != PXM_INVAL) {
cpu_nid = pxm_to_node(target->processor_pxm);
- if (access == 0 || node_state(cpu_nid, N_CPU)) {
+ if (access == ACCESS_COORDINATE_LOCAL ||
+ node_state(cpu_nid, N_CPU)) {
set_bit(target->processor_pxm, p_nodes);
return;
}
@@ -737,7 +776,9 @@ static void hmat_update_target_attrs(struct memory_target *target,
list_for_each_entry(initiator, &initiators, node) {
u32 value;
- if (access == 1 && !initiator->has_cpu) {
+ if ((access == ACCESS_COORDINATE_CPU ||
+ access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&
+ !initiator->has_cpu) {
clear_bit(initiator->processor_pxm, p_nodes);
continue;
}
@@ -770,20 +811,24 @@ static void __hmat_register_target_initiators(struct memory_target *target,
}
}
-static void hmat_register_generic_target_initiators(struct memory_target *target)
+static void hmat_update_generic_target(struct memory_target *target)
{
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
- __hmat_register_target_initiators(target, p_nodes,
- NODE_ACCESS_CLASS_GENPORT_SINK);
+ hmat_update_target_attrs(target, p_nodes,
+ NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL);
+ hmat_update_target_attrs(target, p_nodes,
+ NODE_ACCESS_CLASS_GENPORT_SINK_CPU);
}
static void hmat_register_target_initiators(struct memory_target *target)
{
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
- __hmat_register_target_initiators(target, p_nodes, 0);
- __hmat_register_target_initiators(target, p_nodes, 1);
+ __hmat_register_target_initiators(target, p_nodes,
+ ACCESS_COORDINATE_LOCAL);
+ __hmat_register_target_initiators(target, p_nodes,
+ ACCESS_COORDINATE_CPU);
}
static void hmat_register_target_cache(struct memory_target *target)
@@ -835,7 +880,7 @@ static void hmat_register_target(struct memory_target *target)
*/
mutex_lock(&target_lock);
if (*(u16 *)target->gen_port_device_handle) {
- hmat_register_generic_target_initiators(target);
+ hmat_update_generic_target(target);
target->registered = true;
}
mutex_unlock(&target_lock);
@@ -854,8 +899,8 @@ static void hmat_register_target(struct memory_target *target)
if (!target->registered) {
hmat_register_target_initiators(target);
hmat_register_target_cache(target);
- hmat_register_target_perf(target, NODE_ACCESS_CLASS_0);
- hmat_register_target_perf(target, NODE_ACCESS_CLASS_1);
+ hmat_register_target_perf(target, ACCESS_COORDINATE_LOCAL);
+ hmat_register_target_perf(target, ACCESS_COORDINATE_CPU);
target->registered = true;
}
mutex_unlock(&target_lock);
@@ -927,7 +972,7 @@ static int hmat_calculate_adistance(struct notifier_block *self,
return NOTIFY_OK;
mutex_lock(&target_lock);
- hmat_update_target_attrs(target, p_nodes, 1);
+ hmat_update_target_attrs(target, p_nodes, ACCESS_COORDINATE_CPU);
mutex_unlock(&target_lock);
perf = &target->coord[1];