1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Support for Medifield PNW Camera Imaging ISP subsystem. 4 * 5 * Copyright (c) 2010 Intel Corporation. All Rights Reserved. 6 * 7 * Copyright (c) 2010 Silicon Hive www.siliconhive.com. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License version 11 * 2 as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * 19 */ 20 21 #ifndef __HMM_BO_H__ 22 #define __HMM_BO_H__ 23 24 #include <linux/kernel.h> 25 #include <linux/slab.h> 26 #include <linux/list.h> 27 #include <linux/spinlock.h> 28 #include <linux/mutex.h> 29 #include "mmu/isp_mmu.h" 30 #include "hmm/hmm_common.h" 31 #include "ia_css_types.h" 32 33 #define check_bodev_null_return(bdev, exp) \ 34 check_null_return(bdev, exp, \ 35 "NULL hmm_bo_device.\n") 36 37 #define check_bodev_null_return_void(bdev) \ 38 check_null_return_void(bdev, \ 39 "NULL hmm_bo_device.\n") 40 41 #define check_bo_status_yes_goto(bo, _status, label) \ 42 var_not_equal_goto((bo->status & (_status)), (_status), \ 43 label, \ 44 "HMM buffer status not contain %s.\n", \ 45 #_status) 46 47 #define check_bo_status_no_goto(bo, _status, label) \ 48 var_equal_goto((bo->status & (_status)), (_status), \ 49 label, \ 50 "HMM buffer status contains %s.\n", \ 51 #_status) 52 53 #define rbtree_node_to_hmm_bo(root_node) \ 54 container_of((root_node), struct hmm_buffer_object, node) 55 56 #define list_to_hmm_bo(list_ptr) \ 57 list_entry((list_ptr), struct hmm_buffer_object, list) 58 59 #define kref_to_hmm_bo(kref_ptr) \ 60 list_entry((kref_ptr), struct hmm_buffer_object, kref) 61 62 #define check_bo_null_return(bo, exp) \ 63 check_null_return(bo, exp, "NULL hmm buffer object.\n") 64 65 #define check_bo_null_return_void(bo) \ 66 check_null_return_void(bo, "NULL hmm buffer object.\n") 67 68 #define HMM_MAX_ORDER 3 69 #define HMM_MIN_ORDER 0 70 71 #define ISP_VM_START 0x0 72 #define ISP_VM_SIZE (0x7FFFFFFF) /* 2G address space */ 73 #define ISP_PTR_NULL NULL 74 75 #define HMM_BO_DEVICE_INITED 0x1 76 77 enum hmm_bo_type { 78 HMM_BO_PRIVATE, 79 HMM_BO_SHARE, 80 HMM_BO_USER, 81 HMM_BO_LAST, 82 }; 83 84 enum hmm_page_type { 85 HMM_PAGE_TYPE_RESERVED, 86 HMM_PAGE_TYPE_DYNAMIC, 87 HMM_PAGE_TYPE_GENERAL, 88 }; 89 90 #define HMM_BO_MASK 0x1 91 #define HMM_BO_FREE 0x0 92 #define HMM_BO_ALLOCED 0x1 93 #define HMM_BO_PAGE_ALLOCED 0x2 94 #define HMM_BO_BINDED 0x4 95 #define HMM_BO_MMAPED 0x8 96 #define HMM_BO_VMAPED 0x10 97 #define HMM_BO_VMAPED_CACHED 0x20 98 #define HMM_BO_ACTIVE 0x1000 99 #define HMM_BO_MEM_TYPE_USER 0x1 100 #define HMM_BO_MEM_TYPE_PFN 0x2 101 102 struct hmm_bo_device { 103 struct isp_mmu mmu; 104 105 /* start/pgnr/size is used to record the virtual memory of this bo */ 106 unsigned int start; 107 unsigned int pgnr; 108 unsigned int size; 109 110 /* list lock is used to protect the entire_bo_list */ 111 spinlock_t list_lock; 112 int flag; 113 114 /* linked list for entire buffer object */ 115 struct list_head entire_bo_list; 116 /* rbtree for maintain entire allocated vm */ 117 struct rb_root allocated_rbtree; 118 /* rbtree for maintain entire free vm */ 119 struct rb_root free_rbtree; 120 struct mutex rbtree_mutex; 121 struct kmem_cache *bo_cache; 122 }; 123 124 struct hmm_page_object { 125 struct page *page; 126 enum hmm_page_type type; 127 }; 128 129 struct hmm_buffer_object { 130 struct hmm_bo_device *bdev; 131 struct list_head list; 132 struct kref kref; 133 134 struct page **pages; 135 136 /* mutex protecting this BO */ 137 struct mutex mutex; 138 enum hmm_bo_type type; 139 struct hmm_page_object *page_obj; /* physical pages */ 140 int from_highmem; 141 int mmap_count; 142 int status; 143 int mem_type; 144 void *vmap_addr; /* kernel virtual address by vmap */ 145 146 struct rb_node node; 147 unsigned int start; 148 unsigned int end; 149 unsigned int pgnr; 150 /* 151 * When insert a bo which has the same pgnr with an existed 152 * bo node in the free_rbtree, using "prev & next" pointer 153 * to maintain a bo linked list instead of insert this bo 154 * into free_rbtree directly, it will make sure each node 155 * in free_rbtree has different pgnr. 156 * "prev & next" default is NULL. 157 */ 158 struct hmm_buffer_object *prev; 159 struct hmm_buffer_object *next; 160 }; 161 162 struct hmm_buffer_object *hmm_bo_alloc(struct hmm_bo_device *bdev, 163 unsigned int pgnr); 164 165 void hmm_bo_release(struct hmm_buffer_object *bo); 166 167 int hmm_bo_device_init(struct hmm_bo_device *bdev, 168 struct isp_mmu_client *mmu_driver, 169 unsigned int vaddr_start, unsigned int size); 170 171 /* 172 * clean up all hmm_bo_device related things. 173 */ 174 void hmm_bo_device_exit(struct hmm_bo_device *bdev); 175 176 /* 177 * whether the bo device is inited or not. 178 */ 179 int hmm_bo_device_inited(struct hmm_bo_device *bdev); 180 181 /* 182 * increse buffer object reference. 183 */ 184 void hmm_bo_ref(struct hmm_buffer_object *bo); 185 186 /* 187 * decrese buffer object reference. if reference reaches 0, 188 * release function of the buffer object will be called. 189 * 190 * this call is also used to release hmm_buffer_object or its 191 * upper level object with it embedded in. you need to call 192 * this function when it is no longer used. 193 * 194 * Note: 195 * 196 * user dont need to care about internal resource release of 197 * the buffer object in the release callback, it will be 198 * handled internally. 199 * 200 * this call will only release internal resource of the buffer 201 * object but will not free the buffer object itself, as the 202 * buffer object can be both pre-allocated statically or 203 * dynamically allocated. so user need to deal with the release 204 * of the buffer object itself manually. below example shows 205 * the normal case of using the buffer object. 206 * 207 * struct hmm_buffer_object *bo = hmm_bo_create(bdev, pgnr); 208 * ...... 209 * hmm_bo_unref(bo); 210 * 211 * or: 212 * 213 * struct hmm_buffer_object bo; 214 * 215 * hmm_bo_init(bdev, &bo, pgnr, NULL); 216 * ... 217 * hmm_bo_unref(&bo); 218 */ 219 void hmm_bo_unref(struct hmm_buffer_object *bo); 220 221 /* 222 * allocate/free physical pages for the bo. will try to alloc mem 223 * from highmem if from_highmem is set, and type indicate that the 224 * pages will be allocated by using video driver (for share buffer) 225 * or by ISP driver itself. 226 */ 227 228 int hmm_bo_allocated(struct hmm_buffer_object *bo); 229 230 /* 231 * allocate/free physical pages for the bo. will try to alloc mem 232 * from highmem if from_highmem is set, and type indicate that the 233 * pages will be allocated by using video driver (for share buffer) 234 * or by ISP driver itself. 235 */ 236 int hmm_bo_alloc_pages(struct hmm_buffer_object *bo, 237 enum hmm_bo_type type, int from_highmem, 238 const void __user *userptr, bool cached); 239 void hmm_bo_free_pages(struct hmm_buffer_object *bo); 240 int hmm_bo_page_allocated(struct hmm_buffer_object *bo); 241 242 /* 243 * get physical page info of the bo. 244 */ 245 int hmm_bo_get_page_info(struct hmm_buffer_object *bo, 246 struct hmm_page_object **page_obj, int *pgnr); 247 248 /* 249 * bind/unbind the physical pages to a virtual address space. 250 */ 251 int hmm_bo_bind(struct hmm_buffer_object *bo); 252 void hmm_bo_unbind(struct hmm_buffer_object *bo); 253 int hmm_bo_binded(struct hmm_buffer_object *bo); 254 255 /* 256 * vmap buffer object's pages to contiguous kernel virtual address. 257 * if the buffer has been vmaped, return the virtual address directly. 258 */ 259 void *hmm_bo_vmap(struct hmm_buffer_object *bo, bool cached); 260 261 /* 262 * flush the cache for the vmapped buffer object's pages, 263 * if the buffer has not been vmapped, return directly. 264 */ 265 void hmm_bo_flush_vmap(struct hmm_buffer_object *bo); 266 267 /* 268 * vunmap buffer object's kernel virtual address. 269 */ 270 void hmm_bo_vunmap(struct hmm_buffer_object *bo); 271 272 /* 273 * mmap the bo's physical pages to specific vma. 274 * 275 * vma's address space size must be the same as bo's size, 276 * otherwise it will return -EINVAL. 277 * 278 * vma->vm_flags will be set to (VM_RESERVED | VM_IO). 279 */ 280 int hmm_bo_mmap(struct vm_area_struct *vma, 281 struct hmm_buffer_object *bo); 282 283 extern struct hmm_pool dynamic_pool; 284 extern struct hmm_pool reserved_pool; 285 286 /* 287 * find the buffer object by its virtual address vaddr. 288 * return NULL if no such buffer object found. 289 */ 290 struct hmm_buffer_object *hmm_bo_device_search_start( 291 struct hmm_bo_device *bdev, ia_css_ptr vaddr); 292 293 /* 294 * find the buffer object by its virtual address. 295 * it does not need to be the start address of one bo, 296 * it can be an address within the range of one bo. 297 * return NULL if no such buffer object found. 298 */ 299 struct hmm_buffer_object *hmm_bo_device_search_in_range( 300 struct hmm_bo_device *bdev, ia_css_ptr vaddr); 301 302 /* 303 * find the buffer object with kernel virtual address vaddr. 304 * return NULL if no such buffer object found. 305 */ 306 struct hmm_buffer_object *hmm_bo_device_search_vmap_start( 307 struct hmm_bo_device *bdev, const void *vaddr); 308 309 #endif 310