1 /* 2 * Copyright (C) 2021 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 _OSAL_MMZ_H 20 #define _OSAL_MMZ_H 21 22 #include "hi_osal.h" 23 24 #define CACHE_LINE_SIZE 0x40 25 #define HIL_MMZ_NAME_LEN 32 26 #define HIL_MMB_NAME_LEN 32 27 28 struct hil_media_memory_zone { 29 char name[HIL_MMZ_NAME_LEN]; 30 31 unsigned long gfp; 32 33 unsigned long phys_start; 34 unsigned long nbytes; 35 36 struct osal_list_head list; 37 union { 38 struct device *cma_dev; 39 unsigned char *bitmap; 40 }; 41 struct osal_list_head mmb_list; 42 43 unsigned int alloc_type; 44 unsigned long block_align; 45 46 void (*destructor)(const void *); 47 }; 48 typedef struct hil_media_memory_zone hil_mmz_t; 49 50 #define HIL_MMZ_FMT_S "PHYS(0x%08pK, 0x%08pK), GFP=%lu, nBYTES=%luKB, NAME=\"%s\"" 51 #define hil_mmz_fmt_arg(p) (p)->phys_start, (p)->phys_start + (p)->nbytes - 1, (p)->gfp, (p)->nbytes / SZ_1K, (p)->name 52 53 struct hil_media_memory_block { 54 #ifndef MMZ_V2_SUPPORT 55 unsigned int id; 56 #endif 57 char name[HIL_MMB_NAME_LEN]; 58 struct hil_media_memory_zone *zone; 59 struct osal_list_head list; 60 61 unsigned long phys_addr; 62 void *kvirt; 63 unsigned long length; 64 65 unsigned long flags; 66 67 unsigned int order; 68 69 int phy_ref; 70 int map_ref; 71 }; 72 typedef struct hil_media_memory_block hil_mmb_t; 73 74 #define hil_mmb_kvirt(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->kvirt; }) 75 #define hil_mmb_phys(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->phys_addr; }) 76 #define hil_mmb_length(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->length; }) 77 #define hil_mmb_name(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->name; }) 78 #define hil_mmb_zone(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->zone; }) 79 80 #define HIL_MMB_MAP2KERN (1 << 0) 81 #define HIL_MMB_MAP2KERN_CACHED (1 << 1) 82 #define HIL_MMB_RELEASED (1 << 2) 83 84 #define HIL_MMB_FMT_S "phys(0x%08pK, 0x%08pK), kvirt=0x%08pK, flags=0x%08pK, length=%luKB, name=\"%s\"" 85 #define hil_mmb_fmt_arg(p) \ 86 (p)->phys_addr, mmz_grain_align((p)->phys_addr + (p)->length) - 1, \ 87 (unsigned long)(uintptr_t)((p)->kvirt), (p)->flags, (p)->length / SZ_1K, (p)->name 88 89 #define DEFAULT_ALLOC 0 90 #define SLAB_ALLOC 1 91 #define EQ_BLOCK_ALLOC 2 92 93 #define LOW_TO_HIGH 0 94 #define HIGH_TO_LOW 1 95 96 #define MMZ_DBG_LEVEL 0x0 97 #define MMZ_WARN_LEVEL 4 98 #define MMZ_ERR_LEVEL 1 99 100 #define mmz_trace(level, s, params...) \ 101 do { \ 102 if (level & MMZ_DBG_LEVEL) \ 103 printk(KERN_INFO "[%s, %d]: " s "\n", __FUNCTION__, __LINE__, params); \ 104 } while (0) 105 106 #define mmz_trace_func() mmz_trace(0x02, "%s", __FILE__) 107 108 #define MMZ_GRAIN PAGE_SIZE 109 #define mmz_bitmap_size(p) (mmz_align2(mmz_length2grain((p)->nbytes), 8) / 8) 110 111 #define mmz_get_bit(p, n) (((p)->bitmap[(n) / 8] >> ((n) & 0x7)) & 0x1) 112 #define mmz_set_bit(p, n) ((p)->bitmap[(n) / 8] |= 1 << ((n) & 0x7)) 113 #define mmz_clr_bit(p, n) ((p)->bitmap[(n) / 8] &= ~(1 << ((n) & 0x7))) 114 115 #define mmz_pos2phy_addr(p, n) ((p)->phys_start + (n) * MMZ_GRAIN) 116 #define mmz_phy_addr2pos(p, a) (((a) - (p)->phys_start) / MMZ_GRAIN) 117 118 #define mmz_align2low(x, g) (((g) == 0) ? (0) : (((x) / (g)) * (g))) 119 #define mmz_align2(x, g) (((g) == 0) ? (0) : ((((x) + (g) - 1) / (g)) * (g))) 120 #define mmz_grain_align(x) mmz_align2(x, MMZ_GRAIN) 121 #define mmz_length2grain(len) (mmz_grain_align(len) / MMZ_GRAIN) 122 123 #define begin_list_for_each_mmz(p, gfp, mmz_name) \ 124 list_for_each_entry(p, &g_mmz_list, list) \ 125 { \ 126 if ((gfp) == 0 ? 0 : (p)->gfp != (gfp)) { \ 127 continue; \ 128 } \ 129 if (((mmz_name) == NULL) || (*(mmz_name) == '\0')) { \ 130 if (anony == 1) { \ 131 if (strcmp("anonymous", (p)->name)) { \ 132 continue; \ 133 } \ 134 } else { \ 135 break; \ 136 } \ 137 } else { \ 138 if (strcmp(mmz_name, (p)->name)) { \ 139 continue; \ 140 } \ 141 } \ 142 mmz_trace(1, HIL_MMZ_FMT_S, hil_mmz_fmt_arg(p)); 143 #define end_list_for_each_mmz() } 144 145 #if defined(KERNEL_BIT_64) && defined(USER_BIT_32) 146 #define __phys_addr_type__ unsigned long long 147 #define __phys_len_type__ unsigned long long 148 #define __phys_addr_align__ __attribute__((aligned(8))) 149 #else 150 #define __phys_addr_type__ unsigned long 151 #define __phys_len_type__ unsigned long 152 #define __phys_addr_align__ __attribute__((aligned(sizeof(long)))) 153 #endif 154 155 struct mmb_info { 156 __phys_addr_type__ phys_addr; /* phys-memory address */ 157 __phys_addr_type__ __phys_addr_align__ align; /* if you need your phys-memory have special align size */ 158 __phys_len_type__ __phys_addr_align__ size; /* length of memory you need, in bytes */ 159 unsigned int __phys_addr_align__ order; 160 161 void *__phys_addr_align__ mapped; /* userspace mapped ptr */ 162 163 union { 164 struct { 165 unsigned long prot : 8; /* PROT_READ or PROT_WRITE */ 166 unsigned long flags : 12; /* MAP_SHARED or MAP_PRIVATE */ 167 168 #ifdef __KERNEL__ 169 unsigned long reserved : 8; /* reserved, do not use */ 170 unsigned long delayed_free : 1; 171 unsigned long map_cached : 1; 172 #endif 173 }; 174 unsigned long w32_stuf; 175 } __phys_addr_align__; 176 177 char mmb_name[HIL_MMB_NAME_LEN]; 178 char mmz_name[HIL_MMZ_NAME_LEN]; 179 unsigned long __phys_addr_align__ gfp; /* reserved, do set to 0 */ 180 181 #ifdef __KERNEL__ 182 int map_ref; 183 int mmb_ref; 184 185 struct osal_list_head list; 186 hil_mmb_t *mmb; 187 #endif 188 } __attribute__((aligned(8))); 189 190 struct dirty_area { 191 __phys_addr_type__ dirty_phys_start; /* dirty physical address */ 192 void *__phys_addr_align__ dirty_virt_start; /* dirty virtual address, 193 must be coherent with dirty_phys_addr */ 194 __phys_len_type__ __phys_addr_align__ dirty_size; 195 } __phys_addr_align__; 196 197 #define IOC_MMB_ALLOC _IOWR('m', 10, struct mmb_info) 198 #define IOC_MMB_ATTR _IOR('m', 11, struct mmb_info) 199 #define IOC_MMB_FREE _IOW('m', 12, struct mmb_info) 200 #define IOC_MMB_ALLOC_V2 _IOWR('m', 13, struct mmb_info) 201 202 #define IOC_MMB_USER_REMAP _IOWR('m', 20, struct mmb_info) 203 #define IOC_MMB_USER_REMAP_CACHED _IOWR('m', 21, struct mmb_info) 204 #define IOC_MMB_USER_UNMAP _IOWR('m', 22, struct mmb_info) 205 206 #define IOC_MMB_VIRT_GET_PHYS _IOWR('m', 23, struct mmb_info) 207 208 #define IOC_MMB_SYS_FLUSH_CACHE _IOW('m', 24, struct mmb_info) 209 #define IOC_MMB_BASE_CHECK_ADDR _IOW('m', 25, struct mmb_info) 210 #define IOC_MMB_INVALID_CACHE _IOW('m', 26, struct mmb_info) 211 #define IOC_MMB_CHECK_PHY_ALLOC _IOWR('m', 27, struct mmb_info) 212 #define IOC_MMB_MMF_REMAP _IOWR('m', 28, struct mmb_info) 213 #define IOC_MMB_MMF_REMAP_CACHED _IOWR('m', 29, struct mmb_info) 214 #define IOC_MMB_MMF_UNMAP _IOWR('m', 30, struct mmb_info) 215 216 #define IOC_MMB_ADD_REF _IO('r', 30) /* ioctl(file, cmd, arg), arg is mmb_addr */ 217 #define IOC_MMB_DEC_REF _IO('r', 31) /* ioctl(file, cmd, arg), arg is mmb_addr */ 218 219 #define IOC_MMB_FLUSH_DCACHE _IO('c', 40) 220 221 #define IOC_MMB_FLUSH_DCACHE_DIRTY _IOW('d', 50, struct dirty_area) 222 #define IOC_MMB_TEST_CACHE _IOW('t', 11, struct mmb_info) 223 224 #define MMZ_SETUP_CMDLINE_LEN 256 225 typedef struct hiMMZ_MODULE_PARAMS_S { 226 char mmz[MMZ_SETUP_CMDLINE_LEN]; 227 char map_mmz[MMZ_SETUP_CMDLINE_LEN]; 228 int anony; 229 } MMZ_MODULE_PARAMS_S; 230 231 /* 232 * APIs 233 */ 234 extern hil_mmz_t *hil_mmz_create(const char *name, unsigned long gfp, unsigned long phys_start, 235 unsigned long nbytes); 236 extern hil_mmz_t *hil_mmz_create_v2(const char *name, unsigned long gfp, unsigned long phys_start, 237 unsigned long nbytes, unsigned int alloc_type, unsigned long block_align); 238 239 extern int hil_mmz_destroy(hil_mmz_t *zone); 240 241 extern int hil_mmz_register(hil_mmz_t *zone); 242 extern int hil_mmz_unregister(hil_mmz_t *zone); 243 extern hil_mmz_t *hil_mmz_find(unsigned long gfp, const char *mmz_name); 244 245 extern hil_mmb_t *hil_mmb_alloc(const char *name, unsigned long size, unsigned long align, 246 unsigned long gfp, const char *mmz_name); 247 extern hil_mmb_t *hil_mmb_alloc_v2(const char *name, unsigned long size, unsigned long align, 248 unsigned long gfp, const char *mmz_name, unsigned int order); 249 extern int hil_mmb_free(hil_mmb_t *mmb); 250 extern hil_mmb_t *hil_mmb_getby_phys(unsigned long addr); 251 extern hil_mmb_t *hil_mmb_getby_phys_2(unsigned long addr, unsigned long *out_offset); 252 extern hil_mmb_t *hil_mmb_getby_kvirt(void *virt); 253 extern unsigned long usr_virt_to_phys(unsigned long virt); 254 255 extern int hil_map_mmz_check_phys(unsigned long addr_start, unsigned long addr_len); 256 extern int hil_is_phys_in_mmz(unsigned long addr_start, unsigned long addr_len); 257 258 extern int hil_vma_check(unsigned long vm_start, unsigned long vm_end); 259 extern int hil_mmb_flush_dcache_byaddr_safe(void *kvirt, unsigned long phys_addr, unsigned long length); 260 261 extern unsigned long hil_mmz_get_phys(const char *zone_name); 262 263 extern hil_mmb_t *hil_mmb_alloc_in(const char *name, unsigned long size, unsigned long align, 264 hil_mmz_t *_user_mmz); 265 extern hil_mmb_t *hil_mmb_alloc_in_v2(const char *name, unsigned long size, unsigned long align, 266 hil_mmz_t *_user_mmz, unsigned int order); 267 268 #define hil_mmb_freeby_phys(phys_addr) hil_mmb_free(hil_mmb_getby_phys(phys_addr)) 269 #define hil_mmb_freeby_kvirt(kvirt) hil_mmb_free(hil_mmb_getby_kvirt(kvirt)) 270 271 extern void *hil_mmb_map2kern(hil_mmb_t *mmb); 272 extern void *hil_mmb_map2kern_cached(hil_mmb_t *mmb); 273 274 extern int hil_mmb_flush_dcache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length); 275 extern int hil_mmb_invalid_cache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length); 276 277 extern int hil_mmb_unmap(hil_mmb_t *mmb); 278 extern int hil_mmb_get(hil_mmb_t *mmb); 279 extern int hil_mmb_put(hil_mmb_t *mmb); 280 281 extern void *hil_mmf_map2kern_nocache(unsigned long phys, int len); 282 extern void *hil_mmf_map2kern_cache(unsigned long phys, int len); 283 extern void hil_mmf_unmap(void *virt); 284 285 /* for mmz userdev */ 286 int mmz_userdev_init(void); 287 void mmz_userdev_exit(void); 288 int mmz_flush_dcache_all(void); 289 290 #endif /* _OSAL_MMZ_H */ 291