From d1423b817c3812ba2c8a571d0827aff46eddf1a8 Mon Sep 17 00:00:00 2001 From: Ketan Patil Date: Fri, 19 Apr 2024 05:26:39 +0000 Subject: [PATCH] video: tegra: nvmap: Add numa aware query for system memory NvRmMemQueryHeapParamsNuma API does not have support to query system memory per numa node. Add that support by parsing the meminfo file for the input numa node and obtain total memory, free memory and reclaimable memory values. Bug 4231517 Change-Id: I28e70c5163f5fc4fb746e11b087a003a0345bdf5 Signed-off-by: Ketan Patil Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3119501 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/video/tegra/nvmap/nvmap_ioctl.c | 77 +++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c index dc3de1e9..cf6a17a4 100644 --- a/drivers/video/tegra/nvmap/nvmap_ioctl.c +++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c @@ -38,6 +38,7 @@ #include "nvmap_heap.h" #include +#include #if defined(CONFIG_TEGRA_SYSTEM_TYPE_ACK) MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); @@ -1148,6 +1149,58 @@ int nvmap_ioctl_handle_from_sci_ipc_id(struct file *filp, void __user *arg) } #endif +/* + * This function calculates total memory and allocable free memory by parsing + * /sys/devices/system/node/nodeX/meminfo file + * total memory = value of MemTotal field + * allocable free memory = Value of MemFree field + (Value of KReclaimable) / 2 + * Note that the above allocable free memory value is an estimate and may not be an + * exact value and may need further tuning in future. + */ +#define MEMINFO_SIZE 1536 +static int compute_memory_stat(u64 *total, u64 *free, int numa_id) +{ + struct file *file; + char meminfo_path[64] = {'\0'}; + u8 buf[MEMINFO_SIZE]; + loff_t pos = 0; + char *buffer, *ptr; + u64 mem_total, mem_free, reclaimable; + bool total_found = false, free_found = false, reclaimable_found = false; + int nid, rc; + + sprintf(meminfo_path, "/sys/devices/system/node/node%d/meminfo", numa_id); + file = filp_open(meminfo_path, O_RDONLY, 0); + if (IS_ERR(file)) { + pr_err("Could not open file:%s\n", meminfo_path); + return -EINVAL; + } + + memset(buf, 0, sizeof(buf)); + rc = kernel_read(file, buf, MEMINFO_SIZE - 1, &pos); + buf[rc] = '\n'; + filp_close(file, NULL); + buffer = buf; + ptr = buf; + while ((ptr = strsep(&buffer, "\n")) != NULL) { + if (!ptr[0]) + continue; + else if (sscanf(ptr, "Node %d MemTotal: %llu kB\n", &nid, &mem_total) == 2) + total_found = true; + else if (sscanf(ptr, "Node %d MemFree: %llu kB\n", &nid, &mem_free) == 2) + free_found = true; + else if (sscanf(ptr, "Node %d KReclaimable: %llu kB\n", &nid, &reclaimable) == 2) + reclaimable_found = true; + } + + if (nid == numa_id && total_found && free_found && reclaimable_found) { + *total = mem_total * 1024; + *free = (mem_free + reclaimable / 2) * 1024; + return 0; + } + return -EINVAL; +} + /* * This function calculates allocatable free memory using following formula: * free_mem = avail mem - cma free @@ -1241,11 +1294,25 @@ static int nvmap_query_heap_params(void __user *arg, bool is_numa_aware) return -ENODEV; } else if (type & iovmm_mask) { - op.total = system_heap_total_mem(); - ret = system_heap_free_mem(&free_mem); - if (ret) - goto exit; - op.free = free_mem; + if (num_online_nodes() > 1) { + /* multiple numa node exist */ + ret = compute_memory_stat(&op.total, &op.free, numa_id); + if (ret) + goto exit; + } else { + /* Single numa node case + * Check if input numa_id is zero or not. + */ + if (is_numa_aware && numa_id != 0) { + pr_err("Incorrect input for numa_id:%d\n", numa_id); + return -EINVAL; + } + op.total = system_heap_total_mem(); + ret = system_heap_free_mem(&free_mem); + if (ret) + goto exit; + op.free = free_mem; + } op.granule_size = PAGE_SIZE; }