1 /*************************************************************************/ /*!
3 @Title Device Memory Management internal utility functions
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description Utility functions used internally by device memory management
7 @License Dual MIT/GPLv2
9 The contents of this file are subject to the MIT license as set out below.
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 2 ("GPL") in which case the provisions
23 of GPL are applicable instead of those above.
25 If you wish to allow use of your version of this file only under the terms of
26 GPL, and not to allow others to use your version of this file under the terms
27 of the MIT license, indicate your decision by deleting the provisions above
28 and replace them with the notice and other provisions required by GPL as set
29 out in the file called "GPL-COPYING" included in this distribution. If you do
30 not delete the provisions above, a recipient may use your version of this file
31 under the terms of either the MIT license or GPL.
33 This License is also included in this distribution in the file called
36 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 */ /**************************************************************************/
45 #ifndef _DEVICEMEM_UTILS_H_
46 #define _DEVICEMEM_UTILS_H_
48 #include "devicemem.h"
49 #include "img_types.h"
50 #include "pvrsrv_error.h"
51 #include "pvr_debug.h"
56 #include "devicemem_mmap.h"
57 #include "devicemem_utils.h"
58 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
59 #include "mm_common.h"
60 #include "devicemem_history_shared.h"
63 #define DEVMEM_HEAPNAME_MAXLENGTH 160
66 #if defined(DEVMEM_DEBUG) && defined(REFCOUNT_DEBUG)
67 #define DEVMEM_REFCOUNT_PRINT(fmt, ...) PVRSRVDebugPrintf(PVR_DBG_ERROR, __FILE__, __LINE__, fmt, __VA_ARGS__)
69 #define DEVMEM_REFCOUNT_PRINT(fmt, ...)
73 /* If we need a "hMapping" but we don't have a server-side mapping, we
74 poison the entry with this value so that it's easily recognised in
75 the debugger. Note that this is potentially a valid handle, but
76 then so is IMG_NULL, which is no better, indeed worse, as it's not
77 obvious in the debugger. The value doesn't matter. We _never_ use
78 it (and because it's valid, we never assert it isn't this) but it's
79 nice to have a value in the source code that we can grep for when
81 #define LACK_OF_MAPPING_POISON ((IMG_HANDLE)0x6116dead)
82 #define LACK_OF_RESERVATION_POISON ((IMG_HANDLE)0x7117dead)
84 struct _DEVMEM_CONTEXT_ {
85 /* Cookie of the device on which this memory context resides */
86 IMG_HANDLE hDeviceNode;
88 /* Number of heaps that have been created in this context
89 (regardless of whether they have allocations) */
90 IMG_UINT32 uiNumHeaps;
92 /* Sometimes we need to talk to Kernel Services. In order to do
93 so, we need the connection handle */
94 DEVMEM_BRIDGE_HANDLE hBridge;
97 Each "DEVMEM_CONTEXT" has a counterpart in the server,
98 which is responsible for handling the mapping into device MMU.
99 We have a handle to that here.
101 IMG_HANDLE hDevMemServerContext;
103 /* Number of automagically created heaps in this context,
104 i.e. those that are born at context creation time from the
105 chosen "heap config" or "blueprint" */
106 IMG_UINT32 uiAutoHeapCount;
108 /* pointer to array of such heaps */
109 struct _DEVMEM_HEAP_ **ppsAutoHeapArray;
111 /* Private data handle for device specific data */
112 IMG_HANDLE hPrivData;
115 struct _DEVMEM_HEAP_ {
116 /* Name of heap - for debug and lookup purposes. */
119 /* Number of live imports in the heap */
120 IMG_UINT32 uiImportCount;
123 * Base address of heap, required by clients due to some requesters
124 * not being full range
126 IMG_DEV_VIRTADDR sBaseAddress;
128 /* This RA is for managing sub-allocations in virtual space. Two
129 more RA's will be used under the Hood for managing the coarser
130 allocation of virtual space from the heap, and also for
131 managing the physical backing storage. */
132 RA_ARENA *psSubAllocRA;
133 IMG_CHAR *pszSubAllocRAName;
135 This RA is for the coarse allocation of virtual space from the heap
137 RA_ARENA *psQuantizedVMRA;
138 IMG_CHAR *pszQuantizedVMRAName;
140 /* We also need to store a copy of the quantum size in order to
141 feed this down to the server */
142 IMG_UINT32 uiLog2Quantum;
144 /* The parent memory context for this heap */
145 struct _DEVMEM_CONTEXT_ *psCtx;
147 POS_LOCK hLock; /*!< Lock to protect this structure */
150 Each "DEVMEM_HEAP" has a counterpart in the server,
151 which is responsible for handling the mapping into device MMU.
152 We have a handle to that here.
154 IMG_HANDLE hDevMemServerHeap;
158 typedef struct _DEVMEM_DEVICE_IMPORT_ {
159 DEVMEM_HEAP *psHeap; /*!< Heap this import is bound to */
160 IMG_DEV_VIRTADDR sDevVAddr; /*!< Device virtual address of the import */
161 IMG_UINT32 ui32RefCount; /*!< Refcount of the device virtual address */
162 IMG_HANDLE hReservation; /*!< Device memory reservation handle */
163 IMG_HANDLE hMapping; /*!< Device mapping handle */
164 IMG_BOOL bMapped; /*!< This is import mapped? */
165 POS_LOCK hLock; /*!< Lock to protect the device import */
166 } DEVMEM_DEVICE_IMPORT;
168 typedef struct _DEVMEM_CPU_IMPORT_ {
169 IMG_PVOID pvCPUVAddr; /*!< CPU virtual address of the import */
170 IMG_UINT32 ui32RefCount; /*!< Refcount of the CPU virtual address */
171 IMG_HANDLE hOSMMapData; /*!< CPU mapping handle */
172 POS_LOCK hLock; /*!< Lock to protect the CPU import */
173 #if !defined(__KERNEL__) && defined(SUPPORT_ION)
174 int iDmaBufFd; /*!< >=0 if this was an imported ion allocation */
178 typedef struct _DEVMEM_IMPORT_ {
179 DEVMEM_BRIDGE_HANDLE hBridge; /*!< Bridge connection for the server */
180 IMG_DEVMEM_ALIGN_T uiAlign; /*!< Alignment requirement */
181 DEVMEM_SIZE_T uiSize; /*!< Size of import */
182 IMG_UINT32 ui32RefCount; /*!< Refcount for this import */
183 IMG_BOOL bExportable; /*!< Is this import exportable? */
184 IMG_HANDLE hPMR; /*!< Handle to the PMR */
185 DEVMEM_FLAGS_T uiFlags; /*!< Flags for this import */
186 POS_LOCK hLock; /*!< Lock to protect the import */
188 DEVMEM_DEVICE_IMPORT sDeviceImport; /*!< Device specifics of the import */
189 DEVMEM_CPU_IMPORT sCPUImport; /*!< CPU specifics of the import */
192 typedef struct _DEVMEM_DEVICE_MEMDESC_ {
193 IMG_DEV_VIRTADDR sDevVAddr; /*!< Device virtual address of the allocation */
194 IMG_UINT32 ui32RefCount; /*!< Refcount of the device virtual address */
195 POS_LOCK hLock; /*!< Lock to protect device memdesc */
196 } DEVMEM_DEVICE_MEMDESC;
198 typedef struct _DEVMEM_CPU_MEMDESC_ {
199 IMG_PVOID pvCPUVAddr; /*!< CPU virtual address of the import */
200 IMG_UINT32 ui32RefCount; /*!< Refcount of the device CPU address */
201 POS_LOCK hLock; /*!< Lock to protect CPU memdesc */
202 } DEVMEM_CPU_MEMDESC;
204 struct _DEVMEM_MEMDESC_ {
205 DEVMEM_IMPORT *psImport; /*!< Import this memdesc is on */
206 IMG_DEVMEM_OFFSET_T uiOffset; /*!< Offset into import where our allocation starts */
207 IMG_UINT32 ui32RefCount; /*!< Refcount of the memdesc */
208 POS_LOCK hLock; /*!< Lock to protect memdesc */
210 DEVMEM_DEVICE_MEMDESC sDeviceMemDesc; /*!< Device specifics of the memdesc */
211 DEVMEM_CPU_MEMDESC sCPUMemDesc; /*!< CPU specifics of the memdesc */
212 #if defined(SUPPORT_PAGE_FAULT_DEBUG)
213 DEVICEMEM_HISTORY_MEMDESC_DATA sTraceData;
216 #if defined(PVR_RI_DEBUG)
217 IMG_HANDLE hRIHandle; /*!< Handle to RI information */
221 /******************************************************************************
222 @Function _DevmemValidateParams
223 @Description Check if flags are conflicting and if align is a size multiple.
225 @Input uiSize Size of the import.
226 @Input uiAlign Alignment of the import.
227 @Input uiFlags Flags for the import.
229 ******************************************************************************/
230 PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
231 IMG_DEVMEM_ALIGN_T uiAlign,
232 DEVMEM_FLAGS_T uiFlags);
234 /******************************************************************************
235 @Function _DevmemImportStructAlloc
236 @Description Allocates memory for an import struct. Does not allocate a PMR!
237 Create locks for CPU and Devmem mappings.
239 @Input hBridge Bridge to use for calls from the import.
240 @Input bExportable Is this import is exportable?
241 @Input ppsImport The import to allocate.
243 ******************************************************************************/
244 PVRSRV_ERROR _DevmemImportStructAlloc(IMG_HANDLE hBridge,
245 IMG_BOOL bExportable,
246 DEVMEM_IMPORT **ppsImport);
248 /******************************************************************************
249 @Function _DevmemImportStructInit
250 @Description Initialises the import struct with the given parameters.
251 Set it's refcount to 1!
253 @Input psImport The import to initialise.
254 @Input uiSize Size of the import.
255 @Input uiAlign Alignment of allocations in the import.
257 @Input hPMR Reference to the PMR of this import struct.
258 ******************************************************************************/
259 IMG_VOID _DevmemImportStructInit(DEVMEM_IMPORT *psImport,
260 IMG_DEVMEM_SIZE_T uiSize,
261 IMG_DEVMEM_ALIGN_T uiAlign,
262 PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
265 /******************************************************************************
266 @Function _DevmemImportStructDevMap
267 @Description NEVER call after the last _DevmemMemDescRelease()
268 Maps the PMR referenced by the import struct to the device's
269 virtual address space.
270 Does nothing but increase the cpu mapping refcount if the
271 import struct was already mapped.
273 @Input psHeap The heap to map to.
274 @Input bMap Caller can choose if the import should be really
275 mapped in the page tables or if just a virtual range
276 should be reserved and the refcounts increased.
277 @Input psImport The import we want to map.
279 ******************************************************************************/
280 PVRSRV_ERROR _DevmemImportStructDevMap(DEVMEM_HEAP *psHeap,
282 DEVMEM_IMPORT *psImport);
284 /******************************************************************************
285 @Function _DevmemImportStructDevUnmap
286 @Description Unmaps the PMR referenced by the import struct from the
287 device's virtual address space.
288 If this was not the last remaining CPU mapping on the import
289 struct only the cpu mapping refcount is decreased.
290 ******************************************************************************/
291 IMG_VOID _DevmemImportStructDevUnmap(DEVMEM_IMPORT *psImport);
293 /******************************************************************************
294 @Function _DevmemImportStructCPUMap
295 @Description NEVER call after the last _DevmemMemDescRelease()
296 Maps the PMR referenced by the import struct to the CPU's
297 virtual address space.
298 Does nothing but increase the cpu mapping refcount if the
299 import struct was already mapped.
301 ******************************************************************************/
302 PVRSRV_ERROR _DevmemImportStructCPUMap(DEVMEM_IMPORT *psImport);
304 /******************************************************************************
305 @Function _DevmemImportStructCPUUnmap
306 @Description Unmaps the PMR referenced by the import struct from the CPU's
307 virtual address space.
308 If this was not the last remaining CPU mapping on the import
309 struct only the cpu mapping refcount is decreased.
310 ******************************************************************************/
311 IMG_VOID _DevmemImportStructCPUUnmap(DEVMEM_IMPORT *psImport);
314 /******************************************************************************
315 @Function _DevmemImportStructAcquire
316 @Description Acquire an import struct by increasing it's refcount.
317 ******************************************************************************/
318 IMG_VOID _DevmemImportStructAcquire(DEVMEM_IMPORT *psImport);
320 /******************************************************************************
321 @Function _DevmemImportStructRelease
322 @Description Reduces the refcount of the import struct.
323 Destroys the import in the case it was the last reference.
324 Destroys underlying PMR if this import was the last reference
326 @return A boolean to signal if the import was destroyed. True = yes.
327 ******************************************************************************/
328 IMG_VOID _DevmemImportStructRelease(DEVMEM_IMPORT *psImport);
330 /******************************************************************************
331 @Function _DevmemImportDiscard
332 @Description Discard a created, but unitilised import structure.
333 This must only be called before _DevmemImportStructInit
334 after which _DevmemImportStructRelease must be used to
335 "free" the import structure.
336 ******************************************************************************/
337 IMG_VOID _DevmemImportDiscard(DEVMEM_IMPORT *psImport);
339 /******************************************************************************
340 @Function _DevmemMemDescAlloc
341 @Description Allocates a MemDesc and create it's various locks.
342 Zero the allocated memory.
344 ******************************************************************************/
345 PVRSRV_ERROR _DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc);
347 /******************************************************************************
348 @Function _DevmemMemDescInit
349 @Description Sets the given offset and import struct fields in the MemDesc.
350 Initialises refcount to 1 and other values to 0.
352 @Input psMemDesc MemDesc to initialise.
353 @Input uiOffset Offset in the import structure.
354 @Input psImport Import the MemDesc is on.
355 ******************************************************************************/
356 IMG_VOID _DevmemMemDescInit(DEVMEM_MEMDESC *psMemDesc,
357 IMG_DEVMEM_OFFSET_T uiOffset,
358 DEVMEM_IMPORT *psImport);
360 /******************************************************************************
361 @Function _DevmemMemDescAcquire
362 @Description Acquires the MemDesc by increasing it's refcount.
363 ******************************************************************************/
364 IMG_VOID _DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc);
366 /******************************************************************************
367 @Function _DevmemMemDescRelease
368 @Description Releases the MemDesc by reducing it's refcount.
369 Destroy the MemDesc if it's recount is 0.
370 Destroy the import struct the MemDesc is on if that was the
371 last MemDesc on the import, probably following the destruction
372 of the underlying PMR.
373 ******************************************************************************/
374 IMG_VOID _DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc);
376 /******************************************************************************
377 @Function _DevmemMemDescDiscard
378 @Description Discard a created, but unitilised MemDesc structure.
379 This must only be called before _DevmemMemDescInit
380 after which _DevmemMemDescRelease must be used to
381 "free" the MemDesc structure.
382 ******************************************************************************/
383 IMG_VOID _DevmemMemDescDiscard(DEVMEM_MEMDESC *psMemDesc);
385 #endif /* _DEVICEMEM_UTILS_H_ */