diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 56 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.h | 22 |
2 files changed, 78 insertions, 0 deletions
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 @@ | |||
32 | 32 | ||
33 | #include "gk20a.h" | 33 | #include "gk20a.h" |
34 | #include "mm_gk20a.h" | 34 | #include "mm_gk20a.h" |
35 | #include "fence_gk20a.h" | ||
35 | #include "hw_gmmu_gk20a.h" | 36 | #include "hw_gmmu_gk20a.h" |
36 | #include "hw_fb_gk20a.h" | 37 | #include "hw_fb_gk20a.h" |
37 | #include "hw_bus_gk20a.h" | 38 | #include "hw_bus_gk20a.h" |
@@ -121,10 +122,13 @@ struct gk20a_dmabuf_priv { | |||
121 | struct sg_table *sgt; | 122 | struct sg_table *sgt; |
122 | 123 | ||
123 | int pin_count; | 124 | int pin_count; |
125 | |||
126 | struct list_head states; | ||
124 | }; | 127 | }; |
125 | 128 | ||
126 | static void gk20a_mm_delete_priv(void *_priv) | 129 | static void gk20a_mm_delete_priv(void *_priv) |
127 | { | 130 | { |
131 | struct gk20a_buffer_state *s, *s_tmp; | ||
128 | struct gk20a_dmabuf_priv *priv = _priv; | 132 | struct gk20a_dmabuf_priv *priv = _priv; |
129 | if (!priv) | 133 | if (!priv) |
130 | return; | 134 | return; |
@@ -136,6 +140,13 @@ static void gk20a_mm_delete_priv(void *_priv) | |||
136 | priv->comptags.lines); | 140 | priv->comptags.lines); |
137 | } | 141 | } |
138 | 142 | ||
143 | /* Free buffer states */ | ||
144 | list_for_each_entry_safe(s, s_tmp, &priv->states, list) { | ||
145 | gk20a_fence_put(s->fence); | ||
146 | list_del(&s->list); | ||
147 | kfree(s); | ||
148 | } | ||
149 | |||
139 | kfree(priv); | 150 | kfree(priv); |
140 | } | 151 | } |
141 | 152 | ||
@@ -2438,6 +2449,7 @@ int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev) | |||
2438 | goto priv_exist_or_err; | 2449 | goto priv_exist_or_err; |
2439 | } | 2450 | } |
2440 | mutex_init(&priv->lock); | 2451 | mutex_init(&priv->lock); |
2452 | INIT_LIST_HEAD(&priv->states); | ||
2441 | dma_buf_set_drvdata(dmabuf, dev, priv, gk20a_mm_delete_priv); | 2453 | dma_buf_set_drvdata(dmabuf, dev, priv, gk20a_mm_delete_priv); |
2442 | priv_exist_or_err: | 2454 | priv_exist_or_err: |
2443 | mutex_unlock(&priv_lock); | 2455 | mutex_unlock(&priv_lock); |
@@ -2447,6 +2459,50 @@ priv_exist_or_err: | |||
2447 | return 0; | 2459 | return 0; |
2448 | } | 2460 | } |
2449 | 2461 | ||
2462 | int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct device *dev, | ||
2463 | u64 offset, struct gk20a_buffer_state **state) | ||
2464 | { | ||
2465 | int err = 0; | ||
2466 | struct gk20a_dmabuf_priv *priv; | ||
2467 | struct gk20a_buffer_state *s; | ||
2468 | |||
2469 | if (WARN_ON(offset >= (u64)dmabuf->size)) | ||
2470 | return -EINVAL; | ||
2471 | |||
2472 | err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev); | ||
2473 | if (err) | ||
2474 | return err; | ||
2475 | |||
2476 | priv = dma_buf_get_drvdata(dmabuf, dev); | ||
2477 | if (WARN_ON(!priv)) | ||
2478 | return -ENOSYS; | ||
2479 | |||
2480 | mutex_lock(&priv->lock); | ||
2481 | |||
2482 | list_for_each_entry(s, &priv->states, list) | ||
2483 | if (s->offset == offset) | ||
2484 | goto out; | ||
2485 | |||
2486 | /* State not found, create state. */ | ||
2487 | s = kzalloc(sizeof(*s), GFP_KERNEL); | ||
2488 | if (!s) { | ||
2489 | err = -ENOMEM; | ||
2490 | goto out; | ||
2491 | } | ||
2492 | |||
2493 | s->offset = offset; | ||
2494 | INIT_LIST_HEAD(&s->list); | ||
2495 | mutex_init(&s->lock); | ||
2496 | list_add_tail(&priv->states, &s->list); | ||
2497 | |||
2498 | out: | ||
2499 | mutex_unlock(&priv->lock); | ||
2500 | if (!err) | ||
2501 | *state = s; | ||
2502 | return err; | ||
2503 | |||
2504 | |||
2505 | } | ||
2450 | 2506 | ||
2451 | static int gk20a_dmabuf_get_kind(struct dma_buf *dmabuf) | 2507 | static int gk20a_dmabuf_get_kind(struct dma_buf *dmabuf) |
2452 | { | 2508 | { |
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 { | |||
174 | u64 base_iova; | 174 | u64 base_iova; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | struct gk20a_buffer_state { | ||
178 | struct list_head list; | ||
179 | |||
180 | /* The valid compbits and the fence must be changed atomically. */ | ||
181 | struct mutex lock; | ||
182 | |||
183 | /* Offset of the surface within the dma-buf whose state is | ||
184 | * described by this struct (one dma-buf can contain multiple | ||
185 | * surfaces with different states). */ | ||
186 | size_t offset; | ||
187 | |||
188 | /* A bitmask of valid sets of compbits (0 = uncompressed). */ | ||
189 | u32 valid_compbits; | ||
190 | |||
191 | /* This struct reflects the state of the buffer when this | ||
192 | * fence signals. */ | ||
193 | struct gk20a_fence *fence; | ||
194 | }; | ||
195 | |||
177 | struct page_table_gk20a { | 196 | struct page_table_gk20a { |
178 | /* backing for */ | 197 | /* backing for */ |
179 | /* Either a *page or a *mem_handle */ | 198 | /* 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); | |||
484 | 503 | ||
485 | int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev); | 504 | int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev); |
486 | 505 | ||
506 | int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct device *dev, | ||
507 | u64 offset, struct gk20a_buffer_state **state); | ||
508 | |||
487 | int map_gmmu_pages(void *handle, struct sg_table *sgt, | 509 | int map_gmmu_pages(void *handle, struct sg_table *sgt, |
488 | void **va, size_t size); | 510 | void **va, size_t size); |
489 | void unmap_gmmu_pages(void *handle, struct sg_table *sgt, void *va); | 511 | void unmap_gmmu_pages(void *handle, struct sg_table *sgt, void *va); |