2 * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
3 * author: Jung Zhao jung.zhao@rock-chips.com
4 * Randy Li, randy.li@rock-chips.com
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/slab.h>
19 #include "vcodec_iommu_ops.h"
22 struct vcodec_iommu_session_info *vcodec_iommu_get_session_info
23 (struct vcodec_iommu_info *iommu_info, struct vpu_session *session)
25 struct vcodec_iommu_session_info *session_info = NULL, *n;
27 list_for_each_entry_safe(session_info, n, &iommu_info->session_list,
29 if (session_info->session == session)
36 int vcodec_iommu_create(struct vcodec_iommu_info *iommu_info)
38 if (!iommu_info || !iommu_info->ops->create)
41 return iommu_info->ops->create(iommu_info);
44 int vcodec_iommu_import(struct vcodec_iommu_info *iommu_info,
45 struct vpu_session *session, int fd)
47 struct vcodec_iommu_session_info *session_info = NULL;
49 if (!iommu_info || !iommu_info->ops->import || !session)
52 session_info = vcodec_iommu_get_session_info(iommu_info, session);
54 session_info = kzalloc(sizeof(*session_info), GFP_KERNEL);
58 INIT_LIST_HEAD(&session_info->head);
59 INIT_LIST_HEAD(&session_info->buffer_list);
60 mutex_init(&session_info->list_mutex);
61 session_info->max_idx = 0;
62 session_info->session = session;
63 session_info->mmu_dev = iommu_info->mmu_dev;
64 session_info->dev = iommu_info->dev;
65 session_info->iommu_info = iommu_info;
66 session_info->buffer_nums = 0;
67 mutex_lock(&iommu_info->list_mutex);
68 list_add_tail(&session_info->head, &iommu_info->session_list);
69 mutex_unlock(&iommu_info->list_mutex);
72 session_info->debug_level = iommu_info->debug_level;
74 return iommu_info->ops->import(session_info, fd);
77 int vcodec_iommu_free(struct vcodec_iommu_info *iommu_info,
78 struct vpu_session *session, int idx)
80 struct vcodec_iommu_session_info *session_info = NULL;
82 session_info = vcodec_iommu_get_session_info(iommu_info, session);
84 if (!iommu_info || !iommu_info->ops->free || !session_info)
87 return iommu_info->ops->free(session_info, idx);
90 int vcodec_iommu_free_fd(struct vcodec_iommu_info *iommu_info,
91 struct vpu_session *session, int fd)
93 struct vcodec_iommu_session_info *session_info = NULL;
95 session_info = vcodec_iommu_get_session_info(iommu_info, session);
97 if (!iommu_info || !iommu_info->ops->free_fd || !session_info)
100 return iommu_info->ops->free_fd(session_info, fd);
103 void *vcodec_iommu_map_kernel(struct vcodec_iommu_info *iommu_info,
104 struct vpu_session *session, int idx)
106 struct vcodec_iommu_session_info *session_info = NULL;
108 session_info = vcodec_iommu_get_session_info(iommu_info, session);
110 if (!iommu_info || !iommu_info->ops->map_kernel || !session_info)
113 return iommu_info->ops->map_kernel(session_info, idx);
116 int vcodec_iommu_unmap_kernel(struct vcodec_iommu_info *iommu_info,
117 struct vpu_session *session, int idx)
119 struct vcodec_iommu_session_info *session_info = NULL;
121 session_info = vcodec_iommu_get_session_info(iommu_info, session);
123 if (!iommu_info || !iommu_info->ops->unmap_kernel || !session_info)
126 return iommu_info->ops->unmap_kernel(session_info, idx);
129 int vcodec_iommu_map_iommu(struct vcodec_iommu_info *iommu_info,
130 struct vpu_session *session,
131 int idx, unsigned long *iova,
134 struct vcodec_iommu_session_info *session_info = NULL;
136 session_info = vcodec_iommu_get_session_info(iommu_info, session);
138 if (!iommu_info || !iommu_info->ops->map_iommu || !session_info)
141 return iommu_info->ops->map_iommu(session_info, idx, iova, size);
144 int vcodec_iommu_unmap_iommu(struct vcodec_iommu_info *iommu_info,
145 struct vpu_session *session, int idx)
147 struct vcodec_iommu_session_info *session_info = NULL;
149 session_info = vcodec_iommu_get_session_info(iommu_info, session);
151 if (!iommu_info || !iommu_info->ops->unmap_iommu || !session_info)
154 return iommu_info->ops->unmap_iommu(session_info, idx);
157 int vcodec_iommu_destroy(struct vcodec_iommu_info *iommu_info)
159 if (!iommu_info || !iommu_info->ops->destroy)
162 return iommu_info->ops->destroy(iommu_info);
165 void vcodec_iommu_dump(struct vcodec_iommu_info *iommu_info,
166 struct vpu_session *session)
168 struct vcodec_iommu_session_info *session_info = NULL;
170 session_info = vcodec_iommu_get_session_info(iommu_info, session);
172 if (!iommu_info || !iommu_info->ops->dump || !session_info)
175 iommu_info->ops->dump(session_info);
178 void vcodec_iommu_clear(struct vcodec_iommu_info *iommu_info,
179 struct vpu_session *session)
181 struct vcodec_iommu_session_info *session_info = NULL;
183 session_info = vcodec_iommu_get_session_info(iommu_info, session);
185 if (!iommu_info || !iommu_info->ops->clear || !session_info)
188 iommu_info->ops->clear(session_info);
190 mutex_lock(&iommu_info->list_mutex);
191 list_del_init(&session_info->head);
193 mutex_unlock(&iommu_info->list_mutex);
196 int vcodec_iommu_attach(struct vcodec_iommu_info *iommu_info)
198 if (!iommu_info || !iommu_info->ops->attach)
201 return iommu_info->ops->attach(iommu_info);
204 void vcodec_iommu_detach(struct vcodec_iommu_info *iommu_info)
206 if (!iommu_info || !iommu_info->ops->detach)
209 return iommu_info->ops->detach(iommu_info);
212 struct vcodec_iommu_info *
213 vcodec_iommu_info_create(struct device *dev,
214 struct device *mmu_dev,
217 struct vcodec_iommu_info *iommu_info = NULL;
219 iommu_info = kzalloc(sizeof(*iommu_info), GFP_KERNEL);
223 iommu_info->dev = dev;
224 INIT_LIST_HEAD(&iommu_info->session_list);
225 mutex_init(&iommu_info->list_mutex);
226 mutex_init(&iommu_info->iommu_mutex);
227 switch (alloc_type) {
229 case ALLOCATOR_USE_DRM:
230 vcodec_iommu_drm_set_ops(iommu_info);
234 case ALLOCATOR_USE_ION:
235 vcodec_iommu_ion_set_ops(iommu_info);
239 iommu_info->ops = NULL;
243 iommu_info->mmu_dev = mmu_dev;
245 vcodec_iommu_create(iommu_info);
250 int vcodec_iommu_info_destroy(struct vcodec_iommu_info *iommu_info)
252 vcodec_iommu_destroy(iommu_info);