Skip to content

Commit

Permalink
Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux
Browse files Browse the repository at this point in the history
… 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
  ...
  • Loading branch information
Dave Airlie committed Oct 13, 2017
2 parents 972805c + 8272170 commit 787e1b7
Show file tree
Hide file tree
Showing 19 changed files with 1,148 additions and 330 deletions.
2 changes: 0 additions & 2 deletions drivers/gpu/drm/etnaviv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ config DRM_ETNAVIV
select SHMEM
select SYNC_FILE
select TMPFS
select IOMMU_API
select IOMMU_SUPPORT
select WANT_DEV_COREDUMP
select CMA if HAVE_DMA_CONTIGUOUS
select DMA_CMA if HAVE_DMA_CONTIGUOUS
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/etnaviv/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ etnaviv-y := \
etnaviv_gpu.o \
etnaviv_iommu_v2.o \
etnaviv_iommu.o \
etnaviv_mmu.o
etnaviv_mmu.o \
etnaviv_perfmon.o

obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o
36 changes: 36 additions & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,42 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
}
}

/* Append a 'sync point' to the ring buffer. */
void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event)
{
struct etnaviv_cmdbuf *buffer = gpu->buffer;
unsigned int waitlink_offset = buffer->user_size - 16;
u32 dwords, target;

/*
* We need at most 3 dwords in the return target:
* 1 event + 1 end + 1 wait + 1 link.
*/
dwords = 4;
target = etnaviv_buffer_reserve(gpu, buffer, dwords);

/* Signal sync point event */
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
VIVS_GL_EVENT_FROM_PE);

/* Stop the FE to 'pause' the GPU */
CMD_END(buffer);

/* Append waitlink */
CMD_WAIT(buffer);
CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
buffer->user_size - 4);

/*
* Kick off the 'sync point' command by replacing the previous
* WAIT with a link to the address in the ring buffer.
*/
etnaviv_buffer_replace_wait(buffer, waitlink_offset,
VIV_FE_LINK_HEADER_OP_LINK |
VIV_FE_LINK_HEADER_PREFETCH(dwords),
target);
}

/* Append a command buffer to the ring buffer. */
void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
struct etnaviv_cmdbuf *cmdbuf)
Expand Down
15 changes: 14 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "etnaviv_cmdbuf.h"
#include "etnaviv_gpu.h"
#include "etnaviv_mmu.h"
#include "etnaviv_perfmon.h"

#define SUBALLOC_SIZE SZ_256K
#define SUBALLOC_GRANULE SZ_4K
Expand Down Expand Up @@ -87,9 +88,10 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)

struct etnaviv_cmdbuf *
etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
size_t nr_bos)
size_t nr_bos, size_t nr_pmrs)
{
struct etnaviv_cmdbuf *cmdbuf;
struct etnaviv_perfmon_request *pmrs;
size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),
sizeof(*cmdbuf));
int granule_offs, order, ret;
Expand All @@ -98,6 +100,12 @@ etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
if (!cmdbuf)
return NULL;

sz = sizeof(*pmrs) * nr_pmrs;
pmrs = kzalloc(sz, GFP_KERNEL);
if (!pmrs)
goto out_free_cmdbuf;

cmdbuf->pmrs = pmrs;
cmdbuf->suballoc = suballoc;
cmdbuf->size = size;

Expand All @@ -124,6 +132,10 @@ etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset;

return cmdbuf;

out_free_cmdbuf:
kfree(cmdbuf);
return NULL;
}

void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
Expand All @@ -139,6 +151,7 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
suballoc->free_space = 1;
mutex_unlock(&suballoc->lock);
wake_up_all(&suballoc->free_event);
kfree(cmdbuf->pmrs);
kfree(cmdbuf);
}

Expand Down
6 changes: 5 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

struct etnaviv_gpu;
struct etnaviv_cmdbuf_suballoc;
struct etnaviv_perfmon_request;

struct etnaviv_cmdbuf {
/* suballocator this cmdbuf is allocated from */
Expand All @@ -38,6 +39,9 @@ struct etnaviv_cmdbuf {
u32 exec_state;
/* per GPU in-flight list */
struct list_head node;
/* perfmon requests */
unsigned int nr_pmrs;
struct etnaviv_perfmon_request *pmrs;
/* BOs attached to this command buffer */
unsigned int nr_bos;
struct etnaviv_vram_mapping *bo_map[0];
Expand All @@ -49,7 +53,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);

struct etnaviv_cmdbuf *
etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
size_t nr_bos);
size_t nr_bos, size_t nr_pmrs);
void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);

u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);
Expand Down
39 changes: 38 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
#include "etnaviv_perfmon.h"

#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
static bool reglog;
Expand Down Expand Up @@ -451,6 +452,40 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data,
return ret;
}

static int etnaviv_ioctl_pm_query_dom(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct etnaviv_drm_private *priv = dev->dev_private;
struct drm_etnaviv_pm_domain *args = data;
struct etnaviv_gpu *gpu;

if (args->pipe >= ETNA_MAX_PIPES)
return -EINVAL;

gpu = priv->gpu[args->pipe];
if (!gpu)
return -ENXIO;

return etnaviv_pm_query_dom(gpu, args);
}

static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct etnaviv_drm_private *priv = dev->dev_private;
struct drm_etnaviv_pm_signal *args = data;
struct etnaviv_gpu *gpu;

if (args->pipe >= ETNA_MAX_PIPES)
return -EINVAL;

gpu = priv->gpu[args->pipe];
if (!gpu)
return -ENXIO;

return etnaviv_pm_query_sig(gpu, args);
}

static const struct drm_ioctl_desc etnaviv_ioctls[] = {
#define ETNA_IOCTL(n, func, flags) \
DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
Expand All @@ -463,6 +498,8 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW),
ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW),
ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW),
ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_AUTH|DRM_RENDER_ALLOW),
ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_AUTH|DRM_RENDER_ALLOW),
};

static const struct vm_operations_struct vm_ops = {
Expand Down Expand Up @@ -513,7 +550,7 @@ static struct drm_driver etnaviv_drm_driver = {
.desc = "etnaviv DRM",
.date = "20151214",
.major = 1,
.minor = 1,
.minor = 2,
};

/*
Expand Down
6 changes: 1 addition & 5 deletions drivers/gpu/drm/etnaviv/etnaviv_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/iommu.h>
#include <linux/types.h>
#include <linux/sizes.h>

Expand Down Expand Up @@ -92,15 +91,12 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj);
void etnaviv_gem_free_object(struct drm_gem_object *obj);
int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
u32 size, u32 flags, u32 *handle);
struct drm_gem_object *etnaviv_gem_new_locked(struct drm_device *dev,
u32 size, u32 flags);
struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
u32 size, u32 flags);
int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
uintptr_t ptr, u32 size, u32 flags, u32 *handle);
u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
u16 etnaviv_buffer_config_mmuv2(struct etnaviv_gpu *gpu, u32 mtlb_addr, u32 safe_addr);
void etnaviv_buffer_end(struct etnaviv_gpu *gpu);
void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event);
void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
struct etnaviv_cmdbuf *cmdbuf);
void etnaviv_validate_init(void);
Expand Down
19 changes: 0 additions & 19 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,25 +704,6 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
return ret;
}

struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
u32 size, u32 flags)
{
struct drm_gem_object *obj;
int ret;

obj = __etnaviv_gem_new(dev, size, flags);
if (IS_ERR(obj))
return obj;

ret = etnaviv_gem_obj_add(dev, obj);
if (ret < 0) {
drm_gem_object_put_unlocked(obj);
return ERR_PTR(ret);
}

return obj;
}

int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
struct etnaviv_gem_object **res)
Expand Down
69 changes: 67 additions & 2 deletions drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "etnaviv_drv.h"
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_perfmon.h"

/*
* Cmdstream submission:
Expand Down Expand Up @@ -283,6 +284,54 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream,
return 0;
}

static int submit_perfmon_validate(struct etnaviv_gem_submit *submit,
struct etnaviv_cmdbuf *cmdbuf,
const struct drm_etnaviv_gem_submit_pmr *pmrs,
u32 nr_pms)
{
u32 i;

for (i = 0; i < nr_pms; i++) {
const struct drm_etnaviv_gem_submit_pmr *r = pmrs + i;
struct etnaviv_gem_submit_bo *bo;
int ret;

ret = submit_bo(submit, r->read_idx, &bo);
if (ret)
return ret;

/* at offset 0 a sequence number gets stored used for userspace sync */
if (r->read_offset == 0) {
DRM_ERROR("perfmon request: offset is 0");
return -EINVAL;
}

if (r->read_offset >= bo->obj->base.size - sizeof(u32)) {
DRM_ERROR("perfmon request: offset %u outside object", i);
return -EINVAL;
}

if (r->flags & ~(ETNA_PM_PROCESS_PRE | ETNA_PM_PROCESS_POST)) {
DRM_ERROR("perfmon request: flags are not valid");
return -EINVAL;
}

if (etnaviv_pm_req_validate(r, cmdbuf->exec_state)) {
DRM_ERROR("perfmon request: domain or signal not valid");
return -EINVAL;
}

cmdbuf->pmrs[i].flags = r->flags;
cmdbuf->pmrs[i].domain = r->domain;
cmdbuf->pmrs[i].signal = r->signal;
cmdbuf->pmrs[i].sequence = r->sequence;
cmdbuf->pmrs[i].offset = r->read_offset;
cmdbuf->pmrs[i].bo_vma = etnaviv_gem_vmap(&bo->obj->base);
}

return 0;
}

static void submit_cleanup(struct etnaviv_gem_submit *submit)
{
unsigned i;
Expand All @@ -306,6 +355,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct etnaviv_drm_private *priv = dev->dev_private;
struct drm_etnaviv_gem_submit *args = data;
struct drm_etnaviv_gem_submit_reloc *relocs;
struct drm_etnaviv_gem_submit_pmr *pmrs;
struct drm_etnaviv_gem_submit_bo *bos;
struct etnaviv_gem_submit *submit;
struct etnaviv_cmdbuf *cmdbuf;
Expand Down Expand Up @@ -347,11 +397,12 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
*/
bos = kvmalloc_array(args->nr_bos, sizeof(*bos), GFP_KERNEL);
relocs = kvmalloc_array(args->nr_relocs, sizeof(*relocs), GFP_KERNEL);
pmrs = kvmalloc_array(args->nr_pmrs, sizeof(*pmrs), GFP_KERNEL);
stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL);
cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc,
ALIGN(args->stream_size, 8) + 8,
args->nr_bos);
if (!bos || !relocs || !stream || !cmdbuf) {
args->nr_bos, args->nr_pmrs);
if (!bos || !relocs || !pmrs || !stream || !cmdbuf) {
ret = -ENOMEM;
goto err_submit_cmds;
}
Expand All @@ -373,6 +424,14 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
goto err_submit_cmds;
}

ret = copy_from_user(pmrs, u64_to_user_ptr(args->pmrs),
args->nr_pmrs * sizeof(*pmrs));
if (ret) {
ret = -EFAULT;
goto err_submit_cmds;
}
cmdbuf->nr_pmrs = args->nr_pmrs;

ret = copy_from_user(stream, u64_to_user_ptr(args->stream),
args->stream_size);
if (ret) {
Expand Down Expand Up @@ -441,6 +500,10 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
if (ret)
goto out;

ret = submit_perfmon_validate(submit, cmdbuf, pmrs, args->nr_pmrs);
if (ret)
goto out;

memcpy(cmdbuf->vaddr, stream, args->stream_size);
cmdbuf->user_size = ALIGN(args->stream_size, 8);

Expand Down Expand Up @@ -496,6 +559,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
kvfree(bos);
if (relocs)
kvfree(relocs);
if (pmrs)
kvfree(pmrs);

return ret;
}
Loading

0 comments on commit 787e1b7

Please sign in to comment.