307 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "dm_services.h"27#include "include/vector.h"28 29bool 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 53static 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 default75 * 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 91struct 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 111struct 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 129void dal_vector_destruct(130 struct vector *vector)131{132 kfree(vector->container);133 vector->count = 0;134 vector->capacity = 0;135}136 137void 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 147uint32_t dal_vector_get_count(148 const struct vector *vector)149{150 return vector->count;151}152 153void *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 162bool 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 179void 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 196static inline uint32_t calc_increased_capacity(197 uint32_t old_capacity)198{199 return old_capacity * 2;200}201 202bool 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 234bool dal_vector_append(235 struct vector *vector,236 const void *item)237{238 return dal_vector_insert_at(vector, item, vector->count);239}240 241struct 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 vector252 */253 vec_cloned = dal_vector_create(254 vector->ctx,255 vector->capacity,256 vector->struct_size);257 else258 /* Call "presized create" version, independently of how the259 * original vector was created.260 * The owner of original vector must know how to treat the new261 * 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 279uint32_t dal_vector_capacity(const struct vector *vector)280{281 return vector->capacity;282}283 284bool 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 303void dal_vector_clear(struct vector *vector)304{305 vector->count = 0;306}307