blob: 790f478f71746c6252d34eef12688e072b249eef [file] [log] [blame]
developer02e65912023-08-17 16:33:10 +08001/* adapter_dmabuf.c
2 *
3 * Implementation of the DMA Buffer Allocation API.
4 */
5
6/*****************************************************************************
7* Copyright (c) 2008-2020 by Rambus, Inc. and/or its subsidiaries.
8*
9* This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 2 of the License, or
12* any later version.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>.
21*****************************************************************************/
22
23/*----------------------------------------------------------------------------
24 * This module implements (provides) the following interface(s):
25 */
26
27// DMABuf API
28#include "api_dmabuf.h"
29
30// Adapter DMABuf internal API
31#include "adapter_dmabuf.h"
32
33
34/*----------------------------------------------------------------------------
35 * This module uses (requires) the following interface(s):
36 */
37
38// Logging API
39#include "log.h"
40
41// Driver Framework DMAResource API
42#include "dmares_types.h"
43#include "dmares_mgmt.h"
44#include "dmares_buf.h"
45#include "dmares_addr.h"
46
47// Driver Framework Basic Definitions API
48#include "basic_defs.h"
49
50// Driver Framework C Run-Time Library API
51#include "clib.h" // memcmp
52
53
54/*----------------------------------------------------------------------------
55 * Definitions and macros
56 */
57
58
59/*----------------------------------------------------------------------------
60 * Local variables
61 */
62
63/*----------------------------------------------------------------------------
64 * DMABuf_NULLHandle
65 *
66 */
67const DMABuf_Handle_t DMABuf_NULLHandle = { NULL };
68
69// Initial DMA buffer alignment setting
70static int Adapter_DMABuf_Alignment = ADAPTER_DMABUF_ALIGNMENT_INVALID;
71
72
73/*----------------------------------------------------------------------------
74 * Adapter_DMABuf_Handle2DMAResourceHandle
75 */
76DMAResource_Handle_t
77Adapter_DMABuf_Handle2DMAResourceHandle(
78 DMABuf_Handle_t Handle)
79{
80 if (Handle.p == NULL)
81 {
82 return NULL;
83 }
84 else
85 {
86 return (DMAResource_Handle_t)Handle.p;
87 }
88}
89
90
91/*----------------------------------------------------------------------------
92 * Adapter_DMAResource_Handle2DMABufHandle
93 */
94DMABuf_Handle_t
95Adapter_DMAResource_Handle2DMABufHandle(
96 DMAResource_Handle_t Handle)
97{
98 DMABuf_Handle_t DMABuf_Handle;
99
100 DMABuf_Handle.p = Handle;
101
102 return DMABuf_Handle;
103}
104
105
106/*----------------------------------------------------------------------------
107 * Adapter_DMAResource_IsForeignAllocated
108 */
109bool
110Adapter_DMAResource_IsForeignAllocated(
111 DMAResource_Handle_t Handle)
112{
113 DMAResource_Record_t * Rec_p;
114
115 Rec_p = DMAResource_Handle2RecordPtr(Handle);
116
117 if(!Rec_p)
118 {
119 return false;
120 }
121 else
122 {
123 return (Rec_p->AllocatorRef != 'A' && Rec_p->AllocatorRef != 'R');
124 }
125}
126
127
128/*----------------------------------------------------------------------------
129 * Adapter_DMAResource_HostAddr
130 */
131void *
132Adapter_DMAResource_HostAddr(
133 DMAResource_Handle_t Handle)
134{
135 DMAResource_AddrPair_t HostAddr;
136
137 DMAResource_Translate(Handle, DMARES_DOMAIN_HOST, &HostAddr);
138
139 return HostAddr.Address_p;
140}
141
142
143/*----------------------------------------------------------------------------
144 * Adapter_DMAResource_IsSubRangeOf
145 *
146 * Return true if the address range defined by Handle1 is
147 * within the address range defined by Handle2.
148 */
149bool
150Adapter_DMAResource_IsSubRangeOf(
151 const DMAResource_Handle_t Handle1,
152 const DMAResource_Handle_t Handle2)
153{
154 DMAResource_AddrPair_t AddrPair1, AddrPair2;
155
156 DMAResource_Translate(Handle1, DMARES_DOMAIN_HOST, &AddrPair1);
157 DMAResource_Translate(Handle2, DMARES_DOMAIN_HOST, &AddrPair2);
158
159 if (AddrPair1.Domain == AddrPair2.Domain)
160 {
161 const uint8_t * Addr1 = AddrPair1.Address_p;
162 const uint8_t * Addr2 = AddrPair2.Address_p;
163 const DMAResource_Record_t * const Rec1_p =
164 DMAResource_Handle2RecordPtr(Handle1);
165 const DMAResource_Record_t * const Rec2_p =
166 DMAResource_Handle2RecordPtr(Handle2);
167
168 if ((Rec1_p->Props.Size <= Rec2_p->Props.Size) &&
169 (Addr2 <= Addr1) &&
170 ((Addr1 + Rec1_p->Props.Size) <= (Addr2 + Rec2_p->Props.Size)))
171 {
172 return true;
173 }
174 }
175
176 return false;
177}
178
179
180/*----------------------------------------------------------------------------
181 * Adapter_DMAResource_Alignment_Set
182 */
183void
184Adapter_DMAResource_Alignment_Set(
185 const int Alignment)
186{
187 Adapter_DMABuf_Alignment = Alignment;
188
189 return;
190}
191
192
193/*----------------------------------------------------------------------------
194 * Adapter_DMAResource_Alignment_Get
195 */
196int
197Adapter_DMAResource_Alignment_Get(void)
198{
199 return Adapter_DMABuf_Alignment;
200}
201
202
203/*----------------------------------------------------------------------------
204 * DMABuf_Handle_IsSame
205 */
206bool
207DMABuf_Handle_IsSame(
208 const DMABuf_Handle_t * const Handle1_p,
209 const DMABuf_Handle_t * const Handle2_p)
210{
211 if (memcmp(Handle1_p, Handle2_p, sizeof(DMABuf_Handle_t)) == 0)
212 {
213 return true;
214 }
215
216 return false;
217}
218
219
220/*----------------------------------------------------------------------------
221 * DMABuf_Alloc
222 */
223DMABuf_Status_t
224DMABuf_Alloc(
225 const DMABuf_Properties_t RequestedProperties,
226 DMABuf_HostAddress_t * const Buffer_p,
227 DMABuf_Handle_t * const Handle_p)
228{
229 DMAResource_Handle_t DMAHandle;
230 DMAResource_AddrPair_t AddrPair;
231 DMAResource_Properties_t ActualProperties;
232
233 ZEROINIT(AddrPair);
234 ZEROINIT(ActualProperties);
235
236 if (Handle_p == NULL ||
237 Buffer_p == NULL)
238 {
239 return DMABUF_ERROR_BAD_ARGUMENT;
240 }
241
242 // initialize the output parameters
243 Handle_p->p = NULL;
244 Buffer_p->p = NULL;
245
246 ActualProperties.Size = RequestedProperties.Size;
247 ActualProperties.Bank = RequestedProperties.Bank;
248 ActualProperties.fCached = RequestedProperties.fCached;
249
250 if (Adapter_DMABuf_Alignment != ADAPTER_DMABUF_ALIGNMENT_INVALID &&
251 RequestedProperties.Alignment < Adapter_DMABuf_Alignment)
252 ActualProperties.Alignment = Adapter_DMABuf_Alignment;
253 else
254 ActualProperties.Alignment = RequestedProperties.Alignment;
255
256 if( !DMAResource_Alloc(ActualProperties,&AddrPair,&DMAHandle) )
257 {
258 // set the output parameters
259 Handle_p->p = (void*)DMAHandle;
260 Buffer_p->p = AddrPair.Address_p;
261
262 LOG_INFO("DMABuf_Alloc: allocated handle=%p, host addr=%p, "
263 "alignment requested/actual %d/%d, "
264 "bank requested %d, cached requested %d\n",
265 Handle_p->p,
266 Buffer_p->p,
267 RequestedProperties.Alignment,
268 ActualProperties.Alignment,
269 RequestedProperties.Bank,
270 RequestedProperties.fCached);
271
272 return DMABUF_STATUS_OK;
273 }
274 else
275 {
276 return DMABUF_ERROR_OUT_OF_MEMORY;
277 }
278}
279
280
281/*----------------------------------------------------------------------------
282 * DMABuf_Register
283 */
284DMABuf_Status_t
285DMABuf_Register(
286 const DMABuf_Properties_t RequestedProperties,
287 void * Buffer_p,
288 void * Alternative_p,
289 const char AllocatorRef,
290 DMABuf_Handle_t * const Handle_p)
291{
292 DMAResource_Handle_t DMAHandle;
293 char ActualAllocator;
294 DMAResource_AddrPair_t AddrPair;
295 DMAResource_Properties_t ActualProperties;
296
297 ZEROINIT(AddrPair);
298 ZEROINIT(ActualProperties);
299
300 if (Handle_p == NULL ||
301 Buffer_p == NULL)
302 {
303 return DMABUF_ERROR_BAD_ARGUMENT;
304 }
305
306 // initialize the output parameter
307 Handle_p->p = NULL;
308
309 ActualProperties.Size = RequestedProperties.Size;
310 ActualProperties.Bank = RequestedProperties.Bank;
311 ActualProperties.fCached = RequestedProperties.fCached;
312
313 if (Adapter_DMABuf_Alignment != ADAPTER_DMABUF_ALIGNMENT_INVALID &&
314 RequestedProperties.Alignment < Adapter_DMABuf_Alignment)
315 ActualProperties.Alignment = Adapter_DMABuf_Alignment;
316 else
317 ActualProperties.Alignment = RequestedProperties.Alignment;
318
319 ActualAllocator = AllocatorRef;
320
321 if( AllocatorRef == 'k' || AllocatorRef == 'N' || AllocatorRef == 'R'
322 || AllocatorRef == 'C')
323 {
324 // 'N' is used to register buffers that do not need to be DMA-safe.
325 // 'R' is used to register (subranges of) buffers that are already
326 // allocated with DMAResource_Alloc()/DMABuf_Alloc().
327 // 'k' is supported for Linux kmalloc() allocator only,
328 // e.g. AllocatorRef = 'k' for streaming DMA mappings
329 // 'C' is supported for coherent buffers.
330 AddrPair.Domain = DMARES_DOMAIN_HOST;
331 AddrPair.Address_p = Buffer_p;
332 }
333 else if( AllocatorRef == 0 )
334 {
335 // Linux kmalloc() allocator is used,
336 // e.g. AllocatorRef = 'k' for streaming DMA mappings
337 ActualAllocator = 'k';
338 AddrPair.Domain = DMARES_DOMAIN_HOST;
339 AddrPair.Address_p = Buffer_p;
340 }
341 else
342 {
343 return DMABUF_ERROR_BAD_ARGUMENT;
344 }
345
346 if( DMAResource_CheckAndRegister(ActualProperties,AddrPair,
347 ActualAllocator,&DMAHandle) == 0 )
348 {
349 if( ActualAllocator == 'C' )
350 {
351 // Add bus address for the resource for AllocatorRef = 'C'
352 AddrPair.Domain = DMARES_DOMAIN_BUS;
353 AddrPair.Address_p = Alternative_p;
354
355 DMAResource_AddPair(DMAHandle,AddrPair);
356 }
357
358 // set the output parameters
359 Handle_p->p = (void*)DMAHandle;
360
361 LOG_INFO("DMABuf_Register: registered handle=%p, host addr=%p, "
362 "allocator=%d, alignment requested/actual %d/%d, "
363 "bank requested %d, cached requested %d\n",
364 Handle_p->p,
365 Buffer_p,
366 AllocatorRef,
367 RequestedProperties.Alignment,
368 ActualProperties.Alignment,
369 RequestedProperties.Bank,
370 RequestedProperties.fCached);
371
372 return DMABUF_STATUS_OK;
373 }
374 else
375 {
376 return DMABUF_ERROR_OUT_OF_MEMORY;
377 }
378}
379
380
381/*----------------------------------------------------------------------------
382 * DMABuf_Release
383 */
384DMABuf_Status_t
385DMABuf_Release(
386 DMABuf_Handle_t Handle)
387{
388 DMAResource_Handle_t DMAHandle =
389 Adapter_DMABuf_Handle2DMAResourceHandle(Handle);
390
391 LOG_INFO("DMABuf_Release: handle to release=%p\n",Handle.p);
392
393 if( DMAResource_Release(DMAHandle) == 0 )
394 {
395 return DMABUF_STATUS_OK;
396 }
397 else
398 {
399 return DMABUF_ERROR_INVALID_HANDLE;
400 }
401}
402
403
404/* end of file adapter_dmabuf.c */