History

Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux into drm-next

Most notable addition this time is the support for the GPU performance counters by Christian. This has been in the making for some time and it has matured a lot. Since this is adding UAPI, the corresponding WIP userspace can be found at [1] mesa/libdrm repos. I expect that Christian sends out the final userspace patches for this once you have pulled the kernel bits. Philipp optimized the probe path, so etnaviv gets out of the way for systems that want to boot real quick. I've done mostly cleanups, disentangling etnaviv from the IOMMU API, with some MMUv1 optimizations on the way. * 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux: (36 commits) drm/etnaviv: remove unnecessary clock stabilization delay drm/etnaviv: reduce reset delay drm/etnaviv: remove unused function etnaviv_gem_new drm/etnaviv: remove stale comment drm/etnaviv: submit supports performance monitor requests drm/etnaviv: enable debug registers on demand drm/etnaviv: need to disable clock gating when doing profiling drm/etnaviv: add MC perf domain drm/etnaviv: add TX perf domain drm/etnaviv: add RA perf domain drm/etnaviv: add SE perf domain drm/etnaviv: add PA perf domain drm/etnaviv: add SH perf domain drm/etnaviv: add PE perf domain drm/etnaviv: add HI perf domain drm/etnaviv: use 'sync points' for performance monitor requests drm/etnaviv: clear alloced event drm/etnaviv: add 'sync point' support drm/etnaviv: add performance monitor request processing drm/etnaviv: copy pmrs from userspace ...

Dave Airlie committed 9 years ago

Commit 787e1b72 parents 972805c 827217019 files · +1148 −330Browse files

Unified · Split

19 files
  1. drivers/gpu/drm/etnaviv/Kconfig +0 −2
  2. drivers/gpu/drm/etnaviv/Makefile +2 −1
  3. drivers/gpu/drm/etnaviv/etnaviv_buffer.c +36 −0
  4. drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c +14 −1
  5. drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h +5 −1
  6. drivers/gpu/drm/etnaviv/etnaviv_drv.c +38 −1
  7. drivers/gpu/drm/etnaviv/etnaviv_drv.h +1 −5
  8. drivers/gpu/drm/etnaviv/etnaviv_gem.c +0 −19
  9. drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +67 −2
  10. drivers/gpu/drm/etnaviv/etnaviv_gpu.c +167 −50
  11. drivers/gpu/drm/etnaviv/etnaviv_gpu.h +11 −2
  12. drivers/gpu/drm/etnaviv/etnaviv_iommu.c +73 −124
  13. drivers/gpu/drm/etnaviv/etnaviv_iommu.h +5 −2
  14. drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c +52 −68
  15. drivers/gpu/drm/etnaviv/etnaviv_mmu.c +68 −38
  16. drivers/gpu/drm/etnaviv/etnaviv_mmu.h +23 −13
  17. drivers/gpu/drm/etnaviv/etnaviv_perfmon.c +495 −0
  18. drivers/gpu/drm/etnaviv/etnaviv_perfmon.h +49 −0
  19. include/uapi/drm/etnaviv_drm.h +42 −1
drivers/gpu/drm/etnaviv/Kconfig+0−2
@@ -7,8 +7,6 @@ config DRM_ETNAVIV · 6 unmodified lines
7 select SHMEM7 select SHMEM
8 select SYNC_FILE8 select SYNC_FILE
9 select TMPFS9 select TMPFS
10 select IOMMU_API
11 select IOMMU_SUPPORT
12 select WANT_DEV_COREDUMP10 select WANT_DEV_COREDUMP
13 select CMA if HAVE_DMA_CONTIGUOUS11 select CMA if HAVE_DMA_CONTIGUOUS
14 select DMA_CMA if HAVE_DMA_CONTIGUOUS12 select DMA_CMA if HAVE_DMA_CONTIGUOUS
drivers/gpu/drm/etnaviv/Makefile+2−1
@@ -10,6 +10,7 @@ etnaviv-y := \ · 9 unmodified lines
10 etnaviv_gpu.o \10 etnaviv_gpu.o \
11 etnaviv_iommu_v2.o \11 etnaviv_iommu_v2.o \
12 etnaviv_iommu.o \12 etnaviv_iommu.o \
13 etnaviv_mmu.o13 etnaviv_mmu.o \
14 etnaviv_perfmon.o
14 15
15obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o16obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o
drivers/gpu/drm/etnaviv/etnaviv_buffer.c+36−0
@@ -250,6 +250,42 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) · 249 unmodified lines
250 }250 }
251}251}
252 252
253/* Append a 'sync point' to the ring buffer. */
254void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event)
255{
256 struct etnaviv_cmdbuf *buffer = gpu->buffer;
257 unsigned int waitlink_offset = buffer->user_size - 16;
258 u32 dwords, target;
259
260 /*
261 * We need at most 3 dwords in the return target:
262 * 1 event + 1 end + 1 wait + 1 link.
263 */
264 dwords = 4;
265 target = etnaviv_buffer_reserve(gpu, buffer, dwords);
266
267 /* Signal sync point event */
268 CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
269 VIVS_GL_EVENT_FROM_PE);
270
271 /* Stop the FE to 'pause' the GPU */
272 CMD_END(buffer);
273
274 /* Append waitlink */
275 CMD_WAIT(buffer);
276 CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
277 buffer->user_size - 4);
278
279 /*
280 * Kick off the 'sync point' command by replacing the previous
281 * WAIT with a link to the address in the ring buffer.
282 */
283 etnaviv_buffer_replace_wait(buffer, waitlink_offset,
284 VIV_FE_LINK_HEADER_OP_LINK |
285 VIV_FE_LINK_HEADER_PREFETCH(dwords),
286 target);
287}
288
253/* Append a command buffer to the ring buffer. */289/* Append a command buffer to the ring buffer. */
254void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,290void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
255 struct etnaviv_cmdbuf *cmdbuf)291 struct etnaviv_cmdbuf *cmdbuf)
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c+14−1
@@ -19,6 +19,7 @@ · 18 unmodified lines
19#include "etnaviv_cmdbuf.h"19#include "etnaviv_cmdbuf.h"
20#include "etnaviv_gpu.h"20#include "etnaviv_gpu.h"
21#include "etnaviv_mmu.h"21#include "etnaviv_mmu.h"
22#include "etnaviv_perfmon.h"
22 23
23#define SUBALLOC_SIZE SZ_256K24#define SUBALLOC_SIZE SZ_256K
24#define SUBALLOC_GRANULE SZ_4K25#define SUBALLOC_GRANULE SZ_4K
@@ -87,9 +88,10 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc) · 62 unmodified lines
87 88
88struct etnaviv_cmdbuf *89struct etnaviv_cmdbuf *
89etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,90etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
90 size_t nr_bos)91 size_t nr_bos, size_t nr_pmrs)
91{92{
92 struct etnaviv_cmdbuf *cmdbuf;93 struct etnaviv_cmdbuf *cmdbuf;
94 struct etnaviv_perfmon_request *pmrs;
93 size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),95 size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),
94 sizeof(*cmdbuf));96 sizeof(*cmdbuf));
95 int granule_offs, order, ret;97 int granule_offs, order, ret;
@@ -98,6 +100,12 @@ etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size, · 2 unmodified lines
98 if (!cmdbuf)100 if (!cmdbuf)
99 return NULL;101 return NULL;
100 102
103 sz = sizeof(*pmrs) * nr_pmrs;
104 pmrs = kzalloc(sz, GFP_KERNEL);
105 if (!pmrs)
106 goto out_free_cmdbuf;
107
108 cmdbuf->pmrs = pmrs;
101 cmdbuf->suballoc = suballoc;109 cmdbuf->suballoc = suballoc;
102 cmdbuf->size = size;110 cmdbuf->size = size;
103 111
@@ -124,6 +132,10 @@ retry: · 20 unmodified lines
124 cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset;132 cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset;
125 133
126 return cmdbuf;134 return cmdbuf;
135
136out_free_cmdbuf:
137 kfree(cmdbuf);
138 return NULL;
127}139}
128 140
129void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)141void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
@@ -139,6 +151,7 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf) · 9 unmodified lines
139 suballoc->free_space = 1;151 suballoc->free_space = 1;
140 mutex_unlock(&suballoc->lock);152 mutex_unlock(&suballoc->lock);
141 wake_up_all(&suballoc->free_event);153 wake_up_all(&suballoc->free_event);
154 kfree(cmdbuf->pmrs);
142 kfree(cmdbuf);155 kfree(cmdbuf);
143}156}
144 157
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h+5−1
@@ -21,6 +21,7 @@ · 20 unmodified lines
21 21
22struct etnaviv_gpu;22struct etnaviv_gpu;
23struct etnaviv_cmdbuf_suballoc;23struct etnaviv_cmdbuf_suballoc;
24struct etnaviv_perfmon_request;
24 25
25struct etnaviv_cmdbuf {26struct etnaviv_cmdbuf {
26 /* suballocator this cmdbuf is allocated from */27 /* suballocator this cmdbuf is allocated from */
@@ -38,6 +39,9 @@ struct etnaviv_cmdbuf { · 11 unmodified lines
38 u32 exec_state;39 u32 exec_state;
39 /* per GPU in-flight list */40 /* per GPU in-flight list */
40 struct list_head node;41 struct list_head node;
42 /* perfmon requests */
43 unsigned int nr_pmrs;
44 struct etnaviv_perfmon_request *pmrs;
41 /* BOs attached to this command buffer */45 /* BOs attached to this command buffer */
42 unsigned int nr_bos;46 unsigned int nr_bos;
43 struct etnaviv_vram_mapping *bo_map[0];47 struct etnaviv_vram_mapping *bo_map[0];
@@ -49,7 +53,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc); · 5 unmodified lines
49 53
50struct etnaviv_cmdbuf *54struct etnaviv_cmdbuf *
51etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,55etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
52 size_t nr_bos);56 size_t nr_bos, size_t nr_pmrs);
53void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);57void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);
54 58
55u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);59u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);
drivers/gpu/drm/etnaviv/etnaviv_drv.c+38−1
@@ -23,6 +23,7 @@ · 22 unmodified lines
23#include "etnaviv_gpu.h"23#include "etnaviv_gpu.h"
24#include "etnaviv_gem.h"24#include "etnaviv_gem.h"
25#include "etnaviv_mmu.h"25#include "etnaviv_mmu.h"
26#include "etnaviv_perfmon.h"
26 27
27#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING28#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
28static bool reglog;29static bool reglog;
@@ -451,6 +452,40 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, · 422 unmodified lines
451 return ret;452 return ret;
452}453}
453 454
455static int etnaviv_ioctl_pm_query_dom(struct drm_device *dev, void *data,
456 struct drm_file *file)
457{
458 struct etnaviv_drm_private *priv = dev->dev_private;
459 struct drm_etnaviv_pm_domain *args = data;
460 struct etnaviv_gpu *gpu;
461
462 if (args->pipe >= ETNA_MAX_PIPES)
463 return -EINVAL;
464
465 gpu = priv->gpu[args->pipe];
466 if (!gpu)
467 return -ENXIO;
468
469 return etnaviv_pm_query_dom(gpu, args);
470}
471
472static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data,
473 struct drm_file *file)
474{
475 struct etnaviv_drm_private *priv = dev->dev_private;
476 struct drm_etnaviv_pm_signal *args = data;
477 struct etnaviv_gpu *gpu;
478
479 if (args->pipe >= ETNA_MAX_PIPES)
480 return -EINVAL;
481
482 gpu = priv->gpu[args->pipe];
483 if (!gpu)
484 return -ENXIO;
485
486 return etnaviv_pm_query_sig(gpu, args);
487}
488
454static const struct drm_ioctl_desc etnaviv_ioctls[] = {489static const struct drm_ioctl_desc etnaviv_ioctls[] = {
455#define ETNA_IOCTL(n, func, flags) \490#define ETNA_IOCTL(n, func, flags) \
456 DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)491 DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
@@ -463,6 +498,8 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = { · 6 unmodified lines
463 ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW),498 ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW),
464 ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW),499 ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW),
465 ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW),500 ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW),
501 ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_AUTH|DRM_RENDER_ALLOW),
502 ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_AUTH|DRM_RENDER_ALLOW),
466};503};
467 504
468static const struct vm_operations_struct vm_ops = {505static const struct vm_operations_struct vm_ops = {
@@ -513,7 +550,7 @@ static struct drm_driver etnaviv_drm_driver = { · 44 unmodified lines
513 .desc = "etnaviv DRM",550 .desc = "etnaviv DRM",
514 .date = "20151214",551 .date = "20151214",
515 .major = 1,552 .major = 1,
516 .minor = 1,553 .minor = 2,
517};554};
518 555
519/*556/*
drivers/gpu/drm/etnaviv/etnaviv_drv.h+1−5
@@ -26,7 +26,6 @@ · 25 unmodified lines
26#include <linux/pm_runtime.h>26#include <linux/pm_runtime.h>
27#include <linux/slab.h>27#include <linux/slab.h>
28#include <linux/list.h>28#include <linux/list.h>
29#include <linux/iommu.h>
30#include <linux/types.h>29#include <linux/types.h>
31#include <linux/sizes.h>30#include <linux/sizes.h>
32 31
@@ -92,15 +91,12 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj); · 59 unmodified lines
92void etnaviv_gem_free_object(struct drm_gem_object *obj);91void etnaviv_gem_free_object(struct drm_gem_object *obj);
93int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,92int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
94 u32 size, u32 flags, u32 *handle);93 u32 size, u32 flags, u32 *handle);
95struct drm_gem_object *etnaviv_gem_new_locked(struct drm_device *dev,
96 u32 size, u32 flags);
97struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
98 u32 size, u32 flags);
99int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,94int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
100 uintptr_t ptr, u32 size, u32 flags, u32 *handle);95 uintptr_t ptr, u32 size, u32 flags, u32 *handle);
101u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu);96u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
102u16 etnaviv_buffer_config_mmuv2(struct etnaviv_gpu *gpu, u32 mtlb_addr, u32 safe_addr);97u16 etnaviv_buffer_config_mmuv2(struct etnaviv_gpu *gpu, u32 mtlb_addr, u32 safe_addr);
103void etnaviv_buffer_end(struct etnaviv_gpu *gpu);98void etnaviv_buffer_end(struct etnaviv_gpu *gpu);
99void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event);
104void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,100void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
105 struct etnaviv_cmdbuf *cmdbuf);101 struct etnaviv_cmdbuf *cmdbuf);
106void etnaviv_validate_init(void);102void etnaviv_validate_init(void);
drivers/gpu/drm/etnaviv/etnaviv_gem.c+0−19
@@ -704,25 +704,6 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, · 703 unmodified lines
704 return ret;704 return ret;
705}705}
706 706
707struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
708 u32 size, u32 flags)
709{
710 struct drm_gem_object *obj;
711 int ret;
712
713 obj = __etnaviv_gem_new(dev, size, flags);
714 if (IS_ERR(obj))
715 return obj;
716
717 ret = etnaviv_gem_obj_add(dev, obj);
718 if (ret < 0) {
719 drm_gem_object_put_unlocked(obj);
720 return ERR_PTR(ret);
721 }
722
723 return obj;
724}
725
726int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,707int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
727 struct reservation_object *robj, const struct etnaviv_gem_ops *ops,708 struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
728 struct etnaviv_gem_object **res)709 struct etnaviv_gem_object **res)
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c+67−2
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include "etnaviv_drv.h"21#include "etnaviv_drv.h"
22#include "etnaviv_gpu.h"22#include "etnaviv_gpu.h"
23#include "etnaviv_gem.h"23#include "etnaviv_gem.h"
24#include "etnaviv_perfmon.h"
24 25
25/*26/*
26 * Cmdstream submission:27 * Cmdstream submission:
@@ -283,6 +284,54 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream, · 256 unmodified lines
283 return 0;284 return 0;
284}285}
285 286
287static int submit_perfmon_validate(struct etnaviv_gem_submit *submit,
288 struct etnaviv_cmdbuf *cmdbuf,
289 const struct drm_etnaviv_gem_submit_pmr *pmrs,
290 u32 nr_pms)
291{
292 u32 i;
293
294 for (i = 0; i < nr_pms; i++) {
295 const struct drm_etnaviv_gem_submit_pmr *r = pmrs + i;
296 struct etnaviv_gem_submit_bo *bo;
297 int ret;
298
299 ret = submit_bo(submit, r->read_idx, &bo);
300 if (ret)
301 return ret;
302
303 /* at offset 0 a sequence number gets stored used for userspace sync */
304 if (r->read_offset == 0) {
305 DRM_ERROR("perfmon request: offset is 0");
306 return -EINVAL;
307 }
308
309 if (r->read_offset >= bo->obj->base.size - sizeof(u32)) {
310 DRM_ERROR("perfmon request: offset %u outside object", i);
311 return -EINVAL;
312 }
313
314 if (r->flags & ~(ETNA_PM_PROCESS_PRE | ETNA_PM_PROCESS_POST)) {
315 DRM_ERROR("perfmon request: flags are not valid");
316 return -EINVAL;
317 }
318
319 if (etnaviv_pm_req_validate(r, cmdbuf->exec_state)) {
320 DRM_ERROR("perfmon request: domain or signal not valid");
321 return -EINVAL;
322 }
323
324 cmdbuf->pmrs[i].flags = r->flags;
325 cmdbuf->pmrs[i].domain = r->domain;
326 cmdbuf->pmrs[i].signal = r->signal;
327 cmdbuf->pmrs[i].sequence = r->sequence;
328 cmdbuf->pmrs[i].offset = r->read_offset;
329 cmdbuf->pmrs[i].bo_vma = etnaviv_gem_vmap(&bo->obj->base);
330 }
331
332 return 0;
333}
334
286static void submit_cleanup(struct etnaviv_gem_submit *submit)335static void submit_cleanup(struct etnaviv_gem_submit *submit)
287{336{
288 unsigned i;337 unsigned i;
@@ -306,6 +355,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, · 17 unmodified lines
306 struct etnaviv_drm_private *priv = dev->dev_private;355 struct etnaviv_drm_private *priv = dev->dev_private;
307 struct drm_etnaviv_gem_submit *args = data;356 struct drm_etnaviv_gem_submit *args = data;
308 struct drm_etnaviv_gem_submit_reloc *relocs;357 struct drm_etnaviv_gem_submit_reloc *relocs;
358 struct drm_etnaviv_gem_submit_pmr *pmrs;
309 struct drm_etnaviv_gem_submit_bo *bos;359 struct drm_etnaviv_gem_submit_bo *bos;
310 struct etnaviv_gem_submit *submit;360 struct etnaviv_gem_submit *submit;
311 struct etnaviv_cmdbuf *cmdbuf;361 struct etnaviv_cmdbuf *cmdbuf;
@@ -347,11 +397,12 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, · 35 unmodified lines
347 */397 */
348 bos = kvmalloc_array(args->nr_bos, sizeof(*bos), GFP_KERNEL);398 bos = kvmalloc_array(args->nr_bos, sizeof(*bos), GFP_KERNEL);
349 relocs = kvmalloc_array(args->nr_relocs, sizeof(*relocs), GFP_KERNEL);399 relocs = kvmalloc_array(args->nr_relocs, sizeof(*relocs), GFP_KERNEL);
400 pmrs = kvmalloc_array(args->nr_pmrs, sizeof(*pmrs), GFP_KERNEL);
350 stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL);401 stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL);
351 cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc,402 cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc,
352 ALIGN(args->stream_size, 8) + 8,403 ALIGN(args->stream_size, 8) + 8,
353 args->nr_bos);404 args->nr_bos, args->nr_pmrs);
354 if (!bos || !relocs || !stream || !cmdbuf) {405 if (!bos || !relocs || !pmrs || !stream || !cmdbuf) {
355 ret = -ENOMEM;406 ret = -ENOMEM;
356 goto err_submit_cmds;407 goto err_submit_cmds;
357 }408 }
@@ -373,6 +424,14 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, · 15 unmodified lines
373 goto err_submit_cmds;424 goto err_submit_cmds;
374 }425 }
375 426
427 ret = copy_from_user(pmrs, u64_to_user_ptr(args->pmrs),
428 args->nr_pmrs * sizeof(*pmrs));
429 if (ret) {
430 ret = -EFAULT;
431 goto err_submit_cmds;
432 }
433 cmdbuf->nr_pmrs = args->nr_pmrs;
434
376 ret = copy_from_user(stream, u64_to_user_ptr(args->stream),435 ret = copy_from_user(stream, u64_to_user_ptr(args->stream),
377 args->stream_size);436 args->stream_size);
378 if (ret) {437 if (ret) {
@@ -441,6 +500,10 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, · 62 unmodified lines
441 if (ret)500 if (ret)
442 goto out;501 goto out;
443 502
503 ret = submit_perfmon_validate(submit, cmdbuf, pmrs, args->nr_pmrs);
504 if (ret)
505 goto out;
506
444 memcpy(cmdbuf->vaddr, stream, args->stream_size);507 memcpy(cmdbuf->vaddr, stream, args->stream_size);
445 cmdbuf->user_size = ALIGN(args->stream_size, 8);508 cmdbuf->user_size = ALIGN(args->stream_size, 8);
446 509
@@ -496,6 +559,8 @@ err_submit_cmds: · 49 unmodified lines
496 kvfree(bos);559 kvfree(bos);
497 if (relocs)560 if (relocs)
498 kvfree(relocs);561 kvfree(relocs);
562 if (pmrs)
563 kvfree(pmrs);
499 564
500 return ret;565 return ret;
501}566}
drivers/gpu/drm/etnaviv/etnaviv_gpu.c+167−50
@@ -25,6 +25,7 @@ · 24 unmodified lines
25#include "etnaviv_gpu.h"25#include "etnaviv_gpu.h"
26#include "etnaviv_gem.h"26#include "etnaviv_gem.h"
27#include "etnaviv_mmu.h"27#include "etnaviv_mmu.h"
28#include "etnaviv_perfmon.h"
28#include "common.xml.h"29#include "common.xml.h"
29#include "state.xml.h"30#include "state.xml.h"
30#include "state_hi.xml.h"31#include "state_hi.xml.h"
@@ -420,9 +421,10 @@ static void etnaviv_gpu_update_clock(struct etnaviv_gpu *gpu) · 389 unmodified lines
420 gpu->base_rate_shader >> gpu->freq_scale);421 gpu->base_rate_shader >> gpu->freq_scale);
421 } else {422 } else {
422 unsigned int fscale = 1 << (6 - gpu->freq_scale);423 unsigned int fscale = 1 << (6 - gpu->freq_scale);
423 u32 clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |424 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
424 VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
425 425
426 clock &= ~VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__MASK;
427 clock |= VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
426 etnaviv_gpu_load_clock(gpu, clock);428 etnaviv_gpu_load_clock(gpu, clock);
427 }429 }
428}430}
@@ -433,24 +435,14 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) · 4 unmodified lines
433 unsigned long timeout;435 unsigned long timeout;
434 bool failed = true;436 bool failed = true;
435 437
436 /* TODO
437 *
438 * - clock gating
439 * - puls eater
440 * - what about VG?
441 */
442
443 /* We hope that the GPU resets in under one second */438 /* We hope that the GPU resets in under one second */
444 timeout = jiffies + msecs_to_jiffies(1000);439 timeout = jiffies + msecs_to_jiffies(1000);
445 440
446 while (time_is_after_jiffies(timeout)) {441 while (time_is_after_jiffies(timeout)) {
447 /* enable clock */442 /* enable clock */
448 etnaviv_gpu_update_clock(gpu);443 unsigned int fscale = 1 << (6 - gpu->freq_scale);
449 444 control = VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
450 control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);445 etnaviv_gpu_load_clock(gpu, control);
451
452 /* Wait for stable clock. Vivante's code waited for 1ms */
453 usleep_range(1000, 10000);
454 446
455 /* isolate the GPU. */447 /* isolate the GPU. */
456 control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;448 control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
@@ -461,7 +453,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) · 4 unmodified lines
461 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);453 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
462 454
463 /* wait for reset. */455 /* wait for reset. */
464 msleep(1);456 usleep_range(10, 20);
465 457
466 /* reset soft reset bit. */458 /* reset soft reset bit. */
467 control &= ~VIVS_HI_CLOCK_CONTROL_SOFT_RESET;459 control &= ~VIVS_HI_CLOCK_CONTROL_SOFT_RESET;
@@ -490,6 +482,10 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) · 22 unmodified lines
490 continue;482 continue;
491 }483 }
492 484
485 /* disable debug registers, as they are not normally needed */
486 control |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
487 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
488
493 failed = false;489 failed = false;
494 break;490 break;
495 }491 }
@@ -721,7 +717,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) · 225 unmodified lines
721 }717 }
722 718
723 /* Create buffer: */719 /* Create buffer: */
724 gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0);720 gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0, 0);
725 if (!gpu->buffer) {721 if (!gpu->buffer) {
726 ret = -ENOMEM;722 ret = -ENOMEM;
727 dev_err(gpu->dev, "could not create command buffer\n");723 dev_err(gpu->dev, "could not create command buffer\n");
@@ -739,10 +735,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) · 11 unmodified lines
739 /* Setup event management */735 /* Setup event management */
740 spin_lock_init(&gpu->event_spinlock);736 spin_lock_init(&gpu->event_spinlock);
741 init_completion(&gpu->event_free);737 init_completion(&gpu->event_free);
742 for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {738 bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS);
743 gpu->event[i].used = false;739 for (i = 0; i < ARRAY_SIZE(gpu->event); i++)
744 complete(&gpu->event_free);740 complete(&gpu->event_free);
745 }
746 741
747 /* Now program the hardware */742 /* Now program the hardware */
748 mutex_lock(&gpu->lock);743 mutex_lock(&gpu->lock);
@@ -926,7 +921,7 @@ static void recover_worker(struct work_struct *work) · 177 unmodified lines
926 struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,921 struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
927 recover_work);922 recover_work);
928 unsigned long flags;923 unsigned long flags;
929 unsigned int i;924 unsigned int i = 0;
930 925
931 dev_err(gpu->dev, "hangcheck recover!\n");926 dev_err(gpu->dev, "hangcheck recover!\n");
932 927
@@ -945,14 +940,12 @@ static void recover_worker(struct work_struct *work) · 12 unmodified lines
945 940
946 /* complete all events, the GPU won't do it after the reset */941 /* complete all events, the GPU won't do it after the reset */
947 spin_lock_irqsave(&gpu->event_spinlock, flags);942 spin_lock_irqsave(&gpu->event_spinlock, flags);
948 for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {943 for_each_set_bit_from(i, gpu->event_bitmap, ETNA_NR_EVENTS) {
949 if (!gpu->event[i].used)
950 continue;
951 dma_fence_signal(gpu->event[i].fence);944 dma_fence_signal(gpu->event[i].fence);
952 gpu->event[i].fence = NULL;945 gpu->event[i].fence = NULL;
953 gpu->event[i].used = false;
954 complete(&gpu->event_free);946 complete(&gpu->event_free);
955 }947 }
948 bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS);
956 spin_unlock_irqrestore(&gpu->event_spinlock, flags);949 spin_unlock_irqrestore(&gpu->event_spinlock, flags);
957 gpu->completed_fence = gpu->active_fence;950 gpu->completed_fence = gpu->active_fence;
958 951
@@ -1140,30 +1133,45 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj, · 181 unmodified lines
1140 * event management:1133 * event management:
1141 */1134 */
1142 1135
1143static unsigned int event_alloc(struct etnaviv_gpu *gpu)1136static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
1137 unsigned int *events)
1144{1138{
1145 unsigned long ret, flags;1139 unsigned long flags, timeout = msecs_to_jiffies(10 * 10000);
1146 unsigned int i, event = ~0U;1140 unsigned i, acquired = 0;
1147 1141
1148 ret = wait_for_completion_timeout(&gpu->event_free,1142 for (i = 0; i < nr_events; i++) {
1149 msecs_to_jiffies(10 * 10000));1143 unsigned long ret;
1150 if (!ret)
1151 dev_err(gpu->dev, "wait_for_completion_timeout failed");
1152 1144
1153 spin_lock_irqsave(&gpu->event_spinlock, flags);1145 ret = wait_for_completion_timeout(&gpu->event_free, timeout);
1154 1146
1155 /* find first free event */1147 if (!ret) {
1156 for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {1148 dev_err(gpu->dev, "wait_for_completion_timeout failed");
1157 if (gpu->event[i].used == false) {1149 goto out;
1158 gpu->event[i].used = true;
1159 event = i;
1160 break;
1161 }1150 }
1151
1152 acquired++;
1153 timeout = ret;
1154 }
1155
1156 spin_lock_irqsave(&gpu->event_spinlock, flags);
1157
1158 for (i = 0; i < nr_events; i++) {
1159 int event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS);
1160
1161 events[i] = event;
1162 memset(&gpu->event[event], 0, sizeof(struct etnaviv_event));
1163 set_bit(event, gpu->event_bitmap);
1162 }1164 }
1163 1165
1164 spin_unlock_irqrestore(&gpu->event_spinlock, flags);1166 spin_unlock_irqrestore(&gpu->event_spinlock, flags);
1165 1167
1166 return event;1168 return 0;
1169
1170out:
1171 for (i = 0; i < acquired; i++)
1172 complete(&gpu->event_free);
1173
1174 return -EBUSY;
1167}1175}
1168 1176
1169static void event_free(struct etnaviv_gpu *gpu, unsigned int event)1177static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
@@ -1172,12 +1180,12 @@ static void event_free(struct etnaviv_gpu *gpu, unsigned int event) · 2 unmodified lines
1172 1180
1173 spin_lock_irqsave(&gpu->event_spinlock, flags);1181 spin_lock_irqsave(&gpu->event_spinlock, flags);
1174 1182
1175 if (gpu->event[event].used == false) {1183 if (!test_bit(event, gpu->event_bitmap)) {
1176 dev_warn(gpu->dev, "event %u is already marked as free",1184 dev_warn(gpu->dev, "event %u is already marked as free",
1177 event);1185 event);
1178 spin_unlock_irqrestore(&gpu->event_spinlock, flags);1186 spin_unlock_irqrestore(&gpu->event_spinlock, flags);
1179 } else {1187 } else {
1180 gpu->event[event].used = false;1188 clear_bit(event, gpu->event_bitmap);
1181 spin_unlock_irqrestore(&gpu->event_spinlock, flags);1189 spin_unlock_irqrestore(&gpu->event_spinlock, flags);
1182 1190
1183 complete(&gpu->event_free);1191 complete(&gpu->event_free);
@@ -1311,12 +1319,71 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu) · 127 unmodified lines
1311 pm_runtime_put_autosuspend(gpu->dev);1319 pm_runtime_put_autosuspend(gpu->dev);
1312}1320}
1313 1321
1322static void sync_point_perfmon_sample(struct etnaviv_gpu *gpu,
1323 struct etnaviv_event *event, unsigned int flags)
1324{
1325 const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf;
1326 unsigned int i;
1327
1328 for (i = 0; i < cmdbuf->nr_pmrs; i++) {
1329 const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i;
1330
1331 if (pmr->flags == flags)
1332 etnaviv_perfmon_process(gpu, pmr);
1333 }
1334}
1335
1336static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
1337 struct etnaviv_event *event)
1338{
1339 u32 val;
1340
1341 /* disable clock gating */
1342 val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
1343 val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
1344 gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
1345
1346 /* enable debug register */
1347 val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
1348 val &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
1349 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
1350
1351 sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE);
1352}
1353
1354static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
1355 struct etnaviv_event *event)
1356{
1357 const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf;
1358 unsigned int i;
1359 u32 val;
1360
1361 sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
1362
1363 for (i = 0; i < cmdbuf->nr_pmrs; i++) {
1364 const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i;
1365
1366 *pmr->bo_vma = pmr->sequence;
1367 }
1368
1369 /* disable debug register */
1370 val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
1371 val |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
1372 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
1373
1374 /* enable clock gating */
1375 val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
1376 val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
1377 gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
1378}
1379
1380
1314/* add bo's to gpu's ring, and kick gpu: */1381/* add bo's to gpu's ring, and kick gpu: */
1315int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,1382int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
1316 struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf)1383 struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf)
1317{1384{
1318 struct dma_fence *fence;1385 struct dma_fence *fence;
1319 unsigned int event, i;1386 unsigned int i, nr_events = 1, event[3];
1320 int ret;1387 int ret;
1321 1388
1322 ret = etnaviv_gpu_pm_get_sync(gpu);1389 ret = etnaviv_gpu_pm_get_sync(gpu);
@@ -1332,10 +1399,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, · 9 unmodified lines
1332 *1399 *
1333 */1400 */
1334 1401
1335 event = event_alloc(gpu);1402 /*
1336 if (unlikely(event == ~0U)) {1403 * if there are performance monitor requests we need to have
1337 DRM_ERROR("no free event\n");1404 * - a sync point to re-configure gpu and process ETNA_PM_PROCESS_PRE
1338 ret = -EBUSY;1405 * requests.
1406 * - a sync point to re-configure gpu, process ETNA_PM_PROCESS_POST requests
1407 * and update the sequence number for userspace.
1408 */
1409 if (cmdbuf->nr_pmrs)
1410 nr_events = 3;
1411
1412 ret = event_alloc(gpu, nr_events, event);
1413 if (ret) {
1414 DRM_ERROR("no free events\n");
1339 goto out_pm_put;1415 goto out_pm_put;
1340 }1416 }
1341 1417
@@ -1343,12 +1419,14 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, · 1 unmodified line
1343 1419
1344 fence = etnaviv_gpu_fence_alloc(gpu);1420 fence = etnaviv_gpu_fence_alloc(gpu);
1345 if (!fence) {1421 if (!fence) {
1346 event_free(gpu, event);1422 for (i = 0; i < nr_events; i++)
1423 event_free(gpu, event[i]);
1424
1347 ret = -ENOMEM;1425 ret = -ENOMEM;
1348 goto out_unlock;1426 goto out_unlock;
1349 }1427 }
1350 1428
1351 gpu->event[event].fence = fence;1429 gpu->event[event[0]].fence = fence;
1352 submit->fence = dma_fence_get(fence);1430 submit->fence = dma_fence_get(fence);
1353 gpu->active_fence = submit->fence->seqno;1431 gpu->active_fence = submit->fence->seqno;
1354 1432
@@ -1358,7 +1436,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, · 3 unmodified lines
1358 gpu->lastctx = cmdbuf->ctx;1436 gpu->lastctx = cmdbuf->ctx;
1359 }1437 }
1360 1438
1361 etnaviv_buffer_queue(gpu, event, cmdbuf);1439 if (cmdbuf->nr_pmrs) {
1440 gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre;
1441 gpu->event[event[1]].cmdbuf = cmdbuf;
1442 etnaviv_sync_point_queue(gpu, event[1]);
1443 }
1444
1445 etnaviv_buffer_queue(gpu, event[0], cmdbuf);
1446
1447 if (cmdbuf->nr_pmrs) {
1448 gpu->event[event[2]].sync_point = &sync_point_perfmon_sample_post;
1449 gpu->event[event[2]].cmdbuf = cmdbuf;
1450 etnaviv_sync_point_queue(gpu, event[2]);
1451 }
1362 1452
1363 cmdbuf->fence = fence;1453 cmdbuf->fence = fence;
1364 list_add_tail(&cmdbuf->node, &gpu->active_cmd_list);1454 list_add_tail(&cmdbuf->node, &gpu->active_cmd_list);
@@ -1394,6 +1484,24 @@ out_pm_put: · 29 unmodified lines
1394 return ret;1484 return ret;
1395}1485}
1396 1486
1487static void etnaviv_process_sync_point(struct etnaviv_gpu *gpu,
1488 struct etnaviv_event *event)
1489{
1490 u32 addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
1491
1492 event->sync_point(gpu, event);
1493 etnaviv_gpu_start_fe(gpu, addr + 2, 2);
1494}
1495
1496static void sync_point_worker(struct work_struct *work)
1497{
1498 struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
1499 sync_point_work);
1500
1501 etnaviv_process_sync_point(gpu, &gpu->event[gpu->sync_point_event]);
1502 event_free(gpu, gpu->sync_point_event);
1503}
1504
1397/*1505/*
1398 * Init/Cleanup:1506 * Init/Cleanup:
1399 */1507 */
@@ -1440,7 +1548,15 @@ static irqreturn_t irq_handler(int irq, void *data) · 40 unmodified lines
1440 1548
1441 dev_dbg(gpu->dev, "event %u\n", event);1549 dev_dbg(gpu->dev, "event %u\n", event);
1442 1550
1551 if (gpu->event[event].sync_point) {
1552 gpu->sync_point_event = event;
1553 etnaviv_queue_work(gpu->drm, &gpu->sync_point_work);
1554 }
1555
1443 fence = gpu->event[event].fence;1556 fence = gpu->event[event].fence;
1557 if (!fence)
1558 continue;
1559
1444 gpu->event[event].fence = NULL;1560 gpu->event[event].fence = NULL;
1445 dma_fence_signal(fence);1561 dma_fence_signal(fence);
1446 1562
@@ -1645,6 +1761,7 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master, · 198 unmodified lines
1645 1761
1646 INIT_LIST_HEAD(&gpu->active_cmd_list);1762 INIT_LIST_HEAD(&gpu->active_cmd_list);
1647 INIT_WORK(&gpu->retire_work, retire_worker);1763 INIT_WORK(&gpu->retire_work, retire_worker);
1764 INIT_WORK(&gpu->sync_point_work, sync_point_worker);
1648 INIT_WORK(&gpu->recover_work, recover_worker);1765 INIT_WORK(&gpu->recover_work, recover_worker);
1649 init_waitqueue_head(&gpu->fence_event);1766 init_waitqueue_head(&gpu->fence_event);
1650 1767
drivers/gpu/drm/etnaviv/etnaviv_gpu.h+11−2
@@ -88,13 +88,17 @@ struct etnaviv_chip_identity { · 87 unmodified lines
88};88};
89 89
90struct etnaviv_event {90struct etnaviv_event {
91 bool used;
92 struct dma_fence *fence;91 struct dma_fence *fence;
92 struct etnaviv_cmdbuf *cmdbuf;
93
94 void (*sync_point)(struct etnaviv_gpu *gpu, struct etnaviv_event *event);
93};95};
94 96
95struct etnaviv_cmdbuf_suballoc;97struct etnaviv_cmdbuf_suballoc;
96struct etnaviv_cmdbuf;98struct etnaviv_cmdbuf;
97 99
100#define ETNA_NR_EVENTS 30
101
98struct etnaviv_gpu {102struct etnaviv_gpu {
99 struct drm_device *drm;103 struct drm_device *drm;
100 struct thermal_cooling_device *cooling;104 struct thermal_cooling_device *cooling;
@@ -112,7 +116,8 @@ struct etnaviv_gpu { · 11 unmodified lines
112 u32 memory_base;116 u32 memory_base;
113 117
114 /* event management: */118 /* event management: */
115 struct etnaviv_event event[30];119 DECLARE_BITMAP(event_bitmap, ETNA_NR_EVENTS);
120 struct etnaviv_event event[ETNA_NR_EVENTS];
116 struct completion event_free;121 struct completion event_free;
117 spinlock_t event_spinlock;122 spinlock_t event_spinlock;
118 123
@@ -133,6 +138,10 @@ struct etnaviv_gpu { · 14 unmodified lines
133 /* worker for handling active-list retiring: */138 /* worker for handling active-list retiring: */
134 struct work_struct retire_work;139 struct work_struct retire_work;
135 140
141 /* worker for handling 'sync' points: */
142 struct work_struct sync_point_work;
143 int sync_point_event;
144
136 void __iomem *mmio;145 void __iomem *mmio;
137 int irq;146 int irq;
138 147
drivers/gpu/drm/etnaviv/etnaviv_iommu.c+73−124
@@ -14,7 +14,6 @@ · 13 unmodified lines
14 * this program. If not, see <http://www.gnu.org/licenses/>.14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
16 16
17#include <linux/iommu.h>
18#include <linux/platform_device.h>17#include <linux/platform_device.h>
19#include <linux/sizes.h>18#include <linux/sizes.h>
20#include <linux/slab.h>19#include <linux/slab.h>
@@ -31,174 +30,115 @@ · 10 unmodified lines
31 30
32#define GPU_MEM_START 0x8000000031#define GPU_MEM_START 0x80000000
33 32
34struct etnaviv_iommu_domain_pgtable {33struct etnaviv_iommuv1_domain {
35 u32 *pgtable;34 struct etnaviv_iommu_domain base;
36 dma_addr_t paddr;35 u32 *pgtable_cpu;
36 dma_addr_t pgtable_dma;
37};37};
38 38
39struct etnaviv_iommu_domain {39static struct etnaviv_iommuv1_domain *
40 struct iommu_domain domain;40to_etnaviv_domain(struct etnaviv_iommu_domain *domain)
41 struct device *dev;
42 void *bad_page_cpu;
43 dma_addr_t bad_page_dma;
44 struct etnaviv_iommu_domain_pgtable pgtable;
45 spinlock_t map_lock;
46};
47
48static struct etnaviv_iommu_domain *to_etnaviv_domain(struct iommu_domain *domain)
49{
50 return container_of(domain, struct etnaviv_iommu_domain, domain);
51}
52
53static int pgtable_alloc(struct etnaviv_iommu_domain_pgtable *pgtable,
54 size_t size)
55{
56 pgtable->pgtable = dma_alloc_coherent(NULL, size, &pgtable->paddr, GFP_KERNEL);
57 if (!pgtable->pgtable)
58 return -ENOMEM;
59
60 return 0;
61}
62
63static void pgtable_free(struct etnaviv_iommu_domain_pgtable *pgtable,
64 size_t size)
65{41{
66 dma_free_coherent(NULL, size, pgtable->pgtable, pgtable->paddr);42 return container_of(domain, struct etnaviv_iommuv1_domain, base);
67}
68
69static u32 pgtable_read(struct etnaviv_iommu_domain_pgtable *pgtable,
70 unsigned long iova)
71{
72 /* calcuate index into page table */
73 unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
74 phys_addr_t paddr;
75
76 paddr = pgtable->pgtable[index];
77
78 return paddr;
79}43}
80 44
81static void pgtable_write(struct etnaviv_iommu_domain_pgtable *pgtable,45static int __etnaviv_iommu_init(struct etnaviv_iommuv1_domain *etnaviv_domain)
82 unsigned long iova, phys_addr_t paddr)
83{
84 /* calcuate index into page table */
85 unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
86
87 pgtable->pgtable[index] = paddr;
88}
89
90static int __etnaviv_iommu_init(struct etnaviv_iommu_domain *etnaviv_domain)
91{46{
92 u32 *p;47 u32 *p;
93 int ret, i;48 int i;
94 49
95 etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev,50 etnaviv_domain->base.bad_page_cpu = dma_alloc_coherent(
96 SZ_4K,51 etnaviv_domain->base.dev,
97 &etnaviv_domain->bad_page_dma,52 SZ_4K,
98 GFP_KERNEL);53 &etnaviv_domain->base.bad_page_dma,
99 if (!etnaviv_domain->bad_page_cpu)54 GFP_KERNEL);
55 if (!etnaviv_domain->base.bad_page_cpu)
100 return -ENOMEM;56 return -ENOMEM;
101 57
102 p = etnaviv_domain->bad_page_cpu;58 p = etnaviv_domain->base.bad_page_cpu;
103 for (i = 0; i < SZ_4K / 4; i++)59 for (i = 0; i < SZ_4K / 4; i++)
104 *p++ = 0xdead55aa;60 *p++ = 0xdead55aa;
105 61
106 ret = pgtable_alloc(&etnaviv_domain->pgtable, PT_SIZE);62 etnaviv_domain->pgtable_cpu =
107 if (ret < 0) {63 dma_alloc_coherent(etnaviv_domain->base.dev, PT_SIZE,
108 dma_free_coherent(etnaviv_domain->dev, SZ_4K,64 &etnaviv_domain->pgtable_dma,
109 etnaviv_domain->bad_page_cpu,65 GFP_KERNEL);
110 etnaviv_domain->bad_page_dma);66 if (!etnaviv_domain->pgtable_cpu) {
111 return ret;67 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
68 etnaviv_domain->base.bad_page_cpu,
69 etnaviv_domain->base.bad_page_dma);
70 return -ENOMEM;
112 }71 }
113 72
114 for (i = 0; i < PT_ENTRIES; i++)73 for (i = 0; i < PT_ENTRIES; i++)
115 etnaviv_domain->pgtable.pgtable[i] =74 etnaviv_domain->pgtable_cpu[i] =
116 etnaviv_domain->bad_page_dma;75 etnaviv_domain->base.bad_page_dma;
117
118 spin_lock_init(&etnaviv_domain->map_lock);
119 76
120 return 0;77 return 0;
121}78}
122 79
123static void etnaviv_domain_free(struct iommu_domain *domain)80static void etnaviv_iommuv1_domain_free(struct etnaviv_iommu_domain *domain)
124{81{
125 struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);82 struct etnaviv_iommuv1_domain *etnaviv_domain =
83 to_etnaviv_domain(domain);
126 84
127 pgtable_free(&etnaviv_domain->pgtable, PT_SIZE);85 dma_free_coherent(etnaviv_domain->base.dev, PT_SIZE,
86 etnaviv_domain->pgtable_cpu,
87 etnaviv_domain->pgtable_dma);
128 88
129 dma_free_coherent(etnaviv_domain->dev, SZ_4K,89 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
130 etnaviv_domain->bad_page_cpu,90 etnaviv_domain->base.bad_page_cpu,
131 etnaviv_domain->bad_page_dma);91 etnaviv_domain->base.bad_page_dma);
132 92
133 kfree(etnaviv_domain);93 kfree(etnaviv_domain);
134}94}
135 95
136static int etnaviv_iommuv1_map(struct iommu_domain *domain, unsigned long iova,96static int etnaviv_iommuv1_map(struct etnaviv_iommu_domain *domain,
137 phys_addr_t paddr, size_t size, int prot)97 unsigned long iova, phys_addr_t paddr,
98 size_t size, int prot)
138{99{
139 struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);100 struct etnaviv_iommuv1_domain *etnaviv_domain = to_etnaviv_domain(domain);
101 unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
140 102
141 if (size != SZ_4K)103 if (size != SZ_4K)
142 return -EINVAL;104 return -EINVAL;
143 105
144 spin_lock(&etnaviv_domain->map_lock);106 etnaviv_domain->pgtable_cpu[index] = paddr;
145 pgtable_write(&etnaviv_domain->pgtable, iova, paddr);
146 spin_unlock(&etnaviv_domain->map_lock);
147 107
148 return 0;108 return 0;
149}109}
150 110
151static size_t etnaviv_iommuv1_unmap(struct iommu_domain *domain,111static size_t etnaviv_iommuv1_unmap(struct etnaviv_iommu_domain *domain,
152 unsigned long iova, size_t size)112 unsigned long iova, size_t size)
153{113{
154 struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);114 struct etnaviv_iommuv1_domain *etnaviv_domain =
115 to_etnaviv_domain(domain);
116 unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
155 117
156 if (size != SZ_4K)118 if (size != SZ_4K)
157 return -EINVAL;119 return -EINVAL;
158 120
159 spin_lock(&etnaviv_domain->map_lock);121 etnaviv_domain->pgtable_cpu[index] = etnaviv_domain->base.bad_page_dma;
160 pgtable_write(&etnaviv_domain->pgtable, iova,
161 etnaviv_domain->bad_page_dma);
162 spin_unlock(&etnaviv_domain->map_lock);
163 122
164 return SZ_4K;123 return SZ_4K;
165}124}
166 125
167static phys_addr_t etnaviv_iommu_iova_to_phys(struct iommu_domain *domain,126static size_t etnaviv_iommuv1_dump_size(struct etnaviv_iommu_domain *domain)
168 dma_addr_t iova)
169{
170 struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
171
172 return pgtable_read(&etnaviv_domain->pgtable, iova);
173}
174
175static size_t etnaviv_iommuv1_dump_size(struct iommu_domain *domain)
176{127{
177 return PT_SIZE;128 return PT_SIZE;
178}129}
179 130
180static void etnaviv_iommuv1_dump(struct iommu_domain *domain, void *buf)131static void etnaviv_iommuv1_dump(struct etnaviv_iommu_domain *domain, void *buf)
181{132{
182 struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);133 struct etnaviv_iommuv1_domain *etnaviv_domain =
134 to_etnaviv_domain(domain);
183 135
184 memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE);136 memcpy(buf, etnaviv_domain->pgtable_cpu, PT_SIZE);
185}137}
186 138
187static const struct etnaviv_iommu_ops etnaviv_iommu_ops = {
188 .ops = {
189 .domain_free = etnaviv_domain_free,
190 .map = etnaviv_iommuv1_map,
191 .unmap = etnaviv_iommuv1_unmap,
192 .iova_to_phys = etnaviv_iommu_iova_to_phys,
193 .pgsize_bitmap = SZ_4K,
194 },
195 .dump_size = etnaviv_iommuv1_dump_size,
196 .dump = etnaviv_iommuv1_dump,
197};
198
199void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu)139void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu)
200{140{
201 struct etnaviv_iommu_domain *etnaviv_domain =141 struct etnaviv_iommuv1_domain *etnaviv_domain =
202 to_etnaviv_domain(gpu->mmu->domain);142 to_etnaviv_domain(gpu->mmu->domain);
203 u32 pgtable;143 u32 pgtable;
204 144
@@ -210,7 +150,7 @@ void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu) · 5 unmodified lines
210 gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PE, gpu->memory_base);150 gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PE, gpu->memory_base);
211 151
212 /* set page table address in MC */152 /* set page table address in MC */
213 pgtable = (u32)etnaviv_domain->pgtable.paddr;153 pgtable = (u32)etnaviv_domain->pgtable_dma;
214 154
215 gpu_write(gpu, VIVS_MC_MMU_FE_PAGE_TABLE, pgtable);155 gpu_write(gpu, VIVS_MC_MMU_FE_PAGE_TABLE, pgtable);
216 gpu_write(gpu, VIVS_MC_MMU_TX_PAGE_TABLE, pgtable);156 gpu_write(gpu, VIVS_MC_MMU_TX_PAGE_TABLE, pgtable);
@@ -219,28 +159,37 @@ void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu) · 2 unmodified lines
219 gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, pgtable);159 gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, pgtable);
220}160}
221 161
222struct iommu_domain *etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu)162const struct etnaviv_iommu_domain_ops etnaviv_iommuv1_ops = {
163 .free = etnaviv_iommuv1_domain_free,
164 .map = etnaviv_iommuv1_map,
165 .unmap = etnaviv_iommuv1_unmap,
166 .dump_size = etnaviv_iommuv1_dump_size,
167 .dump = etnaviv_iommuv1_dump,
168};
169
170struct etnaviv_iommu_domain *
171etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu)
223{172{
224 struct etnaviv_iommu_domain *etnaviv_domain;173 struct etnaviv_iommuv1_domain *etnaviv_domain;
174 struct etnaviv_iommu_domain *domain;
225 int ret;175 int ret;
226 176
227 etnaviv_domain = kzalloc(sizeof(*etnaviv_domain), GFP_KERNEL);177 etnaviv_domain = kzalloc(sizeof(*etnaviv_domain), GFP_KERNEL);
228 if (!etnaviv_domain)178 if (!etnaviv_domain)
229 return NULL;179 return NULL;
230 180
231 etnaviv_domain->dev = gpu->dev;181 domain = &etnaviv_domain->base;
232 182
233 etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING;183 domain->dev = gpu->dev;
234 etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops;184 domain->base = GPU_MEM_START;
235 etnaviv_domain->domain.pgsize_bitmap = SZ_4K;185 domain->size = PT_ENTRIES * SZ_4K;
236 etnaviv_domain->domain.geometry.aperture_start = GPU_MEM_START;186 domain->ops = &etnaviv_iommuv1_ops;
237 etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + PT_ENTRIES * SZ_4K - 1;
238 187
239 ret = __etnaviv_iommu_init(etnaviv_domain);188 ret = __etnaviv_iommu_init(etnaviv_domain);
240 if (ret)189 if (ret)
241 goto out_free;190 goto out_free;
242 191
243 return &etnaviv_domain->domain;192 return &etnaviv_domain->base;
244 193
245out_free:194out_free:
246 kfree(etnaviv_domain);195 kfree(etnaviv_domain);
drivers/gpu/drm/etnaviv/etnaviv_iommu.h+5−2
@@ -18,11 +18,14 @@ · 17 unmodified lines
18#define __ETNAVIV_IOMMU_H__18#define __ETNAVIV_IOMMU_H__
19 19
20struct etnaviv_gpu;20struct etnaviv_gpu;
21struct etnaviv_iommu_domain;
21 22
22struct iommu_domain *etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu);23struct etnaviv_iommu_domain *
24etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu);
23void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu);25void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu);
24 26
25struct iommu_domain *etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu);27struct etnaviv_iommu_domain *
28etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu);
26void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu);29void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu);
27 30
28#endif /* __ETNAVIV_IOMMU_H__ */31#endif /* __ETNAVIV_IOMMU_H__ */
drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c+52−68
@@ -14,7 +14,6 @@ · 13 unmodified lines
14 * this program. If not, see <http://www.gnu.org/licenses/>.14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
16 16
17#include <linux/iommu.h>
18#include <linux/platform_device.h>17#include <linux/platform_device.h>
19#include <linux/sizes.h>18#include <linux/sizes.h>
20#include <linux/slab.h>19#include <linux/slab.h>
@@ -40,10 +39,7 @@ · 19 unmodified lines
40#define MMUv2_MAX_STLB_ENTRIES 102439#define MMUv2_MAX_STLB_ENTRIES 1024
41 40
42struct etnaviv_iommuv2_domain {41struct etnaviv_iommuv2_domain {
43 struct iommu_domain domain;42 struct etnaviv_iommu_domain base;
44 struct device *dev;
45 void *bad_page_cpu;
46 dma_addr_t bad_page_dma;
47 /* M(aster) TLB aka first level pagetable */43 /* M(aster) TLB aka first level pagetable */
48 u32 *mtlb_cpu;44 u32 *mtlb_cpu;
49 dma_addr_t mtlb_dma;45 dma_addr_t mtlb_dma;
@@ -52,13 +48,15 @@ struct etnaviv_iommuv2_domain { · 2 unmodified lines
52 dma_addr_t stlb_dma[1024];48 dma_addr_t stlb_dma[1024];
53};49};
54 50
55static struct etnaviv_iommuv2_domain *to_etnaviv_domain(struct iommu_domain *domain)51static struct etnaviv_iommuv2_domain *
52to_etnaviv_domain(struct etnaviv_iommu_domain *domain)
56{53{
57 return container_of(domain, struct etnaviv_iommuv2_domain, domain);54 return container_of(domain, struct etnaviv_iommuv2_domain, base);
58}55}
59 56
60static int etnaviv_iommuv2_map(struct iommu_domain *domain, unsigned long iova,57static int etnaviv_iommuv2_map(struct etnaviv_iommu_domain *domain,
61 phys_addr_t paddr, size_t size, int prot)58 unsigned long iova, phys_addr_t paddr,
59 size_t size, int prot)
62{60{
63 struct etnaviv_iommuv2_domain *etnaviv_domain =61 struct etnaviv_iommuv2_domain *etnaviv_domain =
64 to_etnaviv_domain(domain);62 to_etnaviv_domain(domain);
@@ -68,7 +66,7 @@ static int etnaviv_iommuv2_map(struct iommu_domain *domain, unsigned long iova, · 3 unmodified lines
68 if (size != SZ_4K)66 if (size != SZ_4K)
69 return -EINVAL;67 return -EINVAL;
70 68
71 if (prot & IOMMU_WRITE)69 if (prot & ETNAVIV_PROT_WRITE)
72 entry |= MMUv2_PTE_WRITEABLE;70 entry |= MMUv2_PTE_WRITEABLE;
73 71
74 mtlb_entry = (iova & MMUv2_MTLB_MASK) >> MMUv2_MTLB_SHIFT;72 mtlb_entry = (iova & MMUv2_MTLB_MASK) >> MMUv2_MTLB_SHIFT;
@@ -79,8 +77,8 @@ static int etnaviv_iommuv2_map(struct iommu_domain *domain, unsigned long iova, · 4 unmodified lines
79 return 0;77 return 0;
80}78}
81 79
82static size_t etnaviv_iommuv2_unmap(struct iommu_domain *domain,80static size_t etnaviv_iommuv2_unmap(struct etnaviv_iommu_domain *domain,
83 unsigned long iova, size_t size)81 unsigned long iova, size_t size)
84{82{
85 struct etnaviv_iommuv2_domain *etnaviv_domain =83 struct etnaviv_iommuv2_domain *etnaviv_domain =
86 to_etnaviv_domain(domain);84 to_etnaviv_domain(domain);
@@ -97,38 +95,26 @@ static size_t etnaviv_iommuv2_unmap(struct iommu_domain *domain, · 10 unmodified lines
97 return SZ_4K;95 return SZ_4K;
98}96}
99 97
100static phys_addr_t etnaviv_iommuv2_iova_to_phys(struct iommu_domain *domain,
101 dma_addr_t iova)
102{
103 struct etnaviv_iommuv2_domain *etnaviv_domain =
104 to_etnaviv_domain(domain);
105 int mtlb_entry, stlb_entry;
106
107 mtlb_entry = (iova & MMUv2_MTLB_MASK) >> MMUv2_MTLB_SHIFT;
108 stlb_entry = (iova & MMUv2_STLB_MASK) >> MMUv2_STLB_SHIFT;
109
110 return etnaviv_domain->stlb_cpu[mtlb_entry][stlb_entry] & ~(SZ_4K - 1);
111}
112
113static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain)98static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain)
114{99{
115 u32 *p;100 u32 *p;
116 int ret, i, j;101 int ret, i, j;
117 102
118 /* allocate scratch page */103 /* allocate scratch page */
119 etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev,104 etnaviv_domain->base.bad_page_cpu = dma_alloc_coherent(
120 SZ_4K,105 etnaviv_domain->base.dev,
121 &etnaviv_domain->bad_page_dma,106 SZ_4K,
122 GFP_KERNEL);107 &etnaviv_domain->base.bad_page_dma,
123 if (!etnaviv_domain->bad_page_cpu) {108 GFP_KERNEL);
109 if (!etnaviv_domain->base.bad_page_cpu) {
124 ret = -ENOMEM;110 ret = -ENOMEM;
125 goto fail_mem;111 goto fail_mem;
126 }112 }
127 p = etnaviv_domain->bad_page_cpu;113 p = etnaviv_domain->base.bad_page_cpu;
128 for (i = 0; i < SZ_4K / 4; i++)114 for (i = 0; i < SZ_4K / 4; i++)
129 *p++ = 0xdead55aa;115 *p++ = 0xdead55aa;
130 116
131 etnaviv_domain->mtlb_cpu = dma_alloc_coherent(etnaviv_domain->dev,117 etnaviv_domain->mtlb_cpu = dma_alloc_coherent(etnaviv_domain->base.dev,
132 SZ_4K,118 SZ_4K,
133 &etnaviv_domain->mtlb_dma,119 &etnaviv_domain->mtlb_dma,
134 GFP_KERNEL);120 GFP_KERNEL);
@@ -140,7 +126,7 @@ static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) · 5 unmodified lines
140 /* pre-populate STLB pages (may want to switch to on-demand later) */126 /* pre-populate STLB pages (may want to switch to on-demand later) */
141 for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {127 for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {
142 etnaviv_domain->stlb_cpu[i] =128 etnaviv_domain->stlb_cpu[i] =
143 dma_alloc_coherent(etnaviv_domain->dev,129 dma_alloc_coherent(etnaviv_domain->base.dev,
144 SZ_4K,130 SZ_4K,
145 &etnaviv_domain->stlb_dma[i],131 &etnaviv_domain->stlb_dma[i],
146 GFP_KERNEL);132 GFP_KERNEL);
@@ -159,19 +145,19 @@ static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) · 12 unmodified lines
159 return 0;145 return 0;
160 146
161fail_mem:147fail_mem:
162 if (etnaviv_domain->bad_page_cpu)148 if (etnaviv_domain->base.bad_page_cpu)
163 dma_free_coherent(etnaviv_domain->dev, SZ_4K,149 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
164 etnaviv_domain->bad_page_cpu,150 etnaviv_domain->base.bad_page_cpu,
165 etnaviv_domain->bad_page_dma);151 etnaviv_domain->base.bad_page_dma);
166 152
167 if (etnaviv_domain->mtlb_cpu)153 if (etnaviv_domain->mtlb_cpu)
168 dma_free_coherent(etnaviv_domain->dev, SZ_4K,154 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
169 etnaviv_domain->mtlb_cpu,155 etnaviv_domain->mtlb_cpu,
170 etnaviv_domain->mtlb_dma);156 etnaviv_domain->mtlb_dma);
171 157
172 for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {158 for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {
173 if (etnaviv_domain->stlb_cpu[i])159 if (etnaviv_domain->stlb_cpu[i])
174 dma_free_coherent(etnaviv_domain->dev, SZ_4K,160 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
175 etnaviv_domain->stlb_cpu[i],161 etnaviv_domain->stlb_cpu[i],
176 etnaviv_domain->stlb_dma[i]);162 etnaviv_domain->stlb_dma[i]);
177 }163 }
@@ -179,23 +165,23 @@ fail_mem: · 1 unmodified line
179 return ret;165 return ret;
180}166}
181 167
182static void etnaviv_iommuv2_domain_free(struct iommu_domain *domain)168static void etnaviv_iommuv2_domain_free(struct etnaviv_iommu_domain *domain)
183{169{
184 struct etnaviv_iommuv2_domain *etnaviv_domain =170 struct etnaviv_iommuv2_domain *etnaviv_domain =
185 to_etnaviv_domain(domain);171 to_etnaviv_domain(domain);
186 int i;172 int i;
187 173
188 dma_free_coherent(etnaviv_domain->dev, SZ_4K,174 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
189 etnaviv_domain->bad_page_cpu,175 etnaviv_domain->base.bad_page_cpu,
190 etnaviv_domain->bad_page_dma);176 etnaviv_domain->base.bad_page_dma);
191 177
192 dma_free_coherent(etnaviv_domain->dev, SZ_4K,178 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
193 etnaviv_domain->mtlb_cpu,179 etnaviv_domain->mtlb_cpu,
194 etnaviv_domain->mtlb_dma);180 etnaviv_domain->mtlb_dma);
195 181
196 for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {182 for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {
197 if (etnaviv_domain->stlb_cpu[i])183 if (etnaviv_domain->stlb_cpu[i])
198 dma_free_coherent(etnaviv_domain->dev, SZ_4K,184 dma_free_coherent(etnaviv_domain->base.dev, SZ_4K,
199 etnaviv_domain->stlb_cpu[i],185 etnaviv_domain->stlb_cpu[i],
200 etnaviv_domain->stlb_dma[i]);186 etnaviv_domain->stlb_dma[i]);
201 }187 }
@@ -203,7 +189,7 @@ static void etnaviv_iommuv2_domain_free(struct iommu_domain *domain) · 1 unmodified line
203 vfree(etnaviv_domain);189 vfree(etnaviv_domain);
204}190}
205 191
206static size_t etnaviv_iommuv2_dump_size(struct iommu_domain *domain)192static size_t etnaviv_iommuv2_dump_size(struct etnaviv_iommu_domain *domain)
207{193{
208 struct etnaviv_iommuv2_domain *etnaviv_domain =194 struct etnaviv_iommuv2_domain *etnaviv_domain =
209 to_etnaviv_domain(domain);195 to_etnaviv_domain(domain);
@@ -217,7 +203,7 @@ static size_t etnaviv_iommuv2_dump_size(struct iommu_domain *domain) · 7 unmodified lines
217 return dump_size;203 return dump_size;
218}204}
219 205
220static void etnaviv_iommuv2_dump(struct iommu_domain *domain, void *buf)206static void etnaviv_iommuv2_dump(struct etnaviv_iommu_domain *domain, void *buf)
221{207{
222 struct etnaviv_iommuv2_domain *etnaviv_domain =208 struct etnaviv_iommuv2_domain *etnaviv_domain =
223 to_etnaviv_domain(domain);209 to_etnaviv_domain(domain);
@@ -230,18 +216,6 @@ static void etnaviv_iommuv2_dump(struct iommu_domain *domain, void *buf) · 6 unmodified lines
230 memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K);216 memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K);
231}217}
232 218
233static const struct etnaviv_iommu_ops etnaviv_iommu_ops = {
234 .ops = {
235 .domain_free = etnaviv_iommuv2_domain_free,
236 .map = etnaviv_iommuv2_map,
237 .unmap = etnaviv_iommuv2_unmap,
238 .iova_to_phys = etnaviv_iommuv2_iova_to_phys,
239 .pgsize_bitmap = SZ_4K,
240 },
241 .dump_size = etnaviv_iommuv2_dump_size,
242 .dump = etnaviv_iommuv2_dump,
243};
244
245void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu)219void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu)
246{220{
247 struct etnaviv_iommuv2_domain *etnaviv_domain =221 struct etnaviv_iommuv2_domain *etnaviv_domain =
@@ -254,35 +228,45 @@ void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu) · 6 unmodified lines
254 228
255 prefetch = etnaviv_buffer_config_mmuv2(gpu,229 prefetch = etnaviv_buffer_config_mmuv2(gpu,
256 (u32)etnaviv_domain->mtlb_dma,230 (u32)etnaviv_domain->mtlb_dma,
257 (u32)etnaviv_domain->bad_page_dma);231 (u32)etnaviv_domain->base.bad_page_dma);
258 etnaviv_gpu_start_fe(gpu, (u32)etnaviv_cmdbuf_get_pa(gpu->buffer),232 etnaviv_gpu_start_fe(gpu, (u32)etnaviv_cmdbuf_get_pa(gpu->buffer),
259 prefetch);233 prefetch);
260 etnaviv_gpu_wait_idle(gpu, 100);234 etnaviv_gpu_wait_idle(gpu, 100);
261 235
262 gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);236 gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);
263}237}
264struct iommu_domain *etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu)238
239const struct etnaviv_iommu_domain_ops etnaviv_iommuv2_ops = {
240 .free = etnaviv_iommuv2_domain_free,
241 .map = etnaviv_iommuv2_map,
242 .unmap = etnaviv_iommuv2_unmap,
243 .dump_size = etnaviv_iommuv2_dump_size,
244 .dump = etnaviv_iommuv2_dump,
245};
246
247struct etnaviv_iommu_domain *
248etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu)
265{249{
266 struct etnaviv_iommuv2_domain *etnaviv_domain;250 struct etnaviv_iommuv2_domain *etnaviv_domain;
251 struct etnaviv_iommu_domain *domain;
267 int ret;252 int ret;
268 253
269 etnaviv_domain = vzalloc(sizeof(*etnaviv_domain));254 etnaviv_domain = vzalloc(sizeof(*etnaviv_domain));
270 if (!etnaviv_domain)255 if (!etnaviv_domain)
271 return NULL;256 return NULL;
272 257
273 etnaviv_domain->dev = gpu->dev;258 domain = &etnaviv_domain->base;
274 259
275 etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING;260 domain->dev = gpu->dev;
276 etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops;261 domain->base = 0;
277 etnaviv_domain->domain.pgsize_bitmap = SZ_4K;262 domain->size = (u64)SZ_1G * 4;
278 etnaviv_domain->domain.geometry.aperture_start = 0;263 domain->ops = &etnaviv_iommuv2_ops;
279 etnaviv_domain->domain.geometry.aperture_end = ~0UL & ~(SZ_4K - 1);
280 264
281 ret = etnaviv_iommuv2_init(etnaviv_domain);265 ret = etnaviv_iommuv2_init(etnaviv_domain);
282 if (ret)266 if (ret)
283 goto out_free;267 goto out_free;
284 268
285 return &etnaviv_domain->domain;269 return &etnaviv_domain->base;
286 270
287out_free:271out_free:
288 vfree(etnaviv_domain);272 vfree(etnaviv_domain);
drivers/gpu/drm/etnaviv/etnaviv_mmu.c+68−38
@@ -22,17 +22,64 @@ · 21 unmodified lines
22#include "etnaviv_iommu.h"22#include "etnaviv_iommu.h"
23#include "etnaviv_mmu.h"23#include "etnaviv_mmu.h"
24 24
25static int etnaviv_fault_handler(struct iommu_domain *iommu, struct device *dev,25static void etnaviv_domain_unmap(struct etnaviv_iommu_domain *domain,
26 unsigned long iova, int flags, void *arg)26 unsigned long iova, size_t size)
27{27{
28 DBG("*** fault: iova=%08lx, flags=%d", iova, flags);28 size_t unmapped_page, unmapped = 0;
29 return 0;29 size_t pgsize = SZ_4K;
30
31 if (!IS_ALIGNED(iova | size, pgsize)) {
32 pr_err("unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n",
33 iova, size, pgsize);
34 return;
35 }
36
37 while (unmapped < size) {
38 unmapped_page = domain->ops->unmap(domain, iova, pgsize);
39 if (!unmapped_page)
40 break;
41
42 iova += unmapped_page;
43 unmapped += unmapped_page;
44 }
30}45}
31 46
32int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova,47static int etnaviv_domain_map(struct etnaviv_iommu_domain *domain,
33 struct sg_table *sgt, unsigned len, int prot)48 unsigned long iova, phys_addr_t paddr,
49 size_t size, int prot)
34{50{
35 struct iommu_domain *domain = iommu->domain;51 unsigned long orig_iova = iova;
52 size_t pgsize = SZ_4K;
53 size_t orig_size = size;
54 int ret = 0;
55
56 if (!IS_ALIGNED(iova | paddr | size, pgsize)) {
57 pr_err("unaligned: iova 0x%lx pa %pa size 0x%zx min_pagesz 0x%x\n",
58 iova, &paddr, size, pgsize);
59 return -EINVAL;
60 }
61
62 while (size) {
63 ret = domain->ops->map(domain, iova, paddr, pgsize, prot);
64 if (ret)
65 break;
66
67 iova += pgsize;
68 paddr += pgsize;
69 size -= pgsize;
70 }
71
72 /* unroll mapping in case something went wrong */
73 if (ret)
74 etnaviv_domain_unmap(domain, orig_iova, orig_size - size);
75
76 return ret;
77}
78
79static int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova,
80 struct sg_table *sgt, unsigned len, int prot)
81{
82 struct etnaviv_iommu_domain *domain = iommu->domain;
36 struct scatterlist *sg;83 struct scatterlist *sg;
37 unsigned int da = iova;84 unsigned int da = iova;
38 unsigned int i, j;85 unsigned int i, j;
@@ -47,7 +94,7 @@ int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, · 8 unmodified lines
47 94
48 VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);95 VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
49 96
50 ret = iommu_map(domain, da, pa, bytes, prot);97 ret = etnaviv_domain_map(domain, da, pa, bytes, prot);
51 if (ret)98 if (ret)
52 goto fail;99 goto fail;
53 100
@@ -62,27 +109,24 @@ fail: · 8 unmodified lines
62 for_each_sg(sgt->sgl, sg, i, j) {109 for_each_sg(sgt->sgl, sg, i, j) {
63 size_t bytes = sg_dma_len(sg) + sg->offset;110 size_t bytes = sg_dma_len(sg) + sg->offset;
64 111
65 iommu_unmap(domain, da, bytes);112 etnaviv_domain_unmap(domain, da, bytes);
66 da += bytes;113 da += bytes;
67 }114 }
68 return ret;115 return ret;
69}116}
70 117
71int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova,118static void etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova,
72 struct sg_table *sgt, unsigned len)119 struct sg_table *sgt, unsigned len)
73{120{
74 struct iommu_domain *domain = iommu->domain;121 struct etnaviv_iommu_domain *domain = iommu->domain;
75 struct scatterlist *sg;122 struct scatterlist *sg;
76 unsigned int da = iova;123 unsigned int da = iova;
77 int i;124 int i;
78 125
79 for_each_sg(sgt->sgl, sg, sgt->nents, i) {126 for_each_sg(sgt->sgl, sg, sgt->nents, i) {
80 size_t bytes = sg_dma_len(sg) + sg->offset;127 size_t bytes = sg_dma_len(sg) + sg->offset;
81 size_t unmapped;
82 128
83 unmapped = iommu_unmap(domain, da, bytes);129 etnaviv_domain_unmap(domain, da, bytes);
84 if (unmapped < bytes)
85 return unmapped;
86 130
87 VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);131 VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);
88 132
@@ -90,8 +134,6 @@ int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, · 1 unmodified line
90 134
91 da += bytes;135 da += bytes;
92 }136 }
93
94 return 0;
95}137}
96 138
97static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu *mmu,139static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu *mmu,
@@ -237,7 +279,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu, · 139 unmodified lines
237 mmu->last_iova = node->start + etnaviv_obj->base.size;279 mmu->last_iova = node->start + etnaviv_obj->base.size;
238 mapping->iova = node->start;280 mapping->iova = node->start;
239 ret = etnaviv_iommu_map(mmu, node->start, sgt, etnaviv_obj->base.size,281 ret = etnaviv_iommu_map(mmu, node->start, sgt, etnaviv_obj->base.size,
240 IOMMU_READ | IOMMU_WRITE);282 ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE);
241 283
242 if (ret < 0) {284 if (ret < 0) {
243 drm_mm_remove_node(node);285 drm_mm_remove_node(node);
@@ -271,7 +313,7 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu, · 27 unmodified lines
271void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu)313void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu)
272{314{
273 drm_mm_takedown(&mmu->mm);315 drm_mm_takedown(&mmu->mm);
274 iommu_domain_free(mmu->domain);316 mmu->domain->ops->free(mmu->domain);
275 kfree(mmu);317 kfree(mmu);
276}318}
277 319
@@ -303,11 +345,7 @@ struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu) · 25 unmodified lines
303 mutex_init(&mmu->lock);345 mutex_init(&mmu->lock);
304 INIT_LIST_HEAD(&mmu->mappings);346 INIT_LIST_HEAD(&mmu->mappings);
305 347
306 drm_mm_init(&mmu->mm, mmu->domain->geometry.aperture_start,348 drm_mm_init(&mmu->mm, mmu->domain->base, mmu->domain->size);
307 mmu->domain->geometry.aperture_end -
308 mmu->domain->geometry.aperture_start + 1);
309
310 iommu_set_fault_handler(mmu->domain, etnaviv_fault_handler, gpu->dev);
311 349
312 return mmu;350 return mmu;
313}351}
@@ -338,8 +376,8 @@ int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr, · 24 unmodified lines
338 mutex_unlock(&mmu->lock);376 mutex_unlock(&mmu->lock);
339 return ret;377 return ret;
340 }378 }
341 ret = iommu_map(mmu->domain, vram_node->start, paddr, size,379 ret = etnaviv_domain_map(mmu->domain, vram_node->start, paddr,
342 IOMMU_READ);380 size, ETNAVIV_PROT_READ);
343 if (ret < 0) {381 if (ret < 0) {
344 drm_mm_remove_node(vram_node);382 drm_mm_remove_node(vram_node);
345 mutex_unlock(&mmu->lock);383 mutex_unlock(&mmu->lock);
@@ -362,25 +400,17 @@ void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu, · 16 unmodified lines
362 400
363 if (mmu->version == ETNAVIV_IOMMU_V2) {401 if (mmu->version == ETNAVIV_IOMMU_V2) {
364 mutex_lock(&mmu->lock);402 mutex_lock(&mmu->lock);
365 iommu_unmap(mmu->domain,iova, size);403 etnaviv_domain_unmap(mmu->domain, iova, size);
366 drm_mm_remove_node(vram_node);404 drm_mm_remove_node(vram_node);
367 mutex_unlock(&mmu->lock);405 mutex_unlock(&mmu->lock);
368 }406 }
369}407}
370size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu)408size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu)
371{409{
372 struct etnaviv_iommu_ops *ops;410 return iommu->domain->ops->dump_size(iommu->domain);
373
374 ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops);
375
376 return ops->dump_size(iommu->domain);
377}411}
378 412
379void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf)413void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf)
380{414{
381 struct etnaviv_iommu_ops *ops;415 iommu->domain->ops->dump(iommu->domain, buf);
382
383 ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops);
384
385 ops->dump(iommu->domain, buf);
386}416}
drivers/gpu/drm/etnaviv/etnaviv_mmu.h+23−13
@@ -17,7 +17,8 @@ · 16 unmodified lines
17#ifndef __ETNAVIV_MMU_H__17#ifndef __ETNAVIV_MMU_H__
18#define __ETNAVIV_MMU_H__18#define __ETNAVIV_MMU_H__
19 19
20#include <linux/iommu.h>20#define ETNAVIV_PROT_READ (1 << 0)
21#define ETNAVIV_PROT_WRITE (1 << 1)
21 22
22enum etnaviv_iommu_version {23enum etnaviv_iommu_version {
23 ETNAVIV_IOMMU_V1 = 0,24 ETNAVIV_IOMMU_V1 = 0,
@@ -26,16 +27,31 @@ enum etnaviv_iommu_version { · 2 unmodified lines
26 27
27struct etnaviv_gpu;28struct etnaviv_gpu;
28struct etnaviv_vram_mapping;29struct etnaviv_vram_mapping;
30struct etnaviv_iommu_domain;
29 31
30struct etnaviv_iommu_ops {32struct etnaviv_iommu_domain_ops {
31 struct iommu_ops ops;33 void (*free)(struct etnaviv_iommu_domain *);
32 size_t (*dump_size)(struct iommu_domain *);34 int (*map)(struct etnaviv_iommu_domain *domain, unsigned long iova,
33 void (*dump)(struct iommu_domain *, void *);35 phys_addr_t paddr, size_t size, int prot);
36 size_t (*unmap)(struct etnaviv_iommu_domain *domain, unsigned long iova,
37 size_t size);
38 size_t (*dump_size)(struct etnaviv_iommu_domain *);
39 void (*dump)(struct etnaviv_iommu_domain *, void *);
40};
41
42struct etnaviv_iommu_domain {
43 struct device *dev;
44 void *bad_page_cpu;
45 dma_addr_t bad_page_dma;
46 u64 base;
47 u64 size;
48
49 const struct etnaviv_iommu_domain_ops *ops;
34};50};
35 51
36struct etnaviv_iommu {52struct etnaviv_iommu {
37 struct etnaviv_gpu *gpu;53 struct etnaviv_gpu *gpu;
38 struct iommu_domain *domain;54 struct etnaviv_iommu_domain *domain;
39 55
40 enum etnaviv_iommu_version version;56 enum etnaviv_iommu_version version;
41 57
@@ -49,18 +65,11 @@ struct etnaviv_iommu { · 7 unmodified lines
49 65
50struct etnaviv_gem_object;66struct etnaviv_gem_object;
51 67
52int etnaviv_iommu_attach(struct etnaviv_iommu *iommu, const char **names,
53 int cnt);
54int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova,
55 struct sg_table *sgt, unsigned len, int prot);
56int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova,
57 struct sg_table *sgt, unsigned len);
58int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,68int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
59 struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,69 struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,
60 struct etnaviv_vram_mapping *mapping);70 struct etnaviv_vram_mapping *mapping);
61void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,71void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
62 struct etnaviv_vram_mapping *mapping);72 struct etnaviv_vram_mapping *mapping);
63void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);
64 73
65int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr,74int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr,
66 struct drm_mm_node *vram_node, size_t size,75 struct drm_mm_node *vram_node, size_t size,
@@ -73,6 +82,7 @@ size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu); · 6 unmodified lines
73void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf);82void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf);
74 83
75struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu);84struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu);
85void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);
76void etnaviv_iommu_restore(struct etnaviv_gpu *gpu);86void etnaviv_iommu_restore(struct etnaviv_gpu *gpu);
77 87
78#endif /* __ETNAVIV_MMU_H__ */88#endif /* __ETNAVIV_MMU_H__ */
drivers/gpu/drm/etnaviv/etnaviv_perfmon.c+495−0
@@ -0,0 +1,495 @@
1/*
2 * Copyright (C) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "etnaviv_gpu.h"
19#include "etnaviv_perfmon.h"
20#include "state_hi.xml.h"
21
22struct etnaviv_pm_domain;
23
24struct etnaviv_pm_signal {
25 char name[64];
26 u32 data;
27
28 u32 (*sample)(struct etnaviv_gpu *gpu,
29 const struct etnaviv_pm_domain *domain,
30 const struct etnaviv_pm_signal *signal);
31};
32
33struct etnaviv_pm_domain {
34 char name[64];
35
36 /* profile register */
37 u32 profile_read;
38 u32 profile_config;
39
40 u8 nr_signals;
41 const struct etnaviv_pm_signal *signal;
42};
43
44struct etnaviv_pm_domain_meta {
45 const struct etnaviv_pm_domain *domains;
46 u32 nr_domains;
47};
48
49static u32 simple_reg_read(struct etnaviv_gpu *gpu,
50 const struct etnaviv_pm_domain *domain,
51 const struct etnaviv_pm_signal *signal)
52{
53 return gpu_read(gpu, signal->data);
54}
55
56static u32 perf_reg_read(struct etnaviv_gpu *gpu,
57 const struct etnaviv_pm_domain *domain,
58 const struct etnaviv_pm_signal *signal)
59{
60 gpu_write(gpu, domain->profile_config, signal->data);
61
62 return gpu_read(gpu, domain->profile_read);
63}
64
65static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
66 const struct etnaviv_pm_domain *domain,
67 const struct etnaviv_pm_signal *signal)
68{
69 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
70 u32 value = 0;
71 unsigned i;
72
73 for (i = 0; i < gpu->identity.pixel_pipes; i++) {
74 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
75 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(i);
76 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
77 gpu_write(gpu, domain->profile_config, signal->data);
78 value += gpu_read(gpu, domain->profile_read);
79 }
80
81 /* switch back to pixel pipe 0 to prevent GPU hang */
82 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
83 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(0);
84 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
85
86 return value;
87}
88
89static const struct etnaviv_pm_domain doms_3d[] = {
90 {
91 .name = "HI",
92 .profile_read = VIVS_MC_PROFILE_HI_READ,
93 .profile_config = VIVS_MC_PROFILE_CONFIG2,
94 .nr_signals = 5,
95 .signal = (const struct etnaviv_pm_signal[]) {
96 {
97 "TOTAL_CYCLES",
98 VIVS_HI_PROFILE_TOTAL_CYCLES,
99 &simple_reg_read
100 },
101 {
102 "IDLE_CYCLES",
103 VIVS_HI_PROFILE_IDLE_CYCLES,
104 &simple_reg_read
105 },
106 {
107 "AXI_CYCLES_READ_REQUEST_STALLED",
108 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
109 &perf_reg_read
110 },
111 {
112 "AXI_CYCLES_WRITE_REQUEST_STALLED",
113 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
114 &perf_reg_read
115 },
116 {
117 "AXI_CYCLES_WRITE_DATA_STALLED",
118 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
119 &perf_reg_read
120 }
121 }
122 },
123 {
124 .name = "PE",
125 .profile_read = VIVS_MC_PROFILE_PE_READ,
126 .profile_config = VIVS_MC_PROFILE_CONFIG0,
127 .nr_signals = 5,
128 .signal = (const struct etnaviv_pm_signal[]) {
129 {
130 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
131 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
132 &pipe_reg_read
133 },
134 {
135 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
136 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
137 &pipe_reg_read
138 },
139 {
140 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
141 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
142 &pipe_reg_read
143 },
144 {
145 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
146 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
147 &pipe_reg_read
148 }
149 }
150 },
151 {
152 .name = "SH",
153 .profile_read = VIVS_MC_PROFILE_SH_READ,
154 .profile_config = VIVS_MC_PROFILE_CONFIG0,
155 .nr_signals = 9,
156 .signal = (const struct etnaviv_pm_signal[]) {
157 {
158 "SHADER_CYCLES",
159 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
160 &perf_reg_read
161 },
162 {
163 "PS_INST_COUNTER",
164 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
165 &perf_reg_read
166 },
167 {
168 "RENDERED_PIXEL_COUNTER",
169 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
170 &perf_reg_read
171 },
172 {
173 "VS_INST_COUNTER",
174 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
175 &pipe_reg_read
176 },
177 {
178 "RENDERED_VERTICE_COUNTER",
179 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
180 &pipe_reg_read
181 },
182 {
183 "VTX_BRANCH_INST_COUNTER",
184 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
185 &pipe_reg_read
186 },
187 {
188 "VTX_TEXLD_INST_COUNTER",
189 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
190 &pipe_reg_read
191 },
192 {
193 "PXL_BRANCH_INST_COUNTER",
194 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
195 &pipe_reg_read
196 },
197 {
198 "PXL_TEXLD_INST_COUNTER",
199 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
200 &pipe_reg_read
201 }
202 }
203 },
204 {
205 .name = "PA",
206 .profile_read = VIVS_MC_PROFILE_PA_READ,
207 .profile_config = VIVS_MC_PROFILE_CONFIG1,
208 .nr_signals = 6,
209 .signal = (const struct etnaviv_pm_signal[]) {
210 {
211 "INPUT_VTX_COUNTER",
212 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
213 &perf_reg_read
214 },
215 {
216 "INPUT_PRIM_COUNTER",
217 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
218 &perf_reg_read
219 },
220 {
221 "OUTPUT_PRIM_COUNTER",
222 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
223 &perf_reg_read
224 },
225 {
226 "DEPTH_CLIPPED_COUNTER",
227 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
228 &pipe_reg_read
229 },
230 {
231 "TRIVIAL_REJECTED_COUNTER",
232 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
233 &pipe_reg_read
234 },
235 {
236 "CULLED_COUNTER",
237 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
238 &pipe_reg_read
239 }
240 }
241 },
242 {
243 .name = "SE",
244 .profile_read = VIVS_MC_PROFILE_SE_READ,
245 .profile_config = VIVS_MC_PROFILE_CONFIG1,
246 .nr_signals = 2,
247 .signal = (const struct etnaviv_pm_signal[]) {
248 {
249 "CULLED_TRIANGLE_COUNT",
250 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
251 &perf_reg_read
252 },
253 {
254 "CULLED_LINES_COUNT",
255 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
256 &perf_reg_read
257 }
258 }
259 },
260 {
261 .name = "RA",
262 .profile_read = VIVS_MC_PROFILE_RA_READ,
263 .profile_config = VIVS_MC_PROFILE_CONFIG1,
264 .nr_signals = 7,
265 .signal = (const struct etnaviv_pm_signal[]) {
266 {
267 "VALID_PIXEL_COUNT",
268 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
269 &perf_reg_read
270 },
271 {
272 "TOTAL_QUAD_COUNT",
273 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
274 &perf_reg_read
275 },
276 {
277 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
278 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
279 &perf_reg_read
280 },
281 {
282 "TOTAL_PRIMITIVE_COUNT",
283 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
284 &perf_reg_read
285 },
286 {
287 "PIPE_CACHE_MISS_COUNTER",
288 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
289 &perf_reg_read
290 },
291 {
292 "PREFETCH_CACHE_MISS_COUNTER",
293 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
294 &perf_reg_read
295 },
296 {
297 "CULLED_QUAD_COUNT",
298 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
299 &perf_reg_read
300 }
301 }
302 },
303 {
304 .name = "TX",
305 .profile_read = VIVS_MC_PROFILE_TX_READ,
306 .profile_config = VIVS_MC_PROFILE_CONFIG1,
307 .nr_signals = 9,
308 .signal = (const struct etnaviv_pm_signal[]) {
309 {
310 "TOTAL_BILINEAR_REQUESTS",
311 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
312 &perf_reg_read
313 },
314 {
315 "TOTAL_TRILINEAR_REQUESTS",
316 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
317 &perf_reg_read
318 },
319 {
320 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
321 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
322 &perf_reg_read
323 },
324 {
325 "TOTAL_TEXTURE_REQUESTS",
326 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
327 &perf_reg_read
328 },
329 {
330 "MEM_READ_COUNT",
331 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
332 &perf_reg_read
333 },
334 {
335 "MEM_READ_IN_8B_COUNT",
336 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
337 &perf_reg_read
338 },
339 {
340 "CACHE_MISS_COUNT",
341 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
342 &perf_reg_read
343 },
344 {
345 "CACHE_HIT_TEXEL_COUNT",
346 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
347 &perf_reg_read
348 },
349 {
350 "CACHE_MISS_TEXEL_COUNT",
351 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
352 &perf_reg_read
353 }
354 }
355 },
356 {
357 .name = "MC",
358 .profile_read = VIVS_MC_PROFILE_MC_READ,
359 .profile_config = VIVS_MC_PROFILE_CONFIG2,
360 .nr_signals = 3,
361 .signal = (const struct etnaviv_pm_signal[]) {
362 {
363 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
364 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
365 &perf_reg_read
366 },
367 {
368 "TOTAL_READ_REQ_8B_FROM_IP",
369 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
370 &perf_reg_read
371 },
372 {
373 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
374 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
375 &perf_reg_read
376 }
377 }
378 }
379};
380
381static const struct etnaviv_pm_domain doms_2d[] = {
382 {
383 .name = "PE",
384 .profile_read = VIVS_MC_PROFILE_PE_READ,
385 .profile_config = VIVS_MC_PROFILE_CONFIG0,
386 .nr_signals = 1,
387 .signal = (const struct etnaviv_pm_signal[]) {
388 {
389 "PIXELS_RENDERED_2D",
390 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
391 &pipe_reg_read
392 }
393 }
394 }
395};
396
397static const struct etnaviv_pm_domain doms_vg[] = {
398};
399
400static const struct etnaviv_pm_domain_meta doms_meta[] = {
401 {
402 .nr_domains = ARRAY_SIZE(doms_3d),
403 .domains = &doms_3d[0]
404 },
405 {
406 .nr_domains = ARRAY_SIZE(doms_2d),
407 .domains = &doms_2d[0]
408 },
409 {
410 .nr_domains = ARRAY_SIZE(doms_vg),
411 .domains = &doms_vg[0]
412 }
413};
414
415int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
416 struct drm_etnaviv_pm_domain *domain)
417{
418 const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe];
419 const struct etnaviv_pm_domain *dom;
420
421 if (domain->iter >= meta->nr_domains)
422 return -EINVAL;
423
424 dom = meta->domains + domain->iter;
425
426 domain->id = domain->iter;
427 domain->nr_signals = dom->nr_signals;
428 strncpy(domain->name, dom->name, sizeof(domain->name));
429
430 domain->iter++;
431 if (domain->iter == meta->nr_domains)
432 domain->iter = 0xff;
433
434 return 0;
435}
436
437int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
438 struct drm_etnaviv_pm_signal *signal)
439{
440 const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe];
441 const struct etnaviv_pm_domain *dom;
442 const struct etnaviv_pm_signal *sig;
443
444 if (signal->domain >= meta->nr_domains)
445 return -EINVAL;
446
447 dom = meta->domains + signal->domain;
448
449 if (signal->iter > dom->nr_signals)
450 return -EINVAL;
451
452 sig = &dom->signal[signal->iter];
453
454 signal->id = signal->iter;
455 strncpy(signal->name, sig->name, sizeof(signal->name));
456
457 signal->iter++;
458 if (signal->iter == dom->nr_signals)
459 signal->iter = 0xffff;
460
461 return 0;
462}
463
464int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
465 u32 exec_state)
466{
467 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
468 const struct etnaviv_pm_domain *dom;
469
470 if (r->domain >= meta->nr_domains)
471 return -EINVAL;
472
473 dom = meta->domains + r->domain;
474
475 if (r->signal > dom->nr_signals)
476 return -EINVAL;
477
478 return 0;
479}
480
481void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
482 const struct etnaviv_perfmon_request *pmr)
483{
484 const struct etnaviv_pm_domain_meta *meta = &doms_meta[gpu->exec_state];
485 const struct etnaviv_pm_domain *dom;
486 const struct etnaviv_pm_signal *sig;
487 u32 *bo = pmr->bo_vma;
488 u32 val;
489
490 dom = meta->domains + pmr->domain;
491 sig = &dom->signal[pmr->signal];
492 val = sig->sample(gpu, dom, sig);
493
494 *(bo + pmr->offset) = val;
495}
drivers/gpu/drm/etnaviv/etnaviv_perfmon.h+49−0
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __ETNAVIV_PERFMON_H__
19#define __ETNAVIV_PERFMON_H__
20
21struct etnaviv_gpu;
22struct drm_etnaviv_pm_domain;
23struct drm_etnaviv_pm_signal;
24
25struct etnaviv_perfmon_request
26{
27 u32 flags;
28 u8 domain;
29 u8 signal;
30 u32 sequence;
31
32 /* bo to store a value */
33 u32 *bo_vma;
34 u32 offset;
35};
36
37int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
38 struct drm_etnaviv_pm_domain *domain);
39
40int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
41 struct drm_etnaviv_pm_signal *signal);
42
43int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
44 u32 exec_state);
45
46void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
47 const struct etnaviv_perfmon_request *pmr);
48
49#endif /* __ETNAVIV_PERFMON_H__ */
include/uapi/drm/etnaviv_drm.h+42−1
@@ -150,6 +150,19 @@ struct drm_etnaviv_gem_submit_bo { · 149 unmodified lines
150 __u64 presumed; /* in/out, presumed buffer address */150 __u64 presumed; /* in/out, presumed buffer address */
151};151};
152 152
153/* performance monitor request (pmr) */
154#define ETNA_PM_PROCESS_PRE 0x0001
155#define ETNA_PM_PROCESS_POST 0x0002
156struct drm_etnaviv_gem_submit_pmr {
157 __u32 flags; /* in, when to process request (ETNA_PM_PROCESS_x) */
158 __u8 domain; /* in, pm domain */
159 __u8 pad;
160 __u16 signal; /* in, pm signal */
161 __u32 sequence; /* in, sequence number */
162 __u32 read_offset; /* in, offset from read_bo */
163 __u32 read_idx; /* in, index of read_bo buffer */
164};
165
153/* Each cmdstream submit consists of a table of buffers involved, and166/* Each cmdstream submit consists of a table of buffers involved, and
154 * one or more cmdstream buffers. This allows for conditional execution167 * one or more cmdstream buffers. This allows for conditional execution
155 * (context-restore), and IB buffers needed for per tile/bin draw cmds.168 * (context-restore), and IB buffers needed for per tile/bin draw cmds.
@@ -175,6 +188,9 @@ struct drm_etnaviv_gem_submit { · 19 unmodified lines
175 __u64 stream; /* in, ptr to cmdstream */188 __u64 stream; /* in, ptr to cmdstream */
176 __u32 flags; /* in, mask of ETNA_SUBMIT_x */189 __u32 flags; /* in, mask of ETNA_SUBMIT_x */
177 __s32 fence_fd; /* in/out, fence fd (see ETNA_SUBMIT_FENCE_FD_x) */190 __s32 fence_fd; /* in/out, fence fd (see ETNA_SUBMIT_FENCE_FD_x) */
191 __u64 pmrs; /* in, ptr to array of submit_pmr's */
192 __u32 nr_pmrs; /* in, number of submit_pmr's */
193 __u32 pad;
178};194};
179 195
180/* The normal way to synchronize with the GPU is just to CPU_PREP on196/* The normal way to synchronize with the GPU is just to CPU_PREP on
@@ -210,6 +226,27 @@ struct drm_etnaviv_gem_wait { · 29 unmodified lines
210 struct drm_etnaviv_timespec timeout; /* in */226 struct drm_etnaviv_timespec timeout; /* in */
211};227};
212 228
229/*
230 * Performance Monitor (PM):
231 */
232
233struct drm_etnaviv_pm_domain {
234 __u32 pipe; /* in */
235 __u8 iter; /* in/out, select pm domain at index iter */
236 __u8 id; /* out, id of domain */
237 __u16 nr_signals; /* out, how many signals does this domain provide */
238 char name[64]; /* out, name of domain */
239};
240
241struct drm_etnaviv_pm_signal {
242 __u32 pipe; /* in */
243 __u8 domain; /* in, pm domain index */
244 __u8 pad;
245 __u16 iter; /* in/out, select pm source at index iter */
246 __u16 id; /* out, id of signal */
247 char name[64]; /* out, name of domain */
248};
249
213#define DRM_ETNAVIV_GET_PARAM 0x00250#define DRM_ETNAVIV_GET_PARAM 0x00
214/* placeholder:251/* placeholder:
215#define DRM_ETNAVIV_SET_PARAM 0x01252#define DRM_ETNAVIV_SET_PARAM 0x01
@@ -222,7 +259,9 @@ struct drm_etnaviv_gem_wait { · 6 unmodified lines
222#define DRM_ETNAVIV_WAIT_FENCE 0x07259#define DRM_ETNAVIV_WAIT_FENCE 0x07
223#define DRM_ETNAVIV_GEM_USERPTR 0x08260#define DRM_ETNAVIV_GEM_USERPTR 0x08
224#define DRM_ETNAVIV_GEM_WAIT 0x09261#define DRM_ETNAVIV_GEM_WAIT 0x09
225#define DRM_ETNAVIV_NUM_IOCTLS 0x0a262#define DRM_ETNAVIV_PM_QUERY_DOM 0x0a
263#define DRM_ETNAVIV_PM_QUERY_SIG 0x0b
264#define DRM_ETNAVIV_NUM_IOCTLS 0x0c
226 265
227#define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)266#define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
228#define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)267#define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
@@ -233,6 +272,8 @@ struct drm_etnaviv_gem_wait { · 4 unmodified lines
233#define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)272#define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
234#define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)273#define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)
235#define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)274#define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
275#define DRM_IOCTL_ETNAVIV_PM_QUERY_DOM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_DOM, struct drm_etnaviv_pm_domain)
276#define DRM_IOCTL_ETNAVIV_PM_QUERY_SIG DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_SIG, struct drm_etnaviv_pm_signal)
236 277
237#if defined(__cplusplus)278#if defined(__cplusplus)
238}279}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t