xref: /aosp_15_r20/external/libdrm/tegra/tegra.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker  * Copyright © 2012, 2013 Thierry Reding
3*7688df22SAndroid Build Coastguard Worker  * Copyright © 2013 Erik Faye-Lund
4*7688df22SAndroid Build Coastguard Worker  * Copyright © 2014 NVIDIA Corporation
5*7688df22SAndroid Build Coastguard Worker  *
6*7688df22SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*7688df22SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*7688df22SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*7688df22SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*7688df22SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*7688df22SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*7688df22SAndroid Build Coastguard Worker  *
13*7688df22SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*7688df22SAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*7688df22SAndroid Build Coastguard Worker  *
16*7688df22SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*7688df22SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*7688df22SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*7688df22SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*7688df22SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*7688df22SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*7688df22SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
23*7688df22SAndroid Build Coastguard Worker  */
24*7688df22SAndroid Build Coastguard Worker 
25*7688df22SAndroid Build Coastguard Worker #include <errno.h>
26*7688df22SAndroid Build Coastguard Worker #include <fcntl.h>
27*7688df22SAndroid Build Coastguard Worker #include <string.h>
28*7688df22SAndroid Build Coastguard Worker #include <unistd.h>
29*7688df22SAndroid Build Coastguard Worker 
30*7688df22SAndroid Build Coastguard Worker #include <sys/mman.h>
31*7688df22SAndroid Build Coastguard Worker 
32*7688df22SAndroid Build Coastguard Worker #include <xf86drm.h>
33*7688df22SAndroid Build Coastguard Worker 
34*7688df22SAndroid Build Coastguard Worker #include <tegra_drm.h>
35*7688df22SAndroid Build Coastguard Worker 
36*7688df22SAndroid Build Coastguard Worker #include "private.h"
37*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_free(struct drm_tegra_bo * bo)38*7688df22SAndroid Build Coastguard Worker static void drm_tegra_bo_free(struct drm_tegra_bo *bo)
39*7688df22SAndroid Build Coastguard Worker {
40*7688df22SAndroid Build Coastguard Worker     struct drm_tegra *drm = bo->drm;
41*7688df22SAndroid Build Coastguard Worker 
42*7688df22SAndroid Build Coastguard Worker     if (bo->map)
43*7688df22SAndroid Build Coastguard Worker         munmap(bo->map, bo->size);
44*7688df22SAndroid Build Coastguard Worker 
45*7688df22SAndroid Build Coastguard Worker     drmCloseBufferHandle(drm->fd, bo->handle);
46*7688df22SAndroid Build Coastguard Worker 
47*7688df22SAndroid Build Coastguard Worker     free(bo);
48*7688df22SAndroid Build Coastguard Worker }
49*7688df22SAndroid Build Coastguard Worker 
drm_tegra_wrap(struct drm_tegra ** drmp,int fd,bool close)50*7688df22SAndroid Build Coastguard Worker static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
51*7688df22SAndroid Build Coastguard Worker {
52*7688df22SAndroid Build Coastguard Worker     struct drm_tegra *drm;
53*7688df22SAndroid Build Coastguard Worker 
54*7688df22SAndroid Build Coastguard Worker     if (fd < 0 || !drmp)
55*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
56*7688df22SAndroid Build Coastguard Worker 
57*7688df22SAndroid Build Coastguard Worker     drm = calloc(1, sizeof(*drm));
58*7688df22SAndroid Build Coastguard Worker     if (!drm)
59*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
60*7688df22SAndroid Build Coastguard Worker 
61*7688df22SAndroid Build Coastguard Worker     drm->close = close;
62*7688df22SAndroid Build Coastguard Worker     drm->fd = fd;
63*7688df22SAndroid Build Coastguard Worker 
64*7688df22SAndroid Build Coastguard Worker     *drmp = drm;
65*7688df22SAndroid Build Coastguard Worker 
66*7688df22SAndroid Build Coastguard Worker     return 0;
67*7688df22SAndroid Build Coastguard Worker }
68*7688df22SAndroid Build Coastguard Worker 
drm_tegra_new(int fd,struct drm_tegra ** drmp)69*7688df22SAndroid Build Coastguard Worker drm_public int drm_tegra_new(int fd, struct drm_tegra **drmp)
70*7688df22SAndroid Build Coastguard Worker {
71*7688df22SAndroid Build Coastguard Worker     bool supported = false;
72*7688df22SAndroid Build Coastguard Worker     drmVersionPtr version;
73*7688df22SAndroid Build Coastguard Worker 
74*7688df22SAndroid Build Coastguard Worker     version = drmGetVersion(fd);
75*7688df22SAndroid Build Coastguard Worker     if (!version)
76*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
77*7688df22SAndroid Build Coastguard Worker 
78*7688df22SAndroid Build Coastguard Worker     if (!strncmp(version->name, "tegra", version->name_len))
79*7688df22SAndroid Build Coastguard Worker         supported = true;
80*7688df22SAndroid Build Coastguard Worker 
81*7688df22SAndroid Build Coastguard Worker     drmFreeVersion(version);
82*7688df22SAndroid Build Coastguard Worker 
83*7688df22SAndroid Build Coastguard Worker     if (!supported)
84*7688df22SAndroid Build Coastguard Worker         return -ENOTSUP;
85*7688df22SAndroid Build Coastguard Worker 
86*7688df22SAndroid Build Coastguard Worker     return drm_tegra_wrap(drmp, fd, false);
87*7688df22SAndroid Build Coastguard Worker }
88*7688df22SAndroid Build Coastguard Worker 
drm_tegra_close(struct drm_tegra * drm)89*7688df22SAndroid Build Coastguard Worker drm_public void drm_tegra_close(struct drm_tegra *drm)
90*7688df22SAndroid Build Coastguard Worker {
91*7688df22SAndroid Build Coastguard Worker     if (!drm)
92*7688df22SAndroid Build Coastguard Worker         return;
93*7688df22SAndroid Build Coastguard Worker 
94*7688df22SAndroid Build Coastguard Worker     if (drm->close)
95*7688df22SAndroid Build Coastguard Worker         close(drm->fd);
96*7688df22SAndroid Build Coastguard Worker 
97*7688df22SAndroid Build Coastguard Worker     free(drm);
98*7688df22SAndroid Build Coastguard Worker }
99*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_alloc(struct drm_tegra * drm,uint32_t handle,uint32_t flags,uint32_t size)100*7688df22SAndroid Build Coastguard Worker static struct drm_tegra_bo *drm_tegra_bo_alloc(struct drm_tegra *drm,
101*7688df22SAndroid Build Coastguard Worker                                                uint32_t handle,
102*7688df22SAndroid Build Coastguard Worker                                                uint32_t flags,
103*7688df22SAndroid Build Coastguard Worker                                                uint32_t size)
104*7688df22SAndroid Build Coastguard Worker {
105*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_bo *bo;
106*7688df22SAndroid Build Coastguard Worker 
107*7688df22SAndroid Build Coastguard Worker     bo = calloc(1, sizeof(*bo));
108*7688df22SAndroid Build Coastguard Worker     if (!bo)
109*7688df22SAndroid Build Coastguard Worker         return NULL;
110*7688df22SAndroid Build Coastguard Worker 
111*7688df22SAndroid Build Coastguard Worker     atomic_set(&bo->ref, 1);
112*7688df22SAndroid Build Coastguard Worker     bo->handle = handle;
113*7688df22SAndroid Build Coastguard Worker     bo->flags = flags;
114*7688df22SAndroid Build Coastguard Worker     bo->size = size;
115*7688df22SAndroid Build Coastguard Worker     bo->drm = drm;
116*7688df22SAndroid Build Coastguard Worker 
117*7688df22SAndroid Build Coastguard Worker     return bo;
118*7688df22SAndroid Build Coastguard Worker }
119*7688df22SAndroid Build Coastguard Worker 
120*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_bo_new(struct drm_tegra * drm,uint32_t flags,uint32_t size,struct drm_tegra_bo ** bop)121*7688df22SAndroid Build Coastguard Worker drm_tegra_bo_new(struct drm_tegra *drm, uint32_t flags, uint32_t size,
122*7688df22SAndroid Build Coastguard Worker                  struct drm_tegra_bo **bop)
123*7688df22SAndroid Build Coastguard Worker {
124*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_gem_create args;
125*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_bo *bo;
126*7688df22SAndroid Build Coastguard Worker     int err;
127*7688df22SAndroid Build Coastguard Worker 
128*7688df22SAndroid Build Coastguard Worker     if (!drm || size == 0 || !bop)
129*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
130*7688df22SAndroid Build Coastguard Worker 
131*7688df22SAndroid Build Coastguard Worker     bo = drm_tegra_bo_alloc(drm, 0, flags, size);
132*7688df22SAndroid Build Coastguard Worker     if (!bo)
133*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
134*7688df22SAndroid Build Coastguard Worker 
135*7688df22SAndroid Build Coastguard Worker     memset(&args, 0, sizeof(args));
136*7688df22SAndroid Build Coastguard Worker     args.flags = flags;
137*7688df22SAndroid Build Coastguard Worker     args.size = size;
138*7688df22SAndroid Build Coastguard Worker 
139*7688df22SAndroid Build Coastguard Worker     err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
140*7688df22SAndroid Build Coastguard Worker                               sizeof(args));
141*7688df22SAndroid Build Coastguard Worker     if (err < 0) {
142*7688df22SAndroid Build Coastguard Worker         err = -errno;
143*7688df22SAndroid Build Coastguard Worker         free(bo);
144*7688df22SAndroid Build Coastguard Worker         return err;
145*7688df22SAndroid Build Coastguard Worker     }
146*7688df22SAndroid Build Coastguard Worker 
147*7688df22SAndroid Build Coastguard Worker     bo->handle = args.handle;
148*7688df22SAndroid Build Coastguard Worker 
149*7688df22SAndroid Build Coastguard Worker     *bop = bo;
150*7688df22SAndroid Build Coastguard Worker 
151*7688df22SAndroid Build Coastguard Worker     return 0;
152*7688df22SAndroid Build Coastguard Worker }
153*7688df22SAndroid Build Coastguard Worker 
154*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_bo_wrap(struct drm_tegra * drm,uint32_t handle,uint32_t flags,uint32_t size,struct drm_tegra_bo ** bop)155*7688df22SAndroid Build Coastguard Worker drm_tegra_bo_wrap(struct drm_tegra *drm, uint32_t handle, uint32_t flags,
156*7688df22SAndroid Build Coastguard Worker                   uint32_t size, struct drm_tegra_bo **bop)
157*7688df22SAndroid Build Coastguard Worker {
158*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_bo *bo;
159*7688df22SAndroid Build Coastguard Worker 
160*7688df22SAndroid Build Coastguard Worker     if (!drm || !bop)
161*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
162*7688df22SAndroid Build Coastguard Worker 
163*7688df22SAndroid Build Coastguard Worker     bo = drm_tegra_bo_alloc(drm, handle, flags, size);
164*7688df22SAndroid Build Coastguard Worker     if (!bo)
165*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
166*7688df22SAndroid Build Coastguard Worker 
167*7688df22SAndroid Build Coastguard Worker     *bop = bo;
168*7688df22SAndroid Build Coastguard Worker 
169*7688df22SAndroid Build Coastguard Worker     return 0;
170*7688df22SAndroid Build Coastguard Worker }
171*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_ref(struct drm_tegra_bo * bo)172*7688df22SAndroid Build Coastguard Worker drm_public struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
173*7688df22SAndroid Build Coastguard Worker {
174*7688df22SAndroid Build Coastguard Worker     if (bo)
175*7688df22SAndroid Build Coastguard Worker         atomic_inc(&bo->ref);
176*7688df22SAndroid Build Coastguard Worker 
177*7688df22SAndroid Build Coastguard Worker     return bo;
178*7688df22SAndroid Build Coastguard Worker }
179*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_unref(struct drm_tegra_bo * bo)180*7688df22SAndroid Build Coastguard Worker drm_public void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
181*7688df22SAndroid Build Coastguard Worker {
182*7688df22SAndroid Build Coastguard Worker     if (bo && atomic_dec_and_test(&bo->ref))
183*7688df22SAndroid Build Coastguard Worker         drm_tegra_bo_free(bo);
184*7688df22SAndroid Build Coastguard Worker }
185*7688df22SAndroid Build Coastguard Worker 
186*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_bo_get_handle(struct drm_tegra_bo * bo,uint32_t * handle)187*7688df22SAndroid Build Coastguard Worker drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
188*7688df22SAndroid Build Coastguard Worker {
189*7688df22SAndroid Build Coastguard Worker     if (!bo || !handle)
190*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
191*7688df22SAndroid Build Coastguard Worker 
192*7688df22SAndroid Build Coastguard Worker     *handle = bo->handle;
193*7688df22SAndroid Build Coastguard Worker 
194*7688df22SAndroid Build Coastguard Worker     return 0;
195*7688df22SAndroid Build Coastguard Worker }
196*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_map(struct drm_tegra_bo * bo,void ** ptr)197*7688df22SAndroid Build Coastguard Worker drm_public int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
198*7688df22SAndroid Build Coastguard Worker {
199*7688df22SAndroid Build Coastguard Worker     struct drm_tegra *drm = bo->drm;
200*7688df22SAndroid Build Coastguard Worker 
201*7688df22SAndroid Build Coastguard Worker     if (!bo->map) {
202*7688df22SAndroid Build Coastguard Worker         struct drm_tegra_gem_mmap args;
203*7688df22SAndroid Build Coastguard Worker         int err;
204*7688df22SAndroid Build Coastguard Worker 
205*7688df22SAndroid Build Coastguard Worker         memset(&args, 0, sizeof(args));
206*7688df22SAndroid Build Coastguard Worker         args.handle = bo->handle;
207*7688df22SAndroid Build Coastguard Worker 
208*7688df22SAndroid Build Coastguard Worker         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
209*7688df22SAndroid Build Coastguard Worker                                   sizeof(args));
210*7688df22SAndroid Build Coastguard Worker         if (err < 0)
211*7688df22SAndroid Build Coastguard Worker             return -errno;
212*7688df22SAndroid Build Coastguard Worker 
213*7688df22SAndroid Build Coastguard Worker         bo->offset = args.offset;
214*7688df22SAndroid Build Coastguard Worker 
215*7688df22SAndroid Build Coastguard Worker         bo->map = drm_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
216*7688df22SAndroid Build Coastguard Worker                            drm->fd, bo->offset);
217*7688df22SAndroid Build Coastguard Worker         if (bo->map == MAP_FAILED) {
218*7688df22SAndroid Build Coastguard Worker             bo->map = NULL;
219*7688df22SAndroid Build Coastguard Worker             return -errno;
220*7688df22SAndroid Build Coastguard Worker         }
221*7688df22SAndroid Build Coastguard Worker     }
222*7688df22SAndroid Build Coastguard Worker 
223*7688df22SAndroid Build Coastguard Worker     if (ptr)
224*7688df22SAndroid Build Coastguard Worker         *ptr = bo->map;
225*7688df22SAndroid Build Coastguard Worker 
226*7688df22SAndroid Build Coastguard Worker     return 0;
227*7688df22SAndroid Build Coastguard Worker }
228*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_unmap(struct drm_tegra_bo * bo)229*7688df22SAndroid Build Coastguard Worker drm_public int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
230*7688df22SAndroid Build Coastguard Worker {
231*7688df22SAndroid Build Coastguard Worker     if (!bo)
232*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
233*7688df22SAndroid Build Coastguard Worker 
234*7688df22SAndroid Build Coastguard Worker     if (!bo->map)
235*7688df22SAndroid Build Coastguard Worker         return 0;
236*7688df22SAndroid Build Coastguard Worker 
237*7688df22SAndroid Build Coastguard Worker     if (munmap(bo->map, bo->size))
238*7688df22SAndroid Build Coastguard Worker         return -errno;
239*7688df22SAndroid Build Coastguard Worker 
240*7688df22SAndroid Build Coastguard Worker     bo->map = NULL;
241*7688df22SAndroid Build Coastguard Worker 
242*7688df22SAndroid Build Coastguard Worker     return 0;
243*7688df22SAndroid Build Coastguard Worker }
244*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_get_name(struct drm_tegra_bo * bo,uint32_t * name)245*7688df22SAndroid Build Coastguard Worker drm_public int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name)
246*7688df22SAndroid Build Coastguard Worker {
247*7688df22SAndroid Build Coastguard Worker     struct drm_tegra *drm = bo->drm;
248*7688df22SAndroid Build Coastguard Worker     struct drm_gem_flink args;
249*7688df22SAndroid Build Coastguard Worker     int err;
250*7688df22SAndroid Build Coastguard Worker 
251*7688df22SAndroid Build Coastguard Worker     memset(&args, 0, sizeof(args));
252*7688df22SAndroid Build Coastguard Worker     args.handle = bo->handle;
253*7688df22SAndroid Build Coastguard Worker 
254*7688df22SAndroid Build Coastguard Worker     err = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &args);
255*7688df22SAndroid Build Coastguard Worker     if (err < 0)
256*7688df22SAndroid Build Coastguard Worker         return err;
257*7688df22SAndroid Build Coastguard Worker 
258*7688df22SAndroid Build Coastguard Worker     if (name)
259*7688df22SAndroid Build Coastguard Worker         *name = args.name;
260*7688df22SAndroid Build Coastguard Worker 
261*7688df22SAndroid Build Coastguard Worker     return 0;
262*7688df22SAndroid Build Coastguard Worker }
263*7688df22SAndroid Build Coastguard Worker 
264*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_bo_open(struct drm_tegra * drm,uint32_t name,uint32_t flags,struct drm_tegra_bo ** bop)265*7688df22SAndroid Build Coastguard Worker drm_tegra_bo_open(struct drm_tegra *drm, uint32_t name, uint32_t flags,
266*7688df22SAndroid Build Coastguard Worker                   struct drm_tegra_bo **bop)
267*7688df22SAndroid Build Coastguard Worker {
268*7688df22SAndroid Build Coastguard Worker     struct drm_gem_open args;
269*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_bo *bo;
270*7688df22SAndroid Build Coastguard Worker     int err;
271*7688df22SAndroid Build Coastguard Worker 
272*7688df22SAndroid Build Coastguard Worker     bo = drm_tegra_bo_alloc(drm, 0, flags, 0);
273*7688df22SAndroid Build Coastguard Worker     if (!bo)
274*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
275*7688df22SAndroid Build Coastguard Worker 
276*7688df22SAndroid Build Coastguard Worker     memset(&args, 0, sizeof(args));
277*7688df22SAndroid Build Coastguard Worker     args.name = name;
278*7688df22SAndroid Build Coastguard Worker 
279*7688df22SAndroid Build Coastguard Worker     err = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &args);
280*7688df22SAndroid Build Coastguard Worker     if (err < 0)
281*7688df22SAndroid Build Coastguard Worker         goto free;
282*7688df22SAndroid Build Coastguard Worker 
283*7688df22SAndroid Build Coastguard Worker     bo->handle = args.handle;
284*7688df22SAndroid Build Coastguard Worker     bo->size = args.size;
285*7688df22SAndroid Build Coastguard Worker 
286*7688df22SAndroid Build Coastguard Worker     *bop = bo;
287*7688df22SAndroid Build Coastguard Worker 
288*7688df22SAndroid Build Coastguard Worker     return 0;
289*7688df22SAndroid Build Coastguard Worker 
290*7688df22SAndroid Build Coastguard Worker free:
291*7688df22SAndroid Build Coastguard Worker     free(bo);
292*7688df22SAndroid Build Coastguard Worker     return err;
293*7688df22SAndroid Build Coastguard Worker }
294*7688df22SAndroid Build Coastguard Worker 
drm_tegra_bo_export(struct drm_tegra_bo * bo,uint32_t flags)295*7688df22SAndroid Build Coastguard Worker drm_public int drm_tegra_bo_export(struct drm_tegra_bo *bo, uint32_t flags)
296*7688df22SAndroid Build Coastguard Worker {
297*7688df22SAndroid Build Coastguard Worker     int fd, err;
298*7688df22SAndroid Build Coastguard Worker 
299*7688df22SAndroid Build Coastguard Worker     flags |= DRM_CLOEXEC;
300*7688df22SAndroid Build Coastguard Worker 
301*7688df22SAndroid Build Coastguard Worker     err = drmPrimeHandleToFD(bo->drm->fd, bo->handle, flags, &fd);
302*7688df22SAndroid Build Coastguard Worker     if (err < 0)
303*7688df22SAndroid Build Coastguard Worker         return err;
304*7688df22SAndroid Build Coastguard Worker 
305*7688df22SAndroid Build Coastguard Worker     return fd;
306*7688df22SAndroid Build Coastguard Worker }
307*7688df22SAndroid Build Coastguard Worker 
fd_get_size(int fd)308*7688df22SAndroid Build Coastguard Worker static ssize_t fd_get_size(int fd)
309*7688df22SAndroid Build Coastguard Worker {
310*7688df22SAndroid Build Coastguard Worker     ssize_t size, offset;
311*7688df22SAndroid Build Coastguard Worker     int err;
312*7688df22SAndroid Build Coastguard Worker 
313*7688df22SAndroid Build Coastguard Worker     offset = lseek(fd, 0, SEEK_CUR);
314*7688df22SAndroid Build Coastguard Worker     if (offset < 0)
315*7688df22SAndroid Build Coastguard Worker         return -errno;
316*7688df22SAndroid Build Coastguard Worker 
317*7688df22SAndroid Build Coastguard Worker     size = lseek(fd, 0, SEEK_END);
318*7688df22SAndroid Build Coastguard Worker     if (size < 0)
319*7688df22SAndroid Build Coastguard Worker         return -errno;
320*7688df22SAndroid Build Coastguard Worker 
321*7688df22SAndroid Build Coastguard Worker     err = lseek(fd, offset, SEEK_SET);
322*7688df22SAndroid Build Coastguard Worker     if (err < 0)
323*7688df22SAndroid Build Coastguard Worker         return -errno;
324*7688df22SAndroid Build Coastguard Worker 
325*7688df22SAndroid Build Coastguard Worker     return size;
326*7688df22SAndroid Build Coastguard Worker }
327*7688df22SAndroid Build Coastguard Worker 
328*7688df22SAndroid Build Coastguard Worker drm_public int
drm_tegra_bo_import(struct drm_tegra * drm,int fd,struct drm_tegra_bo ** bop)329*7688df22SAndroid Build Coastguard Worker drm_tegra_bo_import(struct drm_tegra *drm, int fd, struct drm_tegra_bo **bop)
330*7688df22SAndroid Build Coastguard Worker {
331*7688df22SAndroid Build Coastguard Worker     struct drm_tegra_bo *bo;
332*7688df22SAndroid Build Coastguard Worker     ssize_t size;
333*7688df22SAndroid Build Coastguard Worker     int err;
334*7688df22SAndroid Build Coastguard Worker 
335*7688df22SAndroid Build Coastguard Worker     size = fd_get_size(fd);
336*7688df22SAndroid Build Coastguard Worker     if (size < 0)
337*7688df22SAndroid Build Coastguard Worker         return size;
338*7688df22SAndroid Build Coastguard Worker 
339*7688df22SAndroid Build Coastguard Worker     bo = drm_tegra_bo_alloc(drm, 0, 0, size);
340*7688df22SAndroid Build Coastguard Worker     if (!bo)
341*7688df22SAndroid Build Coastguard Worker         return -ENOMEM;
342*7688df22SAndroid Build Coastguard Worker 
343*7688df22SAndroid Build Coastguard Worker     err = drmPrimeFDToHandle(drm->fd, fd, &bo->handle);
344*7688df22SAndroid Build Coastguard Worker     if (err < 0)
345*7688df22SAndroid Build Coastguard Worker         goto free;
346*7688df22SAndroid Build Coastguard Worker 
347*7688df22SAndroid Build Coastguard Worker     *bop = bo;
348*7688df22SAndroid Build Coastguard Worker 
349*7688df22SAndroid Build Coastguard Worker     return 0;
350*7688df22SAndroid Build Coastguard Worker 
351*7688df22SAndroid Build Coastguard Worker free:
352*7688df22SAndroid Build Coastguard Worker     free(bo);
353*7688df22SAndroid Build Coastguard Worker     return err;
354*7688df22SAndroid Build Coastguard Worker }
355