Commit a1390bb0 authored by Zhang Zekun's avatar Zhang Zekun Committed by Zhong Jinghua
Browse files

soc: hisilicon: hisi_hbmdev: Provide extra memory topology information

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I67QNJ


CVE: NA

--------------------------------------------------

Provide additional memory device topology information in
hisi_hbmdev. This memory topology informaton can provide
useful information for userspace to select the closest
memory device to a certain cpu.

Signed-off-by: default avatarZhang Zekun <zhangzekun11@huawei.com>
Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
parent 27443370
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -9,9 +9,12 @@ config HISI_HBMDEV
	depends on ACPI_HOTPLUG_MEMORY
	select ACPI_CONTAINER
	help
	  This driver add extra supports for memory devices. The driver
	  provides methods for userpace to control the power of memory
	  devices in a container.
	  This driver add two extra supports for memory devices. The driver
	  provides methods for userpace to control the power of memory devices
	  in a container. Besides, it provides extra locality information
	  between cpus and memory devices for userspace, which can take
	  advantage of this functionality to select the closet memory device
	  to a certain cpu.

	  To compile this driver as a module, choose M here:
	  the module will be called hisi_hbmdev.
+61 −0
Original line number Diff line number Diff line
@@ -8,6 +8,9 @@
#include <linux/nodemask.h>
#include <linux/acpi.h>
#include <linux/container.h>
#include <linux/node.h>
#include <linux/arch_topology.h>
#include <linux/memory_hotplug.h>

#include "hisi_internal.h"

@@ -21,11 +24,67 @@ struct cdev_node {

struct memory_dev {
	struct kobject *memdev_kobj;
	struct kobject *topo_kobj;
	struct cdev_node cdev_list;
	nodemask_t cluster_cpumask[MAX_NUMNODES];
};

static struct memory_dev *mdev;

static ssize_t memory_locality_show(struct kobject *kobj,
				   struct kobj_attribute *attr,
				   char *buf)
{
	int i, count = 0;

	for (i = 0; i < MAX_NUMNODES; i++) {
		if (hotplug_mdev[i] != NULL && !nodes_empty(mdev->cluster_cpumask[i])) {
			count += sysfs_emit_at(buf, count, "%d %*pbl\n", i,
					       nodemask_pr_args(&mdev->cluster_cpumask[i]));
		}
	}

	return count;
}

static struct kobj_attribute memory_locality_attribute =
	__ATTR(memory_locality, 0444, memory_locality_show, NULL);

static void memory_topo_init(void)
{
	int ret, nid, cluster_id, cpu;
	struct acpi_device *adev;
	nodemask_t mask;

	for (nid = 0; nid < MAX_NUMNODES; nid++) {
		if (!hotplug_mdev[nid])
			continue;

		adev = hotplug_mdev[nid];
		ret = fwnode_property_read_u32(acpi_fwnode_handle(adev),
						"cluster-id", &cluster_id);
		if (ret < 0) {
			pr_debug("Failed to read cluster id\n");
			return;
		}

		nodes_clear(mask);
		for_each_possible_cpu(cpu) {
			if (topology_cluster_id(cpu) == cluster_id)
				node_set(cpu, mask);
		}
		mdev->cluster_cpumask[nid] = mask;
	}

	mdev->topo_kobj = kobject_create_and_add("memory_topo", mdev->memdev_kobj);
	if (!mdev->topo_kobj)
		return;

	ret = sysfs_create_file(mdev->topo_kobj, &memory_locality_attribute.attr);
	if (ret)
		kobject_put(mdev->topo_kobj);
}

static int get_pxm(struct acpi_device *acpi_device, void *arg)
{
	acpi_handle handle = acpi_device->handle;
@@ -224,6 +283,7 @@ static int __init mdev_init(void)
		return -ENOMEM;
	}

	memory_topo_init();
	return ret;
}
module_init(mdev_init);
@@ -232,6 +292,7 @@ static void __exit mdev_exit(void)
{
	container_remove();
	kobject_put(mdev->memdev_kobj);
	kobject_put(mdev->topo_kobj);
	kfree(mdev);
}
module_exit(mdev_exit);