1 /*
2 * Copyright (C) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #ifndef __DRV_MEDIA_MEM_H__
20 #define __DRV_MEDIA_MEM_H__
21
22 #include <linux/scatterlist.h>
23 #include <linux/semaphore.h>
24 #include <asm/cacheflush.h>
25 #include <linux/version.h>
26 #include "hi_type.h"
27 #include "drv_mmz.h"
28 #include "drv_mmz_ioctl.h"
29
30 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
31 #include <linux/ion.h>
32 #else
33 #include <linux/dma-buf.h>
34 #endif
35
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 #define HIL_MAX_NAME_LEN 16
41 extern int g_mmz_print_level;
42
43 #ifndef hi_mmz_print
44 #ifdef CONFIG_SUPPORT_CA_RELEASE
45 #define hi_mmz_print(LEVEL, fmt, args...)
46 #else
47 #define hi_mmz_print(LEVEL, fmt, args...) \
48 do { \
49 if (g_mmz_print_level > LEVEL) { \
50 printk("%s[%d]: " fmt, __func__, __LINE__, ##args); \
51 } \
52 } while (0)
53 #endif
54 #endif
55 #define MMZ_FATAL_PRINT_LEVEL 0
56 #define MMZ_ERROR_PRINT_LEVEL 1
57 #define MMZ_WARN_PRINT_LEVEL 2
58 #define MMZ_INFO_PRINT_LEVEL 3
59 #define MMZ_DEBUG_PRINT_LEVEL 4
60
61 #define hi_mmz_fatal(fmt, args...) hi_mmz_print(0, fmt, ##args)
62 #define hi_mmz_error(fmt, args...) hi_mmz_print(1, fmt, ##args)
63 #define hi_mmz_warn(fmt, args...) hi_mmz_print(2, fmt, ##args)
64 #define hi_mmz_info(fmt, args...) hi_mmz_print(3, fmt, ##args)
65 #define hi_mmz_debug(fmt, args...) hi_mmz_print(4, fmt, ##args)
66
67 #ifdef CONFIG_64BIT
68 /* need to rm when linux-4.14 to support flush cache all in aarch64 */
69 #if (LINUX_VERSION_CODE > (KERNEL_VERSION(4,14,0)))
flush_cache_all(void)70 static inline void flush_cache_all(void)
71 {
72 return;
73 }
74 #endif
75 #define mmz_flush_dcache_all flush_cache_all
76 #define mmz_flush_dcache_area __flush_dcache_area
77 #else
78 #define mmz_flush_dcache_all __cpuc_flush_kern_all
79 #define mmz_flush_dcache_area __cpuc_flush_dcache_area
80 #endif
81
82 /* alloc status */
83 #define HI_USER_ALLOC 0
84 #define HI_KERNEL_ALLOC (1 << 0)
85
86 /* unmap mode */
87 #define EXCEPTION_FLAG 0
88 #define NORMAL_FLAG (1 << 0)
89
90 /* just for inf */
91 struct hil_media_memory_zone {
92 char name[HIL_MAX_NAME_LEN];
93 HI_U32 gfp;
94 HI_U32 zone_start;
95 HI_U32 nbytes;
96 struct list_head list;
97 int iommu;
98 struct rb_root root;
99 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
100 HI_U32 heap_id_mask;
101 #else
102 struct dma_heap *heap;
103 #endif
104 void (*destructor)(const void *);
105 };
106 typedef struct hil_media_memory_zone hil_mmz_t;
107
108 #define HIL_MMZ_FMT "PHYS(0x%08X, 0x%08X), GFP = %u, nBYTES = %uKB, NAME = \"%s\""
109 #define hil_mmz_fmt_arg(p) (p)->zone_start, (p)->zone_start + (p)->nbytes - 1, (p)->gfp, (p)->nbytes / SZ_1K, (p)->name
110
111 /* for inf & usr */
112 struct mmb_kdata {
113 void *kvirt;
114 HI_U32 kmap_ref;
115 HI_U32 map_cached;
116 };
117
118 struct mmb_udata {
119 pid_t tgid;
120 void *uvirt;
121 struct list_head list;
122 HI_U32 map_ref;
123 int map_fd;
124 HI_U32 unmap_flag; /* indicate if normal unmapd or process killed by system */
125 struct {
126 HI_U32 prot : 8; /* PROT_READ or PROT_WRITE */
127 HI_U32 flags : 12; /* MAP_SHARED or MAP_PRIVATE */
128 HI_U32 map_cached : 1;
129 HI_U32 reserved : 11; /* reserved, do not use */
130 };
131 };
132
133 struct hil_media_memory_block {
134 char name[HIL_MAX_NAME_LEN];
135 struct hil_media_memory_zone *zone;
136 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
137 struct ion_handle *handle; /* to buffer in ion */
138 struct ion_client *client;
139 #else
140 struct dma_buf *handle;
141 #endif
142 struct rb_node node; /* cma node */
143 struct rb_node s_node; /* smmu/iommu node */
144 HI_U32 iommu_addr;
145 HI_U32 phys_addr;
146 HI_U32 sec_smmu;
147 struct mmb_kdata *kdata;
148 struct list_head ulist;
149 HI_U32 length;
150 int iommu; /* 0: cma mem , 1: iommu when allocating */
151 int cma_smmu_ref;
152 int phy_ref;
153 int map_ref; /* all map:user space and kernel space */
154 int sec_smmu_ref; /* sec smmu ref in secure os */
155 int sec_flag; /* 1: means the mem is sec mem 0: the mem is no sec mem */
156 int flag; /* indicate whether this buffer allocated in kernel space or not */
157 pid_t owner_id; /* The owner process who alloc the mem */
158 spinlock_t u_lock;
159 };
160 typedef struct hil_media_memory_block hil_mmb_t;
161
162 struct mmz_userdev_info {
163 pid_t tpid;
164 pid_t mmap_tpid;
165 struct semaphore sem;
166 void *private_data;
167 void *tmp;
168 };
169
170 #define HIL_MMB_MAP2KERN (1 << 0)
171 #define HIL_MMB_MAP2KERN_CACHED (1 << 1)
172 #define HIL_MMB_RELEASED (1 << 2)
173
174 #ifdef HI_SMMU_SUPPORT
175 #define HIL_MMB_FMT "phys(0x%08X, 0x%08X), smmu = (0x%08X, 0x%08X),kvirt = %pK, length = %uKB, name = \"%s\""
176 #define hil_mmb_fmt_arg(p) (p)->phys_addr, (unsigned int)mmz_grain_align((p)->phys_addr + (p)->length) - 1, \
177 (p)->iommu_addr, (unsigned int)mmz_grain_align((p)->iommu_addr + (p)->length) - 1, \
178 ((p)->kdata == NULL) ? NULL : (p)->kdata->kvirt, (p)->length / SZ_1K, (p)->name
179 #else
180 #define HIL_MMB_FMT "phys(0x%08X, 0x%08X),kvirt = %pK, length = %uKB, name = \"%s\""
181 #define hil_mmb_fmt_arg(p) (p)->phys_addr, (unsigned int)mmz_grain_align((p)->phys_addr + (p)->length) - 1, \
182 ((p)->kdata == NULL) ? NULL : (p)->kdata->kvirt, (p)->length / SZ_1K, (p)->name
183 #endif
184
185 extern struct list_head g_mmz_list;
186 extern struct semaphore g_mmz_lock;
187 struct mmz_iommu {
188 struct ion_client *client;
189 };
190
191 /* ******** nAPI_0 for inf ******** */
192 extern hil_mmz_t *hil_mmz_create(const char *name, HI_U32 gfp, HI_U32 zone_start, HI_U32 nbytes);
193 extern int hil_mmz_destroy(const hil_mmz_t *zone);
194 extern int hil_mmz_register(hil_mmz_t *zone);
195 extern int hil_mmz_unregister(hil_mmz_t *zone);
196 extern hil_mmb_t *hil_mmb_getby_phys(HI_U32 addr, HI_U32 iommu);
197 extern hil_mmb_t *hil_mmb_getby_kvirt(const void *virt);
198 extern hil_mmb_t *hil_mmb_getby_sec_addr(HI_U32 sec_addr, HI_U32 iommu);
199 extern int set_sec_mmb_flag(u32 addr, int iommu);
200 extern int clr_sec_mmb_flag(u32 addr, int iommu);
201 extern int is_sec_mem(u32 addr, int iommu);
202 extern int sec_delay_release_for_mem(u32 addr, int iommu);
203 extern int sec_mmb_get(u32 addr, int iommu, u32 sec_smmu);
204 extern int sec_mmb_put(u32 addr, int iommu);
205
206 extern int mmb_get(u32 addr, int iommu);
207 extern int mmb_put(u32 addr, int iommu);
208
209 extern int mmb_ref_query(u32 addr, int iommu, u32 *ref);
210 extern int sec_mmb_query_ref(HI_U32 sec_addr, int iommu, HI_U32 *ref);
211 extern int mem_source_query(u32 iommu_addr, int *source);
212 extern int sec_mem_source_query(u32 iommu_addr, int *source);
213 extern void *hil_mmb_map2kern(hil_mmb_t *mmb);
214 extern void *hil_mmb_map2kern_cached(hil_mmb_t *mmb);
215 extern int hil_mmb_unmap(hil_mmb_t *mmb, const void *addr);
216 extern hil_mmb_t *hil_mmbinfo_getby_kvirt(const void *virt);
217
218 /* ********* API_1 for inf & usr ******** */
219 extern hil_mmb_t *hil_mmb_alloc(const char *name, HI_U32 size, HI_U32 align, const char *mmz_name, int kbuf);
220 extern int hil_mmb_free(hil_mmb_t *mmb);
221 extern mmb_addr_t hil_mmb_cma_mapto_iommu(mmb_addr_t addr, int iommu);
222 extern int hil_mmb_cma_unmapfrom_iommu(mmb_addr_t addr, int iommu);
223 extern struct sg_table *hil_get_meminfo(const hil_mmb_t *mmb);
224
225 extern int mmz_read_proc(struct seq_file *m, void *v);
226 extern int mmz_write_proc(struct file *file, const char __user *buffer, HI_U32 count, void *data);
227 #ifndef DMABUF_FLUSH_CACHE
228 void flush_outer_cache_range(mmb_addr_t phyaddr, mmb_addr_t len, HI_U32 iommu);
229 void flush_inner_cache(const void *viraddr, HI_U32 len);
230 #endif
231 int hi_drv_mmz_init(void);
232 void hi_drv_mmz_exit(void);
233
234 #ifdef __cplusplus
235 }
236 #endif
237
238 #endif
239