1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2020 NVIDIA Corporation */
4 #include <linux/host1x.h>
5 #include <linux/iommu.h>
6 #include <linux/list.h>
8 #include <drm/drm_drv.h>
9 #include <drm/drm_file.h>
10 #include <drm/drm_utils.h>
15 static void tegra_drm_mapping_release(struct kref *ref)
17 struct tegra_drm_mapping *mapping =
18 container_of(ref, struct tegra_drm_mapping, ref);
21 dma_unmap_sgtable(mapping->dev, mapping->sgt, mapping->direction,
22 DMA_ATTR_SKIP_CPU_SYNC);
24 host1x_bo_unpin(mapping->dev, mapping->bo, mapping->sgt);
25 host1x_bo_put(mapping->bo);
30 void tegra_drm_mapping_put(struct tegra_drm_mapping *mapping)
32 kref_put(&mapping->ref, tegra_drm_mapping_release);
35 static void tegra_drm_channel_context_close(struct tegra_drm_context *context)
37 struct tegra_drm_mapping *mapping;
40 xa_for_each(&context->mappings, id, mapping)
41 tegra_drm_mapping_put(mapping);
43 xa_destroy(&context->mappings);
45 host1x_channel_put(context->channel);
50 void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
52 struct tegra_drm_context *context;
53 struct host1x_syncpt *sp;
56 xa_for_each(&file->contexts, id, context)
57 tegra_drm_channel_context_close(context);
59 xa_for_each(&file->syncpoints, id, sp)
60 host1x_syncpt_put(sp);
62 xa_destroy(&file->contexts);
63 xa_destroy(&file->syncpoints);
66 static struct tegra_drm_client *tegra_drm_find_client(struct tegra_drm *tegra, u32 class)
68 struct tegra_drm_client *client;
70 list_for_each_entry(client, &tegra->clients, list)
71 if (client->base.class == class)
77 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_file *file)
79 struct tegra_drm_file *fpriv = file->driver_priv;
80 struct tegra_drm *tegra = drm->dev_private;
81 struct drm_tegra_channel_open *args = data;
82 struct tegra_drm_client *client = NULL;
83 struct tegra_drm_context *context;
89 context = kzalloc(sizeof(*context), GFP_KERNEL);
93 client = tegra_drm_find_client(tegra, args->host1x_class);
99 if (client->shared_channel) {
100 context->channel = host1x_channel_get(client->shared_channel);
102 context->channel = host1x_channel_request(&client->base);
103 if (!context->channel) {
109 err = xa_alloc(&fpriv->contexts, &args->context, context, XA_LIMIT(1, U32_MAX),
114 context->client = client;
115 xa_init_flags(&context->mappings, XA_FLAGS_ALLOC1);
117 args->version = client->version;
118 args->capabilities = 0;
120 if (device_get_dma_attr(client->base.dev) == DEV_DMA_COHERENT)
121 args->capabilities |= DRM_TEGRA_CHANNEL_CAP_CACHE_COHERENT;
126 host1x_channel_put(context->channel);
133 int tegra_drm_ioctl_channel_close(struct drm_device *drm, void *data, struct drm_file *file)
135 struct tegra_drm_file *fpriv = file->driver_priv;
136 struct drm_tegra_channel_close *args = data;
137 struct tegra_drm_context *context;
139 mutex_lock(&fpriv->lock);
141 context = xa_load(&fpriv->contexts, args->context);
143 mutex_unlock(&fpriv->lock);
147 xa_erase(&fpriv->contexts, args->context);
149 mutex_unlock(&fpriv->lock);
151 tegra_drm_channel_context_close(context);
156 int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, struct drm_file *file)
158 struct tegra_drm_file *fpriv = file->driver_priv;
159 struct drm_tegra_channel_map *args = data;
160 struct tegra_drm_mapping *mapping;
161 struct tegra_drm_context *context;
164 if (args->flags & ~DRM_TEGRA_CHANNEL_MAP_READ_WRITE)
167 mutex_lock(&fpriv->lock);
169 context = xa_load(&fpriv->contexts, args->context);
171 mutex_unlock(&fpriv->lock);
175 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
181 kref_init(&mapping->ref);
183 mapping->dev = context->client->base.dev;
184 mapping->bo = tegra_gem_lookup(file, args->handle);
190 if (context->client->base.group) {
191 /* IOMMU domain managed directly using IOMMU API */
192 host1x_bo_pin(mapping->dev, mapping->bo, &mapping->iova);
194 switch (args->flags & DRM_TEGRA_CHANNEL_MAP_READ_WRITE) {
195 case DRM_TEGRA_CHANNEL_MAP_READ_WRITE:
196 mapping->direction = DMA_BIDIRECTIONAL;
199 case DRM_TEGRA_CHANNEL_MAP_WRITE:
200 mapping->direction = DMA_FROM_DEVICE;
203 case DRM_TEGRA_CHANNEL_MAP_READ:
204 mapping->direction = DMA_TO_DEVICE;
211 mapping->sgt = host1x_bo_pin(mapping->dev, mapping->bo, NULL);
212 if (IS_ERR(mapping->sgt)) {
213 err = PTR_ERR(mapping->sgt);
217 err = dma_map_sgtable(mapping->dev, mapping->sgt, mapping->direction,
218 DMA_ATTR_SKIP_CPU_SYNC);
222 mapping->iova = sg_dma_address(mapping->sgt->sgl);
225 mapping->iova_end = mapping->iova + host1x_to_tegra_bo(mapping->bo)->size;
227 err = xa_alloc(&context->mappings, &args->mapping, mapping, XA_LIMIT(1, U32_MAX),
232 mutex_unlock(&fpriv->lock);
238 dma_unmap_sgtable(mapping->dev, mapping->sgt, mapping->direction,
239 DMA_ATTR_SKIP_CPU_SYNC);
242 host1x_bo_unpin(mapping->dev, mapping->bo, mapping->sgt);
244 host1x_bo_put(mapping->bo);
247 mutex_unlock(&fpriv->lock);
251 int tegra_drm_ioctl_channel_unmap(struct drm_device *drm, void *data, struct drm_file *file)
253 struct tegra_drm_file *fpriv = file->driver_priv;
254 struct drm_tegra_channel_unmap *args = data;
255 struct tegra_drm_mapping *mapping;
256 struct tegra_drm_context *context;
258 mutex_lock(&fpriv->lock);
260 context = xa_load(&fpriv->contexts, args->context);
262 mutex_unlock(&fpriv->lock);
266 mapping = xa_erase(&context->mappings, args->mapping);
268 mutex_unlock(&fpriv->lock);
273 tegra_drm_mapping_put(mapping);
277 int tegra_drm_ioctl_syncpoint_allocate(struct drm_device *drm, void *data, struct drm_file *file)
279 struct host1x *host1x = tegra_drm_to_host1x(drm->dev_private);
280 struct tegra_drm_file *fpriv = file->driver_priv;
281 struct drm_tegra_syncpoint_allocate *args = data;
282 struct host1x_syncpt *sp;
288 sp = host1x_syncpt_alloc(host1x, HOST1X_SYNCPT_CLIENT_MANAGED, current->comm);
292 args->id = host1x_syncpt_id(sp);
294 err = xa_insert(&fpriv->syncpoints, args->id, sp, GFP_KERNEL);
296 host1x_syncpt_put(sp);
303 int tegra_drm_ioctl_syncpoint_free(struct drm_device *drm, void *data, struct drm_file *file)
305 struct tegra_drm_file *fpriv = file->driver_priv;
306 struct drm_tegra_syncpoint_allocate *args = data;
307 struct host1x_syncpt *sp;
309 mutex_lock(&fpriv->lock);
310 sp = xa_erase(&fpriv->syncpoints, args->id);
311 mutex_unlock(&fpriv->lock);
316 host1x_syncpt_put(sp);
321 int tegra_drm_ioctl_syncpoint_wait(struct drm_device *drm, void *data, struct drm_file *file)
323 struct host1x *host1x = tegra_drm_to_host1x(drm->dev_private);
324 struct drm_tegra_syncpoint_wait *args = data;
325 signed long timeout_jiffies;
326 struct host1x_syncpt *sp;
328 if (args->padding != 0)
331 sp = host1x_syncpt_get_by_id_noref(host1x, args->id);
335 timeout_jiffies = drm_timeout_abs_to_jiffies(args->timeout_ns);
337 return host1x_syncpt_wait(sp, args->threshold, timeout_jiffies, &args->value);