/* * Copyright (C) 2022 Huawei Technologies Co., Ltd. * Decription: memory operation for gp sharedmem. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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. */ #include "mem.h" #include #include #include #include #include #include #include #include #include #include #include #include "smc_smp.h" #include "tc_ns_client.h" #include "teek_ns_client.h" #include "agent.h" #include "tc_ns_log.h" #include "mailbox_mempool.h" #include "internal_functions.h" #include "reserved_mempool.h" void tc_mem_free(struct tc_ns_shared_mem *shared_mem) { if (!shared_mem) return; if (shared_mem->mem_type == RESERVED_TYPE) { reserved_mem_free(shared_mem->kernel_addr); kfree(shared_mem); return; } if (shared_mem->kernel_addr) { #ifndef CONFIG_LIBLINUX vfree(shared_mem->kernel_addr); #else kfree(shared_mem->kernel_addr); #endif shared_mem->kernel_addr = NULL; } kfree(shared_mem); } static void init_shared_mem(struct tc_ns_shared_mem *sh, void *addr, size_t len) { sh->kernel_addr = addr; sh->len = (uint32_t)len; sh->user_addr = INVALID_MAP_ADDR; sh->user_addr_ca = INVALID_MAP_ADDR; atomic_set(&sh->usage, 0); } struct tc_ns_shared_mem *tc_mem_allocate(size_t len) { struct tc_ns_shared_mem *shared_mem = NULL; void *addr = NULL; shared_mem = kmalloc(sizeof(*shared_mem), GFP_KERNEL | __GFP_ZERO); if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)shared_mem)) { tloge("shared_mem kmalloc failed\n"); return ERR_PTR(-ENOMEM); } shared_mem->mem_type = VMALLOC_TYPE; len = ALIGN(len, SZ_4K); if (exist_res_mem()) { if (len > get_res_mem_slice_size()) { tloge("allocate reserved mem size too large\n"); kfree(shared_mem); return ERR_PTR(-EINVAL); } addr = reserved_mem_alloc(len); if (addr) { shared_mem->mem_type = RESERVED_TYPE; init_shared_mem(shared_mem, addr, len); return shared_mem; } else { tlogw("no more reserved memory to alloc so we use system vmalloc.\n"); } } if (len > MAILBOX_POOL_SIZE) { tloge("alloc sharemem size %zu is too large\n", len); kfree(shared_mem); return ERR_PTR(-EINVAL); } #ifndef CONFIG_LIBLINUX addr = vmalloc_user(len); #else addr = kzalloc(len, GFP_KERNEL); #endif if (!addr) { tloge("alloc mailbox failed\n"); kfree(shared_mem); return ERR_PTR(-ENOMEM); } init_shared_mem(shared_mem, addr, len); return shared_mem; }