diff options
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/env/linux/ion.c')
-rw-r--r-- | drivers/gpu/pvr/services4/srvkm/env/linux/ion.c | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c new file mode 100644 index 000000000000..09d8f1055b48 --- /dev/null +++ b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c | |||
@@ -0,0 +1,580 @@ | |||
1 | /*************************************************************************/ /*! | ||
2 | @Title Ion driver inter-operability code. | ||
3 | @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved | ||
4 | @License Dual MIT/GPLv2 | ||
5 | |||
6 | The contents of this file are subject to the MIT license as set out below. | ||
7 | |||
8 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
9 | of this software and associated documentation files (the "Software"), to deal | ||
10 | in the Software without restriction, including without limitation the rights | ||
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
12 | copies of the Software, and to permit persons to whom the Software is | ||
13 | furnished to do so, subject to the following conditions: | ||
14 | |||
15 | The above copyright notice and this permission notice shall be included in | ||
16 | all copies or substantial portions of the Software. | ||
17 | |||
18 | Alternatively, the contents of this file may be used under the terms of | ||
19 | the GNU General Public License Version 2 ("GPL") in which case the provisions | ||
20 | of GPL are applicable instead of those above. | ||
21 | |||
22 | If you wish to allow use of your version of this file only under the terms of | ||
23 | GPL, and not to allow others to use your version of this file under the terms | ||
24 | of the MIT license, indicate your decision by deleting the provisions above | ||
25 | and replace them with the notice and other provisions required by GPL as set | ||
26 | out in the file called "GPL-COPYING" included in this distribution. If you do | ||
27 | not delete the provisions above, a recipient may use your version of this file | ||
28 | under the terms of either the MIT license or GPL. | ||
29 | |||
30 | This License is also included in this distribution in the file called | ||
31 | "MIT-COPYING". | ||
32 | |||
33 | EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS | ||
34 | PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | ||
35 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
36 | PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR | ||
37 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
38 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
39 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
40 | */ /**************************************************************************/ | ||
41 | |||
42 | #include <linux/version.h> | ||
43 | #include "ion.h" | ||
44 | |||
45 | /* Three possible configurations: | ||
46 | * | ||
47 | * - SUPPORT_ION && CONFIG_ION_OMAP | ||
48 | * Real ion support, but sharing with an SOC ion device. We need | ||
49 | * to co-share the heaps too. | ||
50 | * | ||
51 | * - SUPPORT_ION && !CONFIG_ION_OMAP | ||
52 | * "Reference" ion implementation. Creates its own ion device | ||
53 | * and heaps for the driver to use. | ||
54 | */ | ||
55 | |||
56 | #if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) | ||
57 | #include <linux/scatterlist.h> | ||
58 | #include <linux/kernel.h> | ||
59 | #include <linux/slab.h> | ||
60 | #include <linux/err.h> | ||
61 | |||
62 | #if defined(CONFIG_ION_OMAP) | ||
63 | |||
64 | /* Real ion with sharing */ | ||
65 | |||
66 | extern struct ion_device *omap_ion_device; | ||
67 | struct ion_device *gpsIonDev; | ||
68 | |||
69 | PVRSRV_ERROR IonInit(IMG_VOID) | ||
70 | { | ||
71 | gpsIonDev = omap_ion_device; | ||
72 | return PVRSRV_OK; | ||
73 | } | ||
74 | |||
75 | IMG_VOID IonDeinit(IMG_VOID) | ||
76 | { | ||
77 | gpsIonDev = IMG_NULL; | ||
78 | } | ||
79 | |||
80 | #else /* defined(CONFIG_ION_OMAP) */ | ||
81 | |||
82 | #if defined(CONFIG_ION_S5P) | ||
83 | |||
84 | /* Real ion with sharing (s5pv210) */ | ||
85 | |||
86 | extern struct ion_device *s5p_ion_device; | ||
87 | struct ion_device *gpsIonDev; | ||
88 | |||
89 | PVRSRV_ERROR IonInit(IMG_VOID) | ||
90 | { | ||
91 | gpsIonDev = s5p_ion_device; | ||
92 | return PVRSRV_OK; | ||
93 | } | ||
94 | |||
95 | IMG_VOID IonDeinit(IMG_VOID) | ||
96 | { | ||
97 | gpsIonDev = IMG_NULL; | ||
98 | } | ||
99 | |||
100 | #else /* defined(CONFIG_ION_S5P) */ | ||
101 | |||
102 | #if defined(CONFIG_ION_SUNXI) | ||
103 | |||
104 | /* Real ion with sharing (sunxi) */ | ||
105 | |||
106 | extern struct ion_device *sunxi_ion_device; | ||
107 | struct ion_device *gpsIonDev; | ||
108 | |||
109 | PVRSRV_ERROR IonInit(IMG_VOID) | ||
110 | { | ||
111 | gpsIonDev = sunxi_ion_device; | ||
112 | return PVRSRV_OK; | ||
113 | } | ||
114 | |||
115 | IMG_VOID IonDeinit(IMG_VOID) | ||
116 | { | ||
117 | gpsIonDev = IMG_NULL; | ||
118 | } | ||
119 | |||
120 | #else /* defined(CONFIG_ION_SUNXI) */ | ||
121 | |||
122 | #if defined(CONFIG_ION_INCDHAD1) | ||
123 | |||
124 | /* Real ion with sharing (incdhad1) */ | ||
125 | |||
126 | extern struct ion_device *incdhad1_ion_device; | ||
127 | struct ion_device *gpsIonDev; | ||
128 | |||
129 | PVRSRV_ERROR IonInit(IMG_VOID) | ||
130 | { | ||
131 | gpsIonDev = incdhad1_ion_device; | ||
132 | return PVRSRV_OK; | ||
133 | } | ||
134 | |||
135 | |||
136 | IMG_VOID IonDeinit(IMG_VOID) | ||
137 | { | ||
138 | gpsIonDev = IMG_NULL; | ||
139 | } | ||
140 | |||
141 | #else /* defined(CONFIG_ION_INCDHAD1) */ | ||
142 | |||
143 | /* "Reference" ion implementation */ | ||
144 | |||
145 | #include SUPPORT_ION_PRIV_HEADER | ||
146 | #include <linux/version.h> | ||
147 | #include "ion_sys_private.h" | ||
148 | #include "lma_heap_ion.h" | ||
149 | |||
150 | static struct ion_heap **gapsIonHeaps; | ||
151 | struct ion_device *gpsIonDev; | ||
152 | |||
153 | #if defined(LMA) | ||
154 | struct ion_platform_data gsTCIonConfig = { | ||
155 | .nr = 1, | ||
156 | .heaps = | ||
157 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,39)) | ||
158 | #else | ||
159 | (struct ion_platform_heap []) | ||
160 | #endif | ||
161 | { | ||
162 | { | ||
163 | /* This heap must be first. The base address and size are filled | ||
164 | in from data passed down by sysconfig.c. */ | ||
165 | .type = ION_HEAP_TYPE_CUSTOM, | ||
166 | .name = "tc_local_mem", | ||
167 | .id = ION_HEAP_TYPE_CUSTOM, | ||
168 | .base = 0, /* filled in later */ | ||
169 | .size = 0, /* filled in later */ | ||
170 | } | ||
171 | } | ||
172 | }; | ||
173 | |||
174 | PVRSRV_ERROR IonInit(void *pvPrivateData) | ||
175 | { | ||
176 | PVRSRV_ERROR eError = PVRSRV_OK; | ||
177 | int i; | ||
178 | |||
179 | ION_TC_PRIVATE_DATA sPrivateData = *(ION_TC_PRIVATE_DATA *)pvPrivateData; | ||
180 | |||
181 | /* Fill in the heap base and size according to the private data. */ | ||
182 | gsTCIonConfig.heaps[0].base = sPrivateData.uiHeapBase; | ||
183 | gsTCIonConfig.heaps[0].size = sPrivateData.uiHeapSize; | ||
184 | |||
185 | gapsIonHeaps = kzalloc(sizeof(struct ion_heap *) * gsTCIonConfig.nr, | ||
186 | GFP_KERNEL); | ||
187 | gpsIonDev = ion_device_create(NULL); | ||
188 | if (IS_ERR_OR_NULL(gpsIonDev)) | ||
189 | { | ||
190 | kfree(gapsIonHeaps); | ||
191 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
192 | } | ||
193 | |||
194 | for (i = 0; i < gsTCIonConfig.nr; i++) | ||
195 | { | ||
196 | struct ion_platform_heap *psPlatHeapData = &gsTCIonConfig.heaps[i]; | ||
197 | |||
198 | switch (psPlatHeapData->type) | ||
199 | { | ||
200 | case ION_HEAP_TYPE_CUSTOM: | ||
201 | /* Custom heap: this is used to mean a TC-specific heap, | ||
202 | which allocates from local memory. */ | ||
203 | gapsIonHeaps[i] = lma_heap_create(psPlatHeapData); | ||
204 | break; | ||
205 | default: | ||
206 | /* For any other type of heap, hand this to ion to create as | ||
207 | appropriate. We don't necessarily need any of these - | ||
208 | this just gives us the flexibility to have another kind | ||
209 | of heap if necessary. */ | ||
210 | gapsIonHeaps[i] = ion_heap_create(psPlatHeapData); | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | if (IS_ERR_OR_NULL(gapsIonHeaps[i])) | ||
215 | { | ||
216 | printk("%s: Failed to create ion heap '%s'", __func__, psPlatHeapData->name); | ||
217 | IonDeinit(); | ||
218 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
219 | } | ||
220 | |||
221 | ion_device_add_heap(gpsIonDev, gapsIonHeaps[i]); | ||
222 | } | ||
223 | |||
224 | return eError; | ||
225 | } | ||
226 | |||
227 | void IonDeinit(void) | ||
228 | { | ||
229 | int i; | ||
230 | for (i = 0; i < gsTCIonConfig.nr; i++) | ||
231 | if (gapsIonHeaps[i]) | ||
232 | ion_heap_destroy(gapsIonHeaps[i]); | ||
233 | kfree(gapsIonHeaps); | ||
234 | ion_device_destroy(gpsIonDev); | ||
235 | } | ||
236 | |||
237 | #else | ||
238 | |||
239 | #if defined(ION_CARVEOUT_MEM_BASE) && defined(ION_CARVEOUT_MEM_SIZE) | ||
240 | /* Only define the carveout heap on boards with BASE and SIZE defined, | ||
241 | * otherwise crashes may be seen when empty cache flushes are issued | ||
242 | * (seen on the MIPS architecture). | ||
243 | */ | ||
244 | #define ION_HAS_CARVEOUT_HEAP | ||
245 | #endif | ||
246 | |||
247 | static struct ion_platform_data gsGenericConfig = | ||
248 | { | ||
249 | #if defined(ION_HAS_CARVEOUT_HEAP) | ||
250 | .nr = 3, | ||
251 | #else | ||
252 | .nr = 2, | ||
253 | #endif | ||
254 | .heaps = | ||
255 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,39)) | ||
256 | (struct ion_platform_heap []) | ||
257 | #endif | ||
258 | { | ||
259 | { | ||
260 | .type = ION_HEAP_TYPE_SYSTEM, | ||
261 | .name = "system", | ||
262 | .id = ION_HEAP_TYPE_SYSTEM, | ||
263 | }, | ||
264 | { | ||
265 | .type = ION_HEAP_TYPE_DMA, | ||
266 | .name = "dma", | ||
267 | .id = ION_HEAP_TYPE_DMA, | ||
268 | }, | ||
269 | #if defined(ION_HAS_CARVEOUT_HEAP) | ||
270 | { | ||
271 | .type = ION_HEAP_TYPE_CARVEOUT, | ||
272 | .name = "carveout", | ||
273 | .id = ION_HEAP_TYPE_CARVEOUT, | ||
274 | .base = ION_CARVEOUT_MEM_BASE, | ||
275 | .size = ION_CARVEOUT_MEM_SIZE, | ||
276 | }, | ||
277 | #endif /* defined(ION_HAS_CARVEOUT_HEAP) */ | ||
278 | } | ||
279 | }; | ||
280 | |||
281 | PVRSRV_ERROR IonInit(IMG_VOID) | ||
282 | { | ||
283 | int uiHeapCount = gsGenericConfig.nr; | ||
284 | int uiError; | ||
285 | int i; | ||
286 | |||
287 | gapsIonHeaps = kzalloc(sizeof(struct ion_heap *) * uiHeapCount, GFP_KERNEL); | ||
288 | /* Create the ion devicenode */ | ||
289 | gpsIonDev = ion_device_create(NULL); | ||
290 | if (IS_ERR_OR_NULL(gpsIonDev)) { | ||
291 | kfree(gapsIonHeaps); | ||
292 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
293 | } | ||
294 | |||
295 | /* Register all the heaps */ | ||
296 | for (i = 0; i < gsGenericConfig.nr; i++) | ||
297 | { | ||
298 | struct ion_platform_heap *psPlatHeapData = &gsGenericConfig.heaps[i]; | ||
299 | |||
300 | gapsIonHeaps[i] = ion_heap_create(psPlatHeapData); | ||
301 | if (IS_ERR_OR_NULL(gapsIonHeaps[i])) | ||
302 | { | ||
303 | uiError = PTR_ERR(gapsIonHeaps[i]); | ||
304 | goto failHeapCreate; | ||
305 | } | ||
306 | ion_device_add_heap(gpsIonDev, gapsIonHeaps[i]); | ||
307 | } | ||
308 | |||
309 | return PVRSRV_OK; | ||
310 | failHeapCreate: | ||
311 | for (i = 0; i < uiHeapCount; i++) | ||
312 | { | ||
313 | if (gapsIonHeaps[i]) | ||
314 | { | ||
315 | ion_heap_destroy(gapsIonHeaps[i]); | ||
316 | } | ||
317 | } | ||
318 | kfree(gapsIonHeaps); | ||
319 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
320 | } | ||
321 | |||
322 | IMG_VOID IonDeinit(IMG_VOID) | ||
323 | { | ||
324 | int uiHeapCount = gsGenericConfig.nr; | ||
325 | int i; | ||
326 | |||
327 | for (i = 0; i < uiHeapCount; i++) | ||
328 | { | ||
329 | if (gapsIonHeaps[i]) | ||
330 | { | ||
331 | ion_heap_destroy(gapsIonHeaps[i]); | ||
332 | } | ||
333 | } | ||
334 | kfree(gapsIonHeaps); | ||
335 | ion_device_destroy(gpsIonDev); | ||
336 | } | ||
337 | |||
338 | #endif /* defined(LMA) */ | ||
339 | |||
340 | #endif /* defined(CONFIG_ION_INCDHAD1) */ | ||
341 | |||
342 | #endif /* defined(CONFIG_ION_SUNXI) */ | ||
343 | |||
344 | #endif /* defined(CONFIG_ION_S5P) */ | ||
345 | |||
346 | #endif /* defined(CONFIG_ION_OMAP) */ | ||
347 | |||
348 | #define MAX_IMPORT_ION_FDS 3 | ||
349 | |||
350 | typedef struct _ION_IMPORT_DATA_ | ||
351 | { | ||
352 | /* ion client handles are imported into */ | ||
353 | struct ion_client *psIonClient; | ||
354 | |||
355 | /* Number of ion handles represented by this import */ | ||
356 | IMG_UINT32 ui32NumIonHandles; | ||
357 | |||
358 | /* Array of ion handles in use by services */ | ||
359 | struct ion_handle *apsIonHandle[MAX_IMPORT_ION_FDS]; | ||
360 | |||
361 | /* Array of physical addresses represented by these buffers */ | ||
362 | IMG_SYS_PHYADDR *psSysPhysAddr; | ||
363 | |||
364 | #if defined(PDUMP) | ||
365 | /* If ui32NumBuffers is 1 and ion_map_kernel() is implemented by the | ||
366 | * allocator, this may be non-NULL. Otherwise it will be NULL. | ||
367 | */ | ||
368 | IMG_PVOID pvKernAddr0; | ||
369 | #endif /* defined(PDUMP) */ | ||
370 | } | ||
371 | ION_IMPORT_DATA; | ||
372 | |||
373 | PVRSRV_ERROR IonImportBufferAndAcquirePhysAddr(IMG_HANDLE hIonDev, | ||
374 | IMG_UINT32 ui32NumFDs, | ||
375 | IMG_INT32 *pai32BufferFDs, | ||
376 | IMG_UINT32 *pui32PageCount, | ||
377 | IMG_SYS_PHYADDR **ppsSysPhysAddr, | ||
378 | IMG_PVOID *ppvKernAddr0, | ||
379 | IMG_HANDLE *phPriv, | ||
380 | IMG_HANDLE *phUnique) | ||
381 | { | ||
382 | struct scatterlist *psTemp, *psScatterList[MAX_IMPORT_ION_FDS] = {}; | ||
383 | PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY; | ||
384 | struct ion_client *psIonClient = hIonDev; | ||
385 | IMG_UINT32 i, k, ui32PageCount = 0; | ||
386 | ION_IMPORT_DATA *psImportData; | ||
387 | |||
388 | if(ui32NumFDs > MAX_IMPORT_ION_FDS) | ||
389 | { | ||
390 | printk(KERN_ERR "%s: More ion export fds passed in than supported " | ||
391 | "(%d provided, %d max)", __func__, ui32NumFDs, | ||
392 | MAX_IMPORT_ION_FDS); | ||
393 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
394 | } | ||
395 | |||
396 | psImportData = kzalloc(sizeof(ION_IMPORT_DATA), GFP_KERNEL); | ||
397 | if (psImportData == NULL) | ||
398 | { | ||
399 | goto exitFailKMallocImportData; | ||
400 | } | ||
401 | |||
402 | /* Set up import data for free call */ | ||
403 | psImportData->psIonClient = psIonClient; | ||
404 | psImportData->ui32NumIonHandles = ui32NumFDs; | ||
405 | |||
406 | for(i = 0; i < ui32NumFDs; i++) | ||
407 | { | ||
408 | int fd = (int)pai32BufferFDs[i]; | ||
409 | struct sg_table *psSgTable; | ||
410 | |||
411 | psImportData->apsIonHandle[i] = ion_import_dma_buf(psIonClient, fd); | ||
412 | if (psImportData->apsIonHandle[i] == IMG_NULL) | ||
413 | { | ||
414 | eError = PVRSRV_ERROR_BAD_MAPPING; | ||
415 | goto exitFailImport; | ||
416 | } | ||
417 | |||
418 | psSgTable = ion_sg_table(psIonClient, psImportData->apsIonHandle[i]); | ||
419 | psScatterList[i] = psSgTable->sgl; | ||
420 | if (psScatterList[i] == NULL) | ||
421 | { | ||
422 | eError = PVRSRV_ERROR_INVALID_PARAMS; | ||
423 | goto exitFailImport; | ||
424 | } | ||
425 | |||
426 | /* Although all heaps will provide an sg_table, the tables cannot | ||
427 | * always be trusted because sg_lists are just pointers to "struct | ||
428 | * page" values, and some memory e.g. carveout may not have valid | ||
429 | * "struct page" values. In particular, on ARM, carveout is | ||
430 | * generally reserved with memblock_remove(), which leaves the | ||
431 | * "struct page" entries uninitialized when SPARSEMEM is enabled. | ||
432 | * The effect of this is that page_to_pfn(pfn_to_page(pfn)) != pfn. | ||
433 | * | ||
434 | * There's more discussion on this mailing list thread: | ||
435 | * http://lists.linaro.org/pipermail/linaro-mm-sig/2012-August/002440.html | ||
436 | * | ||
437 | * If the heap this buffer comes from implements ->phys(), it's | ||
438 | * probably a contiguous allocator. If the phys() function is | ||
439 | * implemented, we'll use it to check sg_table->sgl[0]. If we find | ||
440 | * they don't agree, we'll assume phys() is more reliable and use | ||
441 | * that. | ||
442 | * | ||
443 | * Some heaps out there will implement phys() even though they are | ||
444 | * not for physically contiguous allocations (so the sg_table must | ||
445 | * be used). Therefore use the sg_table if the phys() and first | ||
446 | * sg_table entry match. This should be reliable because for most | ||
447 | * contiguous allocators, the sg_table should be a single span | ||
448 | * from 'start' to 'start+size'. | ||
449 | * | ||
450 | * Also, ion prints out an error message if the heap doesn't implement | ||
451 | * ->phys(), which we want to avoid, so only use ->phys() if the | ||
452 | * sg_table contains a single span and therefore could plausibly | ||
453 | * be a contiguous allocator. | ||
454 | */ | ||
455 | if(!sg_next(psScatterList[i])) | ||
456 | { | ||
457 | ion_phys_addr_t sPhyAddr; | ||
458 | size_t sLength; | ||
459 | |||
460 | if(!ion_phys(psIonClient, psImportData->apsIonHandle[i], | ||
461 | &sPhyAddr, &sLength)) | ||
462 | { | ||
463 | BUG_ON(sLength & ~PAGE_MASK); | ||
464 | |||
465 | if(sg_phys(psScatterList[i]) != sPhyAddr) | ||
466 | { | ||
467 | psScatterList[i] = IMG_NULL; | ||
468 | ui32PageCount += sLength / PAGE_SIZE; | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | |||
473 | for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp)) | ||
474 | { | ||
475 | IMG_UINT32 j; | ||
476 | for (j = 0; j < psTemp->length; j += PAGE_SIZE) | ||
477 | { | ||
478 | ui32PageCount++; | ||
479 | } | ||
480 | } | ||
481 | } | ||
482 | |||
483 | BUG_ON(ui32PageCount == 0); | ||
484 | |||
485 | psImportData->psSysPhysAddr = kmalloc(sizeof(IMG_SYS_PHYADDR) * ui32PageCount, GFP_KERNEL); | ||
486 | if (psImportData->psSysPhysAddr == NULL) | ||
487 | { | ||
488 | goto exitFailImport; | ||
489 | } | ||
490 | |||
491 | for(i = 0, k = 0; i < ui32NumFDs; i++) | ||
492 | { | ||
493 | if(psScatterList[i]) | ||
494 | { | ||
495 | for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp)) | ||
496 | { | ||
497 | IMG_UINT32 j; | ||
498 | for (j = 0; j < psTemp->length; j += PAGE_SIZE) | ||
499 | { | ||
500 | psImportData->psSysPhysAddr[k].uiAddr = sg_phys(psTemp) + j; | ||
501 | k++; | ||
502 | } | ||
503 | } | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | ion_phys_addr_t sPhyAddr; | ||
508 | size_t sLength, j; | ||
509 | |||
510 | ion_phys(psIonClient, psImportData->apsIonHandle[i], | ||
511 | &sPhyAddr, &sLength); | ||
512 | |||
513 | for(j = 0; j < sLength; j += PAGE_SIZE) | ||
514 | { | ||
515 | psImportData->psSysPhysAddr[k].uiAddr = sPhyAddr + j; | ||
516 | k++; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | |||
521 | *pui32PageCount = ui32PageCount; | ||
522 | *ppsSysPhysAddr = psImportData->psSysPhysAddr; | ||
523 | |||
524 | #if defined(PDUMP) | ||
525 | if(ui32NumFDs == 1) | ||
526 | { | ||
527 | IMG_PVOID pvKernAddr0; | ||
528 | |||
529 | pvKernAddr0 = ion_map_kernel(psIonClient, psImportData->apsIonHandle[0]); | ||
530 | if (IS_ERR(pvKernAddr0)) | ||
531 | { | ||
532 | pvKernAddr0 = IMG_NULL; | ||
533 | } | ||
534 | |||
535 | psImportData->pvKernAddr0 = pvKernAddr0; | ||
536 | *ppvKernAddr0 = pvKernAddr0; | ||
537 | } | ||
538 | else | ||
539 | #endif /* defined(PDUMP) */ | ||
540 | { | ||
541 | *ppvKernAddr0 = NULL; | ||
542 | } | ||
543 | |||
544 | *phPriv = psImportData; | ||
545 | *phUnique = (IMG_HANDLE)psImportData->psSysPhysAddr[0].uiAddr; | ||
546 | |||
547 | return PVRSRV_OK; | ||
548 | |||
549 | exitFailImport: | ||
550 | for(i = 0; psImportData->apsIonHandle[i] != NULL; i++) | ||
551 | { | ||
552 | ion_free(psIonClient, psImportData->apsIonHandle[i]); | ||
553 | } | ||
554 | kfree(psImportData); | ||
555 | exitFailKMallocImportData: | ||
556 | return eError; | ||
557 | } | ||
558 | |||
559 | IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv) | ||
560 | { | ||
561 | ION_IMPORT_DATA *psImportData = hPriv; | ||
562 | IMG_UINT32 i; | ||
563 | |||
564 | #if defined(PDUMP) | ||
565 | if (psImportData->pvKernAddr0) | ||
566 | { | ||
567 | ion_unmap_kernel(psImportData->psIonClient, psImportData->apsIonHandle[0]); | ||
568 | } | ||
569 | #endif /* defined(PDUMP) */ | ||
570 | |||
571 | for(i = 0; i < psImportData->ui32NumIonHandles; i++) | ||
572 | { | ||
573 | ion_free(psImportData->psIonClient, psImportData->apsIonHandle[i]); | ||
574 | } | ||
575 | |||
576 | kfree(psImportData->psSysPhysAddr); | ||
577 | kfree(psImportData); | ||
578 | } | ||
579 | |||
580 | #endif /* defined(SUPPORT_ION) */ | ||