• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * osal_mem.c
3  *
4  * osal driver
5  *
6  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  */
18 
19 #include "osal_mem.h"
20 #include <linux/export.h>
21 #include <linux/slab.h>
22 #include <linux/string.h>
23 #include <linux/vmalloc.h>
24 #include "hdf_log.h"
25 #include "securec.h"
26 
27 #define HDF_LOG_TAG osal_mem
28 
29 #define KMALLOC_SIZE 0x20000
30 
31 struct mem_hdr {
32 	uint32_t type;
33 	uint32_t offset;
34 };
35 
36 struct mem_block {
37 	struct mem_hdr hdr;
38 	uint8_t mem[0];
39 };
40 
41 enum {
42 	TYPE_KMALLOC = 0xa5a5a5a1,
43 	TYPE_VMALLOC = 0xa5a5a5a2,
44 };
45 
osal_mem_alloc(size_t size,uint32_t * type)46 static void *osal_mem_alloc(size_t size, uint32_t *type)
47 {
48 	char *base = NULL;
49 	const uint32_t mng_size = sizeof(struct mem_block);
50 	if (size > (SIZE_MAX - mng_size)) {
51 		HDF_LOGE("%s invalid param %d", __func__, size);
52 		return NULL;
53 	}
54 
55 	if (size > (KMALLOC_SIZE - mng_size)) {
56 		base = (char *)vmalloc(size + mng_size);
57 		*type = TYPE_VMALLOC;
58 	} else {
59 		base = (char *)kmalloc(size + mng_size, GFP_KERNEL);
60 		*type = TYPE_KMALLOC;
61 	}
62 
63 	return base;
64 }
65 
OsalMemAlloc(size_t size)66 void *OsalMemAlloc(size_t size)
67 {
68 	void *buf = NULL;
69 	char *base = NULL;
70 	struct mem_block *block = NULL;
71 	const uint32_t mng_size = sizeof(*block);
72 	uint32_t type;
73 
74 	if (size == 0) {
75 		HDF_LOGE("%s invalid param", __func__);
76 		return NULL;
77 	}
78 
79 	base = osal_mem_alloc(size, &type);
80 	if (base == NULL) {
81 		HDF_LOGE("%s malloc fail %d", __func__, size);
82 		return NULL;
83 	}
84 
85 	block = (struct mem_block *)base;
86 	block->hdr.type = type;
87 	block->hdr.offset = 0;
88 
89 	buf = (void *)(base + mng_size);
90 
91 	return buf;
92 }
93 EXPORT_SYMBOL(OsalMemAlloc);
94 
OsalMemCalloc(size_t size)95 void *OsalMemCalloc(size_t size)
96 {
97 	void *buf = NULL;
98 
99 	if (size == 0) {
100 		HDF_LOGE("%s invalid param", __func__);
101 		return NULL;
102 	}
103 
104 	buf = OsalMemAlloc(size);
105 	if (buf != NULL)
106 		(void)memset_s(buf, size, 0, size);
107 
108 	return buf;
109 }
110 EXPORT_SYMBOL(OsalMemCalloc);
111 
OsalMemAllocAlign(size_t alignment,size_t size)112 void *OsalMemAllocAlign(size_t alignment, size_t size)
113 {
114 	char *base = NULL;
115 	char *buf = NULL;
116 	struct mem_block *block = NULL;
117 	const uint32_t mng_size = sizeof(*block);
118 	uint32_t type;
119 	uint32_t offset;
120 	char *aligned_ptr = NULL;
121 
122 	if (size == 0 || (alignment == 0) || ((alignment & (alignment - 1)) != 0) ||
123 		((alignment % sizeof(void *)) != 0) || size > (SIZE_MAX - alignment)) {
124 		HDF_LOGE("%s invalid param align:%d,size:%d", __func__, alignment, size);
125 		return NULL;
126 	}
127 
128 	base = osal_mem_alloc(size + alignment, &type);
129 	if (base == NULL) {
130 		HDF_LOGE("%s malloc fail %d", __func__, size);
131 		return NULL;
132 	}
133 
134 	buf = base + mng_size;
135 	aligned_ptr = (char *)(uintptr_t)(((size_t)(uintptr_t)buf + alignment - 1) & ~(alignment - 1));
136 	offset = aligned_ptr - buf;
137 	block = (struct mem_block *)(base + offset);
138 	block->hdr.type = type;
139 	block->hdr.offset = offset;
140 
141 	return aligned_ptr;
142 }
143 EXPORT_SYMBOL(OsalMemAllocAlign);
144 
OsalMemFree(void * buf)145 void OsalMemFree(void *buf)
146 {
147 	uint32_t type;
148 	char *base = NULL;
149 	struct mem_block *block = NULL;
150 
151 	if (buf == NULL) {
152 		return;
153 	}
154 
155 	block = (struct mem_block *)((char *)buf - (char *)&((struct mem_block *)0)->mem);
156 	type = block->hdr.type;
157 	base = (char *)block - block->hdr.offset;
158 
159 	if (type == TYPE_KMALLOC)
160 		kfree(base);
161 	else if (type == TYPE_VMALLOC)
162 		vfree(base);
163 	else
164 		HDF_LOGE("%s block : type %u fail", __func__, type);
165 }
166 EXPORT_SYMBOL(OsalMemFree);
167 
168