/* SPDX-License-Identifier: GPL-2.0 */ /* * * (C) COPYRIGHT 2019-2021 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. * */ #ifndef _MEMORY_GROUP_MANAGER_H_ #define _MEMORY_GROUP_MANAGER_H_ #include #include #include #if (KERNEL_VERSION(4, 17, 0) > LINUX_VERSION_CODE) typedef int vm_fault_t; #endif #define MEMORY_GROUP_MANAGER_NR_GROUPS (16) struct memory_group_manager_device; struct memory_group_manager_import_data; /** * struct memory_group_manager_ops - Callbacks for memory group manager * operations * * @mgm_alloc_page: Callback to allocate physical memory in a group * @mgm_free_page: Callback to free physical memory in a group * @mgm_get_import_memory_id: Callback to get the group ID for imported memory * @mgm_update_gpu_pte: Callback to modify a GPU page table entry * @mgm_vmf_insert_pfn_prot: Callback to map a physical memory page for the CPU */ struct memory_group_manager_ops { /** * mgm_alloc_page - Allocate a physical memory page in a group * * @mgm_dev: The memory group manager through which the request is * being made. * @group_id: A physical memory group ID. The meaning of this is defined * by the systems integrator. Its valid range is * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. * @gfp_mask: Bitmask of Get Free Page flags affecting allocator * behavior. * @order: Page order for physical page size (order=0 means 4 KiB, * order=9 means 2 MiB). * * Return: Pointer to allocated page, or NULL if allocation failed. */ struct page *(*mgm_alloc_page)( struct memory_group_manager_device *mgm_dev, int group_id, gfp_t gfp_mask, unsigned int order); /** * mgm_free_page - Free a physical memory page in a group * * @mgm_dev: The memory group manager through which the request * is being made. * @group_id: A physical memory group ID. The meaning of this is * defined by the systems integrator. Its valid range is * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. * @page: Address of the struct associated with a page of physical * memory that was allocated by calling the mgm_alloc_page * method of the same memory pool with the same values of * @group_id and @order. * @order: Page order for physical page size (order=0 means 4 KiB, * order=9 means 2 MiB). */ void (*mgm_free_page)( struct memory_group_manager_device *mgm_dev, int group_id, struct page *page, unsigned int order); /** * mgm_get_import_memory_id - Get the physical memory group ID for the * imported memory * * @mgm_dev: The memory group manager through which the request * is being made. * @import_data: Pointer to the data which describes imported memory. * * Note that provision of this call back is optional, where it is not * provided this call back pointer must be set to NULL to indicate it * is not in use. * * Return: The memory group ID to use when mapping pages from this * imported memory. */ int (*mgm_get_import_memory_id)( struct memory_group_manager_device *mgm_dev, struct memory_group_manager_import_data *import_data); /** * mgm_update_gpu_pte - Modify a GPU page table entry for a memory group * * @mgm_dev: The memory group manager through which the request * is being made. * @group_id: A physical memory group ID. The meaning of this is * defined by the systems integrator. Its valid range is * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. * @mmu_level: The level of the page table entry in @ate. * @pte: The page table entry to modify, in LPAE or AArch64 format * (depending on the driver's configuration). This should be * decoded to determine the physical address and any other * properties of the mapping the manager requires. * * This function allows the memory group manager to modify a GPU page * table entry before it is stored by the kbase module (controller * driver). It may set certain bits in the page table entry attributes * or in the physical address, based on the physical memory group ID. * * Return: A modified GPU page table entry to be stored in a page table. */ u64 (*mgm_update_gpu_pte)(struct memory_group_manager_device *mgm_dev, int group_id, int mmu_level, u64 pte); /** * mgm_vmf_insert_pfn_prot - Map a physical page in a group for the CPU * * @mgm_dev: The memory group manager through which the request * is being made. * @group_id: A physical memory group ID. The meaning of this is * defined by the systems integrator. Its valid range is * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. * @vma: The virtual memory area to insert the page into. * @addr: A virtual address (in @vma) to assign to the page. * @pfn: The kernel Page Frame Number to insert at @addr in @vma. * @pgprot: Protection flags for the inserted page. * * Called from a CPU virtual memory page fault handler. This function * creates a page table entry from the given parameter values and stores * it at the appropriate location (unlike mgm_update_gpu_pte, which * returns a modified entry). * * Return: Type of fault that occurred or VM_FAULT_NOPAGE if the page * table entry was successfully installed. */ vm_fault_t (*mgm_vmf_insert_pfn_prot)( struct memory_group_manager_device *mgm_dev, int group_id, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, pgprot_t pgprot); }; /** * struct memory_group_manager_device - Device structure for a memory group * manager * * @ops - Callbacks associated with this device * @data - Pointer to device private data * * In order for a systems integrator to provide custom behaviors for memory * operations performed by the kbase module (controller driver), they must * provide a platform-specific driver module which implements this interface. * * This structure should be registered with the platform device using * platform_set_drvdata(). */ struct memory_group_manager_device { struct memory_group_manager_ops ops; void *data; struct module *owner; }; enum memory_group_manager_import_type { MEMORY_GROUP_MANAGER_IMPORT_TYPE_DMA_BUF }; /** * struct memory_group_manager_import_data - Structure describing the imported * memory * * @type - type of imported memory * @u - Union describing the imported memory * */ struct memory_group_manager_import_data { enum memory_group_manager_import_type type; union { struct dma_buf *dma_buf; } u; }; #endif /* _MEMORY_GROUP_MANAGER_H_ */