xref: /aosp_15_r20/external/mesa3d/src/freedreno/drm/msm/msm_bo.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2012-2018 Rob Clark <[email protected]>
3  * SPDX-License-Identifier: MIT
4  *
5  * Authors:
6  *    Rob Clark <[email protected]>
7  */
8 
9 #include "msm_priv.h"
10 
11 static int
bo_allocate(struct msm_bo * msm_bo)12 bo_allocate(struct msm_bo *msm_bo)
13 {
14    struct fd_bo *bo = &msm_bo->base;
15    if (!msm_bo->offset) {
16       struct drm_msm_gem_info req = {
17          .handle = bo->handle,
18          .info = MSM_INFO_GET_OFFSET,
19       };
20       int ret;
21 
22       /* if the buffer is already backed by pages then this
23        * doesn't actually do anything (other than giving us
24        * the offset)
25        */
26       ret =
27          drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
28       if (ret) {
29          ERROR_MSG("alloc failed: %s", strerror(errno));
30          return ret;
31       }
32 
33       msm_bo->offset = req.value;
34    }
35 
36    return 0;
37 }
38 
39 static int
msm_bo_offset(struct fd_bo * bo,uint64_t * offset)40 msm_bo_offset(struct fd_bo *bo, uint64_t *offset)
41 {
42    struct msm_bo *msm_bo = to_msm_bo(bo);
43    int ret = bo_allocate(msm_bo);
44    if (ret)
45       return ret;
46    *offset = msm_bo->offset;
47    return 0;
48 }
49 
50 static int
msm_bo_cpu_prep(struct fd_bo * bo,struct fd_pipe * pipe,uint32_t op)51 msm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
52 {
53    struct drm_msm_gem_cpu_prep req = {
54       .handle = bo->handle,
55       .op = op,
56    };
57 
58    get_abs_timeout(&req.timeout, OS_TIMEOUT_INFINITE);
59 
60    return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req));
61 }
62 
63 static int
msm_bo_madvise(struct fd_bo * bo,int willneed)64 msm_bo_madvise(struct fd_bo *bo, int willneed)
65 {
66    struct drm_msm_gem_madvise req = {
67       .handle = bo->handle,
68       .madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,
69    };
70    int ret;
71 
72    /* older kernels do not support this: */
73    if (bo->dev->version < FD_VERSION_MADVISE)
74       return willneed;
75 
76    ret =
77       drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));
78    if (ret)
79       return ret;
80 
81    return req.retained;
82 }
83 
84 static uint64_t
msm_bo_iova(struct fd_bo * bo)85 msm_bo_iova(struct fd_bo *bo)
86 {
87    struct drm_msm_gem_info req = {
88       .handle = bo->handle,
89       .info = MSM_INFO_GET_IOVA,
90    };
91    int ret;
92 
93    ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
94    if (ret)
95       return 0;
96 
97    return req.value;
98 }
99 
100 static void
msm_bo_set_name(struct fd_bo * bo,const char * fmt,va_list ap)101 msm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap)
102 {
103    struct drm_msm_gem_info req = {
104       .handle = bo->handle,
105       .info = MSM_INFO_SET_NAME,
106    };
107    char buf[32];
108    int sz;
109 
110    if (bo->dev->version < FD_VERSION_SOFTPIN)
111       return;
112 
113    sz = vsnprintf(buf, sizeof(buf), fmt, ap);
114 
115    req.value = VOID2U64(buf);
116    req.len = MIN2(sz, sizeof(buf));
117 
118    drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
119 }
120 
121 static void
msm_bo_set_metadata(struct fd_bo * bo,void * metadata,uint32_t metadata_size)122 msm_bo_set_metadata(struct fd_bo *bo, void *metadata, uint32_t metadata_size)
123 {
124    struct drm_msm_gem_info req = {
125       .handle = bo->handle,
126       .info = MSM_INFO_SET_METADATA,
127       .value = (uintptr_t)(void *)metadata,
128       .len = metadata_size,
129    };
130 
131    int ret = drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
132    if (ret) {
133       mesa_logw_once("Failed to set BO metadata with DRM_MSM_GEM_INFO: %d",
134                      ret);
135    }
136 }
137 
138 static int
msm_bo_get_metadata(struct fd_bo * bo,void * metadata,uint32_t metadata_size)139 msm_bo_get_metadata(struct fd_bo *bo, void *metadata, uint32_t metadata_size)
140 {
141    struct drm_msm_gem_info req = {
142       .handle = bo->handle,
143       .info = MSM_INFO_GET_METADATA,
144       .value = (uintptr_t)(void *)metadata,
145       .len = metadata_size,
146    };
147 
148    int ret = drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
149    if (ret) {
150       mesa_logw_once("Failed to get BO metadata with DRM_MSM_GEM_INFO: %d",
151                      ret);
152    }
153 
154    return ret;
155 }
156 
157 static const struct fd_bo_funcs funcs = {
158    .offset = msm_bo_offset,
159    .map = fd_bo_map_os_mmap,
160    .cpu_prep = msm_bo_cpu_prep,
161    .madvise = msm_bo_madvise,
162    .iova = msm_bo_iova,
163    .set_name = msm_bo_set_name,
164    .set_metadata = msm_bo_set_metadata,
165    .get_metadata = msm_bo_get_metadata,
166    .dmabuf = fd_bo_dmabuf_drm,
167    .destroy = fd_bo_fini_common,
168 };
169 
170 /* allocate a buffer handle: */
171 static int
new_handle(struct fd_device * dev,uint32_t size,uint32_t flags,uint32_t * handle)172 new_handle(struct fd_device *dev, uint32_t size, uint32_t flags, uint32_t *handle)
173 {
174    struct drm_msm_gem_new req = {
175       .size = size,
176    };
177    int ret;
178 
179    if (flags & FD_BO_SCANOUT)
180       req.flags |= MSM_BO_SCANOUT;
181 
182    if (flags & FD_BO_GPUREADONLY)
183       req.flags |= MSM_BO_GPU_READONLY;
184 
185    if (flags & FD_BO_CACHED_COHERENT)
186       req.flags |= MSM_BO_CACHED_COHERENT;
187    else
188       req.flags |= MSM_BO_WC;
189 
190    ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW, &req, sizeof(req));
191    if (ret)
192       return ret;
193 
194    *handle = req.handle;
195 
196    return 0;
197 }
198 
199 /* allocate a new buffer object */
200 struct fd_bo *
msm_bo_new(struct fd_device * dev,uint32_t size,uint32_t flags)201 msm_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
202 {
203    uint32_t handle;
204    int ret;
205 
206    ret = new_handle(dev, size, flags, &handle);
207    if (ret)
208       return NULL;
209 
210    return msm_bo_from_handle(dev, size, handle);
211 }
212 
213 /* allocate a new buffer object from existing handle (import) */
214 struct fd_bo *
msm_bo_from_handle(struct fd_device * dev,uint32_t size,uint32_t handle)215 msm_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle)
216 {
217    struct msm_bo *msm_bo;
218    struct fd_bo *bo;
219 
220    msm_bo = calloc(1, sizeof(*msm_bo));
221    if (!msm_bo)
222       return NULL;
223 
224    bo = &msm_bo->base;
225    bo->size = size;
226    bo->handle = handle;
227    bo->funcs = &funcs;
228 
229    fd_bo_init_common(bo, dev);
230 
231    return bo;
232 }
233