mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
gpu: nvgpu: add TSG support for engine context
All channels in a TSG need to share same engine context i.e. pointer in RAMFC of all channels in a TSG must point to same NV_RAMIN_GR_WFI_TARGET To get this, add a pointer to gr_ctx inside TSG struct so that TSG can maintain its own unique gr_ctx Also, change the type of gr_ctx in a channel to pointer variable so that if channel is part of TSG it can point to TSG's gr_ctx otherwise it will point to its own gr_ctx In gk20a_alloc_obj_ctx(), allocate gr_ctx as below : 1) If channel is not part of any TSG - allocate its own gr_ctx buffer if it is already not allocated 2) If channel is part of TSG - Check if TSG has already allocated gr_ctx (as part of TSG) - If yes, channel's gr_ctx will point to that of TSG's - If not, then it means channels is first to be bounded to this TSG - And in this case we will allocate new gr_ctx on TSG first and then make channel's gr_ctx to point to this gr_ctx Also, gr_ctx will be released as below ; 1) If channels is not part of TSG, then it will be released when channels is closed 2) Otherwise, it will be released when TSG itself is closed Bug 1470692 Change-Id: Id347217d5b462e0e972cd3d79d17795b37034a50 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/417065 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
committed by
Dan Willemsen
parent
b6466fbe07
commit
ee66559a0b
@@ -56,7 +56,7 @@ struct fence {
|
||||
|
||||
/* contexts associated with a channel */
|
||||
struct channel_ctx_gk20a {
|
||||
struct gr_ctx_desc gr_ctx;
|
||||
struct gr_ctx_desc *gr_ctx;
|
||||
struct pm_ctx_desc pm_ctx;
|
||||
struct patch_desc patch_ctx;
|
||||
struct zcull_ctx_desc zcull_ctx;
|
||||
|
||||
@@ -801,8 +801,8 @@ static int gr_gk20a_ctx_zcull_setup(struct gk20a *g, struct channel_gk20a *c,
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx.pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx.size) >> PAGE_SHIFT,
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx->pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx->size) >> PAGE_SHIFT,
|
||||
0, pgprot_dmacoherent(PAGE_KERNEL));
|
||||
if (!ctx_ptr)
|
||||
return -ENOMEM;
|
||||
@@ -1562,8 +1562,8 @@ static int gr_gk20a_init_golden_ctx_image(struct gk20a *g,
|
||||
if (!gold_ptr)
|
||||
goto clean_up;
|
||||
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx.pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx.size) >> PAGE_SHIFT,
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx->pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx->size) >> PAGE_SHIFT,
|
||||
0, pgprot_dmacoherent(PAGE_KERNEL));
|
||||
if (!ctx_ptr)
|
||||
goto clean_up;
|
||||
@@ -1602,7 +1602,7 @@ static int gr_gk20a_init_golden_ctx_image(struct gk20a *g,
|
||||
gk20a_mem_rd32(gold_ptr, i);
|
||||
}
|
||||
|
||||
gr_gk20a_commit_inst(c, ch_ctx->gr_ctx.gpu_va);
|
||||
gr_gk20a_commit_inst(c, ch_ctx->gr_ctx->gpu_va);
|
||||
|
||||
gr->ctx_vars.golden_image_initialized = true;
|
||||
|
||||
@@ -1636,8 +1636,8 @@ int gr_gk20a_update_smpc_ctxsw_mode(struct gk20a *g,
|
||||
Flush and invalidate before cpu update. */
|
||||
gk20a_mm_l2_flush(g, true);
|
||||
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx.pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx.size) >> PAGE_SHIFT,
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx->pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx->size) >> PAGE_SHIFT,
|
||||
0, pgprot_dmacoherent(PAGE_KERNEL));
|
||||
if (!ctx_ptr)
|
||||
return -ENOMEM;
|
||||
@@ -1676,8 +1676,8 @@ static int gr_gk20a_load_golden_ctx_image(struct gk20a *g,
|
||||
Flush and invalidate before cpu update. */
|
||||
gk20a_mm_l2_flush(g, true);
|
||||
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx.pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx.size) >> PAGE_SHIFT,
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx->pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx->size) >> PAGE_SHIFT,
|
||||
0, pgprot_dmacoherent(PAGE_KERNEL));
|
||||
if (!ctx_ptr)
|
||||
return -ENOMEM;
|
||||
@@ -2521,12 +2521,11 @@ static void gr_gk20a_unmap_global_ctx_buffers(struct channel_gk20a *c)
|
||||
c->ch_ctx.global_ctx_buffer_mapped = false;
|
||||
}
|
||||
|
||||
static int gr_gk20a_alloc_channel_gr_ctx(struct gk20a *g,
|
||||
struct channel_gk20a *c)
|
||||
static int __gr_gk20a_alloc_gr_ctx(struct gk20a *g,
|
||||
struct gr_ctx_desc **__gr_ctx, struct vm_gk20a *vm)
|
||||
{
|
||||
struct gr_ctx_desc *gr_ctx = NULL;
|
||||
struct gr_gk20a *gr = &g->gr;
|
||||
struct gr_ctx_desc *gr_ctx = &c->ch_ctx.gr_ctx;
|
||||
struct vm_gk20a *ch_vm = c->vm;
|
||||
struct device *d = dev_from_gk20a(g);
|
||||
struct sg_table *sgt;
|
||||
DEFINE_DMA_ATTRS(attrs);
|
||||
@@ -2542,12 +2541,18 @@ static int gr_gk20a_alloc_channel_gr_ctx(struct gk20a *g,
|
||||
gr->ctx_vars.buffer_size = gr->ctx_vars.golden_image_size;
|
||||
gr->ctx_vars.buffer_total_size = gr->ctx_vars.golden_image_size;
|
||||
|
||||
gr_ctx = kzalloc(sizeof(*gr_ctx), GFP_KERNEL);
|
||||
if (!gr_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
gr_ctx->size = gr->ctx_vars.buffer_total_size;
|
||||
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
|
||||
gr_ctx->pages = dma_alloc_attrs(d, gr_ctx->size,
|
||||
&iova, GFP_KERNEL, &attrs);
|
||||
if (!gr_ctx->pages)
|
||||
return -ENOMEM;
|
||||
if (!gr_ctx->pages) {
|
||||
err = -ENOMEM;
|
||||
goto err_free_ctx;
|
||||
}
|
||||
|
||||
gr_ctx->iova = iova;
|
||||
err = gk20a_get_sgtable_from_pages(d, &sgt, gr_ctx->pages,
|
||||
@@ -2555,7 +2560,7 @@ static int gr_gk20a_alloc_channel_gr_ctx(struct gk20a *g,
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
gr_ctx->gpu_va = gk20a_gmmu_map(ch_vm, &sgt, gr_ctx->size,
|
||||
gr_ctx->gpu_va = gk20a_gmmu_map(vm, &sgt, gr_ctx->size,
|
||||
NVHOST_MAP_BUFFER_FLAGS_CACHEABLE_TRUE,
|
||||
gk20a_mem_flag_none);
|
||||
if (!gr_ctx->gpu_va)
|
||||
@@ -2563,6 +2568,8 @@ static int gr_gk20a_alloc_channel_gr_ctx(struct gk20a *g,
|
||||
|
||||
gk20a_free_sgtable(&sgt);
|
||||
|
||||
*__gr_ctx = gr_ctx;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_sgt:
|
||||
@@ -2572,30 +2579,74 @@ static int gr_gk20a_alloc_channel_gr_ctx(struct gk20a *g,
|
||||
gr_ctx->pages, gr_ctx->iova, &attrs);
|
||||
gr_ctx->pages = NULL;
|
||||
gr_ctx->iova = 0;
|
||||
err_free_ctx:
|
||||
kfree(gr_ctx);
|
||||
gr_ctx = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void gr_gk20a_free_channel_gr_ctx(struct channel_gk20a *c)
|
||||
static int gr_gk20a_alloc_tsg_gr_ctx(struct gk20a *g,
|
||||
struct tsg_gk20a *tsg)
|
||||
{
|
||||
struct gr_ctx_desc **gr_ctx = &tsg->tsg_gr_ctx;
|
||||
int err;
|
||||
|
||||
if (!tsg->vm) {
|
||||
gk20a_err(dev_from_gk20a(tsg->g), "No address space bound\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = __gr_gk20a_alloc_gr_ctx(g, gr_ctx, tsg->vm);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gr_gk20a_alloc_channel_gr_ctx(struct gk20a *g,
|
||||
struct channel_gk20a *c)
|
||||
{
|
||||
struct gr_ctx_desc **gr_ctx = &c->ch_ctx.gr_ctx;
|
||||
int err = __gr_gk20a_alloc_gr_ctx(g, gr_ctx, c->vm);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __gr_gk20a_free_gr_ctx(struct gk20a *g,
|
||||
struct vm_gk20a *vm, struct gr_ctx_desc *gr_ctx)
|
||||
{
|
||||
struct channel_ctx_gk20a *ch_ctx = &c->ch_ctx;
|
||||
struct vm_gk20a *ch_vm = c->vm;
|
||||
struct gk20a *g = c->g;
|
||||
struct device *d = dev_from_gk20a(g);
|
||||
DEFINE_DMA_ATTRS(attrs);
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
if (!ch_ctx->gr_ctx.gpu_va)
|
||||
if (!gr_ctx || !gr_ctx->gpu_va)
|
||||
return;
|
||||
|
||||
gk20a_gmmu_unmap(ch_vm, ch_ctx->gr_ctx.gpu_va,
|
||||
ch_ctx->gr_ctx.size, gk20a_mem_flag_none);
|
||||
gk20a_gmmu_unmap(vm, gr_ctx->gpu_va,
|
||||
gr_ctx->size, gk20a_mem_flag_none);
|
||||
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
|
||||
dma_free_attrs(d, ch_ctx->gr_ctx.size,
|
||||
ch_ctx->gr_ctx.pages, ch_ctx->gr_ctx.iova, &attrs);
|
||||
ch_ctx->gr_ctx.pages = NULL;
|
||||
ch_ctx->gr_ctx.iova = 0;
|
||||
dma_free_attrs(d, gr_ctx->size,
|
||||
gr_ctx->pages, gr_ctx->iova, &attrs);
|
||||
gr_ctx->pages = NULL;
|
||||
gr_ctx->iova = 0;
|
||||
}
|
||||
|
||||
void gr_gk20a_free_tsg_gr_ctx(struct tsg_gk20a *tsg)
|
||||
{
|
||||
if (!tsg->vm) {
|
||||
gk20a_err(dev_from_gk20a(tsg->g), "No address space bound\n");
|
||||
return;
|
||||
}
|
||||
__gr_gk20a_free_gr_ctx(tsg->g, tsg->vm, tsg->tsg_gr_ctx);
|
||||
}
|
||||
|
||||
static void gr_gk20a_free_channel_gr_ctx(struct channel_gk20a *c)
|
||||
{
|
||||
__gr_gk20a_free_gr_ctx(c->g, c->vm, c->ch_ctx.gr_ctx);
|
||||
}
|
||||
|
||||
static int gr_gk20a_alloc_channel_patch_ctx(struct gk20a *g,
|
||||
@@ -2684,7 +2735,8 @@ void gk20a_free_channel_ctx(struct channel_gk20a *c)
|
||||
{
|
||||
gr_gk20a_unmap_global_ctx_buffers(c);
|
||||
gr_gk20a_free_channel_patch_ctx(c);
|
||||
gr_gk20a_free_channel_gr_ctx(c);
|
||||
if (!gk20a_is_channel_marked_as_tsg(c))
|
||||
gr_gk20a_free_channel_gr_ctx(c);
|
||||
|
||||
/* zcull_ctx, pm_ctx */
|
||||
|
||||
@@ -2717,7 +2769,9 @@ int gk20a_alloc_obj_ctx(struct channel_gk20a *c,
|
||||
struct nvhost_alloc_obj_ctx_args *args)
|
||||
{
|
||||
struct gk20a *g = c->g;
|
||||
struct fifo_gk20a *f = &g->fifo;
|
||||
struct channel_ctx_gk20a *ch_ctx = &c->ch_ctx;
|
||||
struct tsg_gk20a *tsg = NULL;
|
||||
int err = 0;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
@@ -2736,27 +2790,44 @@ int gk20a_alloc_obj_ctx(struct channel_gk20a *c,
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
c->obj_class = args->class_num;
|
||||
|
||||
if (gk20a_is_channel_marked_as_tsg(c))
|
||||
tsg = &f->tsg[c->tsgid];
|
||||
|
||||
/* allocate gr ctx buffer */
|
||||
if (ch_ctx->gr_ctx.pages == NULL) {
|
||||
err = gr_gk20a_alloc_channel_gr_ctx(g, c);
|
||||
if (err) {
|
||||
if (!tsg) {
|
||||
if (!ch_ctx->gr_ctx) {
|
||||
err = gr_gk20a_alloc_channel_gr_ctx(g, c);
|
||||
if (err) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"fail to allocate gr ctx buffer");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/*TBD: needs to be more subtle about which is
|
||||
* being allocated as some are allowed to be
|
||||
* allocated along same channel */
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"fail to allocate gr ctx buffer");
|
||||
"too many classes alloc'd on same channel");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
c->obj_class = args->class_num;
|
||||
} else {
|
||||
/*TBD: needs to be more subtle about which is being allocated
|
||||
* as some are allowed to be allocated along same channel */
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"too many classes alloc'd on same channel");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
if (!tsg->tsg_gr_ctx) {
|
||||
tsg->vm = c->vm;
|
||||
err = gr_gk20a_alloc_tsg_gr_ctx(g, tsg);
|
||||
if (err) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"fail to allocate TSG gr ctx buffer");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ch_ctx->gr_ctx = tsg->tsg_gr_ctx;
|
||||
}
|
||||
|
||||
/* commit gr ctx buffer */
|
||||
err = gr_gk20a_commit_inst(c, ch_ctx->gr_ctx.gpu_va);
|
||||
err = gr_gk20a_commit_inst(c, ch_ctx->gr_ctx->gpu_va);
|
||||
if (err) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"fail to commit gr ctx buffer");
|
||||
@@ -6657,8 +6728,8 @@ int gr_gk20a_exec_ctx_ops(struct channel_gk20a *ch,
|
||||
|
||||
/* would have been a variant of gr_gk20a_apply_instmem_overrides */
|
||||
/* recoded in-place instead.*/
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx.pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx.size) >> PAGE_SHIFT,
|
||||
ctx_ptr = vmap(ch_ctx->gr_ctx->pages,
|
||||
PAGE_ALIGN(ch_ctx->gr_ctx->size) >> PAGE_SHIFT,
|
||||
0, pgprot_dmacoherent(PAGE_KERNEL));
|
||||
if (!ctx_ptr) {
|
||||
err = -ENOMEM;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "tsg_gk20a.h"
|
||||
#include "gr_ctx_gk20a.h"
|
||||
|
||||
#define GR_IDLE_CHECK_DEFAULT 100 /* usec */
|
||||
@@ -414,4 +415,6 @@ void gr_gk20a_get_sm_dsm_perf_ctrl_regs(struct gk20a *g,
|
||||
u32 **sm_dsm_perf_regs,
|
||||
u32 *perf_register_stride);
|
||||
int gr_gk20a_setup_rop_mapping(struct gk20a *g, struct gr_gk20a *gr);
|
||||
|
||||
void gr_gk20a_free_tsg_gr_ctx(struct tsg_gk20a *c);
|
||||
#endif /*__GR_GK20A_H__*/
|
||||
|
||||
@@ -165,6 +165,9 @@ int gk20a_tsg_dev_open(struct inode *inode, struct file *filp)
|
||||
tsg->g = g;
|
||||
tsg->num_runnable_channels = 0;
|
||||
|
||||
tsg->tsg_gr_ctx = NULL;
|
||||
tsg->vm = NULL;
|
||||
|
||||
filp->private_data = tsg;
|
||||
|
||||
gk20a_dbg(gpu_dbg_fn, "tsg opened %d\n", tsg->tsgid);
|
||||
@@ -185,6 +188,13 @@ int gk20a_tsg_dev_release(struct inode *inode, struct file *filp)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (tsg->tsg_gr_ctx) {
|
||||
gr_gk20a_free_tsg_gr_ctx(tsg);
|
||||
tsg->tsg_gr_ctx = NULL;
|
||||
}
|
||||
if (tsg->vm)
|
||||
tsg->vm = NULL;
|
||||
|
||||
release_used_tsg(&g->fifo, tsg);
|
||||
|
||||
gk20a_dbg(gpu_dbg_fn, "tsg released %d\n", tsg->tsgid);
|
||||
|
||||
@@ -39,6 +39,10 @@ struct tsg_gk20a {
|
||||
struct list_head ch_runnable_list;
|
||||
int num_runnable_channels;
|
||||
struct mutex ch_list_lock;
|
||||
|
||||
struct gr_ctx_desc *tsg_gr_ctx;
|
||||
|
||||
struct vm_gk20a *vm;
|
||||
};
|
||||
|
||||
#endif /* __TSG_GK20A_H_ */
|
||||
|
||||
Reference in New Issue
Block a user