1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include "dm_services.h" 27 #include "include/vector.h" 28 29 bool dal_vector_construct( 30 struct vector *vector, 31 struct dc_context *ctx, 32 uint32_t capacity, 33 uint32_t struct_size) 34 { 35 vector->container = NULL; 36 37 if (!struct_size || !capacity) { 38 /* Container must be non-zero size*/ 39 BREAK_TO_DEBUGGER(); 40 return false; 41 } 42 43 vector->container = kcalloc(capacity, struct_size, GFP_KERNEL); 44 if (vector->container == NULL) 45 return false; 46 vector->capacity = capacity; 47 vector->struct_size = struct_size; 48 vector->count = 0; 49 vector->ctx = ctx; 50 return true; 51 } 52 53 static bool dal_vector_presized_costruct(struct vector *vector, 54 struct dc_context *ctx, 55 uint32_t count, 56 void *initial_value, 57 uint32_t struct_size) 58 { 59 uint32_t i; 60 61 vector->container = NULL; 62 63 if (!struct_size || !count) { 64 /* Container must be non-zero size*/ 65 BREAK_TO_DEBUGGER(); 66 return false; 67 } 68 69 vector->container = kcalloc(count, struct_size, GFP_KERNEL); 70 71 if (vector->container == NULL) 72 return false; 73 74 /* If caller didn't supply initial value then the default 75 * of all zeros is expected, which is exactly what dal_alloc() 76 * initialises the memory to. */ 77 if (NULL != initial_value) { 78 for (i = 0; i < count; ++i) 79 memmove( 80 vector->container + i * struct_size, 81 initial_value, 82 struct_size); 83 } 84 85 vector->capacity = count; 86 vector->struct_size = struct_size; 87 vector->count = count; 88 return true; 89 } 90 91 struct vector *dal_vector_presized_create( 92 struct dc_context *ctx, 93 uint32_t size, 94 void *initial_value, 95 uint32_t struct_size) 96 { 97 struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); 98 99 if (vector == NULL) 100 return NULL; 101 102 if (dal_vector_presized_costruct( 103 vector, ctx, size, initial_value, struct_size)) 104 return vector; 105 106 BREAK_TO_DEBUGGER(); 107 kfree(vector); 108 return NULL; 109 } 110 111 struct vector *dal_vector_create( 112 struct dc_context *ctx, 113 uint32_t capacity, 114 uint32_t struct_size) 115 { 116 struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); 117 118 if (vector == NULL) 119 return NULL; 120 121 if (dal_vector_construct(vector, ctx, capacity, struct_size)) 122 return vector; 123 124 BREAK_TO_DEBUGGER(); 125 kfree(vector); 126 return NULL; 127 } 128 129 void dal_vector_destruct( 130 struct vector *vector) 131 { 132 kfree(vector->container); 133 vector->count = 0; 134 vector->capacity = 0; 135 } 136 137 void dal_vector_destroy( 138 struct vector **vector) 139 { 140 if (vector == NULL || *vector == NULL) 141 return; 142 dal_vector_destruct(*vector); 143 kfree(*vector); 144 *vector = NULL; 145 } 146 147 uint32_t dal_vector_get_count( 148 const struct vector *vector) 149 { 150 return vector->count; 151 } 152 153 void *dal_vector_at_index( 154 const struct vector *vector, 155 uint32_t index) 156 { 157 if (vector->container == NULL || index >= vector->count) 158 return NULL; 159 return vector->container + (index * vector->struct_size); 160 } 161 162 bool dal_vector_remove_at_index( 163 struct vector *vector, 164 uint32_t index) 165 { 166 if (index >= vector->count) 167 return false; 168 169 if (index != vector->count - 1) 170 memmove( 171 vector->container + (index * vector->struct_size), 172 vector->container + ((index + 1) * vector->struct_size), 173 (vector->count - index - 1) * vector->struct_size); 174 vector->count -= 1; 175 176 return true; 177 } 178 179 void dal_vector_set_at_index( 180 const struct vector *vector, 181 const void *what, 182 uint32_t index) 183 { 184 void *where = dal_vector_at_index(vector, index); 185 186 if (!where) { 187 BREAK_TO_DEBUGGER(); 188 return; 189 } 190 memmove( 191 where, 192 what, 193 vector->struct_size); 194 } 195 196 static inline uint32_t calc_increased_capacity( 197 uint32_t old_capacity) 198 { 199 return old_capacity * 2; 200 } 201 202 bool dal_vector_insert_at( 203 struct vector *vector, 204 const void *what, 205 uint32_t position) 206 { 207 uint8_t *insert_address; 208 209 if (vector->count == vector->capacity) { 210 if (!dal_vector_reserve( 211 vector, 212 calc_increased_capacity(vector->capacity))) 213 return false; 214 } 215 216 insert_address = vector->container + (vector->struct_size * position); 217 218 if (vector->count && position < vector->count) 219 memmove( 220 insert_address + vector->struct_size, 221 insert_address, 222 vector->struct_size * (vector->count - position)); 223 224 memmove( 225 insert_address, 226 what, 227 vector->struct_size); 228 229 vector->count++; 230 231 return true; 232 } 233 234 bool dal_vector_append( 235 struct vector *vector, 236 const void *item) 237 { 238 return dal_vector_insert_at(vector, item, vector->count); 239 } 240 241 struct vector *dal_vector_clone( 242 const struct vector *vector) 243 { 244 struct vector *vec_cloned; 245 uint32_t count; 246 247 /* create new vector */ 248 count = dal_vector_get_count(vector); 249 250 if (count == 0) 251 /* when count is 0 we still want to create clone of the vector 252 */ 253 vec_cloned = dal_vector_create( 254 vector->ctx, 255 vector->capacity, 256 vector->struct_size); 257 else 258 /* Call "presized create" version, independently of how the 259 * original vector was created. 260 * The owner of original vector must know how to treat the new 261 * vector - as "presized" or as "regular". 262 * But from vector point of view it doesn't matter. */ 263 vec_cloned = dal_vector_presized_create(vector->ctx, count, 264 NULL,/* no initial value */ 265 vector->struct_size); 266 267 if (NULL == vec_cloned) { 268 BREAK_TO_DEBUGGER(); 269 return NULL; 270 } 271 272 /* copy vector's data */ 273 memmove(vec_cloned->container, vector->container, 274 vec_cloned->struct_size * vec_cloned->capacity); 275 276 return vec_cloned; 277 } 278 279 uint32_t dal_vector_capacity(const struct vector *vector) 280 { 281 return vector->capacity; 282 } 283 284 bool dal_vector_reserve(struct vector *vector, uint32_t capacity) 285 { 286 void *new_container; 287 288 if (capacity <= vector->capacity) 289 return true; 290 291 new_container = krealloc(vector->container, 292 capacity * vector->struct_size, GFP_KERNEL); 293 294 if (new_container) { 295 vector->container = new_container; 296 vector->capacity = capacity; 297 return true; 298 } 299 300 return false; 301 } 302 303 void dal_vector_clear(struct vector *vector) 304 { 305 vector->count = 0; 306 } 307