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	ISP_VM_START	0x0
69#define	ISP_VM_SIZE	(0x7FFFFFFF)	/* 2G address space */
70#define	ISP_PTR_NULL	NULL
71
72#define	HMM_BO_DEVICE_INITED	0x1
73
74enum hmm_bo_type {
75	HMM_BO_PRIVATE,
76	HMM_BO_VMALLOC,
77	HMM_BO_LAST,
78};
79
80#define	HMM_BO_MASK		0x1
81#define	HMM_BO_FREE		0x0
82#define	HMM_BO_ALLOCED	0x1
83#define	HMM_BO_PAGE_ALLOCED	0x2
84#define	HMM_BO_BINDED		0x4
85#define	HMM_BO_MMAPED		0x8
86#define	HMM_BO_VMAPED		0x10
87#define	HMM_BO_VMAPED_CACHED	0x20
88#define	HMM_BO_ACTIVE		0x1000
89
90struct hmm_bo_device {
91	struct isp_mmu		mmu;
92
93	/* start/pgnr/size is used to record the virtual memory of this bo */
94	unsigned int start;
95	unsigned int pgnr;
96	unsigned int size;
97
98	/* list lock is used to protect the entire_bo_list */
99	spinlock_t	list_lock;
100	int flag;
101
102	/* linked list for entire buffer object */
103	struct list_head entire_bo_list;
104	/* rbtree for maintain entire allocated vm */
105	struct rb_root allocated_rbtree;
106	/* rbtree for maintain entire free vm */
107	struct rb_root free_rbtree;
108	struct mutex rbtree_mutex;
109	struct kmem_cache *bo_cache;
110};
111
112struct hmm_buffer_object {
113	struct hmm_bo_device	*bdev;
114	struct list_head	list;
115	struct kref	kref;
116
117	struct page **pages;
118
119	/* mutex protecting this BO */
120	struct mutex		mutex;
121	enum hmm_bo_type	type;
122	int		mmap_count;
123	int		status;
124	void		*vmap_addr; /* kernel virtual address by vmap */
125
126	struct rb_node	node;
127	unsigned int	start;
128	unsigned int	end;
129	unsigned int	pgnr;
130	/*
131	 * When insert a bo which has the same pgnr with an existed
132	 * bo node in the free_rbtree, using "prev & next" pointer
133	 * to maintain a bo linked list instead of insert this bo
134	 * into free_rbtree directly, it will make sure each node
135	 * in free_rbtree has different pgnr.
136	 * "prev & next" default is NULL.
137	 */
138	struct hmm_buffer_object	*prev;
139	struct hmm_buffer_object	*next;
140};
141
142struct hmm_buffer_object *hmm_bo_alloc(struct hmm_bo_device *bdev,
143				       unsigned int pgnr);
144
145void hmm_bo_release(struct hmm_buffer_object *bo);
146
147int hmm_bo_device_init(struct hmm_bo_device *bdev,
148		       struct isp_mmu_client *mmu_driver,
149		       unsigned int vaddr_start, unsigned int size);
150
151/*
152 * clean up all hmm_bo_device related things.
153 */
154void hmm_bo_device_exit(struct hmm_bo_device *bdev);
155
156/*
157 * whether the bo device is inited or not.
158 */
159int hmm_bo_device_inited(struct hmm_bo_device *bdev);
160
161/*
162 * increse buffer object reference.
163 */
164void hmm_bo_ref(struct hmm_buffer_object *bo);
165
166/*
167 * decrese buffer object reference. if reference reaches 0,
168 * release function of the buffer object will be called.
169 *
170 * this call is also used to release hmm_buffer_object or its
171 * upper level object with it embedded in. you need to call
172 * this function when it is no longer used.
173 *
174 * Note:
175 *
176 * user dont need to care about internal resource release of
177 * the buffer object in the release callback, it will be
178 * handled internally.
179 *
180 * this call will only release internal resource of the buffer
181 * object but will not free the buffer object itself, as the
182 * buffer object can be both pre-allocated statically or
183 * dynamically allocated. so user need to deal with the release
184 * of the buffer object itself manually. below example shows
185 * the normal case of using the buffer object.
186 *
187 *	struct hmm_buffer_object *bo = hmm_bo_create(bdev, pgnr);
188 *	......
189 *	hmm_bo_unref(bo);
190 *
191 * or:
192 *
193 *	struct hmm_buffer_object bo;
194 *
195 *	hmm_bo_init(bdev, &bo, pgnr, NULL);
196 *	...
197 *	hmm_bo_unref(&bo);
198 */
199void hmm_bo_unref(struct hmm_buffer_object *bo);
200
201int hmm_bo_allocated(struct hmm_buffer_object *bo);
202
203/*
204 * Allocate/Free physical pages for the bo. Type indicates if the
205 * pages will be allocated by using video driver (for share buffer)
206 * or by ISP driver itself.
207 */
208int hmm_bo_alloc_pages(struct hmm_buffer_object *bo,
209		       enum hmm_bo_type type,
210		       void *vmalloc_addr);
211void hmm_bo_free_pages(struct hmm_buffer_object *bo);
212int hmm_bo_page_allocated(struct hmm_buffer_object *bo);
213
214/*
215 * bind/unbind the physical pages to a virtual address space.
216 */
217int hmm_bo_bind(struct hmm_buffer_object *bo);
218void hmm_bo_unbind(struct hmm_buffer_object *bo);
219int hmm_bo_binded(struct hmm_buffer_object *bo);
220
221/*
222 * vmap buffer object's pages to contiguous kernel virtual address.
223 * if the buffer has been vmaped, return the virtual address directly.
224 */
225void *hmm_bo_vmap(struct hmm_buffer_object *bo, bool cached);
226
227/*
228 * flush the cache for the vmapped buffer object's pages,
229 * if the buffer has not been vmapped, return directly.
230 */
231void hmm_bo_flush_vmap(struct hmm_buffer_object *bo);
232
233/*
234 * vunmap buffer object's kernel virtual address.
235 */
236void hmm_bo_vunmap(struct hmm_buffer_object *bo);
237
238/*
239 * mmap the bo's physical pages to specific vma.
240 *
241 * vma's address space size must be the same as bo's size,
242 * otherwise it will return -EINVAL.
243 *
244 * vma->vm_flags will be set to (VM_RESERVED | VM_IO).
245 */
246int hmm_bo_mmap(struct vm_area_struct *vma,
247		struct hmm_buffer_object *bo);
248
249/*
250 * find the buffer object by its virtual address vaddr.
251 * return NULL if no such buffer object found.
252 */
253struct hmm_buffer_object *hmm_bo_device_search_start(
254    struct hmm_bo_device *bdev, ia_css_ptr vaddr);
255
256/*
257 * find the buffer object by its virtual address.
258 * it does not need to be the start address of one bo,
259 * it can be an address within the range of one bo.
260 * return NULL if no such buffer object found.
261 */
262struct hmm_buffer_object *hmm_bo_device_search_in_range(
263    struct hmm_bo_device *bdev, ia_css_ptr vaddr);
264
265/*
266 * find the buffer object with kernel virtual address vaddr.
267 * return NULL if no such buffer object found.
268 */
269struct hmm_buffer_object *hmm_bo_device_search_vmap_start(
270    struct hmm_bo_device *bdev, const void *vaddr);
271
272#endif
273