xref: /third_party/libdrm/freedreno/msm/msm_bo.c (revision d722e3fb)
1d722e3fbSopenharmony_ci/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2d722e3fbSopenharmony_ci
3d722e3fbSopenharmony_ci/*
4d722e3fbSopenharmony_ci * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
5d722e3fbSopenharmony_ci *
6d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
9d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12d722e3fbSopenharmony_ci *
13d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next
14d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
15d722e3fbSopenharmony_ci * Software.
16d722e3fbSopenharmony_ci *
17d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20d722e3fbSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21d722e3fbSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22d722e3fbSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23d722e3fbSopenharmony_ci * SOFTWARE.
24d722e3fbSopenharmony_ci *
25d722e3fbSopenharmony_ci * Authors:
26d722e3fbSopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
27d722e3fbSopenharmony_ci */
28d722e3fbSopenharmony_ci
29d722e3fbSopenharmony_ci#include "msm_priv.h"
30d722e3fbSopenharmony_ci
31d722e3fbSopenharmony_cistatic int bo_allocate(struct msm_bo *msm_bo)
32d722e3fbSopenharmony_ci{
33d722e3fbSopenharmony_ci	struct fd_bo *bo = &msm_bo->base;
34d722e3fbSopenharmony_ci	if (!msm_bo->offset) {
35d722e3fbSopenharmony_ci		struct drm_msm_gem_info req = {
36d722e3fbSopenharmony_ci				.handle = bo->handle,
37d722e3fbSopenharmony_ci		};
38d722e3fbSopenharmony_ci		int ret;
39d722e3fbSopenharmony_ci
40d722e3fbSopenharmony_ci		/* if the buffer is already backed by pages then this
41d722e3fbSopenharmony_ci		 * doesn't actually do anything (other than giving us
42d722e3fbSopenharmony_ci		 * the offset)
43d722e3fbSopenharmony_ci		 */
44d722e3fbSopenharmony_ci		ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO,
45d722e3fbSopenharmony_ci				&req, sizeof(req));
46d722e3fbSopenharmony_ci		if (ret) {
47d722e3fbSopenharmony_ci			ERROR_MSG("alloc failed: %s", strerror(errno));
48d722e3fbSopenharmony_ci			return ret;
49d722e3fbSopenharmony_ci		}
50d722e3fbSopenharmony_ci
51d722e3fbSopenharmony_ci		msm_bo->offset = req.offset;
52d722e3fbSopenharmony_ci	}
53d722e3fbSopenharmony_ci
54d722e3fbSopenharmony_ci	return 0;
55d722e3fbSopenharmony_ci}
56d722e3fbSopenharmony_ci
57d722e3fbSopenharmony_cistatic int msm_bo_offset(struct fd_bo *bo, uint64_t *offset)
58d722e3fbSopenharmony_ci{
59d722e3fbSopenharmony_ci	struct msm_bo *msm_bo = to_msm_bo(bo);
60d722e3fbSopenharmony_ci	int ret = bo_allocate(msm_bo);
61d722e3fbSopenharmony_ci	if (ret)
62d722e3fbSopenharmony_ci		return ret;
63d722e3fbSopenharmony_ci	*offset = msm_bo->offset;
64d722e3fbSopenharmony_ci	return 0;
65d722e3fbSopenharmony_ci}
66d722e3fbSopenharmony_ci
67d722e3fbSopenharmony_cistatic int msm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
68d722e3fbSopenharmony_ci{
69d722e3fbSopenharmony_ci	struct drm_msm_gem_cpu_prep req = {
70d722e3fbSopenharmony_ci			.handle = bo->handle,
71d722e3fbSopenharmony_ci			.op = op,
72d722e3fbSopenharmony_ci	};
73d722e3fbSopenharmony_ci
74d722e3fbSopenharmony_ci	get_abs_timeout(&req.timeout, 5000000000);
75d722e3fbSopenharmony_ci
76d722e3fbSopenharmony_ci	return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req));
77d722e3fbSopenharmony_ci}
78d722e3fbSopenharmony_ci
79d722e3fbSopenharmony_cistatic void msm_bo_cpu_fini(struct fd_bo *bo)
80d722e3fbSopenharmony_ci{
81d722e3fbSopenharmony_ci	struct drm_msm_gem_cpu_fini req = {
82d722e3fbSopenharmony_ci			.handle = bo->handle,
83d722e3fbSopenharmony_ci	};
84d722e3fbSopenharmony_ci
85d722e3fbSopenharmony_ci	drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_FINI, &req, sizeof(req));
86d722e3fbSopenharmony_ci}
87d722e3fbSopenharmony_ci
88d722e3fbSopenharmony_cistatic int msm_bo_madvise(struct fd_bo *bo, int willneed)
89d722e3fbSopenharmony_ci{
90d722e3fbSopenharmony_ci	struct drm_msm_gem_madvise req = {
91d722e3fbSopenharmony_ci			.handle = bo->handle,
92d722e3fbSopenharmony_ci			.madv = willneed ? MSM_MADV_WILLNEED : MSM_MADV_DONTNEED,
93d722e3fbSopenharmony_ci	};
94d722e3fbSopenharmony_ci	int ret;
95d722e3fbSopenharmony_ci
96d722e3fbSopenharmony_ci	/* older kernels do not support this: */
97d722e3fbSopenharmony_ci	if (bo->dev->version < FD_VERSION_MADVISE)
98d722e3fbSopenharmony_ci		return willneed;
99d722e3fbSopenharmony_ci
100d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_MADVISE, &req, sizeof(req));
101d722e3fbSopenharmony_ci	if (ret)
102d722e3fbSopenharmony_ci		return ret;
103d722e3fbSopenharmony_ci
104d722e3fbSopenharmony_ci	return req.retained;
105d722e3fbSopenharmony_ci}
106d722e3fbSopenharmony_ci
107d722e3fbSopenharmony_cistatic uint64_t msm_bo_iova(struct fd_bo *bo)
108d722e3fbSopenharmony_ci{
109d722e3fbSopenharmony_ci	struct drm_msm_gem_info req = {
110d722e3fbSopenharmony_ci			.handle = bo->handle,
111d722e3fbSopenharmony_ci			.flags = MSM_INFO_IOVA,
112d722e3fbSopenharmony_ci	};
113d722e3fbSopenharmony_ci
114d722e3fbSopenharmony_ci	drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
115d722e3fbSopenharmony_ci
116d722e3fbSopenharmony_ci	return req.offset;
117d722e3fbSopenharmony_ci}
118d722e3fbSopenharmony_ci
119d722e3fbSopenharmony_cistatic void msm_bo_destroy(struct fd_bo *bo)
120d722e3fbSopenharmony_ci{
121d722e3fbSopenharmony_ci	struct msm_bo *msm_bo = to_msm_bo(bo);
122d722e3fbSopenharmony_ci	free(msm_bo);
123d722e3fbSopenharmony_ci
124d722e3fbSopenharmony_ci}
125d722e3fbSopenharmony_ci
126d722e3fbSopenharmony_cistatic const struct fd_bo_funcs funcs = {
127d722e3fbSopenharmony_ci		.offset = msm_bo_offset,
128d722e3fbSopenharmony_ci		.cpu_prep = msm_bo_cpu_prep,
129d722e3fbSopenharmony_ci		.cpu_fini = msm_bo_cpu_fini,
130d722e3fbSopenharmony_ci		.madvise = msm_bo_madvise,
131d722e3fbSopenharmony_ci		.iova = msm_bo_iova,
132d722e3fbSopenharmony_ci		.destroy = msm_bo_destroy,
133d722e3fbSopenharmony_ci};
134d722e3fbSopenharmony_ci
135d722e3fbSopenharmony_ci/* allocate a buffer handle: */
136d722e3fbSopenharmony_cidrm_private int msm_bo_new_handle(struct fd_device *dev,
137d722e3fbSopenharmony_ci		uint32_t size, uint32_t flags, uint32_t *handle)
138d722e3fbSopenharmony_ci{
139d722e3fbSopenharmony_ci	struct drm_msm_gem_new req = {
140d722e3fbSopenharmony_ci			.size = size,
141d722e3fbSopenharmony_ci			.flags = MSM_BO_WC,  // TODO figure out proper flags..
142d722e3fbSopenharmony_ci	};
143d722e3fbSopenharmony_ci	int ret;
144d722e3fbSopenharmony_ci
145d722e3fbSopenharmony_ci	ret = drmCommandWriteRead(dev->fd, DRM_MSM_GEM_NEW,
146d722e3fbSopenharmony_ci			&req, sizeof(req));
147d722e3fbSopenharmony_ci	if (ret)
148d722e3fbSopenharmony_ci		return ret;
149d722e3fbSopenharmony_ci
150d722e3fbSopenharmony_ci	*handle = req.handle;
151d722e3fbSopenharmony_ci
152d722e3fbSopenharmony_ci	return 0;
153d722e3fbSopenharmony_ci}
154d722e3fbSopenharmony_ci
155d722e3fbSopenharmony_ci/* allocate a new buffer object */
156d722e3fbSopenharmony_cidrm_private struct fd_bo * msm_bo_from_handle(struct fd_device *dev,
157d722e3fbSopenharmony_ci		uint32_t size, uint32_t handle)
158d722e3fbSopenharmony_ci{
159d722e3fbSopenharmony_ci	struct msm_bo *msm_bo;
160d722e3fbSopenharmony_ci	struct fd_bo *bo;
161d722e3fbSopenharmony_ci
162d722e3fbSopenharmony_ci	msm_bo = calloc(1, sizeof(*msm_bo));
163d722e3fbSopenharmony_ci	if (!msm_bo)
164d722e3fbSopenharmony_ci		return NULL;
165d722e3fbSopenharmony_ci
166d722e3fbSopenharmony_ci	bo = &msm_bo->base;
167d722e3fbSopenharmony_ci	bo->funcs = &funcs;
168d722e3fbSopenharmony_ci
169d722e3fbSopenharmony_ci	return bo;
170d722e3fbSopenharmony_ci}
171