diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 31 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.h | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 7 |
5 files changed, 59 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 3065e8403559..0a48f6a551ae 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -3,7 +3,7 @@ * * GK20A Graphics channel * - * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -669,7 +669,7 @@ void gk20a_free_channel(struct channel_gk20a *ch, bool finish) memset(&ch->ramfc, 0, sizeof(struct mem_desc_sub)); /* free gpfifo */ - if (ch->gpfifo.gpu_va) + if (ch->vm && ch->gpfifo.gpu_va) gk20a_gmmu_unmap(ch_vm, ch->gpfifo.gpu_va, ch->gpfifo.size, gk20a_mem_flag_none); if (ch->gpfifo.cpu_va) @@ -698,8 +698,9 @@ unbind: channel_gk20a_unbind(ch); channel_gk20a_free_inst(g, ch); - ch->vpr = false; + gk20a_vm_put(ch->vm); /* Don't use VM after this. */ ch->vm = NULL; + ch->vpr = false; WARN_ON(ch->sync); /* unlink all debug sessions */ @@ -2066,6 +2067,18 @@ long gk20a_channel_ioctl(struct file *filp, (struct nvhost_alloc_obj_ctx_args *)buf); gk20a_idle(dev); break; + case NVHOST_IOCTL_CHANNEL_FREE_OBJ_CTX: + err = gk20a_busy(dev); + if (err) { + dev_err(&dev->dev, + "%s: failed to host gk20a for ioctl cmd: 0x%x", + __func__, cmd); + return err; + } + err = gk20a_free_obj_ctx(ch, + (struct nvhost_free_obj_ctx_args *)buf); + gk20a_idle(dev); + break; case NVHOST_IOCTL_CHANNEL_ALLOC_GPFIFO: err = gk20a_busy(dev); if (err) { diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 831db0f4986a..547bb064fd63 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -3,7 +3,7 @@ * * GK20A graphics channel * - * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -98,6 +98,7 @@ struct channel_gk20a { u64 userd_iova; u64 userd_gpu_va; + s32 num_objects; u32 obj_class; /* we support only one obj per channel */ struct priv_cmd_queue priv_cmd_q; diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index d5a3bbd34a78..db34cc0e85e9 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -1,7 +1,7 @@ /* * GK20A Graphics * - * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -26,6 +26,7 @@ #include <linux/dma-mapping.h> #include <linux/firmware.h> #include <linux/nvhost.h> +#include <asm/barrier.h> #include "gk20a.h" #include "kind_gk20a.h" @@ -2697,6 +2698,7 @@ void gk20a_free_channel_ctx(struct channel_gk20a *c) memset(&c->ch_ctx, 0, sizeof(struct channel_ctx_gk20a)); + c->num_objects = 0; c->first_init = false; } @@ -2847,6 +2849,8 @@ int gk20a_alloc_obj_ctx(struct channel_gk20a *c, c->first_init = true; } + c->num_objects++; + gk20a_dbg_fn("done"); return 0; out: @@ -2858,6 +2862,29 @@ out: return err; } +int gk20a_free_obj_ctx(struct channel_gk20a *c, + struct nvhost_free_obj_ctx_args *args) +{ + unsigned long timeout = gk20a_get_gr_idle_timeout(c->g); + + gk20a_dbg_fn(""); + + if (c->num_objects == 0) + return 0; + + c->num_objects--; + + if (c->num_objects == 0) { + c->first_init = false; + gk20a_disable_channel(c, + !c->has_timedout, + timeout); + gr_gk20a_unmap_channel_patch_ctx(c); + } + + return 0; +} + static void gk20a_remove_gr_support(struct gr_gk20a *gr) { struct gk20a *g = gr->g; @@ -3568,6 +3595,7 @@ int gr_gk20a_add_zbc(struct gk20a *g, struct gr_gk20a *gr, mutex_lock(&gr->zbc_lock); switch (zbc_val->type) { case GK20A_ZBC_TYPE_COLOR: + speculation_barrier(); /* search existing tables */ for (i = 0; i < gr->max_used_color_index; i++) { @@ -3606,6 +3634,7 @@ int gr_gk20a_add_zbc(struct gk20a *g, struct gr_gk20a *gr, } break; case GK20A_ZBC_TYPE_DEPTH: + speculation_barrier(); /* search existing tables */ for (i = 0; i < gr->max_used_depth_index; i++) { diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 526eefb46b6f..2a31aa0b830f 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h @@ -1,7 +1,7 @@ /* * GK20A Graphics Engine * - * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -324,9 +324,12 @@ int gk20a_init_gr_channel(struct channel_gk20a *ch_gk20a); int gr_gk20a_init_ctx_vars(struct gk20a *g, struct gr_gk20a *gr); struct nvhost_alloc_obj_ctx_args; +struct nvhost_free_obj_ctx_args; int gk20a_alloc_obj_ctx(struct channel_gk20a *c, struct nvhost_alloc_obj_ctx_args *args); +int gk20a_free_obj_ctx(struct channel_gk20a *c, + struct nvhost_free_obj_ctx_args *args); void gk20a_free_channel_ctx(struct channel_gk20a *c); int gk20a_gr_isr(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 2bbd973ad0b1..c5a5791f9489 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c @@ -1329,6 +1329,12 @@ u64 gk20a_vm_map(struct vm_gk20a *vm, bfr.pgsz_idx = -1; mapping_size = mapping_size ? mapping_size : bfr.size; + if ((mapping_size > bfr.size) || + (buffer_offset > (bfr.size - mapping_size))) { + err = -EINVAL; + goto clean_up; + } + /* If FIX_OFFSET is set, pgsz is determined. Otherwise, select * page size according to memory alignment */ if (flags & NVHOST_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) { @@ -2420,6 +2426,7 @@ int gk20a_vm_bind_channel(struct gk20a_as_share *as_share, gk20a_dbg_fn(""); + gk20a_vm_get(vm); ch->vm = vm; err = channel_gk20a_commit_va(ch); if (err) |