UPSTREAM: DT/arm,gic-v3: Documment PPI partition support
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_kernel_descriptor_mapping.c
1 /*
2  * Copyright (C) 2010, 2012-2014 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 "mali_kernel_common.h"
12 #include "mali_kernel_descriptor_mapping.h"
13 #include "mali_osk.h"
14 #include "mali_osk_bitops.h"
15 #include "mali_memory_types.h"
16 #include "mali_session.h"
17
18 #define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1))
19
20 /**
21  * Allocate a descriptor table capable of holding 'count' mappings
22  * @param count Number of mappings in the table
23  * @return Pointer to a new table, NULL on error
24  */
25 static mali_descriptor_table *descriptor_table_alloc(int count);
26
27 /**
28  * Free a descriptor table
29  * @param table The table to free
30  */
31 static void descriptor_table_free(mali_descriptor_table *table);
32
33 mali_descriptor_mapping *mali_descriptor_mapping_create(int init_entries, int max_entries)
34 {
35         mali_descriptor_mapping *map = _mali_osk_calloc(1, sizeof(mali_descriptor_mapping));
36
37         init_entries = MALI_PAD_INT(init_entries);
38         max_entries = MALI_PAD_INT(max_entries);
39
40         if (NULL != map) {
41                 map->table = descriptor_table_alloc(init_entries);
42                 if (NULL != map->table) {
43                         map->lock = _mali_osk_mutex_rw_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP);
44                         if (NULL != map->lock) {
45                                 _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
46                                 map->max_nr_mappings_allowed = max_entries;
47                                 map->current_nr_mappings = init_entries;
48                                 return map;
49                         }
50                         descriptor_table_free(map->table);
51                 }
52                 _mali_osk_free(map);
53         }
54         return NULL;
55 }
56
57 void mali_descriptor_mapping_destroy(mali_descriptor_mapping *map)
58 {
59         descriptor_table_free(map->table);
60         _mali_osk_mutex_rw_term(map->lock);
61         _mali_osk_free(map);
62 }
63
64 _mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping *map, void *target, int *odescriptor)
65 {
66         _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
67         int new_descriptor;
68         mali_mem_allocation *descriptor;
69         struct mali_session_data *session;
70
71         MALI_DEBUG_ASSERT_POINTER(map);
72         MALI_DEBUG_ASSERT_POINTER(odescriptor);
73         MALI_DEBUG_ASSERT_POINTER(target);
74
75         _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
76         new_descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings);
77         if (new_descriptor == map->current_nr_mappings) {
78                 /* no free descriptor, try to expand the table */
79                 mali_descriptor_table *new_table, * old_table;
80                 if (map->current_nr_mappings >= map->max_nr_mappings_allowed) goto unlock_and_exit;
81
82                 map->current_nr_mappings += BITS_PER_LONG;
83                 new_table = descriptor_table_alloc(map->current_nr_mappings);
84                 if (NULL == new_table) goto unlock_and_exit;
85
86                 old_table = map->table;
87                 _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG);
88                 _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void *));
89                 map->table = new_table;
90                 descriptor_table_free(old_table);
91         }
92
93         /* we have found a valid descriptor, set the value and usage bit */
94         _mali_osk_set_nonatomic_bit(new_descriptor, map->table->usage);
95         map->table->mappings[new_descriptor] = target;
96         *odescriptor = new_descriptor;
97
98         /* To calculate the mali mem usage for the session */
99         descriptor = (mali_mem_allocation *)target;
100         session = descriptor->session;
101
102         MALI_DEBUG_ASSERT_POINTER(session);
103
104         session->mali_mem_array[descriptor->type] += descriptor->size;
105         if ((MALI_MEM_OS == descriptor->type || MALI_MEM_BLOCK == descriptor->type) &&
106             (session->mali_mem_array[MALI_MEM_OS] + session->mali_mem_array[MALI_MEM_BLOCK] > session->max_mali_mem_allocated)) {
107                 session->max_mali_mem_allocated = session->mali_mem_array[MALI_MEM_OS] + session->mali_mem_array[MALI_MEM_BLOCK];
108         }
109         err = _MALI_OSK_ERR_OK;
110
111 unlock_and_exit:
112         _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
113         MALI_ERROR(err);
114 }
115
116 void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping *map, void (*callback)(int, void *))
117 {
118         int i;
119
120         MALI_DEBUG_ASSERT_POINTER(map);
121         MALI_DEBUG_ASSERT_POINTER(callback);
122
123         _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
124         /* id 0 is skipped as it's an reserved ID not mapping to anything */
125         for (i = 1; i < map->current_nr_mappings; ++i) {
126                 if (_mali_osk_test_bit(i, map->table->usage)) {
127                         callback(i, map->table->mappings[i]);
128                 }
129         }
130         _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
131 }
132
133 _mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping *map, int descriptor, void **target)
134 {
135         _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT;
136         MALI_DEBUG_ASSERT_POINTER(map);
137         _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
138         if ((descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
139                 *target = map->table->mappings[descriptor];
140                 result = _MALI_OSK_ERR_OK;
141         } else *target = NULL;
142         _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
143         MALI_ERROR(result);
144 }
145
146 _mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping *map, int descriptor, void *target)
147 {
148         _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT;
149         _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
150         if ((descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
151                 map->table->mappings[descriptor] = target;
152                 result = _MALI_OSK_ERR_OK;
153         }
154         _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
155         MALI_ERROR(result);
156 }
157
158 void *mali_descriptor_mapping_free(mali_descriptor_mapping *map, int descriptor)
159 {
160         void *old_value = NULL;
161         mali_mem_allocation *tmp_descriptor;
162         struct mali_session_data *session;
163
164         _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
165         if ((descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
166                 old_value = map->table->mappings[descriptor];
167                 map->table->mappings[descriptor] = NULL;
168                 _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
169         }
170         if (NULL != old_value) {
171                 tmp_descriptor = (mali_mem_allocation *)old_value;
172                 session = tmp_descriptor->session;
173
174                 MALI_DEBUG_ASSERT_POINTER(session);
175
176                 MALI_DEBUG_ASSERT(session->mali_mem_array[tmp_descriptor->type] >= tmp_descriptor->size);
177
178                 session->mali_mem_array[tmp_descriptor->type] -= tmp_descriptor->size;
179         }
180         _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
181
182         return old_value;
183 }
184
185 static mali_descriptor_table *descriptor_table_alloc(int count)
186 {
187         mali_descriptor_table *table;
188
189         table = _mali_osk_calloc(1, sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count) / BITS_PER_LONG) + (sizeof(void *) * count));
190
191         if (NULL != table) {
192                 table->usage = (u32 *)((u8 *)table + sizeof(mali_descriptor_table));
193                 table->mappings = (void **)((u8 *)table + sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count) / BITS_PER_LONG));
194         }
195
196         return table;
197 }
198
199 static void descriptor_table_free(mali_descriptor_table *table)
200 {
201         _mali_osk_free(table);
202 }