bcca43c09f0bb6a5950e84cc8fea4dfffb80a4d9
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / linux / mali_memory_util.c
1 /*
2  * Copyright (C) 2013-2015 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 #include <linux/list.h>
12 #include <linux/mm.h>
13 #include <linux/mm_types.h>
14 #include <linux/fs.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/slab.h>
17 #include <linux/platform_device.h>
18
19 #include "mali_osk.h"
20 #include "mali_osk_mali.h"
21 #include "mali_kernel_linux.h"
22 #include "mali_scheduler.h"
23
24 #include "mali_memory.h"
25 #include "mali_memory_os_alloc.h"
26 #if defined(CONFIG_DMA_SHARED_BUFFER)
27 #include "mali_memory_dma_buf.h"
28 #endif
29 #if defined(CONFIG_MALI400_UMP)
30 #include "mali_memory_ump.h"
31 #endif
32 #include "mali_memory_external.h"
33 #include "mali_memory_manager.h"
34 #include "mali_memory_virtual.h"
35 #include "mali_memory_cow.h"
36 #include "mali_memory_block_alloc.h"
37 #include "mali_memory_swap_alloc.h"
38
39
40
41 /**
42 *function @_mali_free_allocation_mem - free a memory allocation
43 */
44 static u32 _mali_free_allocation_mem(mali_mem_allocation *mali_alloc)
45 {
46         mali_mem_backend *mem_bkend = NULL;
47         u32 free_pages_nr = 0;
48
49         struct mali_session_data *session = mali_alloc->session;
50         MALI_DEBUG_PRINT(4, (" _mali_free_allocation_mem, psize =0x%x! \n", mali_alloc->psize));
51         if (0 == mali_alloc->psize)
52                 goto out;
53
54         /* Get backend memory & Map on CPU */
55         mutex_lock(&mali_idr_mutex);
56         mem_bkend = idr_find(&mali_backend_idr, mali_alloc->backend_handle);
57         mutex_unlock(&mali_idr_mutex);
58         MALI_DEBUG_ASSERT(NULL != mem_bkend);
59
60         switch (mem_bkend->type) {
61         case MALI_MEM_OS:
62                 free_pages_nr = mali_mem_os_release(mem_bkend);
63                 atomic_sub(free_pages_nr, &session->mali_mem_allocated_pages);
64                 break;
65         case MALI_MEM_UMP:
66 #if defined(CONFIG_MALI400_UMP)
67                 mali_mem_unbind_ump_buf(mem_bkend);
68                 atomic_sub(mem_bkend->size / MALI_MMU_PAGE_SIZE, &session->mali_mem_array[mem_bkend->type]);
69 #else
70                 MALI_DEBUG_PRINT(2, ("UMP not supported\n"));
71 #endif
72                 break;
73         case MALI_MEM_DMA_BUF:
74 #if defined(CONFIG_DMA_SHARED_BUFFER)
75                 mali_mem_unbind_dma_buf(mem_bkend);
76                 atomic_sub(mem_bkend->size / MALI_MMU_PAGE_SIZE, &session->mali_mem_array[mem_bkend->type]);
77 #else
78                 MALI_DEBUG_PRINT(2, ("DMA not supported\n"));
79 #endif
80                 break;
81         case MALI_MEM_EXTERNAL:
82                 mali_mem_unbind_ext_buf(mem_bkend);
83                 atomic_sub(mem_bkend->size / MALI_MMU_PAGE_SIZE, &session->mali_mem_array[mem_bkend->type]);
84                 break;
85
86         case MALI_MEM_BLOCK:
87                 free_pages_nr = mali_mem_block_release(mem_bkend);
88                 atomic_sub(free_pages_nr, &session->mali_mem_allocated_pages);
89                 break;
90
91         case MALI_MEM_COW:
92                 if (mem_bkend->flags & MALI_MEM_BACKEND_FLAG_SWAP_COWED) {
93                         free_pages_nr = mali_mem_swap_release(mem_bkend, MALI_TRUE);
94                 } else {
95                         free_pages_nr = mali_mem_cow_release(mem_bkend, MALI_TRUE);
96                 }
97                 atomic_sub(free_pages_nr, &session->mali_mem_allocated_pages);
98                 break;
99         case MALI_MEM_SWAP:
100                 free_pages_nr = mali_mem_swap_release(mem_bkend, MALI_TRUE);
101                 atomic_sub(free_pages_nr, &session->mali_mem_allocated_pages);
102                 atomic_sub(free_pages_nr, &session->mali_mem_array[mem_bkend->type]);
103                 break;
104         default:
105                 MALI_DEBUG_PRINT(1, ("mem type %d is not in the mali_mem_type enum.\n", mem_bkend->type));
106                 break;
107         }
108
109         /*Remove backend memory idex */
110         mutex_lock(&mali_idr_mutex);
111         idr_remove(&mali_backend_idr, mali_alloc->backend_handle);
112         mutex_unlock(&mali_idr_mutex);
113         kfree(mem_bkend);
114 out:
115         /* remove memory allocation  */
116         mali_vma_offset_remove(&session->allocation_mgr, &mali_alloc->mali_vma_node);
117         mali_mem_allocation_struct_destory(mali_alloc);
118         return free_pages_nr;
119 }
120
121 /**
122 *  ref_count for allocation
123 */
124 u32 mali_allocation_unref(struct mali_mem_allocation **alloc)
125 {
126         u32 free_pages_nr = 0;
127         mali_mem_allocation *mali_alloc = *alloc;
128         *alloc = NULL;
129         if (0 == _mali_osk_atomic_dec_return(&mali_alloc->mem_alloc_refcount)) {
130                 free_pages_nr = _mali_free_allocation_mem(mali_alloc);
131         }
132         return free_pages_nr;
133 }
134
135 void mali_allocation_ref(struct mali_mem_allocation *alloc)
136 {
137         _mali_osk_atomic_inc(&alloc->mem_alloc_refcount);
138 }
139
140 void mali_free_session_allocations(struct mali_session_data *session)
141 {
142         struct mali_mem_allocation *entry, *next;
143
144         MALI_DEBUG_PRINT(4, (" mali_free_session_allocations! \n"));
145
146         list_for_each_entry_safe(entry, next, &session->allocation_mgr.head, list) {
147                 mali_allocation_unref(&entry);
148         }
149 }