diff --git a/drivers/gpu/nvgpu/common/linux/comptags.c b/drivers/gpu/nvgpu/common/linux/comptags.c index 92e8aa3ef..4a96e07b6 100644 --- a/drivers/gpu/nvgpu/common/linux/comptags.c +++ b/drivers/gpu/nvgpu/common/linux/comptags.c @@ -39,10 +39,11 @@ void gk20a_get_comptags(struct nvgpu_os_buffer *buf, *comptags = priv->comptags; } -int gk20a_alloc_comptags(struct gk20a *g, - struct nvgpu_os_buffer *buf, - struct gk20a_comptag_allocator *allocator, - u32 lines) +int gk20a_alloc_or_get_comptags(struct gk20a *g, + struct nvgpu_os_buffer *buf, + struct gk20a_comptag_allocator *allocator, + u32 lines, + struct gk20a_comptags *comptags) { struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(buf->dmabuf, buf->dev); @@ -55,15 +56,23 @@ int gk20a_alloc_comptags(struct gk20a *g, if (!lines) return -EINVAL; + if (priv->comptags.allocated) { + /* already allocated */ + *comptags = priv->comptags; + return 0; + } + /* store the allocator so we can use it when we free the ctags */ priv->comptag_allocator = allocator; err = gk20a_comptaglines_alloc(allocator, &offset, lines); if (!err) { priv->comptags.offset = offset; priv->comptags.lines = lines; + priv->comptags.needs_clear = true; } else { priv->comptags.offset = 0; priv->comptags.lines = 0; + priv->comptags.needs_clear = false; } /* @@ -74,5 +83,14 @@ int gk20a_alloc_comptags(struct gk20a *g, */ priv->comptags.allocated = true; + *comptags = priv->comptags; return 0; } + +void gk20a_mark_comptags_cleared(struct nvgpu_os_buffer *buf) +{ + struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(buf->dmabuf, + buf->dev); + if (priv) + priv->comptags.needs_clear = false; +} diff --git a/drivers/gpu/nvgpu/common/mm/vm.c b/drivers/gpu/nvgpu/common/mm/vm.c index be7e42073..7a451956a 100644 --- a/drivers/gpu/nvgpu/common/mm/vm.c +++ b/drivers/gpu/nvgpu/common/mm/vm.c @@ -857,53 +857,39 @@ struct nvgpu_mapped_buf *nvgpu_vm_map(struct vm_gk20a *vm, struct gk20a_comptags comptags = { 0 }; /* - * Get the comptags state + * Get the comptags state, alloc if necessary */ - gk20a_get_comptags(os_buf, &comptags); + err = gk20a_alloc_or_get_comptags(g, os_buf, + &g->gr.comp_tags, + binfo.ctag_lines, &comptags); + if (err) { + /* + * This is an irrecoverable failure and we need to + * abort. In particular, it is not safe to proceed with + * the incompressible fallback, since we cannot not mark + * our alloc failure anywere. Later we would retry + * allocation and break compressible map aliasing. + */ + nvgpu_err(g, "Error %d setting up comptags", err); + goto clean_up; + } /* - * Allocate if not yet allocated + * Newly allocated comptags needs to be cleared */ - if (!comptags.allocated) { - err = gk20a_alloc_comptags(g, os_buf, - &g->gr.comp_tags, - binfo.ctag_lines); - if (err) { + if (comptags.needs_clear) { + if (g->ops.ltc.cbc_ctrl) { + g->ops.ltc.cbc_ctrl( + g, gk20a_cbc_op_clear, + comptags.offset, + (comptags.offset + + comptags.lines - 1)); + gk20a_mark_comptags_cleared(os_buf); + } else { /* - * This is an irrecoverable failure and we need - * to abort. In particular, it is not safe to - * proceed with incompressible fallback, since - * we could not mark our alloc failure - * anywere. Later we would retry allocation and - * break compressible map aliasing. + * Cleared as part of gmmu map */ - nvgpu_err(g, - "Error %d setting up comptags", err); - goto clean_up; - } - - /* - * Refresh comptags state after alloc. Field - * comptags.lines will be 0 if alloc failed. - */ - gk20a_get_comptags(os_buf, &comptags); - - /* - * Newly allocated comptags needs to be cleared - */ - if (comptags.lines) { - if (g->ops.ltc.cbc_ctrl) - g->ops.ltc.cbc_ctrl( - g, gk20a_cbc_op_clear, - comptags.offset, - (comptags.offset + - comptags.lines - 1)); - else - /* - * The comptags will be cleared as part - * of mapping (vgpu) - */ - clear_ctags = true; + clear_ctags = true; } } @@ -959,6 +945,9 @@ struct nvgpu_mapped_buf *nvgpu_vm_map(struct vm_gk20a *vm, goto clean_up; } + if (clear_ctags) + gk20a_mark_comptags_cleared(os_buf); + nvgpu_init_list_node(&mapped_buffer->buffer_list); nvgpu_ref_init(&mapped_buffer->ref); mapped_buffer->addr = map_addr; diff --git a/drivers/gpu/nvgpu/include/nvgpu/comptags.h b/drivers/gpu/nvgpu/include/nvgpu/comptags.h index 2d9f034a6..41a918b59 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/comptags.h +++ b/drivers/gpu/nvgpu/include/nvgpu/comptags.h @@ -27,12 +27,17 @@ struct gk20a_comptags { u32 lines; /* - * This signals whether allocation has been attempted. Observe - * 'lines' to see whether comptags were actually allocated. We - * try alloc only once per buffer in order not to break - * multiple compressible-kind mappings. + * This signals whether allocation has been attempted. Observe 'lines' + * to see whether the comptags were actually allocated. We try alloc + * only once per buffer in order not to break multiple compressible-kind + * mappings. */ bool allocated; + + /* + * Do comptags need to be cleared before mapping? + */ + bool needs_clear; }; struct gk20a_comptag_allocator { @@ -63,13 +68,13 @@ void gk20a_comptaglines_free(struct gk20a_comptag_allocator *allocator, * Defined by OS specific code since comptags are stored in a highly OS specific * way. */ -int gk20a_alloc_comptags(struct gk20a *g, - struct nvgpu_os_buffer *buf, - struct gk20a_comptag_allocator *allocator, - u32 lines); +int gk20a_alloc_or_get_comptags(struct gk20a *g, + struct nvgpu_os_buffer *buf, + struct gk20a_comptag_allocator *allocator, + u32 lines, + struct gk20a_comptags *comptags); void gk20a_get_comptags(struct nvgpu_os_buffer *buf, struct gk20a_comptags *comptags); - - +void gk20a_mark_comptags_cleared(struct nvgpu_os_buffer *buf); #endif