• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010-2011, 2013-2014, 2016-2017 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 
ump_descriptor_mapping_create(int init_entries,int max_entries)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 		map->table = descriptor_table_alloc(init_entries);
41 		if (NULL != map->table) {
42 			map->lock = _mali_osk_mutex_rw_init(_MALI_OSK_LOCKFLAG_UNORDERED, 0);
43 			if (NULL != map->lock) {
44 				_mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
45 				map->max_nr_mappings_allowed = max_entries;
46 				map->current_nr_mappings = init_entries;
47 				return map;
48 			}
49 			descriptor_table_free(map->table);
50 		}
51 		_mali_osk_free(map);
52 	}
53 	return NULL;
54 }
55 
ump_descriptor_mapping_destroy(ump_descriptor_mapping * map)56 void ump_descriptor_mapping_destroy(ump_descriptor_mapping *map)
57 {
58 	descriptor_table_free(map->table);
59 	_mali_osk_mutex_rw_term(map->lock);
60 	_mali_osk_free(map);
61 }
62 
ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map,void * target)63 int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping *map, void *target)
64 {
65 	int descriptor = -1;/*-EFAULT;*/
66 	_mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
67 	descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings);
68 	if (descriptor == map->current_nr_mappings) {
69 		int nr_mappings_new;
70 		/* no free descriptor, try to expand the table */
71 		ump_descriptor_table *new_table;
72 		ump_descriptor_table *old_table = map->table;
73 		nr_mappings_new = map->current_nr_mappings * 2;
74 
75 		if (map->current_nr_mappings >= map->max_nr_mappings_allowed) {
76 			descriptor = -1;
77 			goto unlock_and_exit;
78 		}
79 
80 		new_table = descriptor_table_alloc(nr_mappings_new);
81 		if (NULL == new_table) {
82 			descriptor = -1;
83 			goto unlock_and_exit;
84 		}
85 
86 		_mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG);
87 		_mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void *));
88 		map->table = new_table;
89 		map->current_nr_mappings = nr_mappings_new;
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(descriptor, map->table->usage);
95 	map->table->mappings[descriptor] = target;
96 
97 unlock_and_exit:
98 	_mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
99 	return descriptor;
100 }
101 
ump_descriptor_mapping_get(ump_descriptor_mapping * map,int descriptor,void ** target)102 int ump_descriptor_mapping_get(ump_descriptor_mapping *map, int descriptor, void **target)
103 {
104 	int result = -1;/*-EFAULT;*/
105 	DEBUG_ASSERT(map);
106 	_mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
107 	if ((descriptor > 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
108 		*target = map->table->mappings[descriptor];
109 		result = 0;
110 	} else *target = NULL;
111 	_mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
112 	return result;
113 }
114 
ump_descriptor_mapping_set(ump_descriptor_mapping * map,int descriptor,void * target)115 int ump_descriptor_mapping_set(ump_descriptor_mapping *map, int descriptor, void *target)
116 {
117 	int result = -1;/*-EFAULT;*/
118 	_mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
119 	if ((descriptor > 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
120 		map->table->mappings[descriptor] = target;
121 		result = 0;
122 	}
123 	_mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
124 	return result;
125 }
126 
ump_descriptor_mapping_free(ump_descriptor_mapping * map,int descriptor)127 void ump_descriptor_mapping_free(ump_descriptor_mapping *map, int descriptor)
128 {
129 	_mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
130 	if ((descriptor > 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
131 		map->table->mappings[descriptor] = NULL;
132 		_mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
133 	}
134 	_mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
135 }
136 
descriptor_table_alloc(int count)137 static ump_descriptor_table *descriptor_table_alloc(int count)
138 {
139 	ump_descriptor_table *table;
140 
141 	table = _mali_osk_calloc(1, sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count) / BITS_PER_LONG) + (sizeof(void *) * count));
142 
143 	if (NULL != table) {
144 		table->usage = (u32 *)((u8 *)table + sizeof(ump_descriptor_table));
145 		table->mappings = (void **)((u8 *)table + sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count) / BITS_PER_LONG));
146 	}
147 
148 	return table;
149 }
150 
descriptor_table_free(ump_descriptor_table * table)151 static void descriptor_table_free(ump_descriptor_table *table)
152 {
153 	_mali_osk_free(table);
154 }
155 
156