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 = kzalloc(struct_size * capacity, 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 bool dal_vector_presized_costruct( 54 struct vector *vector, 55 struct dc_context *ctx, 56 uint32_t count, 57 void *initial_value, 58 uint32_t struct_size) 59 { 60 uint32_t i; 61 62 vector->container = NULL; 63 64 if (!struct_size || !count) { 65 /* Container must be non-zero size*/ 66 BREAK_TO_DEBUGGER(); 67 return false; 68 } 69 70 vector->container = kzalloc(struct_size * count, GFP_KERNEL); 71 72 if (vector->container == NULL) 73 return false; 74 75 /* If caller didn't supply initial value then the default 76 * of all zeros is expected, which is exactly what dal_alloc() 77 * initialises the memory to. */ 78 if (NULL != initial_value) { 79 for (i = 0; i < count; ++i) 80 memmove( 81 vector->container + i * struct_size, 82 initial_value, 83 struct_size); 84 } 85 86 vector->capacity = count; 87 vector->struct_size = struct_size; 88 vector->count = count; 89 return true; 90 } 91 92 struct vector *dal_vector_presized_create( 93 struct dc_context *ctx, 94 uint32_t size, 95 void *initial_value, 96 uint32_t struct_size) 97 { 98 struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); 99 100 if (vector == NULL) 101 return NULL; 102 103 if (dal_vector_presized_costruct( 104 vector, ctx, size, initial_value, struct_size)) 105 return vector; 106 107 BREAK_TO_DEBUGGER(); 108 kfree(vector); 109 return NULL; 110 } 111 112 struct vector *dal_vector_create( 113 struct dc_context *ctx, 114 uint32_t capacity, 115 uint32_t struct_size) 116 { 117 struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); 118 119 if (vector == NULL) 120 return NULL; 121 122 if (dal_vector_construct(vector, ctx, capacity, struct_size)) 123 return vector; 124 125 BREAK_TO_DEBUGGER(); 126 kfree(vector); 127 return NULL; 128 } 129 130 void dal_vector_destruct( 131 struct vector *vector) 132 { 133 if (vector->container != NULL) 134 kfree(vector->container); 135 vector->count = 0; 136 vector->capacity = 0; 137 } 138 139 void dal_vector_destroy( 140 struct vector **vector) 141 { 142 if (vector == NULL || *vector == NULL) 143 return; 144 dal_vector_destruct(*vector); 145 kfree(*vector); 146 *vector = NULL; 147 } 148 149 uint32_t dal_vector_get_count( 150 const struct vector *vector) 151 { 152 return vector->count; 153 } 154 155 void *dal_vector_at_index( 156 const struct vector *vector, 157 uint32_t index) 158 { 159 if (vector->container == NULL || index >= vector->count) 160 return NULL; 161 return vector->container + (index * vector->struct_size); 162 } 163 164 bool dal_vector_remove_at_index( 165 struct vector *vector, 166 uint32_t index) 167 { 168 if (index >= vector->count) 169 return false; 170 171 if (index != vector->count - 1) 172 memmove( 173 vector->container + (index * vector->struct_size), 174 vector->container + ((index + 1) * vector->struct_size), 175 (vector->count - index - 1) * vector->struct_size); 176 vector->count -= 1; 177 178 return true; 179 } 180 181 void dal_vector_set_at_index( 182 const struct vector *vector, 183 const void *what, 184 uint32_t index) 185 { 186 void *where = dal_vector_at_index(vector, index); 187 188 if (!where) { 189 BREAK_TO_DEBUGGER(); 190 return; 191 } 192 memmove( 193 where, 194 what, 195 vector->struct_size); 196 } 197 198 static inline uint32_t calc_increased_capacity( 199 uint32_t old_capacity) 200 { 201 return old_capacity * 2; 202 } 203 204 bool dal_vector_insert_at( 205 struct vector *vector, 206 const void *what, 207 uint32_t position) 208 { 209 uint8_t *insert_address; 210 211 if (vector->count == vector->capacity) { 212 if (!dal_vector_reserve( 213 vector, 214 calc_increased_capacity(vector->capacity))) 215 return false; 216 } 217 218 insert_address = vector->container + (vector->struct_size * position); 219 220 if (vector->count && position < vector->count) 221 memmove( 222 insert_address + vector->struct_size, 223 insert_address, 224 vector->struct_size * (vector->count - position)); 225 226 memmove( 227 insert_address, 228 what, 229 vector->struct_size); 230 231 vector->count++; 232 233 return true; 234 } 235 236 bool dal_vector_append( 237 struct vector *vector, 238 const void *item) 239 { 240 return dal_vector_insert_at(vector, item, vector->count); 241 } 242 243 struct vector *dal_vector_clone( 244 const struct vector *vector) 245 { 246 struct vector *vec_cloned; 247 uint32_t count; 248 249 /* create new vector */ 250 count = dal_vector_get_count(vector); 251 252 if (count == 0) 253 /* when count is 0 we still want to create clone of the vector 254 */ 255 vec_cloned = dal_vector_create( 256 vector->ctx, 257 vector->capacity, 258 vector->struct_size); 259 else 260 /* Call "presized create" version, independently of how the 261 * original vector was created. 262 * The owner of original vector must know how to treat the new 263 * vector - as "presized" or as "regular". 264 * But from vector point of view it doesn't matter. */ 265 vec_cloned = dal_vector_presized_create(vector->ctx, count, 266 NULL,/* no initial value */ 267 vector->struct_size); 268 269 if (NULL == vec_cloned) { 270 BREAK_TO_DEBUGGER(); 271 return NULL; 272 } 273 274 /* copy vector's data */ 275 memmove(vec_cloned->container, vector->container, 276 vec_cloned->struct_size * vec_cloned->capacity); 277 278 return vec_cloned; 279 } 280 281 uint32_t dal_vector_capacity(const struct vector *vector) 282 { 283 return vector->capacity; 284 } 285 286 bool dal_vector_reserve(struct vector *vector, uint32_t capacity) 287 { 288 void *new_container; 289 290 if (capacity <= vector->capacity) 291 return true; 292 293 new_container = krealloc(vector->container, 294 capacity * vector->struct_size, GFP_KERNEL); 295 296 if (new_container) { 297 vector->container = new_container; 298 vector->capacity = capacity; 299 return true; 300 } 301 302 return false; 303 } 304 305 void dal_vector_clear(struct vector *vector) 306 { 307 vector->count = 0; 308 } 309