summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.c32
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.h4
2 files changed, 22 insertions, 14 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
index c9f2a840..d66e46b8 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
@@ -902,7 +902,8 @@ static int gk20a_init_vidmem(struct mm_gk20a *mm)
902 mm->vidmem.bootstrap_base = bootstrap_base; 902 mm->vidmem.bootstrap_base = bootstrap_base;
903 mm->vidmem.bootstrap_size = bootstrap_size; 903 mm->vidmem.bootstrap_size = bootstrap_size;
904 904
905 INIT_WORK(&mm->vidmem_clear_mem_worker, gk20a_vidmem_clear_mem_worker); 905 INIT_WORK(&mm->vidmem.clear_mem_worker, gk20a_vidmem_clear_mem_worker);
906 atomic_set(&mm->vidmem.clears_pending, 0);
906 INIT_LIST_HEAD(&mm->vidmem.clear_list_head); 907 INIT_LIST_HEAD(&mm->vidmem.clear_list_head);
907 mutex_init(&mm->vidmem.clear_list_mutex); 908 mutex_init(&mm->vidmem.clear_list_mutex);
908 909
@@ -2982,10 +2983,10 @@ int gk20a_gmmu_alloc_attr_vid_at(struct gk20a *g, enum dma_attr attr,
2982#if defined(CONFIG_GK20A_VIDMEM) 2983#if defined(CONFIG_GK20A_VIDMEM)
2983 u64 addr; 2984 u64 addr;
2984 int err; 2985 int err;
2985 bool clear_list_empty;
2986 struct gk20a_allocator *vidmem_alloc = g->mm.vidmem.cleared ? 2986 struct gk20a_allocator *vidmem_alloc = g->mm.vidmem.cleared ?
2987 &g->mm.vidmem.allocator : 2987 &g->mm.vidmem.allocator :
2988 &g->mm.vidmem.bootstrap_allocator; 2988 &g->mm.vidmem.bootstrap_allocator;
2989 int before_pending;
2989 2990
2990 gk20a_dbg_fn(""); 2991 gk20a_dbg_fn("");
2991 2992
@@ -2996,16 +2997,19 @@ int gk20a_gmmu_alloc_attr_vid_at(struct gk20a *g, enum dma_attr attr,
2996 * are not done anyway */ 2997 * are not done anyway */
2997 WARN_ON(attr != 0 && attr != DMA_ATTR_NO_KERNEL_MAPPING); 2998 WARN_ON(attr != 0 && attr != DMA_ATTR_NO_KERNEL_MAPPING);
2998 2999
3000 mutex_lock(&g->mm.vidmem.clear_list_mutex);
3001 before_pending = atomic_read(&g->mm.vidmem.clears_pending);
2999 addr = __gk20a_gmmu_alloc(vidmem_alloc, at, size); 3002 addr = __gk20a_gmmu_alloc(vidmem_alloc, at, size);
3003 mutex_unlock(&g->mm.vidmem.clear_list_mutex);
3000 if (!addr) { 3004 if (!addr) {
3001 mutex_lock(&g->mm.vidmem.clear_list_mutex); 3005 /*
3002 clear_list_empty = list_empty(&g->mm.vidmem.clear_list_head); 3006 * If memory is known to be freed soon, let the user know that
3003 mutex_unlock(&g->mm.vidmem.clear_list_mutex); 3007 * it may be available after a while.
3004 3008 */
3005 if (clear_list_empty) 3009 if (before_pending)
3006 return -ENOMEM;
3007 else
3008 return -EAGAIN; 3010 return -EAGAIN;
3011 else
3012 return -ENOMEM;
3009 } 3013 }
3010 3014
3011 if (at) 3015 if (at)
@@ -3057,11 +3061,12 @@ static void gk20a_gmmu_free_attr_vid(struct gk20a *g, enum dma_attr attr,
3057 was_empty = list_empty(&g->mm.vidmem.clear_list_head); 3061 was_empty = list_empty(&g->mm.vidmem.clear_list_head);
3058 list_add_tail(&mem->clear_list_entry, 3062 list_add_tail(&mem->clear_list_entry,
3059 &g->mm.vidmem.clear_list_head); 3063 &g->mm.vidmem.clear_list_head);
3064 atomic_inc(&g->mm.vidmem.clears_pending);
3060 mutex_unlock(&g->mm.vidmem.clear_list_mutex); 3065 mutex_unlock(&g->mm.vidmem.clear_list_mutex);
3061 3066
3062 if (was_empty) { 3067 if (was_empty) {
3063 cancel_work_sync(&g->mm.vidmem_clear_mem_worker); 3068 cancel_work_sync(&g->mm.vidmem.clear_mem_worker);
3064 schedule_work(&g->mm.vidmem_clear_mem_worker); 3069 schedule_work(&g->mm.vidmem.clear_mem_worker);
3065 } 3070 }
3066 } else { 3071 } else {
3067 gk20a_memset(g, mem, 0, 0, mem->size); 3072 gk20a_memset(g, mem, 0, 0, mem->size);
@@ -3136,7 +3141,7 @@ static struct mem_desc *get_pending_mem_desc(struct mm_gk20a *mm)
3136static void gk20a_vidmem_clear_mem_worker(struct work_struct *work) 3141static void gk20a_vidmem_clear_mem_worker(struct work_struct *work)
3137{ 3142{
3138 struct mm_gk20a *mm = container_of(work, struct mm_gk20a, 3143 struct mm_gk20a *mm = container_of(work, struct mm_gk20a,
3139 vidmem_clear_mem_worker); 3144 vidmem.clear_mem_worker);
3140 struct gk20a *g = mm->g; 3145 struct gk20a *g = mm->g;
3141 struct mem_desc *mem; 3146 struct mem_desc *mem;
3142 3147
@@ -3146,6 +3151,7 @@ static void gk20a_vidmem_clear_mem_worker(struct work_struct *work)
3146 sg_dma_address(mem->sgt->sgl)); 3151 sg_dma_address(mem->sgt->sgl));
3147 gk20a_free_sgtable(&mem->sgt); 3152 gk20a_free_sgtable(&mem->sgt);
3148 3153
3154 WARN_ON(atomic_dec_return(&mm->vidmem.clears_pending) < 0);
3149 mem->size = 0; 3155 mem->size = 0;
3150 mem->aperture = APERTURE_INVALID; 3156 mem->aperture = APERTURE_INVALID;
3151 3157
@@ -5098,7 +5104,7 @@ int gk20a_mm_suspend(struct gk20a *g)
5098{ 5104{
5099 gk20a_dbg_fn(""); 5105 gk20a_dbg_fn("");
5100 5106
5101 cancel_work_sync(&g->mm.vidmem_clear_mem_worker); 5107 cancel_work_sync(&g->mm.vidmem.clear_mem_worker);
5102 5108
5103 g->ops.mm.cbc_clean(g); 5109 g->ops.mm.cbc_clean(g);
5104 g->ops.mm.l2_flush(g, false); 5110 g->ops.mm.l2_flush(g, false);
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
index 9002290e..8ce110a1 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
@@ -420,8 +420,10 @@ struct mm_gk20a {
420 420
421 struct list_head clear_list_head; 421 struct list_head clear_list_head;
422 struct mutex clear_list_mutex; 422 struct mutex clear_list_mutex;
423
424 struct work_struct clear_mem_worker;
425 atomic_t clears_pending;
423 } vidmem; 426 } vidmem;
424 struct work_struct vidmem_clear_mem_worker;
425}; 427};
426 428
427int gk20a_mm_init(struct mm_gk20a *mm); 429int gk20a_mm_init(struct mm_gk20a *mm);