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( 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 = kcalloc(count, struct_size, 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 kfree(vector->container); 134 vector->count = 0; 135 vector->capacity = 0; 136 } 137 138 void dal_vector_destroy( 139 struct vector **vector) 140 { 141 if (vector == NULL || *vector == NULL) 142 return; 143 dal_vector_destruct(*vector); 144 kfree(*vector); 145 *vector = NULL; 146 } 147 148 uint32_t dal_vector_get_count( 149 const struct vector *vector) 150 { 151 return vector->count; 152 } 153 154 void *dal_vector_at_index( 155 const struct vector *vector, 156 uint32_t index) 157 { 158 if (vector->container == NULL || index >= vector->count) 159 return NULL; 160 return vector->container + (index * vector->struct_size); 161 } 162 163 bool dal_vector_remove_at_index( 164 struct vector *vector, 165 uint32_t index) 166 { 167 if (index >= vector->count) 168 return false; 169 170 if (index != vector->count - 1) 171 memmove( 172 vector->container + (index * vector->struct_size), 173 vector->container + ((index + 1) * vector->struct_size), 174 (vector->count - index - 1) * vector->struct_size); 175 vector->count -= 1; 176 177 return true; 178 } 179 180 void dal_vector_set_at_index( 181 const struct vector *vector, 182 const void *what, 183 uint32_t index) 184 { 185 void *where = dal_vector_at_index(vector, index); 186 187 if (!where) { 188 BREAK_TO_DEBUGGER(); 189 return; 190 } 191 memmove( 192 where, 193 what, 194 vector->struct_size); 195 } 196 197 static inline uint32_t calc_increased_capacity( 198 uint32_t old_capacity) 199 { 200 return old_capacity * 2; 201 } 202 203 bool dal_vector_insert_at( 204 struct vector *vector, 205 const void *what, 206 uint32_t position) 207 { 208 uint8_t *insert_address; 209 210 if (vector->count == vector->capacity) { 211 if (!dal_vector_reserve( 212 vector, 213 calc_increased_capacity(vector->capacity))) 214 return false; 215 } 216 217 insert_address = vector->container + (vector->struct_size * position); 218 219 if (vector->count && position < vector->count) 220 memmove( 221 insert_address + vector->struct_size, 222 insert_address, 223 vector->struct_size * (vector->count - position)); 224 225 memmove( 226 insert_address, 227 what, 228 vector->struct_size); 229 230 vector->count++; 231 232 return true; 233 } 234 235 bool dal_vector_append( 236 struct vector *vector, 237 const void *item) 238 { 239 return dal_vector_insert_at(vector, item, vector->count); 240 } 241 242 struct vector *dal_vector_clone( 243 const struct vector *vector) 244 { 245 struct vector *vec_cloned; 246 uint32_t count; 247 248 /* create new vector */ 249 count = dal_vector_get_count(vector); 250 251 if (count == 0) 252 /* when count is 0 we still want to create clone of the vector 253 */ 254 vec_cloned = dal_vector_create( 255 vector->ctx, 256 vector->capacity, 257 vector->struct_size); 258 else 259 /* Call "presized create" version, independently of how the 260 * original vector was created. 261 * The owner of original vector must know how to treat the new 262 * vector - as "presized" or as "regular". 263 * But from vector point of view it doesn't matter. */ 264 vec_cloned = dal_vector_presized_create(vector->ctx, count, 265 NULL,/* no initial value */ 266 vector->struct_size); 267 268 if (NULL == vec_cloned) { 269 BREAK_TO_DEBUGGER(); 270 return NULL; 271 } 272 273 /* copy vector's data */ 274 memmove(vec_cloned->container, vector->container, 275 vec_cloned->struct_size * vec_cloned->capacity); 276 277 return vec_cloned; 278 } 279 280 uint32_t dal_vector_capacity(const struct vector *vector) 281 { 282 return vector->capacity; 283 } 284 285 bool dal_vector_reserve(struct vector *vector, uint32_t capacity) 286 { 287 void *new_container; 288 289 if (capacity <= vector->capacity) 290 return true; 291 292 new_container = krealloc(vector->container, 293 capacity * vector->struct_size, GFP_KERNEL); 294 295 if (new_container) { 296 vector->container = new_container; 297 vector->capacity = capacity; 298 return true; 299 } 300 301 return false; 302 } 303 304 void dal_vector_clear(struct vector *vector) 305 { 306 vector->count = 0; 307 } 308