From c60a300c4ac903dd7e0b53f2542a081fa4c334cb Mon Sep 17 00:00:00 2001 From: Lauri Peltonen Date: Fri, 18 Jul 2014 02:31:44 +0300 Subject: gpu: nvgpu: Attach compression state to dma-buf Bug 1509620 Change-Id: I694fe43ef5d1f4f329d997a3d60e006785374cc3 Signed-off-by: Lauri Peltonen Reviewed-on: http://git-master/r/439849 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Arto Merilainen Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 56 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/mm_gk20a.h | 22 +++++++++++++++ 2 files changed, 78 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index e7a97207..57c61d51 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c @@ -32,6 +32,7 @@ #include "gk20a.h" #include "mm_gk20a.h" +#include "fence_gk20a.h" #include "hw_gmmu_gk20a.h" #include "hw_fb_gk20a.h" #include "hw_bus_gk20a.h" @@ -121,10 +122,13 @@ struct gk20a_dmabuf_priv { struct sg_table *sgt; int pin_count; + + struct list_head states; }; static void gk20a_mm_delete_priv(void *_priv) { + struct gk20a_buffer_state *s, *s_tmp; struct gk20a_dmabuf_priv *priv = _priv; if (!priv) return; @@ -136,6 +140,13 @@ static void gk20a_mm_delete_priv(void *_priv) priv->comptags.lines); } + /* Free buffer states */ + list_for_each_entry_safe(s, s_tmp, &priv->states, list) { + gk20a_fence_put(s->fence); + list_del(&s->list); + kfree(s); + } + kfree(priv); } @@ -2438,6 +2449,7 @@ int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev) goto priv_exist_or_err; } mutex_init(&priv->lock); + INIT_LIST_HEAD(&priv->states); dma_buf_set_drvdata(dmabuf, dev, priv, gk20a_mm_delete_priv); priv_exist_or_err: mutex_unlock(&priv_lock); @@ -2447,6 +2459,50 @@ priv_exist_or_err: return 0; } +int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct device *dev, + u64 offset, struct gk20a_buffer_state **state) +{ + int err = 0; + struct gk20a_dmabuf_priv *priv; + struct gk20a_buffer_state *s; + + if (WARN_ON(offset >= (u64)dmabuf->size)) + return -EINVAL; + + err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev); + if (err) + return err; + + priv = dma_buf_get_drvdata(dmabuf, dev); + if (WARN_ON(!priv)) + return -ENOSYS; + + mutex_lock(&priv->lock); + + list_for_each_entry(s, &priv->states, list) + if (s->offset == offset) + goto out; + + /* State not found, create state. */ + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) { + err = -ENOMEM; + goto out; + } + + s->offset = offset; + INIT_LIST_HEAD(&s->list); + mutex_init(&s->lock); + list_add_tail(&priv->states, &s->list); + +out: + mutex_unlock(&priv->lock); + if (!err) + *state = s; + return err; + + +} static int gk20a_dmabuf_get_kind(struct dma_buf *dmabuf) { diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h index 30f9e50b..df64d2ca 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h @@ -174,6 +174,25 @@ struct compbit_store_desc { u64 base_iova; }; +struct gk20a_buffer_state { + struct list_head list; + + /* The valid compbits and the fence must be changed atomically. */ + struct mutex lock; + + /* Offset of the surface within the dma-buf whose state is + * described by this struct (one dma-buf can contain multiple + * surfaces with different states). */ + size_t offset; + + /* A bitmask of valid sets of compbits (0 = uncompressed). */ + u32 valid_compbits; + + /* This struct reflects the state of the buffer when this + * fence signals. */ + struct gk20a_fence *fence; +}; + struct page_table_gk20a { /* backing for */ /* Either a *page or a *mem_handle */ @@ -484,6 +503,9 @@ dma_addr_t gk20a_mm_gpuva_to_iova(struct vm_gk20a *vm, u64 gpu_vaddr); int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev); +int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct device *dev, + u64 offset, struct gk20a_buffer_state **state); + int map_gmmu_pages(void *handle, struct sg_table *sgt, void **va, size_t size); void unmap_gmmu_pages(void *handle, struct sg_table *sgt, void *va); -- cgit v1.2.2