diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 32 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.h | 4 |
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) | |||
3136 | static void gk20a_vidmem_clear_mem_worker(struct work_struct *work) | 3141 | static 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 | ||
427 | int gk20a_mm_init(struct mm_gk20a *mm); | 429 | int gk20a_mm_init(struct mm_gk20a *mm); |