import OT_8063_20170412 mali driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / ump / linux / ump_kernel_random_mapping.c
1 /*
2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2008-2011, 2013-2015 ARM Limited
5 * ALL RIGHTS RESERVED
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
9 */
10
11 #include "mali_kernel_common.h"
12 #include "mali_osk.h"
13 #include "ump_osk.h"
14 #include "ump_kernel_common.h"
15 #include "ump_kernel_types.h"
16 #include "ump_kernel_random_mapping.h"
17
18 #include <linux/random.h>
19 #include <linux/rbtree.h>
20 #include <linux/sched.h>
21 #include <linux/jiffies.h>
22
23
24 static ump_dd_mem *search(struct rb_root *root, int id)
25 {
26 struct rb_node *node = root->rb_node;
27
28 while (node) {
29 ump_dd_mem *e = container_of(node, ump_dd_mem, node);
30
31 if (id < e->secure_id) {
32 node = node->rb_left;
33 } else if (id > e->secure_id) {
34 node = node->rb_right;
35 } else {
36 return e;
37 }
38 }
39
40 return NULL;
41 }
42
43 static mali_bool insert(struct rb_root *root, int id, ump_dd_mem *mem)
44 {
45 struct rb_node **new = &(root->rb_node);
46 struct rb_node *parent = NULL;
47
48 while (*new) {
49 ump_dd_mem *this = container_of(*new, ump_dd_mem, node);
50
51 parent = *new;
52 if (id < this->secure_id) {
53 new = &((*new)->rb_left);
54 } else if (id > this->secure_id) {
55 new = &((*new)->rb_right);
56 } else {
57 pr_warn("UMP: ID already used %x\n", id);
58 return MALI_FALSE;
59 }
60 }
61
62 rb_link_node(&mem->node, parent, new);
63 rb_insert_color(&mem->node, root);
64
65 return MALI_TRUE;
66 }
67
68
69 ump_random_mapping *ump_random_mapping_create(void)
70 {
71 ump_random_mapping *map = _mali_osk_calloc(1, sizeof(ump_random_mapping));
72
73 if (NULL == map)
74 return NULL;
75
76 map->lock = _mali_osk_mutex_rw_init(_MALI_OSK_LOCKFLAG_ORDERED,
77 _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP);
78 if (NULL != map->lock) {
79 map->root = RB_ROOT;
80 #if UMP_RANDOM_MAP_DELAY
81 map->failed.count = 0;
82 map->failed.timestamp = jiffies;
83 #endif
84 return map;
85 }
86 return NULL;
87 }
88
89 void ump_random_mapping_destroy(ump_random_mapping *map)
90 {
91 _mali_osk_mutex_rw_term(map->lock);
92 _mali_osk_free(map);
93 }
94
95 int ump_random_mapping_insert(ump_random_mapping *map, ump_dd_mem *mem)
96 {
97 _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
98
99 while (1) {
100 u32 id;
101
102 get_random_bytes(&id, sizeof(id));
103
104 /* Try a new random number if id happened to be the invalid
105 * secure ID (-1). */
106 if (unlikely(id == UMP_INVALID_SECURE_ID))
107 continue;
108
109 /* Insert into the tree. If the id was already in use, get a
110 * new random id and try again. */
111 if (insert(&map->root, id, mem)) {
112 mem->secure_id = id;
113 break;
114 }
115 }
116 _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
117
118 return 0;
119 }
120
121 ump_dd_mem *ump_random_mapping_get(ump_random_mapping *map, int id)
122 {
123 ump_dd_mem *mem = NULL;
124 #if UMP_RANDOM_MAP_DELAY
125 int do_delay = 0;
126 #endif
127
128 DEBUG_ASSERT(map);
129
130 _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
131 mem = search(&map->root, id);
132
133 if (unlikely(NULL == mem)) {
134 #if UMP_RANDOM_MAP_DELAY
135 map->failed.count++;
136
137 if (time_is_before_jiffies(map->failed.timestamp +
138 UMP_FAILED_LOOKUP_DELAY * HZ)) {
139 /* If it is a long time since last failure, reset
140 * the counter and skip the delay this time. */
141 map->failed.count = 0;
142 } else if (map->failed.count > UMP_FAILED_LOOKUPS_ALLOWED) {
143 do_delay = 1;
144 }
145
146 map->failed.timestamp = jiffies;
147 #endif /* UMP_RANDOM_MAP_DELAY */
148 } else {
149 ump_dd_reference_add(mem);
150 }
151 _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
152
153 #if UMP_RANDOM_MAP_DELAY
154 if (do_delay) {
155 /* Apply delay */
156 schedule_timeout_killable(UMP_FAILED_LOOKUP_DELAY);
157 }
158 #endif /* UMP_RANDOM_MAP_DELAY */
159
160 return mem;
161 }
162
163 static ump_dd_mem *ump_random_mapping_remove_internal(ump_random_mapping *map, int id)
164 {
165 ump_dd_mem *mem = NULL;
166
167 mem = search(&map->root, id);
168
169 if (mem) {
170 rb_erase(&mem->node, &map->root);
171 }
172
173 return mem;
174 }
175
176 void ump_random_mapping_put(ump_dd_mem *mem)
177 {
178 int new_ref;
179
180 _mali_osk_mutex_rw_wait(device.secure_id_map->lock, _MALI_OSK_LOCKMODE_RW);
181
182 new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count);
183 DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n",
184 mem->secure_id, new_ref));
185
186 if (0 == new_ref) {
187 DBG_MSG(3, ("Final release of memory. ID: %u\n", mem->secure_id));
188
189 ump_random_mapping_remove_internal(device.secure_id_map, mem->secure_id);
190
191 mem->release_func(mem->ctx, mem);
192 _mali_osk_free(mem);
193 }
194
195 _mali_osk_mutex_rw_signal(device.secure_id_map->lock, _MALI_OSK_LOCKMODE_RW);
196 }
197
198 ump_dd_mem *ump_random_mapping_remove(ump_random_mapping *map, int descriptor)
199 {
200 ump_dd_mem *mem;
201
202 _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
203 mem = ump_random_mapping_remove_internal(map, descriptor);
204 _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
205
206 return mem;
207 }