diff options
Diffstat (limited to 'jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/dmabuf.c')
-rw-r--r-- | jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/dmabuf.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/dmabuf.c b/jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/dmabuf.c new file mode 100644 index 0000000..29c7d5d --- /dev/null +++ b/jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/dmabuf.c | |||
@@ -0,0 +1,283 @@ | |||
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 "dmabuf.h" | ||
43 | #include <linux/platform_device.h> | ||
44 | #include <linux/dma-buf.h> | ||
45 | #include <linux/dma-direction.h> | ||
46 | #include <linux/scatterlist.h> | ||
47 | #include <linux/kernel.h> | ||
48 | #include <linux/slab.h> | ||
49 | #include <linux/err.h> | ||
50 | |||
51 | extern struct platform_device *gpsPVRLDMDev; | ||
52 | |||
53 | #define MAX_IMPORT_DMABUF_FDS 3 | ||
54 | |||
55 | typedef struct _DMABUF_IMPORT_DATA_ | ||
56 | { | ||
57 | /* Number of dma_buf handles represented by this import */ | ||
58 | IMG_UINT32 ui32NumHandles; | ||
59 | |||
60 | /* Array of dma_buf handles in use by services */ | ||
61 | struct dma_buf *apsDmaBuf[MAX_IMPORT_DMABUF_FDS]; | ||
62 | |||
63 | /* Array of dma_buf attachments */ | ||
64 | struct dma_buf_attachment *apsDmaBufAttachment[MAX_IMPORT_DMABUF_FDS]; | ||
65 | |||
66 | /* Array of sg_tables */ | ||
67 | struct sg_table *apsSgTable[MAX_IMPORT_DMABUF_FDS]; | ||
68 | |||
69 | /* Array of physical addresses represented by these buffers */ | ||
70 | IMG_SYS_PHYADDR *psSysPhysAddr; | ||
71 | |||
72 | #if defined(PDUMP) | ||
73 | /* FIXME: Not sure if this is needed here */ | ||
74 | IMG_PVOID pvKernAddr0; | ||
75 | #endif /* defined(PDUMP) */ | ||
76 | } | ||
77 | DMABUF_IMPORT_DATA; | ||
78 | |||
79 | PVRSRV_ERROR DmabufImportBufferAndAcquirePhysAddr(IMG_UINT32 ui32NumFDs, | ||
80 | IMG_INT32 *pai32BufferFDs, | ||
81 | IMG_UINT32 *pui32PageCount, | ||
82 | IMG_SYS_PHYADDR **ppsSysPhysAddr, | ||
83 | IMG_PVOID *ppvKernAddr0, | ||
84 | IMG_HANDLE *phPriv, | ||
85 | IMG_HANDLE *phUnique) | ||
86 | { | ||
87 | struct scatterlist *psTemp, *psScatterList[MAX_IMPORT_DMABUF_FDS] = {}; | ||
88 | PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY; | ||
89 | IMG_UINT32 i, k, ui32PageCount = 0; | ||
90 | DMABUF_IMPORT_DATA *psImportData; | ||
91 | |||
92 | if(ui32NumFDs > MAX_IMPORT_DMABUF_FDS) | ||
93 | { | ||
94 | printk(KERN_ERR "%s: More passed in than supported " | ||
95 | "(%d provided, %d max)", __func__, ui32NumFDs, | ||
96 | MAX_IMPORT_DMABUF_FDS); | ||
97 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
98 | } | ||
99 | |||
100 | psImportData = kzalloc(sizeof(DMABUF_IMPORT_DATA), GFP_KERNEL); | ||
101 | if (psImportData == NULL) | ||
102 | { | ||
103 | goto exitFailKMallocImportData; | ||
104 | } | ||
105 | |||
106 | /* Set up import data for free call */ | ||
107 | psImportData->ui32NumHandles = ui32NumFDs; | ||
108 | |||
109 | for(i = 0; i < ui32NumFDs; i++) | ||
110 | { | ||
111 | int fd = (int)pai32BufferFDs[i]; | ||
112 | |||
113 | psImportData->apsDmaBuf[i] = dma_buf_get(fd); | ||
114 | if (psImportData->apsDmaBuf[i] == IMG_NULL) | ||
115 | { | ||
116 | eError = PVRSRV_ERROR_BAD_MAPPING; | ||
117 | goto exitFailImport; | ||
118 | } | ||
119 | |||
120 | psImportData->apsDmaBufAttachment[i] = dma_buf_attach(psImportData->apsDmaBuf[i], | ||
121 | &gpsPVRLDMDev->dev); | ||
122 | |||
123 | psImportData->apsSgTable[i] = dma_buf_map_attachment(psImportData->apsDmaBufAttachment[i], | ||
124 | DMA_BIDIRECTIONAL); | ||
125 | |||
126 | psScatterList[i] = psImportData->apsSgTable[i]->sgl; | ||
127 | if (psScatterList[i] == NULL) | ||
128 | { | ||
129 | eError = PVRSRV_ERROR_INVALID_PARAMS; | ||
130 | goto exitFailImport; | ||
131 | } | ||
132 | |||
133 | /* Although all heaps will provide an sg_table, the tables cannot | ||
134 | * always be trusted because sg_lists are just pointers to "struct | ||
135 | * page" values, and some memory e.g. carveout may not have valid | ||
136 | * "struct page" values. In particular, on ARM, carveout is | ||
137 | * generally reserved with memblock_remove(), which leaves the | ||
138 | * "struct page" entries uninitialized when SPARSEMEM is enabled. | ||
139 | * The effect of this is that page_to_pfn(pfn_to_page(pfn)) != pfn. | ||
140 | * | ||
141 | * There's more discussion on this mailing list thread: | ||
142 | * http://lists.linaro.org/pipermail/linaro-mm-sig/2012-August/002440.html | ||
143 | * | ||
144 | * probably a contiguous allocator. If the phys() function is | ||
145 | * implemented, we'll use it to check sg_table->sgl[0]. If we find | ||
146 | * they don't agree, we'll assume phys() is more reliable and use | ||
147 | * that. | ||
148 | * | ||
149 | * Some heaps out there will implement phys() even though they are | ||
150 | * not for physically contiguous allocations (so the sg_table must | ||
151 | * be used). Therefore use the sg_table if the phys() and first | ||
152 | * sg_table entry match. This should be reliable because for most | ||
153 | * contiguous allocators, the sg_table should be a single span | ||
154 | * from 'start' to 'start+size'. | ||
155 | * | ||
156 | * Also, ion prints out an error message if the heap doesn't implement | ||
157 | * ->phys(), which we want to avoid, so only use ->phys() if the | ||
158 | * sg_table contains a single span and therefore could plausibly | ||
159 | * be a contiguous allocator. | ||
160 | */ | ||
161 | #if 0 | ||
162 | if(!sg_next(psScatterList[i])) | ||
163 | { | ||
164 | ion_phys_addr_t sPhyAddr; | ||
165 | size_t sLength; | ||
166 | |||
167 | if(!ion_phys(psIonClient, psImportData->apsIonHandle[i], | ||
168 | &sPhyAddr, &sLength)) | ||
169 | { | ||
170 | BUG_ON(sLength & ~PAGE_MASK); | ||
171 | |||
172 | if(sg_phys(psScatterList[i]) != sPhyAddr) | ||
173 | { | ||
174 | psScatterList[i] = IMG_NULL; | ||
175 | ui32PageCount += sLength / PAGE_SIZE; | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | #endif | ||
180 | for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp)) | ||
181 | { | ||
182 | IMG_UINT32 j; | ||
183 | for (j = 0; j < psTemp->length; j += PAGE_SIZE) | ||
184 | { | ||
185 | ui32PageCount++; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | |||
190 | BUG_ON(ui32PageCount == 0); | ||
191 | |||
192 | psImportData->psSysPhysAddr = kmalloc(sizeof(IMG_SYS_PHYADDR) * ui32PageCount, GFP_KERNEL); | ||
193 | if (psImportData->psSysPhysAddr == NULL) | ||
194 | { | ||
195 | goto exitFailImport; | ||
196 | } | ||
197 | |||
198 | for(i = 0, k = 0; i < ui32NumFDs; i++) | ||
199 | { | ||
200 | if(psScatterList[i]) | ||
201 | { | ||
202 | for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp)) | ||
203 | { | ||
204 | IMG_UINT32 j; | ||
205 | for (j = 0; j < psTemp->length; j += PAGE_SIZE) | ||
206 | { | ||
207 | psImportData->psSysPhysAddr[k].uiAddr = sg_phys(psTemp) + j; | ||
208 | k++; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | #if 0 | ||
213 | else | ||
214 | { | ||
215 | ion_phys_addr_t sPhyAddr; | ||
216 | size_t sLength, j; | ||
217 | |||
218 | ion_phys(psIonClient, psImportData->apsIonHandle[i], | ||
219 | &sPhyAddr, &sLength); | ||
220 | |||
221 | for(j = 0; j < sLength; j += PAGE_SIZE) | ||
222 | { | ||
223 | psImportData->psSysPhysAddr[k].uiAddr = sPhyAddr + j; | ||
224 | k++; | ||
225 | } | ||
226 | } | ||
227 | #endif | ||
228 | } | ||
229 | |||
230 | *pui32PageCount = ui32PageCount; | ||
231 | *ppsSysPhysAddr = psImportData->psSysPhysAddr; | ||
232 | |||
233 | #if defined(PDUMP) | ||
234 | if(ui32NumFDs == 1) | ||
235 | { | ||
236 | /*FIXME */ | ||
237 | /* Need to handle kernel mapping */ | ||
238 | } | ||
239 | else | ||
240 | #endif /* defined(PDUMP) */ | ||
241 | { | ||
242 | *ppvKernAddr0 = NULL; | ||
243 | } | ||
244 | |||
245 | *phPriv = psImportData; | ||
246 | *phUnique = (IMG_HANDLE)psImportData->psSysPhysAddr[0].uiAddr; | ||
247 | |||
248 | return PVRSRV_OK; | ||
249 | |||
250 | exitFailImport: | ||
251 | for(i = 0; psImportData->apsDmaBuf[i] != NULL; i++) | ||
252 | { | ||
253 | dma_buf_put(psImportData->apsDmaBuf[i]); | ||
254 | } | ||
255 | kfree(psImportData); | ||
256 | exitFailKMallocImportData: | ||
257 | return eError; | ||
258 | } | ||
259 | |||
260 | IMG_VOID DmabufUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv) | ||
261 | { | ||
262 | DMABUF_IMPORT_DATA *psImportData = hPriv; | ||
263 | IMG_UINT32 i; | ||
264 | |||
265 | #if defined(PDUMP) | ||
266 | if (psImportData->pvKernAddr0) | ||
267 | { | ||
268 | //FIXME | ||
269 | } | ||
270 | #endif /* defined(PDUMP) */ | ||
271 | for(i = 0; i < psImportData->ui32NumHandles; i++) | ||
272 | { | ||
273 | dma_buf_unmap_attachment(psImportData->apsDmaBufAttachment[i], | ||
274 | psImportData->apsSgTable[i], | ||
275 | DMA_BIDIRECTIONAL); | ||
276 | dma_buf_detach(psImportData->apsDmaBuf[i], | ||
277 | psImportData->apsDmaBufAttachment[i]); | ||
278 | dma_buf_put(psImportData->apsDmaBuf[i]); | ||
279 | } | ||
280 | |||
281 | kfree(psImportData->psSysPhysAddr); | ||
282 | kfree(psImportData); | ||
283 | } | ||