summaryrefslogtreecommitdiff
path: root/mali_pixel/memory_group_manager.c
diff options
context:
space:
mode:
authorSidath Senanayake <sidaths@google.com>2021-06-15 13:39:30 +0100
committerSidath Senanayake <sidaths@google.com>2021-06-15 14:11:16 +0100
commitfca8613cfcf585bf9113dca96a05daea9fd89794 (patch)
treef2baa14910f83edf00450bc30d3703eb255a0bba /mali_pixel/memory_group_manager.c
parent8037b534570814775d79aeddd06b76e5ee941f59 (diff)
downloadgpu-fca8613cfcf585bf9113dca96a05daea9fd89794.tar.gz
Mali Valhall DDK r31p0 KMD
Provenance: 2ea0ef9bd (collaborate/EAC/v_r31p0) VX504X08X-BU-00000-r31p0-01eac0 - Valhall Android DDK VX504X08X-BU-60000-r31p0-01eac0 - Valhall Android Document Bundle VX504X08X-DC-11001-r31p0-01eac0 - Valhall Android DDK Software Errata VX504X08X-SW-99006-r31p0-01eac0 - Valhall Android Renderscript AOSP parts Signed-off-by: Sidath Senanayake <sidaths@google.com> Change-Id: Ide9d5fdc6d9c95fa66a3546b01f619b43c09496d
Diffstat (limited to 'mali_pixel/memory_group_manager.c')
-rw-r--r--mali_pixel/memory_group_manager.c492
1 files changed, 0 insertions, 492 deletions
diff --git a/mali_pixel/memory_group_manager.c b/mali_pixel/memory_group_manager.c
deleted file mode 100644
index 6e10722..0000000
--- a/mali_pixel/memory_group_manager.c
+++ /dev/null
@@ -1,492 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *
- * (C) COPYRIGHT 2019-2020 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation, and any use by you of this program is subject to the terms
- * of such GNU license.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you can access it online at
- * http://www.gnu.org/licenses/gpl-2.0.html.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#endif
-#include <linux/mm.h>
-#include <linux/memory_group_manager.h>
-
-#if (KERNEL_VERSION(4, 20, 0) > LINUX_VERSION_CODE)
-static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma,
- unsigned long addr, unsigned long pfn, pgprot_t pgprot)
-{
- int err;
-
-#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \
- ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \
- (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE)))
- if (pgprot_val(pgprot) != pgprot_val(vma->vm_page_prot))
- return VM_FAULT_SIGBUS;
-
- err = vm_insert_pfn(vma, addr, pfn);
-#else
- err = vm_insert_pfn_prot(vma, addr, pfn, pgprot);
-#endif
-
- if (unlikely(err == -ENOMEM))
- return VM_FAULT_OOM;
- if (unlikely(err < 0 && err != -EBUSY))
- return VM_FAULT_SIGBUS;
-
- return VM_FAULT_NOPAGE;
-}
-#endif
-
-#define IMPORTED_MEMORY_ID (MEMORY_GROUP_MANAGER_NR_GROUPS - 1)
-
-/**
- * struct mgm_group - Structure to keep track of the number of allocated
- * pages per group
- *
- * @size: The number of allocated small(4KB) pages
- * @lp_size: The number of allocated large(2MB) pages
- * @insert_pfn: The number of calls to map pages for CPU access.
- * @update_gpu_pte: The number of calls to update GPU page table entries.
- *
- * This structure allows page allocation information to be displayed via
- * debugfs. Display is organized per group with small and large sized pages.
- */
-struct mgm_group {
- size_t size;
- size_t lp_size;
- size_t insert_pfn;
- size_t update_gpu_pte;
-};
-
-/**
- * struct mgm_groups - Structure for groups of memory group manager
- *
- * @groups: To keep track of the number of allocated pages of all groups
- * @dev: device attached
- * @mgm_debugfs_root: debugfs root directory of memory group manager
- *
- * This structure allows page allocation information to be displayed via
- * debugfs. Display is organized per group with small and large sized pages.
- */
-struct mgm_groups {
- struct mgm_group groups[MEMORY_GROUP_MANAGER_NR_GROUPS];
- struct device *dev;
-#ifdef CONFIG_DEBUG_FS
- struct dentry *mgm_debugfs_root;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_FS
-
-static int mgm_size_get(void *data, u64 *val)
-{
- struct mgm_group *group = data;
-
- *val = group->size;
-
- return 0;
-}
-
-static int mgm_lp_size_get(void *data, u64 *val)
-{
- struct mgm_group *group = data;
-
- *val = group->lp_size;
-
- return 0;
-}
-
-static int mgm_insert_pfn_get(void *data, u64 *val)
-{
- struct mgm_group *group = data;
-
- *val = group->insert_pfn;
-
- return 0;
-}
-
-static int mgm_update_gpu_pte_get(void *data, u64 *val)
-{
- struct mgm_group *group = data;
-
- *val = group->update_gpu_pte;
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_mgm_size, mgm_size_get, NULL, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(fops_mgm_lp_size, mgm_lp_size_get, NULL, "%llu\n");
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_mgm_insert_pfn, mgm_insert_pfn_get, NULL,
- "%llu\n");
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_mgm_update_gpu_pte, mgm_update_gpu_pte_get, NULL,
- "%llu\n");
-
-static void mgm_term_debugfs(struct mgm_groups *data)
-{
- debugfs_remove_recursive(data->mgm_debugfs_root);
-}
-
-#define MGM_DEBUGFS_GROUP_NAME_MAX 10
-static int mgm_initialize_debugfs(struct mgm_groups *mgm_data)
-{
- int i;
- struct dentry *e, *g;
- char debugfs_group_name[MGM_DEBUGFS_GROUP_NAME_MAX];
-
- /*
- * Create root directory of memory-group-manager
- */
- mgm_data->mgm_debugfs_root =
- debugfs_create_dir("physical-memory-group-manager", NULL);
- if (IS_ERR(mgm_data->mgm_debugfs_root)) {
- dev_err(mgm_data->dev, "fail to create debugfs root directory\n");
- return -ENODEV;
- }
-
- /*
- * Create debugfs files per group
- */
- for (i = 0; i < MEMORY_GROUP_MANAGER_NR_GROUPS; i++) {
- scnprintf(debugfs_group_name, MGM_DEBUGFS_GROUP_NAME_MAX,
- "group_%d", i);
- g = debugfs_create_dir(debugfs_group_name,
- mgm_data->mgm_debugfs_root);
- if (IS_ERR(g)) {
- dev_err(mgm_data->dev, "fail to create group[%d]\n", i);
- goto remove_debugfs;
- }
-
- e = debugfs_create_file("size", 0444, g, &mgm_data->groups[i],
- &fops_mgm_size);
- if (IS_ERR(e)) {
- dev_err(mgm_data->dev, "fail to create size[%d]\n", i);
- goto remove_debugfs;
- }
-
- e = debugfs_create_file("lp_size", 0444, g,
- &mgm_data->groups[i], &fops_mgm_lp_size);
- if (IS_ERR(e)) {
- dev_err(mgm_data->dev,
- "fail to create lp_size[%d]\n", i);
- goto remove_debugfs;
- }
-
- e = debugfs_create_file("insert_pfn", 0444, g,
- &mgm_data->groups[i], &fops_mgm_insert_pfn);
- if (IS_ERR(e)) {
- dev_err(mgm_data->dev,
- "fail to create insert_pfn[%d]\n", i);
- goto remove_debugfs;
- }
-
- e = debugfs_create_file("update_gpu_pte", 0444, g,
- &mgm_data->groups[i], &fops_mgm_update_gpu_pte);
- if (IS_ERR(e)) {
- dev_err(mgm_data->dev,
- "fail to create update_gpu_pte[%d]\n", i);
- goto remove_debugfs;
- }
- }
-
- return 0;
-
-remove_debugfs:
- mgm_term_debugfs(mgm_data);
- return -ENODEV;
-}
-
-#else
-
-static void mgm_term_debugfs(struct mgm_groups *data)
-{
-}
-
-static int mgm_initialize_debugfs(struct mgm_groups *mgm_data)
-{
- return 0;
-}
-
-#endif /* CONFIG_DEBUG_FS */
-
-#define ORDER_SMALL_PAGE 0
-#define ORDER_LARGE_PAGE 9
-static void update_size(struct memory_group_manager_device *mgm_dev, int
- group_id, int order, bool alloc)
-{
- struct mgm_groups *data = mgm_dev->data;
-
- switch (order) {
- case ORDER_SMALL_PAGE:
- if (alloc)
- data->groups[group_id].size++;
- else {
- WARN_ON(data->groups[group_id].size == 0);
- data->groups[group_id].size--;
- }
- break;
-
- case ORDER_LARGE_PAGE:
- if (alloc)
- data->groups[group_id].lp_size++;
- else {
- WARN_ON(data->groups[group_id].lp_size == 0);
- data->groups[group_id].lp_size--;
- }
- break;
-
- default:
- dev_err(data->dev, "Unknown order(%d)\n", order);
- break;
- }
-}
-
-static struct page *example_mgm_alloc_page(
- struct memory_group_manager_device *mgm_dev, int group_id,
- gfp_t gfp_mask, unsigned int order)
-{
- struct mgm_groups *const data = mgm_dev->data;
- struct page *p;
-
- dev_dbg(data->dev, "%s(mgm_dev=%p, group_id=%d gfp_mask=0x%x order=%u\n",
- __func__, (void *)mgm_dev, group_id, gfp_mask, order);
-
- if (WARN_ON(group_id < 0) ||
- WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS))
- return NULL;
-
- p = alloc_pages(gfp_mask, order);
-
- if (p) {
- update_size(mgm_dev, group_id, order, true);
- } else {
- struct mgm_groups *data = mgm_dev->data;
-
- dev_err(data->dev, "alloc_pages failed\n");
- }
-
- return p;
-}
-
-static void example_mgm_free_page(
- struct memory_group_manager_device *mgm_dev, int group_id,
- struct page *page, unsigned int order)
-{
- struct mgm_groups *const data = mgm_dev->data;
-
- dev_dbg(data->dev, "%s(mgm_dev=%p, group_id=%d page=%p order=%u\n",
- __func__, (void *)mgm_dev, group_id, (void *)page, order);
-
- if (WARN_ON(group_id < 0) ||
- WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS))
- return;
-
- __free_pages(page, order);
-
- update_size(mgm_dev, group_id, order, false);
-}
-
-static int example_mgm_get_import_memory_id(
- struct memory_group_manager_device *mgm_dev,
- struct memory_group_manager_import_data *import_data)
-{
- struct mgm_groups *const data = mgm_dev->data;
-
- dev_dbg(data->dev, "%s(mgm_dev=%p, import_data=%p (type=%d)\n",
- __func__, (void *)mgm_dev, (void *)import_data,
- (int)import_data->type);
-
- if (!WARN_ON(!import_data)) {
- WARN_ON(!import_data->u.dma_buf);
-
- WARN_ON(import_data->type !=
- MEMORY_GROUP_MANAGER_IMPORT_TYPE_DMA_BUF);
- }
-
- return IMPORTED_MEMORY_ID;
-}
-
-static u64 example_mgm_update_gpu_pte(
- struct memory_group_manager_device *const mgm_dev, int const group_id,
- int const mmu_level, u64 pte)
-{
- struct mgm_groups *const data = mgm_dev->data;
- const u32 pbha_bit_pos = 59; /* bits 62:59 */
- const u32 pbha_bit_mask = 0xf; /* 4-bit */
-
- dev_dbg(data->dev,
- "%s(mgm_dev=%p, group_id=%d, mmu_level=%d, pte=0x%llx)\n",
- __func__, (void *)mgm_dev, group_id, mmu_level, pte);
-
- if (WARN_ON(group_id < 0) ||
- WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS))
- return pte;
-
- pte |= ((u64)group_id & pbha_bit_mask) << pbha_bit_pos;
-
- data->groups[group_id].update_gpu_pte++;
-
- return pte;
-}
-
-static vm_fault_t example_mgm_vmf_insert_pfn_prot(
- struct memory_group_manager_device *const mgm_dev, int const group_id,
- struct vm_area_struct *const vma, unsigned long const addr,
- unsigned long const pfn, pgprot_t const prot)
-{
- struct mgm_groups *const data = mgm_dev->data;
- vm_fault_t fault;
-
- dev_dbg(data->dev,
- "%s(mgm_dev=%p, group_id=%d, vma=%p, addr=0x%lx, pfn=0x%lx, prot=0x%llx)\n",
- __func__, (void *)mgm_dev, group_id, (void *)vma, addr, pfn,
- (unsigned long long int) pgprot_val(prot));
-
- if (WARN_ON(group_id < 0) ||
- WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS))
- return VM_FAULT_SIGBUS;
-
- fault = vmf_insert_pfn_prot(vma, addr, pfn, prot);
-
- if (fault == VM_FAULT_NOPAGE)
- data->groups[group_id].insert_pfn++;
- else
- dev_err(data->dev, "vmf_insert_pfn_prot failed\n");
-
- return fault;
-}
-
-static int mgm_initialize_data(struct mgm_groups *mgm_data)
-{
- int i;
-
- for (i = 0; i < MEMORY_GROUP_MANAGER_NR_GROUPS; i++) {
- mgm_data->groups[i].size = 0;
- mgm_data->groups[i].lp_size = 0;
- mgm_data->groups[i].insert_pfn = 0;
- mgm_data->groups[i].update_gpu_pte = 0;
- }
-
- return mgm_initialize_debugfs(mgm_data);
-}
-
-static void mgm_term_data(struct mgm_groups *data)
-{
- int i;
-
- for (i = 0; i < MEMORY_GROUP_MANAGER_NR_GROUPS; i++) {
- if (data->groups[i].size != 0)
- dev_warn(data->dev,
- "%zu 0-order pages in group(%d) leaked\n",
- data->groups[i].size, i);
- if (data->groups[i].lp_size != 0)
- dev_warn(data->dev,
- "%zu 9 order pages in group(%d) leaked\n",
- data->groups[i].lp_size, i);
- }
-
- mgm_term_debugfs(data);
-}
-
-static int memory_group_manager_probe(struct platform_device *pdev)
-{
- struct memory_group_manager_device *mgm_dev;
- struct mgm_groups *mgm_data;
-
- mgm_dev = kzalloc(sizeof(*mgm_dev), GFP_KERNEL);
- if (!mgm_dev)
- return -ENOMEM;
-
- mgm_dev->owner = THIS_MODULE;
- mgm_dev->ops.mgm_alloc_page = example_mgm_alloc_page;
- mgm_dev->ops.mgm_free_page = example_mgm_free_page;
- mgm_dev->ops.mgm_get_import_memory_id =
- example_mgm_get_import_memory_id;
- mgm_dev->ops.mgm_vmf_insert_pfn_prot = example_mgm_vmf_insert_pfn_prot;
- mgm_dev->ops.mgm_update_gpu_pte = example_mgm_update_gpu_pte;
-
- mgm_data = kzalloc(sizeof(*mgm_data), GFP_KERNEL);
- if (!mgm_data) {
- kfree(mgm_dev);
- return -ENOMEM;
- }
-
- mgm_dev->data = mgm_data;
- mgm_data->dev = &pdev->dev;
-
- if (mgm_initialize_data(mgm_data)) {
- kfree(mgm_data);
- kfree(mgm_dev);
- return -ENOENT;
- }
-
- platform_set_drvdata(pdev, mgm_dev);
- dev_info(&pdev->dev, "Memory group manager probed successfully\n");
-
- return 0;
-}
-
-static int memory_group_manager_remove(struct platform_device *pdev)
-{
- struct memory_group_manager_device *mgm_dev =
- platform_get_drvdata(pdev);
- struct mgm_groups *mgm_data = mgm_dev->data;
-
- mgm_term_data(mgm_data);
- kfree(mgm_data);
-
- kfree(mgm_dev);
-
- dev_info(&pdev->dev, "Memory group manager removed successfully\n");
-
- return 0;
-}
-
-static const struct of_device_id memory_group_manager_dt_ids[] = {
- { .compatible = "arm,physical-memory-group-manager" },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, memory_group_manager_dt_ids);
-
-static struct platform_driver memory_group_manager_driver = {
- .probe = memory_group_manager_probe,
- .remove = memory_group_manager_remove,
- .driver = {
- .name = "physical-memory-group-manager",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(memory_group_manager_dt_ids),
- /*
- * Prevent the mgm_dev from being unbound and freed, as other's
- * may have pointers to it and would get confused, or crash, if
- * it suddenly disappear.
- */
- .suppress_bind_attrs = true,
- }
-};
-
-module_platform_driver(memory_group_manager_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("ARM Ltd.");
-MODULE_VERSION("1.0");