tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / ump / common / ump_kernel_descriptor_mapping.c
1 /*
2  * Copyright (C) 2011-2012 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_osk.h"
13 #include "mali_osk_bitops.h"
14 #include "ump_kernel_common.h"
15 #include "ump_kernel_descriptor_mapping.h"
16
17 #define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1))
18
19 /**
20  * Allocate a descriptor table capable of holding 'count' mappings
21  * @param count Number of mappings in the table
22  * @return Pointer to a new table, NULL on error
23  */
24 static ump_descriptor_table * descriptor_table_alloc(int count);
25
26 /**
27  * Free a descriptor table
28  * @param table The table to free
29  */
30 static void descriptor_table_free(ump_descriptor_table * table);
31
32 ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries)
33 {
34         ump_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(ump_descriptor_mapping) );
35
36         init_entries = MALI_PAD_INT(init_entries);
37         max_entries = MALI_PAD_INT(max_entries);
38
39         if (NULL != map)
40         {
41                 map->table = descriptor_table_alloc(init_entries);
42                 if (NULL != map->table)
43                 {
44                         map->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_READERWRITER, 0 , 0);
45                         if ( NULL != map->lock )
46                         {
47                                 _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
48                                 map->max_nr_mappings_allowed = max_entries;
49                                 map->current_nr_mappings = init_entries;
50                                 return map;
51                         }
52                         descriptor_table_free(map->table);
53                 }
54                 _mali_osk_free(map);
55         }
56         return NULL;
57 }
58
59 void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map)
60 {
61         descriptor_table_free(map->table);
62         _mali_osk_lock_term( map->lock );
63         _mali_osk_free(map);
64 }
65
66 int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target)
67 {
68         int descriptor = -1;/*-EFAULT;*/
69         _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
70         descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings);
71         if (descriptor == map->current_nr_mappings)
72         {
73                 int nr_mappings_new;
74                 /* no free descriptor, try to expand the table */
75                 ump_descriptor_table * new_table;
76                 ump_descriptor_table * old_table = map->table;
77                 nr_mappings_new= map->current_nr_mappings *2;
78
79                 if (map->current_nr_mappings >= map->max_nr_mappings_allowed)
80                 {
81                         descriptor = -1;
82                         goto unlock_and_exit;
83                 }
84
85                 new_table = descriptor_table_alloc(nr_mappings_new);
86                 if (NULL == new_table)
87                 {
88                         descriptor = -1;
89                         goto unlock_and_exit;
90                 }
91
92                 _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG);
93                 _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*));
94                 map->table = new_table;
95                 map->current_nr_mappings = nr_mappings_new;
96                 descriptor_table_free(old_table);
97         }
98
99         /* we have found a valid descriptor, set the value and usage bit */
100         _mali_osk_set_nonatomic_bit(descriptor, map->table->usage);
101         map->table->mappings[descriptor] = target;
102
103 unlock_and_exit:
104         _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
105         return descriptor;
106 }
107
108 int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target)
109 {
110         int result = -1;/*-EFAULT;*/
111         DEBUG_ASSERT(map);
112         _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
113         if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) )
114         {
115                 *target = map->table->mappings[descriptor];
116                 result = 0;
117         }
118         else *target = NULL;
119         _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
120         return result;
121 }
122
123 int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target)
124 {
125         int result = -1;/*-EFAULT;*/
126         _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
127         if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) )
128         {
129                 map->table->mappings[descriptor] = target;
130                 result = 0;
131         }
132         _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
133         return result;
134 }
135
136 void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor)
137 {
138         _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
139         if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) )
140         {
141                 map->table->mappings[descriptor] = NULL;
142                 _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
143         }
144         _mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
145 }
146
147 static ump_descriptor_table * descriptor_table_alloc(int count)
148 {
149         ump_descriptor_table * table;
150
151         table = _mali_osk_calloc(1, sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count) );
152
153         if (NULL != table)
154         {
155                 table->usage = (u32*)((u8*)table + sizeof(ump_descriptor_table));
156                 table->mappings = (void**)((u8*)table + sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG));
157         }
158
159         return table;
160 }
161
162 static void descriptor_table_free(ump_descriptor_table * table)
163 {
164         _mali_osk_free(table);
165 }
166