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